MC Escher MixVibes:

Reversing A Menu Disabled Target (and more)...


by Clandestiny
published by +Tsehp Oct 2001
MC 				Escher
Target: mixvibespro223.zip Location: http://www.mixvibes.com/mixvibes/download/mixvibespro223.zip Size: 853 KB
Introduction:





Greetings,
This essay was inspired by one of the mini projects at The Newbies Forum and will hopefully serve as an introductory essay to enabling disabled menu items. I learned a heap from this project so I decided to share what I learned. Being a newbie myself, I will attempt to *show* you my thought process as I approached this target rather than just outlining the most direct solution. In keeping with this, I may put in some various hints and sidenotes along the way. Most likely, they are some new things I learned while researching the "crippled menu" topic so feel free to skip over them if you are already familiar with this material or wish to get straight to the point. I plan to share 2 entirely different ways that this program can be cracked as well as explore a few possiblites for "fully functionalizing" our target (ie. removing the nag and time limits). I'll warn you now. This is going to be a pretty long one so sit back in a comfy chair and enjoy a beer or cup of coffee while you read :-) Below, you will find the actual project as posted by Kayaker along with a few suggested readings. A couple of the readings may be a bit advanced for the "true newbie", but they are worthwile nontheless.



The Project:



Hi All,

I thought I'd suggest this as a project to explore the process of enabling a disabled menu item and hopefully fully restoring its functionality. This is a 30 day registerable Save-disabled audio mixer. While it can be registered, the main tasks will be to:

1. Enable (ungray) the Save and SaveAs menu items.
2. Enable the Save functionality.

There are at least 2 required readings for this:

Theory and practice of menus reversing by +Spath. http://www.woodmann.net/fravia/menusspa.htm
Enabling Menu Items - Techniques by Lord Soth http://www.immortaldescendants.org/database/essays/lordsoth/menu-items.txt
I've used some of the techniques in a couple of tuts that might help as well:

Enabling Print-Challenged PDF Files http://www.searchlores.org/pdffing.htm
Implementing an Inline Patch from the Menu http://www.woodmann.net/fravia/TracePlus_MenuPatch.html

An API monitor with all the 'menu' APIs enabled is indispensible here, as is the Win32 Programmers Reference. A couple of tips - the decision to enable or disable a menu item in a drop down list is usually made when the main menu item is clicked on. As for actually restoring the Save functionality, familiarize yourself with a couple of the Common Dialogs dll (Comdlg32.dll) functions used in this program, and study closely Lord Soth's tut. Have fun.

Cheers,
Kayaker

Tools:



  1. SoftIce (required)
  2. Wdasm (required)
  3. Hex Editor (required: I use Hex Workshop in the tut)
  4. Windowse (strongly suggested)
  5. API monitor (strongly suggested)
  6. IceDump (suggested)
The Essay




The first thing I did after installing MixVibes was to run it with an eye for the limitations of this demo version. The missing functionality of several menu items is a given...but there were a few additional "bugs" that might be worth investigating as well. Namely, I am referring to that lovely nag which politely informs us our unregistered version will be limited to 30 minutes of use (after which time, of course, it will rather unpolitely throw us out of the program). Altogether, I found 3 targets for our reversing efforts...
  1. Crippled Menu Items - including New, Open,Save, Save As, and Export File
  2. Nag Screen
  3. Time Limit - 30 minutes of use
The discussion of the Crippled Menu Items will be done in 2 parts where each part outlines a different method of attack. Towards enabing these items, Part 1 discusses the use of the WM_COMMAND function and Part 2 explores the use of SICE's back trace range feature. Hopefully, at the end we'll be able to draw a few conclusions regarding the whens, whys, and hows of choosing your approach on this type of target.


1.1 Enabling Crippled Menu Items: Part 1 (using the WM_COMMAND message)

