3.Essay
(steps)
|
PART
I - adding the menu
Taking a look at the exe, we see that it has no .rsrc section.
Since we are not allowed to add any other sections, we will add
our menu in the .data section. I have added the menu starting with
offset 0xC50. And here it is:
Now,
a little explaining:
-first 16 bytes describe the top entry, which contains 1 ID entry
(byte 0xC5E);
-then we have the next 8 bytes containing the type and offset (relative
to the beggining of the .rsrc section, that is byte 0xC50) of this
top entry, that is 04 (byte 0xC60)=menu, 18 (byte0xC64)=offset to
the directory entry of the menu. Add 0xC50 to that, and you wil
get 0xC68, that's where the menu directory entry starts;
-next 16 bytes=directory entry of menu, it contains 1 named entry;
-next 8 bytes: offset of the name of the named entry (0x58)->'THEMENU'
and offset to its directory structure (0x30), again, add 0xC50 to
get actual file offsets;
-next 16 bytes=directory entry for the named entry, it contains
one ID entry;
-next 8 bytes: ID of popup=0 and a pointer to its definition:0x48;
-we are at offset 0x48, where we have our popup which is a leaf,
and consists of 16 bytes: 4 bytes-relative virtual address of leaf
:0x30B8 (that is 0xCB8 as file offset), 4 bytes-size of leaf, 4
bytes-codepage and another 4 bytes-reserved;
-the following bytes, to the end of the menu definition, contain
mainly the text of the menu.
Also, last but not least, the ID's for our buttons are 65h, 66h,67h
(101,102,103 dec).
We now need to let the program know that we have a resources section
in it. Start PEBuild, select the exe and change in the Data Directory
tab the Resource RVA to 3050 and the total size to 80.
Now that we added the menu, we must make it the default menu for
our app. The menu for the window is defined at the creation of the
window. Let's take a look at the api definition for the class that
RegisterClassEx uses (the reme uses for creating the class of the
main window this api).
typedef struct _WNDCLASSEX {
// wc
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
HICON hIconSm;
} WNDCLASSEX;
So,
we need the lpszMenuName param of the api call to point to the name
of our menu ('THEMENU', remember?). Therefore, add 'THEMENU' at
0xD20 and than change (in hiew) at 40106A from mov d,[ebp-0c],0
to mov d,[ebp-0c],403120. Run the program. Kewl, we have ourselves
a menu. Now we only need to alter the message loop just a little
bit :)
PART II - changing the message loop
This would be a good time to check out the disassembly of
the file in IDA. Looking at it, we arrive here:
0040115C cmp [ebp+arg_4], 0Fh; is the message WM_PAINT?
00401160 jnz loc_40121E
00401166 lea eax, [ebp+var_44]
00401169 push eax
0040116A push [ebp+arg_0]
0040116D call j_BeginPaint
00401172 mov [ebp+var_4], eax
00401175 lea eax, [ebp+var_54]
00401178 push eax
00401179 push [ebp+arg_0]
0040117C call j_GetClientRect
00401181 push dword_403044;color of the brush=color of the window
background
00401187 call j_CreateSolidBrush
0040118C mov [ebp+var_5C], eax
0040118F push [ebp+var_5C]
00401192 lea eax, [ebp+var_54]
00401195 push eax
00401196 push [ebp+var_4]
00401199 call j_FillRect
0040119E push offset aArial ; "Arial"
004011A3 push 20h
004011A5 push 0
004011A7 push 0
004011A9 push 0
004011AB push 0FFh
004011B0 push 0
004011B2 push 0
004011B4 push 0
004011B6 push 190h
004011BB push 0
004011BD push 0
004011BF push 10h
004011C1 push 18h
004011C3 call j_CreateFontA
004011C8 push eax
004011C9 push [ebp+var_4]
004011CC call j_SelectObject ;selects the font
004011D1 mov [ebp+var_58], eax ;store handle of replaced object
in [ebp-58]
004011D4 push dword_403044;color of text color
004011DA push [ebp+var_4]
004011DD call j_SetTextColor
004011E2 push dword_403044;color of text background
004011E8 push [ebp+var_4]
004011EB call j_SetBkColor
004011F0 push 25h
004011F2 lea eax, [ebp+var_54]
004011F5 push eax
004011F6 push 0FFFFFFFFh
004011F8 push offset aSecretMessage ; "Secret Message"
004011FD push [ebp+var_4]
00401200 call j_DrawTextA
00401205 push [ebp+var_58]
00401208 push [ebp+var_4]
0040120B call j_SelectObject ;restore the selection to the window
00401210 lea eax, [ebp+var_44]
00401213 push eax
00401214 push [ebp+arg_0]
00401217 call j_EndPaint
0040121C jmp short loc_40124A
Also,
take a look over here:
0040121E cmp [ebp+arg_4], 203h
00401225 jnz short loc_401235
00401227 push 1
00401229 push 0
0040122B push [ebp+arg_0]
0040122E call j_InvalidateRect
00401233 jmp short loc_40124A
What
do the two sequences mean?
The first one is run when an WM_PAINT message is posted to the window,
the second whenever our window gets overlayed by another one. First
sequence does the following: BeginPaint->GetClientRect(coordinates
of window)->CreateSolidBrush(creates a brush whose color is at
403044)->FillRect(fills the rect got at GetClientRect with the
color got at CreateSolidBrush)-> CreateFontA(creates the font
which will be displayed)->SelectObject(font)->SetTextColor->SetBkColor->DrawTextA(draws
the text on screen)->SelectObject(restores selection)->EndPaint.
The second simply invalidates the window rectangle, that means that
on the next WM_PAINT message the window gets redrawn.
Well, this is exactly the code we need, but we do not want to write
all this one more time. So, how do we do that? We simply pretend
the window got overlayed and we send a WM_PAINT message to the app.
We must find a place to do that, and a place where we will add our
code. Also, we need two places where we will keep our text and window
color. I have chosen:
-401131:jump to our code;
-4012E6:our code;
-403044:background color;
-403048:text color.
Remember what was previously at 401131, we will need to add it later.
00401131 cmp [ebp+arg_4], 1
00401135 jnz short loc_40115C
So, at 401131 assemble a jmp 4012E6 and a nop in hiew, and
at 4012E6 start coding:
004012E6 cmp dword ptr [ebp+0Ch], 111h ;is the message WM_COMMAND
004012ED jnz short loc_40135A ;if not continue normal program flow
004012EF cmp dword ptr [ebp+10h], 65h ;if it is, was the button's
ID 65h(BLACK)
004012F3 jnz short loc_40130E
004012F5 mov dword_403044, 0 ;bkcolor=black
004012FF mov dword_403048, 0FFFFFFh ;textcolor=white
00401309 jmp loc_401347
0040130E cmp dword ptr [ebp+10h], 66h ;was the button's ID 66h(WHITE)
00401312 jnz short loc_40132D
00401314 mov dword_403044, 0FFFFFFh ;white
0040131E mov dword_403048, 0 ;black
00401328 jmp loc_401347
0040132D cmp dword ptr [ebp+10h], 67h ;was the button's ID 67h(GRAY)
00401331 jnz short loc_40135A
00401333 mov dword_403044, 808080h ;gray
0040133D mov dword_403048, 0 ;black
00401347 mov dword ptr [ebp+0Ch], 0Fh
0040134E push 1
00401350 push 0
00401352 push dword ptr [ebp+8]
00401355 call j_InvalidateRect ;pretend the rectangle has been invalidated
0040135A cmp dword ptr [ebp+0Ch], 1;original portions
0040135E jnz loc_40115C ;of code
00401364 jmp loc_401137 ;go back
The code is almost self-explanatory, so I won't comment much on
it. We first check if the current message is WM_COMMAND - obtained
by 'mouse clicks', then if the wParam is 65, 66 or 67. If so, change
the color values accordingly.
Now we only need to change the code at 4011D4 to push 403048 (the
original code set the text color to be the same as the window color,
that's why you couldn't see the secret message).
And
that's about it!
|
5.Greets
(Acknowledgements)
|
Greets
go to:
evilTeach, for writing this reverseme, and also
Crudd, extasy, amante4, SantMat, vissie, noptical, Iczelion, NeuRaL_NoiSE,
the guys at #Cracking4Newbies, #win32asm, the guys in ID (your database
is really great), and everyone else I forgot.
|