I am trying to find what a button does, so I want to set a breakpoint to catch button click event. Is that possible?
Any tools or tricks to assist in this?
Reverse Engineering Stack Exchange is a question and answer site for researchers and developers who explore the principles of a system through analysis of its structure, function, and operation. It only takes a minute to sign up.
Sign up to join this communityI am trying to find what a button does, so I want to set a breakpoint to catch button click event. Is that possible?
Any tools or tricks to assist in this?
It very much depends on what framework they use in order to do their windowing. It could be MFC, WPF, WinForms, WTL, QT, wxWidgets, pure Windows API. There's a lot of frameworks and they all handle the final routing of messages differently.
I'll answer the question for the cases that are either directly built on top of Windows API or where they're using the Windows API directly. WPF does not use the Windows API windowing system other than for the outermost windows.
Initially the program registers a function that handles messages intended for a particular window. This can be done using the RegisterClass or RegisterClassEx functions. The function which will be responsible for handling the messages sent to the window is the lpfnWndProc member of the structures passed to these functions. This is called the window procedure.
What happens when a button is pressed is that a message, in this case WM_COMMAND, is pushed into the thread message queue by Windows. This message is then fetched using GetMessage or PeekMessage. Some messages use short cuts and can result in a call to the window procedure directly when you call GetMessage, some messages only result in a call to the window procedure when the application calls DispatchMessage. If you're dealing with a dialog, the message will be handled by a call to IsDialogMessage.
Now that we have some background on how this works behind the scenes, OllyDbg actually has a helper for dealing with this sort of thing. You can simply open the View->Windows dialog item. Right click the window you want to catch button presses in, select message breakpoint on classproc, select command and notifications from the message dropdown or select the WM_COMMAND message. Now whenever you click the button you will break in the window procedure the application registered for that window. You still need to trace the code so that you can find the code that examines the message type and then handles the message. From now on it will be different depending on what type of framework is being used.
open calc.exe in ollydbg c:\ollydbg.exe calc.exe
press Ctrl + G and type GetMessageW
press F2
to set a breakpoint and press F9
until it breaks
when it is broken press ctrl+f9
to run until return
press shift+f4
to set a conditional log breakpoint
in the expression edit box type [esp+4]
in the decode value of expression select pointer to MSG structure (UNICODE)
set radio button pause to never
set radio button log expression to Always
hit ok
now look at log window for all the messages that are handled
refine your conditional breakpoint to handle only the cases you want to examine
for example this condition will log only mouseup and wm_char messages
Breakpoints, item 1
Address=7E41920E
Module=USER32
Active=Log when [[esp+4]+4] == WM_KEYDOWN || [[esp+4]+4] == WM_LBUTTONUP
Disassembly=RETN 10
like results posted below notice the hwnd for each button you can refine to a multiple condition with a specifc Window Handle hWnd 2e048a etc
\Log data
Message
COND: 0007FEE8 WM_LBUTTONUP hw = 2E048A ("C") Keys = 0 X = 57. Y = 14.
COND: 0007FEE8 WM_LBUTTONUP hw = 10053E ("And") Keys = 0 X = 22. Y = 10.
COND: 0007FEE8 WM_LBUTTONUP hw = 200404 ("Xor") Keys = 0 X = 22. Y = 18.
COND: 0007FEE8 WM_LBUTTONUP hw = 270402 ("M+") Keys = 0 X = 22. Y = 11.
COND: 0007FEE8 WM_LBUTTONUP hw = D036A ("Sta") Keys = 0 X = 27. Y = 15.
COND: 0007FEE8 WM_LBUTTONUP hw = 1B04F0 ("x^2") Keys = 0 X = 18. Y = 17.
COND: 0007FEE8 WM_KEYDOWN hw = 1B04F0 ("x^2") Key = 35 ('5') KeyData = 60001
COND: 0007FEE8 WM_KEYDOWN hw = 4303EC (class="Edit") Key = 42 ('B') KeyData = 300001
COND: 0007FEE8 WM_KEYDOWN hw = 4303EC (class="Edit") Key = 41 ('A') KeyData = 1E0001
to simulate same in windbg put this commands in a txt file and run windbg (you should have skywings sdbgext extension loaded for verbose display )
bp user32!GetMessageW "pt;gc"
g
bc *
.load sdbgext
bp @eip ".if (poi(poi(esp+4)+4) == 0x202) {!hwnd poi(poi(esp+4));gc } .else {gc}"
g
windbg -c "$$>a< ......\wtf.txt" calc
Window 00600438
Name And
Class Button
WndProc 00000000
Style WS_OVERLAPPED
ExStyle WS_EX_NOPARENTNOTIFY WS_EX_LEFT WS_EX_LTRREADING WS_EX_RIGHTSCROLLBAR
HInstance 01000000
ParentWnd 00490534
Id 00000056
UserData 00000000
Unicode TRUE
ThreadId 00000df0
ProcessId 00000f68
Window 00150436
Name Xor
Class Button
WndProc 00000000
Style WS_OVERLAPPED