It's a good season for remes ! After
Crudd with his ForwardMe, SantMat strikes back with a new one : PopupMe
??( there's no "title" for now :). Do you know how the popup menus are
created ?? I don't ! So, it seems to be a really interesting subject :).
But, as most of you are in the same case, i'll first try to find out how
to create a popup menu in a program coded, and then we will be able to
reverse this target. So here's the first part :
I/ Eh ! How do i create a popup menu ?
So take a basic dialogbox program,
and our goal is to make him display a popup menu when we right-click on
it. I included in the zip the "basic" asm program that just displays a
dialog, and that has no button. This prog is close to the simplest one
that exists :). Now we have to figure out how we can create a popup menu.
Take your api reference, and first try to locate an api beginning with
"popup". Nothing. Let's have a little "zen" :). Windows needs to inform
the program that a right click has been done, no ? And how windows does
that generally ? Try WM_POPUP. Nothing. But, eh, there's a synonym for
popup menu : CONTEXT MENU !!!!!!. Try WM_CONTEXTMENU. WOOOHOOOO ! We found
it. So get back to your program source and add a .ELSEIF uMsg==WM_CONTEXTMENU
in the message loop, and inside it an int 3 . Try to compile it. (don't
forget to type "i3here on" in softice). Yeah ! It breaks when you right-click
into the program. But don't think it's that easy :). As it's written in
the rules, you have to display a menu there. Now look into your api reference
at the links provided :) : DefWindowProc, TrackPopupMenu, TrackPopupMenuEx,
WM_NCRBUTTONUP, WM_RBUTTONUP. Let's look what's TrackPopupMenu.
The TrackPopupMenu function displays
a floating pop-up menu at the specified location and tracks the selection
of items on the pop-up menu. The floating pop-up menu can appear anywhere
on the screen.
One more good thing is done :), we
have the api needed. Now let's look how it works :
BOOL TrackPopupMenu(
HMENU hMenu,
// handle of pop-up menu
UINT uFlags,
// screen-position and mouse-button flags
int x, //
horizontal position, in screen coordinates
int y, //
vertical position, in screen coordinates
int nReserved,
// reserved, must be zero
HWND hWnd,
// handle of owner window
CONST RECT
* prcRect // points to RECT that specifies no-dismissal area
);
The only thing we don't have is the
Menu Handle ! Normal, we don't have any menu yet ! Let's look at the hMenu
description :
hMenu
Identifies the pop-up menu to
be displayed. The handle can be obtained by calling CreatePopupMenu to
create a new pop-up menu, or by calling GetSubMenu to retrieve the handle
of a pop-up menu associated with an existing menu item.
So, we need to call CreatePopupMenu
:). Let's jump into his description :).
The CreatePopupMenu function
creates a pop-up menu. The menu is initially empty, but it can be filled
with menu items by using the AppendMenu and InsertMenu functions (in Windows
95 you can also use the InsertMenuItem function to both append and insert
menu items).
The CreatePopupMenu is VOID, it only
returns a handle to the popup menu. As we only need to create one menu
item, the AppendMenu api will be enough for us. Description and use :
The AppendMenu function appends a new item to the end of the specified menu. An application can use this function to specify the content, appearance, and behavior of the menu item.
BOOL AppendMenu(
HMENU hMenu,
// handle of menu
UINT uFlags,
// menu item flags
UINT uIDNewItem,
// menu item identifier or pop-up menu handle
LPCTSTR lpNewItem
// menu item content
);
This time it's enough :) So we have
to call : CreatePopupMenu and AppendMenu at the inilization, and then TrackPopupMenu
in respond to the WM_CONTEXTMENU message. To see the exact use of the apis,
look into the source code named "popup.asm" :)
Now that we know how to create an
Popup menu in the "easy" way, we have to do that in the target .exe.
II/ Having fun with reme4.exe
Let's grab the info we need to do that
without our lovely compiler :p.
CreatePopupMenu ,AppendMenuA, TrackPopupMenu,
MessageBoxA are in USER32.DLL.
WM_CONTEXTMENU is 7Bh
We need 1 DWORD, and 2 strings
To add the apis into the proggie, use SantMat IidKing :), configure it to put 50 more bytes into the exe, for our data. I got this :
AppendMenuA: call dword ptr [405064]
CreatePopupMenu: call dword ptr [405068]
MessageBoxA: call dword ptr [40506C]
TrackPopupMenu: call dword ptr [405070]
We can place our code at 401080, and
we have there 120h bytes.I think it will be enough for only our code as
we have a small place for our data at 405100 :). Now fireup IDA, we have
to start the "real" work. Here's the end of the message loop.
00401048 81 7D 0C 11 01+
cmp [ebp+arg_4], 111h
0040104F 75 05
jnz short loc_401056
00401051 8B 45 10
mov eax, [ebp+arg_8]
00401054 EB 09
jmp short loc_40105F
00401056
; ---------------------------------------------------------------------------
00401056
00401056
loc_401056:
; CODE XREF: sub_401028+27j
00401056 B8 00 00 00 00
mov eax, 0
0040105B C9
leave
0040105C C2 10 00
retn 10h
0040105F
; ---------------------------------------------------------------------------
0040105F
0040105F
loc_40105F:
; CODE XREF: sub_401028+Cj
0040105F B8 01 00 00 00
; sub_401028+1Ej ...
0040105F
mov eax, 1
00401064 C9
leave
00401065 C2 10 00
retn 10h
So the "no know message" jmp is at
40104F. As we are adding our code just after the actual code, and as it's
a win32asm baby, we simply have to make the actual jump a little bit longer,
so it points to our code. Change 7505 to EB2F and we're done, we have the
control on the message loop :). We could have keeped the jnz instead of
a jmp, but, we need to catch the WM_COMMAND for a later use. But it isn't
finished. Do you remember, we have to take the control over the INTIALIZE
message too :).
00401028 55
push ebp
00401029 8B EC
mov ebp, esp
0040102B 81 7D 0C 10 01+
cmp [ebp+arg_4], 110h
00401032 75 02
jnz short loc_401036
00401034 EB 29
jmp short loc_40105F
But this time, if you try to redirect the jmp at 401034 to our code, it won't work :(, the "target" of the jump is too far from the actual position. ( it creates a long jump, and, there's not enough space for it). But we can cheat :) Make it jump to the place we already modified :). So change the jmp 40105F to jmp 401048 :). Now we have to think about "our" message loop. Let's take a closer look on the WM_CONTEXTMENU message :).
hwnd = (HWND) wParam;
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
Arg, we will have to separate the low and high word of it.It's not a real problem, the following code will do perfectly :
mov eax,[ebp+14]
mov ebx,eax
shr ebx,10h
and eax,0FFFFh
and ebx,0FFFFh
Now run HIEW, we will start to code :)
cmp d,[ebp+0c], 7b
jnz 4b5
mov eax,[ebp+14]
mov ebx,eax
shr ebx,10h
and eax,0FFFFh
and ebx,0FFFFh
push 0
push d,[ebp+8]
push 0
push ebx
push eax
push 0
push d,[405100]
call d,[405070]
jmp 45f
That should make the TrackPopupMenu work :). Now let's code the initializing part :)
@4010B5:
cmp d,[ebp+0c],110
jnz 4e3
call d,[405068]
mov d,[405100],eax
push 405104
push 19
push 0
push d,[405100]
call d,[405064]
jmp 45f
Don't forget to add the string you
want at 405104. I choosed "Y'know what ?". Let's finish it now :) All that
remains is to code a messagebox that says what you want.
@4010E3:
cmp [ebp+0ch],111
jnz 456
cmp [ebp+10],69
jnz 456
push 0
push 405130
push 405116
push d,[ebp+08]
call d,[40506c]
jmp 45f
Fill the string at 405016 with the
text, at 405030 with the title, and you're done !
I hope you learned something :)
You can find me on Efnet, at #immortaldescendants,
or mail me extasy@immortaldescendants.org
Thanks : SantMat, Crudd, MagicRaph,Edy,Tam,C_DKnight,ep-180,promethee,
V-Rom,analyst,amante, to everyone from [ID], #c4n, #crack.fr.