简体   繁体   English

单击按钮后WinDbg中断

[英]WinDbg break on button click

Imagine an application that displays a button: OK . 想象一下显示按钮的应用程序: 好的 Is it possible to break the execution of the program and view the disassembly using WinDbg, right after the button has received a click? 是否可以在按钮收到点击后立即中断程序的执行并使用WinDbg查看反汇编? How would I do that? 我该怎么办? In this scenario, the source code is not available. 在这种情况下,源代码不可用。

So, your description is very general, and not very well defined, and the exact research really depends on the application that you are trying to reverse. 因此,您的描述非常通用,并且定义不明确,确切的研究实际上取决于您试图扭转的应用程序。 You will have easier time if you have symbols, but these aren't required. 如果您有符号,您将有更多的时间,但这些不是必需的。

First, some (trivial) background: Windows communicates with the application through Windows Messages. 首先,一些(琐碎的)背景:Windows通过Windows消息与应用程序通信。 The application will fetch messages from the message queue, and almost always will dispatch those messages to the appropriate Windows Procedure. 应用程序将从消息队列中获取消息,并且几乎总是将这些消息分派给相应的Windows过程。

So, first - what do you mean: "right after the button has received a click"? 那么,首先 - 你是什么意思:“按钮收到点击后”? I suspect that you actually don't care about this code. 我怀疑你实际上并不关心这段代码。 Although your application could have a custom button, and you really care how the button handles a WM_LBUTTONDOWN message. 虽然您的应用程序可以有一个自定义按钮,但您真的关心该按钮如何处理WM_LBUTTONDOWN消息。 I'm going to assume that your application has a Windows stock button (implemented in user32.dll or comctl32.dll), and that you don't care about that. 我将假设您的应用程序有一个Windows库存按钮(在user32.dll或comctl32.dll中实现),并且您不关心它。

The default implementation of a button control handling WM_LBUTTONDOWN is to send WM_COMMAND to the window that contains the button. 处理WM_LBUTTONDOWN的按钮控件的默认实现是将WM_COMMAND发送到包含该按钮的窗口。 Typically, the application that you want to investigate handles the "click" there. 通常,您要调查的应用程序处理“单击”。 Now, if this is the 'OK' button, it's ID would be IDOK (defined to be 1), and Windows will send you the same message also when you click the 'Enter' key. 现在,如果这是“确定”按钮,它的ID将是IDOK(定义为1),当您单击“Enter”键时,Windows也会向您发送相同的消息。

So, we are now looking for how the application handles WM_COMMAND. 所以,我们现在正在寻找应用程序如何处理WM_COMMAND。 What you want to find is the Windows procedure. 你想要找到的是Windows程序。 Do that with Spy++. 用Spy ++做到这一点。 Open Spy and find the Window that contain your button. 打开间谍,找到包含按钮的窗口。 Most chances that the code you are looking for is in the Windows Procedure of that window. 您正在寻找的代码最有可能位于该窗口的Windows过程中。 Spy++ will tell you the address of the Window Procedure. Spy ++会告诉你Window Procedure的地址。

As an example, let's look at the 'Save' button of the 'Save As' dialog in Notepad. 例如,让我们看一下记事本中“另存为”对话框的“保存”按钮。 On my machine the address is: 0x73611142, which is in ComCtl32.dll 在我的机器上,地址是:0x73611142,它位于ComCtl32.dll中

Go to WinDbg, and take a look at the function. 转到WinDbg,看一下该函数。

0:000> u 73611142
COMCTL32!MasterSubclassProc
73611142 8bff            mov     edi,edi
73611144 55              push    ebp
73611145 8bec            mov     ebp,esp
73611147 6afe            push    0FFFFFFFEh
73611149 6858126173      push    offset COMCTL32!Ordinal377+0x146 (73611258)
7361114e 68a1b06273      push    offset COMCTL32!DllGetVersion+0x336f (7362b0a1)
73611153 64a100000000    mov     eax,dword ptr fs:[00000000h]
73611159 50              push    eax

This is indeed a function. 这确实是一种功能。 Like all Windows, it starts with move edi,edi , and then it sets the frame pointer. 像所有Windows一样,它从move edi,edi ,然后设置帧指针。