We'll first explore the possibility of enabling the crippled menu items using the WM_COMMAND message. The first thing I did was to fire up Wdasm and take a look at the dead listing. We can actually determine several useful pieces of information here. Scrooling down a little bit in the listing you will see a header entitled "menu information". This lets us know right off that our crippled menu is created using a menu template and that ungreying the items could possibly (though not necessarily) be as simple as changing a parameter in the resources file using a hex editor. From the listing we can also obtain the menu ID for each item. For reference, write down the ID's of our crippled items.


+++++++++++++++++++ MENU INFORMATION ++++++++++++++++++

Number of Menus =    4 (decimal)


MenuID_0064

      File {Popup}
           New   Ctrl+N                [ID=E100h]
           Open...   Ctrl+O            [ID=E101h]
           Save   Ctrl+S               [ID=E103h]
           Save As...                  [ID=E104h]
           Import file                 [ID=1F40h]
           Export file                 [ID=1F41h]
           Scan                        [ID=1F49h]
           Create Autorun              [ID=7D2Ch]
           Recent File                 [ID=E110h]

Note:
There are 2 methods for creating menus. The first (and most common) is the menu template method like you see above. The second involves creating the menu during runtime using API's such as CreateMenu (creates a menu bar) and InsertMenu (adds an item to a menu). Also, each menu item, regardless of how it is created, is given a unique indentification number (ie. in our target Save ID = E103h) This number is important because it allows Windows to identify exactly which menu item you choose via the WM_COMMAND mesage. More on this a little later...


