Subject: [original] Message omnipotent breakpoint
Author: wxxw
Time: 2009-09-: 28: 34
Chain: http://bbs.pediy.com/showthread.php? T = 98274
Since window is a message-based system, let's take a look at the message processing of the application. Let's test it with the simplest window program.
The following is a simple window creation routine written by iczelion.
. 386
. Model flat, stdcall
Option Casemap: None
Include windows. inc
Include user32.inc
Extends delib user32.lib; callto functions in user32.lib and kernel32.lib
Include kernel32.inc
Includelib kernel32.lib
Winmain proto: DWORD,: DWORD
. Data; initialized data
Classname DB "simplewinclass", 0; the name of our window class
Appname DB "our first window", 0; the name of our window
. Data? ; Uninitialized data
Hinstance? ; Instance handle of our program
CommandLine lpstr?
. Code; here begins our code
Start:
Invoke getmodulehandle, null; get the instance handle of our program.
; Under Win32, hmodule = hinstance mov hinstance, eax
MoV hinstance, eax
Invoke getcommandline; get the command line. You don't have to call this function if
; Your program doesn' t process the command line.
MoV CommandLine, eax
Invoke winmain, hinstance, null, CommandLine, sw_showdefault; call the main function
Invoke exitprocess, eax; quit our program. The exit code is returned in eax from winmain.
Winmain proc hinst: hinstance, hprevinst: hinstance, using line: lpstr, cmdshow: DWORD
Local WC: wndclassex; Create local variables on Stack
Local MSG: msg
Local hwnd: hwnd
MoV WC. cbsize, sizeof wndclassex; fill values in members of WC
MoV WC. style, cs_hredraw or cs_vredraw
MoV WC. lpfnwndproc, offset wndproc
MoV WC. cbclsextra, null
MoV WC. cbwndextra, null
Push hinstance
Pop WC. hinstance
MoV WC. hbrbackground, color_window + 1
MoV WC. lpszmenuname, null
MoV WC. lpszclassname, offset classname
Invoke loadicon, null, idi_application
MoV WC. hicon, eax
MoV WC. hiconsm, eax
Invoke loadcursor, null, idc_arrow
MoV WC. hcursor, eax
Invoke registerclassex, addr wc; register our window class
Invoke createmediawex, null ,/
ADDR classname ,/
ADDR appname ,/
Ws_overlappedwindow ,/
Cw_usedefault ,/
Cw_usedefault ,/
Cw_usedefault ,/
Cw_usedefault ,/
Null ,/
Null ,/
Hinst ,/
Null
MoV hwnd, eax
Invoke showwindow, hwnd, cmdshow; display our window on desktop
Invoke updatewindow, hwnd; refresh the client area
. While true; enter message loop
Invoke getmessage, addr msg, null, 0, 0
. Break. If (! Eax)
Invoke translatemessage, ADDR msg
Invoke dispatchmessage, ADDR msg
. Endw
MoV eax, MSG. wparam
; Return exit code in eax
RET
Winmain endp
Wndproc proc hwnd: hwnd, umsg: uint, wparam: wparam, lparam: lparam
. If umsg = wm_destroy; if the user closes our window
Invoke postquitmessage, null; quit our application
. Else
Invoke defwindowproc, hwnd, umsg, wparam, lparam; Default Message Processing
RET
. Endif
XOR eax, eax
RET
Wndproc endp
End start
At the beginning, I thought the original message processing was so simple. I constructed a message loop, used getmessage to get all the messages, and used dispatchmessage to send messages to the window. Is that true?
In the first test, change invoke getmessage, addr msg, null, to invoke getmessage, addr msg, hwnd, and you will find that when you close the window, the program does not exit in the process list. Why? This is because currently only messages whose window handle is hwnd can be accepted. When the window is closed, the wm_quit message sent by calling postquitmessage in the window after the message wm_destroy is received is sent to the application, not to the window, therefore, getmessage does not receive this message. Change the invoke getmessage statement back.
Now the second test, loaded with OD
0040110b >|. E8 42000000 | call <JMP. & user32.dispatchmessagea>;/dispatchmessagea
Next condition breakpoint [[esp] + 4] = wm_destory. When we close the window, the program is not broken as we think, but directly exited. Why? Let's change the breakpoint. At the entry point 00401119 of the window process, the next condition breakpoint [esp + 8] = wm_destory,
00401119>/. 55 push EBP
0040111a |. 8bec mov EBP, ESP
0040111c |. 837d 0C 02 cmp dword ptr ss: [EBP + C], 2
00401120 |. 75 09 jnz short trial.0040112b
00401122 |. 6a 00 push 0;/exitcode = 0
00401124 |. E8 41000000 call <JMP. & user32.postquitmessage>;/postquitmessage
Try again. This time it was broken down. Well, now we start to suspect that the wm_destory message does not seem to come to the window through the message loop we designed, so how does it come to our window process? Is it related to the registration of window classes in the system before? (Because the Window Process mov WC. lpfnwndproc, offset wndproc is defined), when we re-run the breakpoint in the following places, the result surprised us.
004010d0 |. E8 71000000 call <JMP. & user32.create1_wexa>;/create1_wexa
004010de |. E8 93000000 call <JMP. & user32.showwindow>;/showwindow
004010e6 |. E8 97000000 call <JMP. & user32.updatewindow>;/updatewindow
004010f5 |. E8 5e000000 | call <JMP. & user32.getmessagea>;/getmessagea
0040110b |. E8 42000000 | call <JMP. & user32.dispatchmessagea>;/dispatchmessagea
Our window process has been used in calling the createmediawexa function. The message codes processed are 24 h, 81 h, 83 H, 01 H (01h is wm_create)
Showwindow also calls our window process and processes messages for 18 h, 46 h, 1C, 86 H, 0dh, 06 h, 281 H, 282 H, 7 h, 85 H, 0d, 14 h, 47 h, 05 h, 03 h
Updatewindow also calls our window process and processes the message 0fh.
Getmessagea also calls our window process and processes the messages 7fh, 7fh, and 7fh. This is not the process that is sent to the window by dispatchmessagea after it is returned, but it calls the internal function.
If you are interested, try again. First run the program and narrow down the OD window so that we can see the program window. Then, at the return position of getmessagea, we can see the breakpoint at 004010fa and at the entry 00401119 of the window process.
004010f5 |. E8 5e000000 | call <JMP. & user32.getmessagea>;/getmessagea
004010fa |. 0bc0 | or eax, eax
Then move the mouse to the program window. At this time, the message is broken at 00401119 and 84 h and 20 h are processed. Then, it is our turn to getmessagea to return a 200 h (wm_mousemove) message, then the dispatchmessagea will hand over the 00401119
From the experiment above, we can see that the system has been managing our message processing. Many Internal messages directly call our window process functions, however, only a few messages are sent back to getmessagea, such as moving the mouse, pressing the buttons, and keyboard. After my experiment, the title bar is minimized, maximized, and the button is closed when the window is restored, and the window border display is completed by the system calling our window process, and the wm_paint message sent to getmessagea is only used to display the customer zone.
Now, let's focus on it. Although the message loop we designed only processes a small part of the message, all the messages are processed by our window process. Observe the stack and find that, whether it is system calls or distributed by our dispatchmessagea, our window process ends and returns to 77d18734.
0012 fdec 77d18734 returned to user32.77d18734
Okay, let's go there and see if there is anything.
77d1870c 55 push EBP
77d1870d 8bec mov EBP, ESP
77d1870f 56 push ESI
77d18710 57 push EDI
77d18711 53 push EBX
77d18712 68 cdabbadc push dcbaabcd
77d18717 56 push ESI
77d18718 ff75 18 push dword ptr ss: [EBP + 18]
77d1871b ff75 14 push dword ptr ss: [EBP + 14]
77d1871e ff75 10 push dword ptr ss: [EBP + 10]
77d18721 ff75 0C push dword ptr ss: [EBP + C]
77d18724 64: A1 18000000 mov eax, dword ptr fs: [18]
77d1872a 8088 b40f0000 0> or byte ptr ds: [eax + fb4], 1
77d18731 ff55 08 call dword ptr ss: [EBP + 8]: [EBP + 8] Here is our window process function, some systems may display call dword ptr [EBX + x], but the essence is the same.
77d18734 64: 8b0d 1800000> mov ECx, dword ptr fs: [18]
Let's reload the program. At the next breakpoint of 77d1870c, observe what the stack finds, and all message processing goes through this. Here is the real underlying message processing function of the system, the address of the window procedure function is put in [esp + 4]. For example, Here 00401119, [esp + 8] is the window handle, and [esp + C] is the message code, 77d1870c is our all-purpose message breakpoint. During the fast snow, Brother Qing pointed out that this address is a USER32 internal function named
User32.internalcallwinproc, which is not a fixed value in different systems, for example, 7e41870c. I would like to thank quicksnow for its clearing time. As for how to find the omnipotent breakpoint address of your system, please refer to the reply from Qingyi in quicksnow below.
To find the window procedure function, [esp + 4] after interruption is used. If you want to view the processing of a specific message, add a condition at this breakpoint, such as the wm_command of the menu and button, [esp + C] = wm_command, some people may say that if it is a new control and does not know the message code, for example, in the List View, click and select a item, we can directly break the condition breakpoint, [esp + C] = wm_lbuttondown. The trigger message is broken, for example, here
0012fe00 77d18816 returned to user32.77d18816 from user32.77d1870c
0012fe04 5d176e16 returned to comctl32.5d176e16
It can be seen that the subcontrol processes messages by itself (the subcontrol is also a window and has its own window process function ), finally, the converted message will be sent to the parent window. If you want to directly go to the window processing function of our program, it will be directly stored in the memory. if you want to know how the system transfers message processing to our function, change the condition breakpoint to a direct breakpoint. Press F9 and you will find that the message is called in turn.
0012fb5c 77d18816 returned to user32.77d18816 from user32.77d1870c
Window procedure functions of the 0012fb60 5d177512 comctl32.5d177512 sub-control
0012fb64 00060d4a message information
0012fb68 00000407
0012fa8c 77d18816 returned to user32.77d18816 from user32.77d1870c
0012fa90 5d176e16 returned to comctl32.5d176e16
0012fa94 00390c24
0012fa98 00000215
0012f9f8 77d23ce4 returned to user32.77d23ce4 from user32.77d1870c
0012f9fc 0040113d returned to import.0040113d from <JMP. & comctl32.initcommoncontrols>
0012fa00 00070cc0
0012fa04 0000004e
Haha, finally come to our 3D
2009.12.12
Determine the breakpoint position of the new method, the first need to load the Microsoft symbol library, see the sea breeze big post http://bbs.pediy.com/showthread.php? T = 96856
Then you can use BP _ internalcallwinproc @ 20.