Put a break point, hit go, and you'll almost immediately break. 放一个断点,击中去,你几乎会立即突破。 Let's take a look: 让我们来看看:

0:000> bu 73611142
0:000> g
0:000> kb1

ChildEBP RetAddr Args to Child ChildEBP RetAddr Args to Child
0101f220 75d87443 00120c6a 00000046 00000000 COMCTL32!MasterSubclassProc 0101f220 75d87443 00120c6a 00000046 00000000 COMCTL32!MasterSubclassProc

The first argument (00120c6a) is handle of the window. 第一个参数(00120c6a)是窗口的句柄。 Compare with the value on Spy++, it should be the same. 与Spy ++上的值相比,它应该是相同的。 The second argument is the message. 第二个参数是消息。 In my case it was 0x46 which is WM_WINDOWPOSCHANGING. 在我的情况下,它是0x46,这是WM_WINDOWPOSCHANGING。

OK, I don't care about all those messages, and I want to break only on the messages I care about. 好吧,我不关心所有这些消息,我只想打破我关心的消息。 You care about WM_COMMAND which is 0X0111 (winuser.h) 你关心的是WM_COMMAND,它是0X0111(winuser.h)

Now, put the following (a little bit complex command): 现在,把以下(有点复杂的命令):

0:000> bu 73611142 "j poi(esp+4)==00120c6a AND poi(esp+8)==111 AND poi(esp+''; 'gc'"
breakpoint 0 redefined

You set a breakpoint on the windows procedure, and you tell WinDbg to break only when the first argument ( that's the poi(esp+4) ) is your Windows handle, and the second argument is 111. The 'gc' tells WinDBG to continue the execution when the condition will not meet. 你在windows程序上设置一个断点,只有当第一个参数(即poi(esp + 4))是你的Windows句柄,而第二个参数是111时,你告诉WinDbg才会中断.'gc'告诉WinDBG继续当条件不符合时执行。

Now you can debug the disassembly. 现在您可以调试反汇编。 If you have symbols, you'll have an easier job, but this isn't necessary. 如果你有符号,你会有一个更容易的工作,但这不是必要的。 In any case, remember to download the Microsoft stripped down symbols from the symbols server, so if the code you are debugging is calling a Windows API, you can see it. 在任何情况下,请记住从符号服务器下载Microsoft精简符号,因此如果您正在调试的代码正在调用Windows API,则可以看到它。

That's about it. 就是这样。 Modify this technique if your requirements are different (different Window, different message, etc). 如果您的要求不同(不同的窗口,不同的消息等),请修改此技术。 As a last resort consider putting a breakpoint on PostMessage or DispatchMessage if you can't reliably find the Windows Procedure (although, you'll have to follow that code). 如果您无法可靠地找到Windows过程(尽管如此,您必须遵循该代码),请考虑在PostMessage或DispatchMessage上设置断点。 For heavy lifting reversing use IDA, which will disassemble the executable, and solve various cross reference. 对于重型提升倒车使用IDA,它将拆卸可执行文件,并解决各种交叉引用。

Assuming you had the pdbs and they did not have the private symbols stripped then you would set the breakpoint on the button handler like so: 假设你有pdbs并且它们没有剥离私有符号,那么你应该在按钮处理程序上设置断点,如下所示:

bp myDLL!myWindowApp::onOKBtnClicked

If you had the pdbs then you could search for a likely handler using x: 如果您有pdbs,那么您可以使用x搜索可能的处理程序:

x myDLL!myWindowApp::*ok*

this presumes that you know or can guess which dll and what the function name is, otherwise you could gleam this information using spy++, Win Spy++ or Win Detective to get the handle for the button and intercept the window messages and from that info set the breakpoint. 这假设你知道或者可以猜出哪个dll和函数名称是什么,否则你可以使用spy ++,Win Spy ++或Win Detective来获取这些信息以获取按钮的句柄并截取窗口消息并从该信息设置断点。

Once it hits the breakpoint you can view the assembly code using u , there is a msdn guide if you require it. 一旦它到达断点,您可以使用u查看汇编代码,如果需要,可以使用msdn指南

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM