10101010101010
010101010101000010100
10100101
10101010100101010
10101000010010110
00101000101000010

-Crudd's StrMan-
solution of the reverseme
~by tank_~

10101000100011111001
101000110010101100
1000100001111111011
10001000011111101010
1000111000101100100
1001111110001000100

Wise quote

Section:
Contents:
1.Tools used

SoftIce (for tracing/debugging)
IDA (for dead-listings)
Hiew (for modifying the exe's instructions/opcodes)
PeBuild (for modifying the exe's sections and writing strings)
Sadd (by NeuRaL_NoiSe, for adding sections to a PE file)
OpGen (by NeuraL_NoiSe, for getting the right calls/jmps in the exe)
Api reference (for the coding part of the reverseme)
MASM (for the DLL)

2.Initial approach (Introduction)

Hello and welcome to another one of my reversing tutorials, this time we will take a look at another reverseme by Crudd, called StrMan. Reading the assignment, we find out that we need to make 2 functions work (ROR and NOT), by means of using a DLL that we will code. This is my first asm coding experience, so I must ask for the reader's patience with my source code which lacks style but yet works ;) Analysing the task, we realise we have to:
a) change the code that displays the ugly messageboxes;
b) add some code to the messageloop to process the 2 functions;
c) code the DLL (the fun part :) ).

3.Essay
(steps)

Let's start by adding a new section to our exe, let's call it '.tank_'. Use Sadd to do this. But hey, what happens !? (The exe gets smaller ????) So, the exe header must be a little bit tampered with I think. Take a look at the .rsrc section details in PEBuild. It starts at 1400 and ends at 5908 (hex). that means a difference of 4508 (actual size of section). But the Virtual and Phisical Size of the section are 62C. Let's change that to 4508. Now try again to add the '.tank_' section. Voila, the file size is more like it.
Now, at this point take a look at both the exe and the dll, so that you can get the idea on how to start. I will tell you what I have discovered.
Here is where the exe loads the functions from the dll.

00401380		 push	 offset	aString_dll ; "String.dll"
00401385		 call	 _LoadLibraryA@4
0040138A		 mov	 ds:MyDLL, eax
0040138F		 cmp	 ds:MyDLL, 0
00401396		 jnz	 short loc_4013B8
00401398		 push	 0
0040139A		 push	 offset	Title	 ; "Crudd's String Manipulator"
0040139F		 push	 offset	aANeededDllCoul	
; "A needed DLL	could not be loaded."
004013A4		 push	 [ebp+hDlg]
004013A7		 call	 _MessageBoxA@16
004013AC		 push	 0
004013AE		 push	 [ebp+hDlg]
004013B1		 call	 _EndDialog@8
004013B6		 jmp	 short loc_40140C
004013B8		 push	 offset	aCut_his_dick_o	; "Cut_his_dick_off"
004013BD		 push	 ds:MyDLL
004013C3		 call	 _GetProcAddress@8
004013C8		 mov	 ds:CutIt, eax
004013CD		 push	 offset	aSomeone_bit_me	; "Someone_BIT_me"
004013D2		 push	 ds:MyDLL
004013D8		 call	 _GetProcAddress@8
004013DD		 mov	 ds:BiteIt, eax
004013E2		 push	 offset	aSo_byte_him_ba	; "So_BYTE_him_back"
004013E7		 push	 ds:MyDLL
004013ED		 call	 _GetProcAddress@8
004013F2		 mov	 ds:ByteIt, eax
004013F7		 push	 offset	aYoure_worthles	; "Youre_worthless_anyway"
004013FC		 push	 ds:MyDLL
00401402		 call	 _GetProcAddress@8
00401407		 mov	 ds:Worthless, eax
Now, by looking at the dll we realise that:
1. Someone_BIT_me does the ROL part
2. So_BYTE_him_back does the XOR part
3. Youre_worthless_anyway displays the 2 messageboxes
4. Cut_his_dick_off does some variable initialisation that ROL and XOR need.
Now, we realise that our dll actually needs to export 5 functions ( Someone_BIT_me, So_BYTE_him_back and Youre_worthless_anyway from the original exe and our functions for ROL and NOT).
Therefore, the original exe importing only 4 functions, we need to add one by altering the code. First look in the exe for 'string.dll' and replace it with 'tank.dll' (the name of our dll)
We will call our 5 functions in the DLL f_CUT f_ROL f_ROR f_NOT f_XOR. Replace the original names in the exe at .4040DF with these strings. I did it like this:
004040DF aF_ror		 db 'f_ROR',0            ; DATA XREF: _InitializeApp+13Fo
004040E5		 db    0 ;  
004040E6		 db    0 ;  
004040E7		 db    0 ;  
004040E8		 db    0 ;  
004040E9		 db    0 ;  
004040EA		 db    0 ;  
004040EB		 db    0 ;  
004040EC		 db    0 ;  
004040ED		 db    0 ;  
004040EE		 db    0 ;  
004040EF		 db    0 ;  
004040F0 aF_not		 db 'f_NOT',0            ; DATA XREF: .tank:_0040B11Ao
004040F6 aF_xor		 db 'f_XOR',0            ; DATA XREF: _InitializeApp+12Ao
004040FC		 db    0 ;  
004040FD		 db    0 ;  
004040FE		 db    0 ;  
004040FF		 db    0 ;  
00404100		 db    0 ;  
00404101		 db    0 ;  
00404102		 db    0 ;  
00404103		 db    0 ;  
00404104		 db    0 ;  
00404105		 db    0 ;  
00404106		 db    0 ;  
00404107 aF_rol		 db 'f_ROL',0            ; DATA XREF: _InitializeApp+115o
0040410D		 align 4
00404110 unk_404110	 db    0 ;		 ; DATA	XREF: .tank:_0040B000o
00404111		 db    0 ;  
00404112		 db    0 ;  
00404113		 db    0 ;  
00404114		 db    0 ;  
00404115		 db    0 ;  
00404116 aF_cut		 db 'f_CUT',0            ; DATA XREF: .tank_:0040B010o
00404116					 ; .tank:_0040B12Fo
0040411C		 db    0 ; 

