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?

  • As Peter mentioned it depends on many things, what I usually do in Olly is pausing the program, and clicking on "Stop at user input" (or something similar to that), which will break when you press the button. Commented Dec 26, 2013 at 21:11

2 Answers 2


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.

  • Thanks a lot for your comment , I tried what you said before and for some reason i never manage to find the application's function so i thought I'm doing it wrong .. I guess i need to try harder! Thanks!
    – Menna
    Commented Dec 26, 2013 at 13:46
  • 4
    A tip I can give you that I've used to get familiar with the windowing systems (although admittedly not all of them) is to code something up that uses the framework and have the call back be your own inline assembly (something obvious like 20 nops/int3s/etc) then find the function in your debugger/disassembler. You can trace it back from there to see what you could look for in a real sample. Depends on how you learn but it might help.
    – Fewmitz
    Commented Dec 26, 2013 at 15:21
  • 1
    I've used this learning technique to learn most of reverse engineering tricks i know , didn't come to my mind this time though..Thanks!
    – Menna
    Commented Dec 27, 2013 at 9:02

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
 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
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"
bc *
.load sdbgext
bp @eip ".if (poi(poi(esp+4)+4) == 0x202) {!hwnd poi(poi(esp+4));gc } .else {gc}"

windbg  -c "$$>a< ......\wtf.txt" calc

Window    00600438
Name      And
Class     Button
WndProc   00000000
HInstance 01000000
ParentWnd 00490534
Id        00000056
UserData  00000000
Unicode   TRUE
ThreadId  00000df0
ProcessId 00000f68
Window    00150436
Name      Xor
Class     Button
WndProc   00000000

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.