Now, to explore the most simple solution first...Fire up Hex Workshop and load mixvibespro.exe. We are going to be looking at the menu definition in the executable to see if we can ungrey the items from there. The menu items will appear in the "wide char format" in the executable (ie. .S.a.v.e.) So go to Find and do an ascii search for "F.i.l.e" (don't forget to enable the unicode option). Your search will yield something like the following:


00114A90 0000 0000 1000 2600 4600 6900 6C00 6500 ......&.F.i.l.e.
00114AA0 0000 0000 00E1 2600 4E00 6500 7700 0900 ......&.N.e.w...
00114AB0 4300 7400 7200 6C00 2B00 4E00 0000 0000 C.t.r.l.+.N.....
00114AC0 01E1 2600 4F00 7000 6500 6E00 2E00 2E00 ..&.O.p.e.n.....
00114AD0 2E00 0900 4300 7400 7200 6C00 2B00 4F00 ....C.t.r.l.+.O.
00114AE0 0000 0000 03E1 2600 5300 6100 7600 6500 ......&.S.a.v.e.
00114AF0 0900 4300 7400 7200 6C00 2B00 5300 0000 ..C.t.r.l.+.S...
00114B00 0000 04E1 2600 5300 6100 7600 6500 2000 ....&.S.a.v.e. .
00114B10 4100 7300 2E00 2E00 2E00 0000 0000 401F A.s...........@.
00114B20 2600 4900 6D00 7000 6F00 7200 7400 2000 &.I.m.p.o.r.t. .
00114B30 6600 6900 6C00 6500 0000 0000 411F 2600 f.i.l.e.....A.&.
00114B40 4500 7800 7000 6F00 7200 7400 2000 6600 E.x.p.o.r.t. .f.
Note:
The resources in an executable are found in the following order: Options, Menu ID, and Menu Item String.
Options: Number that determies the state of the menu: 00=active, 01=greyed, 02=disabled.
Menu ID: The unique number identifying menu items to Windows that we found and wrote down from the dead listing
Menu Item String: The name of the menu item (ie. File, Save, ect)
/>

Lets examine the Options on each of our menu items. We'll take Save as our example: 0000 03E1 2600 5300 6100 7600 6500

0000:Options = 0 03E1: Menu ID = E103 2600: '&' 5300: 'S' 6100: 'a' 7600: 'v' 6500: 'e'

From this we can see that the Options flag for save is 0 (active) and if you examine the other menu items you will see that this is true for all of them. Obviously, in the program, these items are not active which means they must be being disabled during run-time and we'll have to do a little more work :-) At this point we need to determine what is responsible for disabling our menu items so go back to the deadlisting for a moment. Checking under imported functions, we can make a list of all of the functions relating to menu items. They include: EnableMenuItem, GetMenu, GetMenuItemCount, GetMenuItemID, GetMenuState, GetMenuString A, GetSubMenu, InsertMenu, LoadMenuA, ModifyMenuA. Consulting an API Reference, it looks like EnableMenuItem is the most likely candidate.


From the Win32 Programmers API Reference:

The EnableMenuItem function enables, disables, or grays the specified menu item. 

BOOL EnableMenuItem(

    HMENU hMenu,	// handle to menu
    UINT uIDEnableItem,	// menu item to enable, disable, or gray
    UINT uEnable	// menu item flags

Menu Item Flags:

MF_ENABLED (00h) - Indicates that the menu item is enabled and restored from a grayed state so that it can be selected.

MF_DISABLED (03h) - Indicates that the menu item is disabled, but not grayed, so it cannot be selected.

MF_GRAYED (01h) - Indicates that the menu item is disabled and grayed so that it cannot be selected.



















Realizing this, we break out SoftIce and set a breakpoint on the EnableMenuItem function IF the menu item flag equals 1 (greyed): bpx EnableMenuItem IF ((@(ss:(esp+0c))&1) = = 1). Now when you attempt to select a menu item, SoftIce will break at the following location.


:0049A76A 8B4C240C                mov ecx, dword ptr [esp+0C]
:0049A76E F7D9                    neg ecx
:0049A770 1BC9                    sbb ecx, ecx
:0049A772 83E1FD                  and ecx, FFFFFFFD
:0049A775 83C103                  add ecx, 00000003
:0049A778 80CD04                  or ch, 04
:0049A77B 51                      push ecx        //save the menu item flags 
:0049A77C FF7608                  push [esi+08]	  //save the menu item location
:0049A77F FF7004                  push [eax+04]   //save handle to menu

* Reference To: USER32.EnableMenuItem, Ord:00B0h
                                  |
:0049A782 FF150C264C00            Call dword ptr [004C260C] //call EnableMenuItem
:0049A788 EB53                    jmp 0049A7DD

Looking at this code and tracing through it in SoftIce a couple of times you can see the menu item flag in ecx is 403 for disabled and 400 for enabled menu items. For the items to be enabled, this flag should always be 400 (our flag is only the lower 2 bytes) and we can do a patch at:

:0049A778 mov cl,0
:0049A77A nop
:0049A77B push ecx

Now the program will always pass 400 (the active flag) to the EnableMenuItem API. If you go back and check the target, all of the menu items are ungreyed and active. Unfortunately, this is the point where we make the distinction between an "active" menu item and an "enabled" menu item since clicking on our newly activated menu items does nothing at all. Having explored the simple options and done the preliminary work with EnableMenuItem, we get to the hard part of function enabling our menu items. Once again, we can choose to rule out all simple solutions by doing a search in Wdasm for the MenuItem ID's hoping perhaps it will turn up some type of direct comparison. And though it is a valid approach, this type search won't turn up anything for MixVibes which seems to reference all of its menu items indirectly using the GetMenuID function. Having exhausted the obvious, we are now going to make use of the Windows message WM_COMMAND. Basically, Windows sits in an infinite loop waiting for various messages. The message, WM_COMMAND is the message sent when a menu item is clicked and we need to intercept it so we can find out where the program branches in response to a specific menu item being clicked.

First, find the class name of the window using a utility like Windowse. In this case the class is Afx:400000:b:1466. Now type TASK in SoftIce to see the task list. You will find the taskname of mixvibespro.exe to be MIXVIBES. Now type HWND MIXVIBES. From the list you need to pick out the hwnd of the Afx:400000:b:1466 class. Once you have this, set a message breakpoint in Sice: BMSG (hwnd class) WM_COMMAND where (hwnd class) is the hwnd you just found. SoftIce will break when you attempt to select a menu item. Now, in order to get back into MixVibe's code, we'll borrow Lord Soth's trick of setting a breakpoint on K32Thk1632Prolog: BPX K32THK1632PROLOG. Press F5 and you'll land inside the K32THK1632PROLOG function. Press F11 to return and you'll be inside of some Kernel32 dll code here:

:BFF94402 CALL KERNEL32!K32THK1632PROLOG
:BFF94407 CALL BFF735FD
:BFF9440C CALL KERNEL32!K32THK1632EPILOG

F8 step into the middle funcion CALL BFF735FD. You'll now be looking for a far call so trace forward a bit until you come to CALL GS:[esi + 08]. Trace into this call and you'll be back in our target's code.

Now, that we are back into MixVibes code after a menu item has been selected, we are looking for a type of reg / unreg flag comparison that will determine weather or not to enable our menu item. Unfortunately for the cracker, the code from here on out becomes a jumbled maze of jumps and calls possessing very few "landmarks" to ease our search. And though the exact path to this critical flag will be different for every menu disabled target, we will borrow from Kayaker's experience in our approach. Indeed, he has concluded several interesting tips for finding ones way to this point in a menu disabled target.

Tips for finding the critical flag:

  1. Watch the parameters being pushed on the stack, specifically the Menu ID for the function, the Hwnd of the windows class, and the WM_COMMAND message value (111h). Be suspicious of calls passing several or all of these parameters.
  2. F8 step into the first indirect calls in a function (ie. calls like call [ebp + 08] or call [esi + 04])
  3. If there are no indirect calls in a function, F8 step into the direct call just before the ret.
Following this advice trace through the code until you get to 00496688, the direct call closest to the return. F8 step into it.
:004969A0 55                      push ebp
:004969A1 8BEC                    mov ebp, esp
:004969A3 817D0C60030000          cmp dword ptr [ebp+0C], 00000360
:004969AA 7505                    jne 004969B1
:004969AC 6A01                    push 00000001
:004969AE 58                      pop eax
:004969AF EB1A                    jmp 004969CB

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004969AA(C)
|
:004969B1 FF7508                  push [ebp+08]
:004969B4 E863FFFFFF              call 0049691C
:004969B9 FF7514                  push [ebp+14]
:004969BC FF7510                  push [ebp+10]
:004969BF FF750C                  push [ebp+0C]
:004969C2 FF7508                  push [ebp+08]
:004969C5 50                      push eax
:004969C6 E8BDFCFFFF              call 00496688 //step into direct call before ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004969AF(U)
|
:004969CB 5D                      pop ebp
:004969CC C21000                  ret 0010
Now, trace until you see the first indirect call, [eax+A0] and then F8 step into it.
:00496688 B840F94B00              mov eax, 004BF940
:0049668D E8FE92FEFF              call 0047F990
:00496692 51                      push ecx
:00496693 83EC30                  sub esp, 00000030
:
:
:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004966F4(C)
|
:00496704 FF7518                  push [ebp+18]
:00496707 8B07                    mov eax, dword ptr [edi]
:00496709 8BCF                    mov ecx, edi
:0049670B FF7514                  push [ebp+14]
:0049670E 56                      push esi
:0049670F FF90A0000000            call dword ptr [eax+000000A0] //step into first indirect call

You get the idea... As you continue to trace through the code you will step into each of the following calls:

:004978C1 CALL [eax + A4]
:00497912 CALL [eax + 80]
:004AC153 CALL 00497E88
:00497EC1 CALL [eax + 14]
:004ACB03 CALL [edx + 14]
:0049DDDE CALL [eax + 14]
:0049FDB9 CALL [eax + 14]
:004A183A CALL 0049A449
:0049A51B CALL [eax + 30]
:0049A54E CALL 0049A561
:0049A628 CALL [ebp + 14] // the magic location !!!

Finally after you F8 step into 0049A54E CALL 0049A561, you will notice a notice a bunch of indirect parameters being pushed:

:0049A53B push [ebp+14]
:0049A53E push [eax+10]
:0049A541 push [ebp+10]
:0049A544 push [eax+14]
:0049A547 push [ebp+0C]
:0049A54A push [ebp+08]
:0049A54D push edi
:0049A54E call 0049A561


This looks a little suspicious so we trace into the call...and soon we'll see another indirect call :0049A628 call [ebp+14]. Step into this one and you'll find the magic location!
:0045AF20 8B8134080000            mov eax, dword ptr [ecx+00000834] // reg flag 
:0045AF26 85C0                    test eax, eax // is the flag == 0 ?
:0045AF28 750A                    jne 0045AF34 // regged if eax != 0 
:0045AF2A 8B4C2404                mov ecx, dword ptr [esp+04] //not regged if eax=0
:0045AF2E 6A00                    push 00000000
:0045AF30 8B01                    mov eax, dword ptr [ecx]
:0045AF32 FF10                    call dword ptr [eax]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045AF28(C)
|
:0045AF34 C20400                  ret 0004
From the above code you can see eax holds the flag that determines weather or not our program is registered. If this flag = 0 (unregistered), the program will proceed to disable and grey the selected menu item. However, if the flag is not zero the program will ret and continue on to the correct menu item function. Now knowing that we want this flag not equal to 0, we need only to apply the patch in our favorite hex editor.

Well, there you have it: how to crack MixVibes using windows messages. This was my first approach to cracking this target and there is much to learn from it. Nevertheless, in retrospect, it was not the best approach. Unless you are *very* familiar with the windows message structures, there is way too much unmarked code to trace and it becomes very easy to get lost. Fortunately, there is another way to crack this target and IMO, it's a lot easier to follow than the WM_COMMAND route...


1.2 Enabling Crippled Menu Items: Part 2 (making use of Sice's backtrace range feature)

For those who have never used this handy feature before, a backtrace range records instruction flow in a program. This is useful beacuse it allows us to "trap" important information relating to the protection scheme of a program during execution. Unlike a deadlisting where the jumps and calls are not in the correct order and one must search for their references and backtread carefully, the backtrace gives us an ordered listing of instructions exactly as they were executed.

Now, just a couple of quick notes about this feature:

  1. Settting The Traps: Backtracing is only useful if you set careful "traps" for the information you're looking for. Basically, you're aiming to trap your information between 2 carefully selected breakpoints. The API monitor could be a useful tool to guide you in their selection.
  2. The Backtrace Buffer Memory Allocation:During initial configuration Sice only allocates 4k for the backtrace buffer. You will probably need to increase this amount. This can be done by editing the TRA= line in your winice.dat file. I currently have mine set to 100k, but you should set its value depending on you needs.
Lets apply this information to our target. Break out your API monitor and the list of MixVibe's imported menu functions you made earlier. We'll set it to spy on all of these functions. After doing this, run the target and try to select a menu item. Below, you'll find an excerpt from the log:
004AC599:LoadMenuA(HANDLE:00400000,LPSTR:00000064)
004AC59F:LoadMenuA = 5A4
004A82AF:GetSystemMenu(HWND:00001250,BOOL:00000000)
004A82B5:GetSystemMenu = 638
004AC831:GetMenu(HWND:00000438)
004AC837:GetMenu = 5A4
:
:
:
004AD239:GetMenuItemID(HANDLE:00000440,DWORD:00000002)
004AD23B:GetMenuItemID E103
0049A782:EnableMenuItem(HANDLE:00000440,DWORD:00000002,DWORD:00000000)
0049A788:EnableMenuItem = FFFFFFFF
004AD2A4:GetMenuItemCount(HANDLE:00000440)

We'll use the log to choose our breakpoints for the backtrace. Right off, EnableMenuItem stands out as a good choice since we know there must be some prior condition which determines whether or not to disable our menu item. It will be the 1st boundary of our trap and we now look at the API calls above EnableMenuItem in order to define the second boundary. Directly above is the GetMenuItemID API. Like its name implies, this function retrieves the menu ID so the program can determine what item was selected. Thinking about the functions of these 2 API's, it seems likely that the program performs a check sometime *after* GetMenuItemID determines which item was selected, but *before* EnableMenuItem disables the selection. Therefore, we can conclude that GetMenuItemID would be a good choice for the second boundary of the trap. Having determined this, we'll go ahead and set the breakpoints:

BPX GETMENUITEMID IF *(ss:esp+8) == 2
BPX ENABLEMENUITEM IF *(ss:esp+8) == 2

Both of these functions accept the menu item position as their second parameter hence we can pinpoint the exact menu item for Sice to break on (ie. if the 2nd parameter pushed on the stack = the position of the menu item (for Save=2 and remember we start counting @ 0).

After setting the breakpoints, we'll set up the trace. First get the module handle for mixvibes using the MOD command in Sice.

MOD MIXVIBES (task name)

You'll find the module handle to be MIXVIBESPRO. Now, set a range breakpoint of the form:

BPRW MIXVIBESPRO T

This sets up the backtrace. Now, exit SoftIce and select the Save menu item. Sice will break at our first breakpoint (the GetMenuItemID). Press F5 and it will break again at the second EnableMenuItem API. This fills up the backtrace range buffer with the program instructions between these 2 API's and hopefully trapped the flag that determines whether the menu items are enabled. You can see the results of the backtrace using the SHOW command in Sice but before doing so it is a good idea turn off the register, code, and data windows using the WC, WR, and WD commands.

SHOW 1 will display the last command executed in the trace and you may use the arow keys to scrool up through the instructions.

Note: If you have IceDump 6 installed, you can do a nice screendump of your trace using /SCREENDUMP "path".txt where "path" specifies the path to the filename on your hard drive.

Here is an excerpt from my trace:

000020  017F:0049A5CE  0F878E000000        JA        0049A662                   
00001F  017F:0049A5D4  FF248568A64900      JMP       [EAX*4+0049A668]           
00001E  017F:0049A621  8B7518              MOV       ESI,[EBP+18]               
00001D  017F:0049A624  8B4D08              MOV       ECX,[EBP+08]               
00001C  017F:0049A627  56                  PUSH      ESI                        
00001B  017F:0049A628  FF5514              CALL      [EBP+14]                   
00001A  017F:0045AF20  8B8134080000        MOV       EAX,[ECX+00000834]         
000019  017F:0045AF26  85C0                TEST      EAX,EAX     // the magic flag !!!
000018  017F:0045AF28  750A                JNZ       0045AF34                   
000017  017F:0045AF2A  8B4C2404            MOV       ECX,[ESP+04]               
000016  017F:0045AF2E  6A00                PUSH      00                         
000015  017F:0045AF30  8B01                MOV       EAX,[ECX]                  
000014  017F:0045AF32  FF10                CALL      [EAX]                      
000013  017F:0049A759  56                  PUSH      ESI                        
000012  017F:0049A75A  8BF1                MOV       ESI,ECX                    
000011  017F:0049A75C  57                  PUSH      EDI                        
000010  017F:0049A75D  8B460C              MOV       EAX,[ESI+0C]               
00000F  017F:0049A760  85C0                TEST      EAX,EAX                    
00000E  017F:0049A762  7426                JZ        0049A78A                   
00000D  017F:0049A764  837E1000            CMP       DWORD PTR [ESI+10],00      
00000C  017F:0049A768  757A                JNZ       0049A7E4                   
00000B  017F:0049A76A  8B4C240C            MOV       ECX,[ESP+0C]               
00000A  017F:0049A76E  F7D9                NEG       ECX                        
000009  017F:0049A770  1BC9                SBB       ECX,ECX                    
000008  017F:0049A772  83E1FD              AND       ECX,-03                    
000007  017F:0049A775  83C103              ADD       ECX,03                     
000006  017F:0049A778  B100                MOV       CL,00                      
000005  017F:0049A77A  90                  NOP                                  
000004  017F:0049A77B  51                  PUSH      ECX                        
000003  017F:0049A77C  FF7608              PUSH      DWORD PTR [ESI+08]         
000002  017F:0049A77F  FF7004              PUSH      DWORD PTR [EAX+04]         
000001  017F:0049A782  FF150C264C00        CALL      [USER32!EnableMenuItem]    
Looking backwards from the EnableMenuItem function, you'll quickly see 2 compare / jumps :

00000D 017F:0049A764 837E1000 CMP DWORD PTR [ESI+10],00
00000C 017F:0049A768 757A JNZ 0049A7E4

:and

00001A 017F:0045AF20 8B8134080000 MOV EAX,[ECX+00000834]
000019 017F:0045AF26 85C0 TEST EAX,EAX // the magic reg / unreg flag !!!

Both being so close to the EnableMenuItem function and being of the form cmp memory location, 0 makes them suspect. Having already cracked this once before we know that the test eax,eax is the magic flag. Nevertheless, even if you didn't know this you could easily set bpx's on both instructions and bpm's on the memory locations being compared to narrow it down. IMO, the uses of Sice's backtrace range function cannot be overestimated...and it goes to show that RTFM about your tools is good advice :-)


2. Nag Removal

After the difficulty of finding the memory location of the reg / unreg flag to enable our menu items, short circuiting the nag is going to be relatively easy. First, load MixVibes into SoftIce (it will break at the program entry point). We'll set our breakpoint here before the nag is shown at the memory location of the reg / unreg flag.

BPMD 0050F8A4 Press F5 and SoftIce will break for the first out of a total of 4 times.

Break # 1:

:00459A33 89BE34080000            mov dword ptr [esi+00000834], edi // reg flag
:00459A39 89BE3C080000            mov dword ptr [esi+0000083C], edi
:00459A3F 89BE44080000            mov dword ptr [esi+00000844], edi
:00459A45 89864C080000            mov dword ptr [esi+0000084C], eax
:00459A4B 898650080000            mov dword ptr [esi+00000850], eax
:00459A51 89BEC0080000            mov dword ptr [esi+000008C0], edi
:00459A57 89BE34090000            mov dword ptr [esi+00000934], edi
Here it appears to be loading the flag into memory. Well, lets continue and see what else we find...Press F5.

Break #2:

:00459DA6 83BA3408000000          cmp dword ptr [edx+00000834], 00000000 //reg flag
:00459DAD 0F8560010000            jne 00459F13
:00459DB3 6A00                    push 00000000
:
:
:
:00459E41 E8BA0B0000              call 0045AA00
:00459E46 8B55A0                  mov edx, dword ptr [ebp-60]
:00459E49 895584                  mov dword ptr [ebp-7C], edx
:00459E4C 8D4D90                  lea ecx, dword ptr [ebp-70]
:00459E4F E82C0B0000              call 0045A980
:00459E54 894588                  mov dword ptr [ebp-78], eax
:00459E57 8D8D28FFFFFF            lea ecx, dword ptr [ebp+FFFFFF28]
:00459E5D E8D5FD0300              call 00499C37 //show nag screen
Continue tracing a little bit after the second break and you'll see the nag screen pop up at call 00499C37. Once again, we want the flag [edx + 834] != to 0 in order to bypass it. Change the jne to jmp and the nag removal mission is acomplished, but we'll still examine the other locations where this flag is checked for curiosity's sake. F5 again and you'll be at the third break.

Break #3:

:00459EDF 83B83408000000          cmp dword ptr [eax+00000834], 00000000b //reg flag
:00459EE6 751C                    jne 00459F04
:00459EE8 8B4DA0                  mov ecx, dword ptr [ebp-60]
:00459EEB 83C101                  add ecx, 00000001
:00459EEE 51                      push ecx

* Possible StringData Ref from Data Obj ->"uTu"
                                  |
:00459EEF 680CED4F00              push 004FED0C

* Possible StringData Ref from Data Obj ->"Settings"
                                  |
:00459EF4 680CD14F00              push 004FD10C
:00459EF9 8B8D88FDFFFF            mov ecx, dword ptr [ebp+FFFFFD88]
:00459EFF E851930400              call 004A3255
The function of this one isn't obvious, but for consistancy we should patch it too!

Break #4:

:0045AF20 8B8134080000            mov eax, dword ptr [ecx+00000834] // reg flag 
:0045AF26 85C0                    test eax, eax // is the flag == 0 ?
:0045AF28 750A                    jne 0045AF34 // regged if eax != 0 
:0045AF2A 8B4C2404                mov ecx, dword ptr [esp+04] //not regged if eax=0
:0045AF2E 6A00                    push 00000000
:0045AF30 8B01                    mov eax, dword ptr [ecx]
:0045AF32 FF10                    call dword ptr [eax]
This little snippet of code should look familiar :-) It's just the first flag we found and used to reenable the menu items. Interestingly, we don't get to the time limit reg flag this way. Possibly this is because it doesn't check until the 30 minutes have elapsed. Rather than wait around to see if Sice breaks in the next 30 minutes, we'll find it another way...


3. 30 Minute Time Limit Removal

By this time you've probably had occasion to notice the nice little message box informing you that the unregistered version is limited to 30 minutes of use. Well, we're going to finish off by fixing this little nag. Doing a search in the String References in Wdasm you'll soon find the message:

String Resource ID=61219: "unregistred version 30'' limited time thanks for trying MixV"

Clicking on this reference will land you at 004256E in MixVibes code:

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00442528(C), :0044252C(C)
|
:0044253F 8B86A0000000            mov eax, dword ptr [esi+000000A0]
:00442545 85C0                    test eax, eax
:00442547 7540                    jne 00442589
:00442549 8B8134080000            mov eax, dword ptr [ecx+00000834]
:0044254F 85C0                    test eax, eax
:00442551 7536                    jne 00442589
:00442553 8B8E18080000            mov ecx, dword ptr [esi+00000818]
:00442559 81C140771B00            add ecx, 001B7740
:0044255F 3BE9                    cmp ebp, ecx
:00442561 7626                    jbe 00442589
:00442563 8BCE                    mov ecx, esi
:00442565 E8F68DFFFF              call 0043B360
:0044256A 6AFF                    push FFFFFFFF
:0044256C 6A10                    push 00000010

* Possible Reference to String Resource ID=61219: "unregistred version
30'' limited time
thanks for trying MixV"
                                  |
:0044256E 6823EF0000              push 0000EF23
:00442573 E866F40500              call 004A19DE
Looking above this reference, you'll see several suspicious jumps (which all bypass the time limit message, BTW). The 1st one (jbe 00442589) will clearly bypass the time limit message if ecx is less than or equal to ebp...which makes perfect sense...since if the time is less than or equal to 30 minutes, we'll bypass the time limit. We could patch the program here, but looking a little further up you'll see our infamous reg / unreg flag comparison:

mov eax, dword ptr [ecx+00000834]
test eax, eax
jne 00442589

Change this jne to a jmp like we did to remove the nag and you'll automatically take care of the time limit since the reg / unreg comparison is above the time limit comparison. Really, you could do a patch at either of these locations with the same effect, but IMHO it seems like patching all of the reg flag locations is a bit more elegant :-)


Last But NOT Least: A Special Thanks



A special thanks to Kayaker for this excellent learning experience and to everyone at the Newbies Forum who've helped make these RCE projects possible !!!