Solution to SantMat's ReverseMe 4
by Lord Rhesus
Introduction
I haven't had a lot of free time lately, I've recently finished my exams and have been taking a breather for a while. I come back to check how things are going on at SantMat's ReverseMe website and I find this little gem of a ReverseMe to have a crack at. Basically the ReverseMe is a simple dialog box and the challenge is to add code to the program so that when you right click on the box a menu comes up containing selectable menu items which have to do something.
Tools Used
- Iczelion's Snippet Creator (I use this for convenience as you can assemble
Masm code straight into the program)
- SoftICE/TRW2000 (just used for debugging my code)
- Ida Pro (for exploring the ReverseMe)
- Exescope (for exploring the ReverseMe)
- Procdump (for looking at the PE headers)
- Cygnus Hex Editor (lame editor which was the first program I cracked years
ago, so I use it out of nostalgia ;-)
- Jump Calculator (small program written by me to save calculating jumps/calls
etc. by hand)
- Masm32 (assembler for writing our code in)
Plan Of Attack
If your like me and have never written code in Win32Asm for dealing with right clicking it will be a good idea to practice before jumping straight into the ReverseMe. The code I used is included with this tutorial. I used Borland's WinApi reference and Microsoft's MSDN library to obtain the following API calls which will be a requirement of the ReverseMe for popping up the menu:
- User32.dll - AppendMenuA - CreatePopupMenu - TrackPopupMenu
Now we have to decide what menu items to create and what they are going to do. I am only going to make 3 items. The first item will play a wave file that's included in the package of a cat meowing (Why a cat? I hate cats!), the second will be a link to my web site (Yes! I know it's a cheap plug but it's my tutorial so like it or lump it ;-), the third item will close the ReverseMe. The API's which I will need to do this are as follows:
- Shell32.dll - ShellExecuteA (this is for linking to my website) - Winmm.dll - PlaySound (this API only plays wave files)
I know this is skipping a bit but all of the code above is explained in the example source code.
Now that we know how to implement popup menus we can now plan how to insert the code into the ReverseMe. The API calls for producing the menu need certain parameters to work such as hwndDlg, uMsg, wParam and lParam. The API TrackPopupMenu requires the handle (hwndDlg) of the window or dialog box which will contain the menu. uMsg is needed so we can identify which messages have been sent to the window/dialog box such as WM_INITDIALOG, which is send when a dialog box is created. wParam for our code (not always) will contain the ID number of which menu item has been selected. lParam will contain some values which are sent along with the message, for us this will be the co-ordinates of the mouse relative to the dialog box when the right button is clicked. One of the problems we will have to solve will be how to find out these values (which isn't that hard in a Win32Asm program but often a hell of a lot harder in something compiled in a high level language).
After finding out the above values we will need to add imports to the ReverseMe which aren't already there and then we will need to find out where we can add our code.
The Essay
Ok enough time messing about in front of the drawing board. From here on it will be assumed that everyone knows how to implement a popup menu in Win32Asm from studying the source code.
Now we need to find out where our four mystery values (hwndDlg, uMsg, wParam and lParam) are held in memory. This is easier than it sounds. Upon creating a dialog using the 'DialogBoxParamA' API the memory location of a procedure is passed into it which will receive all of the messages relating to the dialog box, such as has it just been created (WM_INITDIALOG), or has someone selected something on it (WM_COMMAND) like buttons or *menu items*. The memory location of this procedure is the second value which is pushed onto the stack before it is called (this procedure is called a call-back procedure). Four values are passed to the procedure which happen to be our mystery values. These values are shown by the DialogProc call-back function which is described as below (taken from a help file):
BOOL CALLBACK DialogProc( HWND hwndDlg, // handle of dialog box UINT uMsg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); PARAMETERS hwndDlg - Identifies the dialog box. uMsg - Specifies the message. wParam - Specifies additional message-specific information. lParam - Specifies additional message-specific information.
Below is a list of where these values are always stored at the beginning of this procedure (after the 'push ebp' then the 'mov ebp, esp'):
hwndDlg = [ebp+8] uMsg = [ebp+0ch] wParam = [ebp+10h] lParam = [ebp+14h]
Now that we have these values it's all straight forward from here on. Next we need to see if there is any free space for us to insert our code. Open up Procdump, then open reme4.exe in the PE editor and go to the sections editor. If we take a look at the section named '.text' and we subtract it's virtual size from it's raw size: 200h - 80h = 180h. That gives us 384 bytes to play around with which is plenty. If we start at a round number such as 100h instead of 80h (which is the the end of the virtual size) then the VA where we will be entering our code in is 100h + virtual offset + base address = 100h + 1000h + 400000h = 401100h. Since I will be using Iczelion's Snippet Creator, this is the location we will need to tell it to add our code into.
Next we need to find out if the program contains any of the imports we will need, so we know what we have to add ourselves. I used Exescope to find out what imports are used. Just open up the file reme4.exe in Exescope and have a look at the imports. The only import that will be of use to us is EndDialog. Now we have to add the imports below into the exe for it to do what we want:
- User32.dll - AppendMenuA - CreatePopupMenu - TrackPopupMenu - Shell32.dll - ShellExecuteA - Winmm.dll - PlaySound
I did this using Snippet Creator but an alternative program for doing this would be SantMat's IDDKing. Since I am using Snippet Creator to insert my code, open up Snippet Creator and create a new project for reme4. Now insert the imports above using the option provided under the menu item 'Action'. After this is done it's time to find out where we are to link to our code from. Disassemble the program using Ida Pro and look for references to the API 'DialogBoxParamA'. You will find the code listing as below:
0040100C push 0 0040100E push offset sub_401028 <---- This is the dialog's callback procedure 00401013 push 0 00401015 push 1 00401017 push dword_403000 0040101D call j_DialogBoxParamA
From this we can see that the procedure for dealing with this dialog's messages starts at memory location 401028h so lets have a look at Ida Pro's disassembly of this region:
00401028 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ 00401028 00401028 ; Attributes: bp-based frame 00401028 00401028 sub_401028 proc near ; DATA XREF: start+Eo 00401028 00401028 arg_0 = dword ptr 8 <--- Only 3 arguments here because 00401028 arg_4 = dword ptr 0Ch <--- SantMat's ReverseMe only uses 00401028 arg_8 = dword ptr 10h <--- 3. Else Ida would list all 4 00401028 00401028 push ebp 00401029 mov ebp, ESP 0040102B cmp [ebp+arg_4], 110h <--- 110h = WM_INITDIALOG (windows message) 00401032 jnz short loc_401036 <--- jump if message not WM_INITDIALOG 00401034 jmp short loc_40105F <--- jump if WM_INITDIALOG 00401036 ; ---------------------------------------------------------------------------
Already we have found the information we need. The fact that there is a check for WM_INITDIALOG already in the code means that we can replace this with a link to the code we are going to inject. Using my Jump Calculator, select the jump as being a 'jmp', enter as the Jump VA = 401034, the Target VA = 401100 and press Calculate. Arrrgg, the result is a long jump (E9C7000000) which is too large to fit in a short jump's space (2 bytes in case you didn't know ;-). Never mind, we will have to replace the 'cmp [ebp+arg_4], 110h' instruction with our jump and do this calculation again in our injected code. So using the jump calculator repeat the steps above but using 40102B as Jump VA. The result we get is E9D0000000 which we can add in later using a hex editor.
Now we have added the imports we need to the ReverseMe, we have found space to insert our code and we have found out where to link to our code from and the jump instructions needed to do this. Now all we have left to do is to write the code which we are going to insert and assemble it into the program. Below is the code which I pasted into Snippet Creator's code window with a few comments added:
;Snippet Code ;------------ WinMain proto :DWORD,:DWORD,:DWORD,:DWORD PlaySound PROTO STDCALL :DWORD, :DWORD, :DWORD include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\gdi32.inc include \masm32\include\shell32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\gdi32.lib includelib \masm32\lib\shell32.lib includelib \masm32\lib\winmm.lib ;Assumptions made: ;------------------ ;hWnd = [ebp+8h] ;luMsg = [ebp+0ch] ;wParam = [ebp+10h] ;lParam = [ebp+14h] ;After redirect from WM_INITDIALOG: ;---------------------------------- cmp dword ptr [ebp+0ch], 110h jz over_data ;do my WM_INITDIALOG code jmp restofcode ;else see if other injected code needs to be done Menu1 db "Meow",0 Menu2 db "Shameful Plugging Of My Site",0 Menu3 db "Exit Program",0 mnuhWnd HWND ? Operation db "open",0 Meow db "meow.wav",0 MySite db "http://www.codeinjection.cjb.net",0 over_data: invoke CreatePopupMenu mov mnuhWnd, eax invoke AppendMenuA, mnuhWnd, MF_STRING, 101, addr Menu1 invoke AppendMenuA, mnuhWnd, MF_STRING, 102, addr Menu2 invoke AppendMenuA, mnuhWnd, MF_STRING, 103, addr Menu3 push 40105fh ret ; check the rest of my code restofcode: .IF dword ptr [ebp+0ch]==WM_CONTEXTMENU mov eax, dword ptr [ebp+14h] and eax, 0ffffh mov ebx, dword ptr [ebp+14h] shr ebx, 16 invoke TrackPopupMenu, mnuhWnd, TPM_LEFTALIGN, eax, ebx, 0, [ebp+8], 0 .ELSEIF dword ptr [ebp+0ch]==WM_COMMAND mov eax, dword ptr [ebp+10h] .IF ax==101 ;first menu item selected invoke PlaySound, addr Meow, NULL, NULL .ELSEIF ax==102 ;second menu item selected invoke ShellExecute, NULL, addr Operation, addr MySite, 0, 0, 0 .ELSEIF ax==103 ;third menu item selected push 40103ch ret .ENDIF .ENDIF push 401036h ret
In case your wondering what all the 'push xxxxxxh' then 'ret' instructions are doing, they are just easy ways of assembling direct jump instructions in assembler without having to supply a direct address which will be rejected by the assembler. Also in the above code when the third menu item is selected there is just a 'push 40103ch' and 'ret' instruction....I'm not going to tell you what this does as finding out for yourself will help you understand the ReverseMe's code better.
Before assembling the above code into the ReverseMe you must remember to select 'Project Options' in Snippet Creator and set the snippet VA to 401100 and select 'Patch into Existing Section'. Leave the other options untouched. Now click the Assemble button and everything should assemble OK If you click on the Action menu item then you will see that the option 'Patch target File' is now enabled. Select this and if everything goes according to plan then then program will tell you the patch was successful. If it doesn't work then check that all of the imports have been added. If you still have trouble then check that you have set up Snippet Creator properly by following the instructions in the help file provided, else drop me an e-mail and I'll see what I can do.
Last but not least don't forget to add a jump to this code at 40102B as described earlier, or nothing will happen. Now run the patched program and hopefully when you right click on the dialog, a menu will appear. If you select one of these options hopefully something will happen i.e. a cat will meow or your default web browser will open and try and go to my website or the dialog will close.
Final Notes
Nothing much to say here really! I hope this tutorial has been of use to some of you. I tried to explain each step carefully so that people with little experience will be able to understand what's going on and why it's happening. Any queries, comments or criticisms can be made to me at lordrhesus@yahoo.co.uk
Greetings
Thanks go SantMat for writing an excellent ReverseMe and (hopefully) posting this tutorial.
Greetings go out to Harlequin, Extasy, [yAtEs], [basic], tank, Crudd, Volatility, Iczelion and anyone else who contributes to the scene (especially to the code injection scene :-).