实验目的 : 想直接拦截按钮操作的消息处理, 分析按钮操作的逻辑.
实验程序 : <<使用OllyDbg从零开始Cracking 第一章翻译>> 中附带的一个CrackMe.
使用OD加载目标程序, 当程序运行起来后, 暂停OD
经过实验, 点击菜单会触发主窗体WM_COMMAND消息.
如果直接捕获弹出的注册窗口的WM_COMMAND, 捕获不到.
准备捕获主窗体的WM_COMMAND消息, 找到菜单生成注册窗体的处理.
找到注册窗体的创建函数传入的注册窗口处理过程,从而找到注册窗体的所有消息处理实现逻辑.
点击菜单属于WM_COMMAND, 按照消息名称排序, 好找一些.
下完消息断电后, 确认一下是否消息断点已下.
F9, 让程序跑起来. 点击注册菜单. 程序被断在WM_COMMAND消息断点处.
00401128 > $ C8 000000 ENTER 0,0 ; 主窗体消息断点WM_COMMAND
0040112C . 56 PUSH ESI
0040112D . 57 PUSH EDI
0040112E . 53 PUSH EBX
0040112F . 837D 0C 02 CMP DWORD PTR SS:[EBP+C],2
00401133 . 74 5E JE SHORT CRACKME.00401193
00401135 . 817D 0C 040200>CMP DWORD PTR SS:[EBP+C],204
0040113C . 74 65 JE SHORT CRACKME.004011A3
F8往下走, 找到创建注册窗体的代码.
00401209 > 6A 00 PUSH 0 ; /lParam = NULL
0040120B . 68 53124000 PUSH CRACKME.00401253 ; |DlgProc = CRACKME.00401253
00401210 . FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
00401213 . 68 15214000 PUSH CRACKME.00402115 ; |pTemplate = "DLG_REGIS"
00401218 . FF35 CA204000 PUSH DWORD PTR DS:[4020CA] ; |hInst = 00400000
0040121E . E8 7D020000 CALL <JMP.&USER32.DialogBoxParamA> ; \DialogBoxParamA
CRACKME.00401253 是注册窗体的消息处理过程. 转到那看看.
00401253 /. C8 000000 ENTER 0,0 ; 注册窗体消息处理过程
00401257 |. 53 PUSH EBX
00401258 |. 56 PUSH ESI
00401259 |. 57 PUSH EDI
0040125A |. 817D 0C 100100>CMP DWORD PTR SS:[EBP+C],110 ; WM_INITDIALOG
00401261 |. 74 34 JE SHORT CRACKME.00401297
00401263 |. 817D 0C 110100>CMP DWORD PTR SS:[EBP+C],111 ; WM_COMMAND
0040126A |. 74 35 JE SHORT CRACKME.004012A1
0040126C |. 837D 0C 10 CMP DWORD PTR SS:[EBP+C],10 ; WM_CLOSE
00401270 |. 0F84 81000000 JE CRACKME.004012F7
00401276 |. 817D 0C 010200>CMP DWORD PTR SS:[EBP+C],201 ; WM_LBUTTONDOWN
0040127D |. 74 0C JE SHORT CRACKME.0040128B
0040127F |. B8 00000000 MOV EAX,0
00401284 |> 5F POP EDI
00401285 |. 5E POP ESI
00401286 |. 5B POP EBX
00401287 |. C9 LEAVE
00401288 |. C2 1000 RETN 10
可以看到 CRACKME.004012A1 是注册窗体WM_COMMAND命令处理函数.
注册窗体一共处理了4种消息(窗体初始化, 退出, 确定, 命令处理)
在 地址 0040126A 上回车, 去看看按钮处理逻辑.
004012A1 |> 33C0 /XOR EAX,EAX ; 注册窗体: 按钮处理逻辑
004012A3 |. 817D 10 EB0300>|CMP DWORD PTR SS:[EBP+10],3EB
004012AA |. 74 4B |JE SHORT CRACKME.004012F7
004012AC |. 817D 10 EA0300>|CMP DWORD PTR SS:[EBP+10],3EA
004012B3 |. 75 3B |JNZ SHORT CRACKME.004012F0
004012B5 |. 6A 0B |PUSH 0B ; /Count = B (11.)
004012B7 |. 68 8E214000 |PUSH CRACKME.0040218E ; |Buffer = CRACKME.0040218E
004012BC |. 68 E8030000 |PUSH 3E8 ; |ControlID = 3E8 (1000.)
004012C1 |. FF75 08 |PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012C4 |. E8 07020000 |CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012C9 |. 83F8 01 |CMP EAX,1
004012CC |. C745 10 EB0300>|MOV DWORD PTR SS:[EBP+10],3EB
004012D3 |.^72 CC \JB SHORT CRACKME.004012A1
004012D5 |. 6A 0B PUSH 0B ; /Count = B (11.)
004012D7 |. 68 7E214000 PUSH CRACKME.0040217E ; |Buffer = CRACKME.0040217E
004012DC |. 68 E9030000 PUSH 3E9 ; |ControlID = 3E9 (1001.)
004012E1 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012E4 |. E8 E7010000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012E9 |. B8 01000000 MOV EAX,1
004012EE |. EB 07 JMP SHORT CRACKME.004012F7
004012F0 |> B8 00000000 MOV EAX,0
004012F5 |.^EB 8D JMP SHORT CRACKME.00401284
004012F7 |> 50 PUSH EAX ; /Result
004012F8 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012FB |. E8 B2010000 CALL <JMP.&USER32.EndDialog> ; \EndDialog
00401300 |. B8 01000000 MOV EAX,1
00401305 \.^E9 7AFFFFFF JMP CRACKME.00401284
如果F2 在地址 004012A1 上下普通代码断点, 已经断住了注册窗体的WM_COMMAND逻辑
为了只断住按钮(OK, Quit)的处理, 将断点下在004012B5
F9, 让程序跑起来. 填入Name, SN, 按下确定按钮
可以看出, 注册窗口消息处理只是得到用户输入
004012A1 |> 33C0 /XOR EAX,EAX ; 注册窗体: 按钮处理逻辑
004012A3 |. 817D 10 EB0300>|CMP DWORD PTR SS:[EBP+10],3EB
004012AA |. 74 4B |JE SHORT CRACKME.004012F7
004012AC |. 817D 10 EA0300>|CMP DWORD PTR SS:[EBP+10],3EA
004012B3 |. 75 3B |JNZ SHORT CRACKME.004012F0
004012B5 |. 6A 0B |PUSH 0B ; /Count = B (11.)
004012B7 |. 68 8E214000 |PUSH CRACKME.0040218E ; |name
004012BC |. 68 E8030000 |PUSH 3E8 ; |ControlID = 3E8 (1000.)
004012C1 |. FF75 08 |PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012C4 |. E8 07020000 |CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012C9 |. 83F8 01 |CMP EAX,1
004012CC |. C745 10 EB0300>|MOV DWORD PTR SS:[EBP+10],3EB
004012D3 |.^72 CC \JB SHORT CRACKME.004012A1
004012D5 |. 6A 0B PUSH 0B ; /Count = B (11.)
004012D7 |. 68 7E214000 PUSH CRACKME.0040217E ; |pwd
004012DC |. 68 E9030000 PUSH 3E9 ; |ControlID = 3E9 (1001.)
004012E1 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012E4 |. E8 E7010000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004012E9 |. B8 01000000 MOV EAX,1
004012EE |. EB 07 JMP SHORT CRACKME.004012F7
004012F0 |> B8 00000000 MOV EAX,0
004012F5 |.^EB 8D JMP SHORT CRACKME.00401284
004012F7 |> 50 PUSH EAX ; /Result
004012F8 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004012FB |. E8 B2010000 CALL <JMP.&USER32.EndDialog> ; \EndDialog
00401300 |. B8 01000000 MOV EAX,1
00401305 \.^E9 7AFFFFFF JMP CRACKME.00401284
从00401305继续往下走, 进行数据有效性的校验.
总结:通过消息断点, 可以从父窗口WMCOMMAND操作(菜单点击, 按钮点击)得到子窗体的消息处理过程.
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)