Also, at .4013B8 make a jump to our code which will be at .40B11A. So, if you do that, it will look something like this:

004013B8		 jmp	 loc_40B11A
004013BD		 push	 ds:MyDLL
004013C3		 call	 _GetProcAddress@8
004013C8		 mov	 ds:CutIt, eax
004013CD		 push	 offset	aF_rol	 ; "f_ROL"
004013D2		 push	 ds:MyDLL
004013D8		 call	 _GetProcAddress@8
004013DD		 mov	 ds:BiteIt, eax
004013E2		 push	 offset	aF_xor	 ; "f_XOR"
004013E7		 push	 ds:MyDLL
004013ED		 call	 _GetProcAddress@8
004013F2		 mov	 ds:ByteIt, eax
004013F7		 push	 offset	aF_ror	 ; "f_ROR"
004013FC		 push	 ds:MyDLL
00401402		 call	 _GetProcAddress@8
00401407		 mov	 ds:Worthless, eax
Now, at .40B11A, enter the following code:
0040B11A		 push	 offset	aF_not	               ; "f_NOT"
0040B11F		 push	 ds:MyDLL
0040B125		 call	 _GetProcAddress@8           ;get f_NOT's process address
0040B12A		 mov	 ds:dword_40B1F0, eax   ;store it in 40B1F00
0040B12F		 push	 offset	aF_cut	                
; "f_CUT" -overwritten by our jump from .4013B8
0040B134		 jmp	 loc_4013BD                        ;go back to main code
If you did as adviced, now when the program runs you will have the 5 functions from tank.dll ready for use.
Next step, let us change the code that shows the 2 messageboxes when you click ROL or NOT. It's easy to find by looking in the disasm of the file. You probably found it by now, but just in case you haven't, I'll tell you where it is: .4015A7 for ROL and .4015C9 for NOT. So, @.4015A7 assemble a jmp .40B01A and @.4015C9 assemble a jmp .40B05A. And starting with .40B01A assemble:

0040B01A		 push	 5                    ;SW_SHOW
0040B01C		 push	 ds:hEdit2
0040B022		 call	 _ShowWindow@8
0040B027		 push	 5                    ;SW_SHOW
0040B029		 push	 ds:hStatic1
0040B02F		 call	 _ShowWindow@8
0040B034		 push	 0                    ;SW_HIDE
0040B036		 push	 ds:hCB1
0040B03C		 call	 _ShowWindow@8
0040B041		 push	 offset	aNumberOfBits ;	"Number	of Bits:"
0040B046		 push	 66h                  ;ID of second label (get it with BRW)
0040B048		 push	 dword ptr [ebp+8]    ;application window handle
0040B04B		 call _SetDlgItemTextA@12  ;set the second label to "Number of Bits:" 
0040B050		 mov	 eax, 1               ;don't ask me why, just do so
0040B055		 jmp	 loc_40163E           ;go back to original code
0040B05A		 push	 0                    ;SW_HIDE 
0040B05C		 push	 ds:hEdit2            ;second edit box handle 
(remember, Crudd wanted us to hide second edit box when NOT is selected)
0040B062		 call	 _ShowWindow@8        ;hide second edit box
0040B067		 push	 0
0040B069		 push	 ds:hStatic1
0040B06F		 call	 _ShowWindow@8        ;hide first label
0040B074		 push	 0
0040B076		 push	 ds:hCB1
0040B07C		 call	 _ShowWindow@8        ;hide checkbox
0040B081		 push	 offset	aSecondString ;	"Second	String:"
0040B086		 push	 66h
0040B088		 push	 dword ptr [ebp+8]
0040B08B		 call	 _SetDlgItemTextA@12  ;put "Second String:" in second label
0040B090		 mov	 eax, 1
0040B095		 jmp	 loc_40163E           ;back to original code

Now, we have our 2 radio buttons getting things changing, we only need to add the code for them. Therefore, we need to find the main message loop. Again, take a good look at the dissassembly. See at .401446 that 'cmp edi,111h'. That means - compare message to WM_COMMAND, or see if a button was clicked or smth. If so, go at .40146E. Then, let's do that:

0040146E movzx ebx, word ptr [ebp+wParam]
00401472 cmp ebx, 1
00401475 jz short loc_401496


So, if ebx==1 (wParam of WM_COMMAND, it means control with id equal to 1, that is if the Do it! button was pushed) go at .401496 and start the code. Therefore, at .401496 we will jump to our code which will check which radio button was used. So, at .401496 do a jmp .40B0A0, and at that location assemble:


0040B0A0      push ds:hEdit1                    ;handle of first textbox
0040B0A6      call _GetWindowTextLengthA@4      ;get the length of text
0040B0AB      mov [ebp-4], eax                  ;store it in [ebp-4]
0040B0AE      cmp eax, 0                        ;if it is 0
0040B0B1      jz loc_4014AA            ;then go to original code that displays an error message
0040B0B7      push 69h                          ;ID of ROL radio button 
0040B0B9      push dword ptr [ebp+8]            ;handle of app window
0040B0BC      call _IsDlgButtonChecked@8        ;see if ROL is checked
0040B0C1      cmp eax, 0                        ;see if do
0040B0C4      jnz short loc_40B0E4              ;if eax!=0, that means ROL checked go to .40B0E4
0040B0C6      push 6Ah                          ;same
0040B0C8      push dword ptr [ebp+8]            ;for
0040B0CB      call _IsDlgButtonChecked@8        ;NOT
0040B0D0      cmp eax, 0                        ;if NOT isnt selected
0040B0D3      jz loc_4014C2                     ;return to normal program flow
0040B0D9      call ds:dword_40B1F0              ;if it is call the function we have stored in .40B1F0
0040B0DF      jmp loc_401639                    ;return to normal program flow
0040B0E4      call ds:Worthless                 ;call f_ROL in tank.dll
0040B0EA      jmp loc_401639                    ;return to normal program flow

Well, that's about it for the exe, we now need to code the dll, and we're all set.
4.Final words
Wow, this was a blasting reme, I really enjoyed every part of it, but then I ran out of time and actually struggled to write an essay on it. The essay was written almost 3 weeks after completing the reme, but, as they say, better late than sorry ;P Thanks again Crudd for this great reverseme, I actually coded my first asm thingie thanks to him.

5.Greets
(Acknowledgements)

Greets go to:
Crudd, for writing the reverseme, and also
extasy, amante4, SantMat, vissie. Also thanks to Iczelion, nchanta, Dawai for various tips, the guys at #Cracking4Newbies, #win32asm, the guys in ID (your database is really great), and everyone else I forgot.
6.Contact me
You can mail me with questions/problems/queries/threats and so on at tank__@hotmail.com