想象一个显示按钮的应用程序:OK. 是否可以在按钮收到点击后立即中断程序的执行并使用 WinDbg 查看反汇编?我该怎么做?在这种情况下,源代码不可用。
2 回答
因此,您的描述非常笼统,并且定义不明确,并且确切的研究实际上取决于您要反转的应用程序。如果您有符号,您将有更轻松的时间,但这些不是必需的。
首先,一些(琐碎的)背景:Windows 通过 Windows Messages 与应用程序通信。应用程序将从消息队列中获取消息,并且几乎总是将这些消息分派给适当的 Windows 过程。
那么,首先 - 你是什么意思:“在按钮收到点击之后”?我怀疑您实际上并不关心此代码。尽管您的应用程序可能有一个自定义按钮,但您真的很关心该按钮如何处理 WM_LBUTTONDOWN 消息。我将假设您的应用程序有一个 Windows 股票按钮(在 user32.dll 或 comctl32.dll 中实现),而您并不关心这一点。
处理 WM_LBUTTONDOWN 的按钮控件的默认实现是将 WM_COMMAND 发送到包含该按钮的窗口。通常,您要调查的应用程序会在那里处理“点击”。现在,如果这是“确定”按钮,它的 ID 将为 IDOK(定义为 1),当您单击“Enter”键时,Windows 也会向您发送相同的消息。
所以,我们现在正在寻找应用程序如何处理 WM_COMMAND。您要查找的是 Windows 程序。用 Spy++ 做到这一点。打开 Spy 并找到包含您的按钮的窗口。您要查找的代码很可能在该窗口的 Windows 过程中。Spy++ 会告诉你窗口过程的地址。
例如,让我们看一下记事本中“另存为”对话框的“保存”按钮。在我的机器上地址是:0x73611142,在 ComCtl32.dll
去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
这确实是一个功能。像所有 Windows 一样,它以 开头move edi,edi
,然后设置帧指针。
设置一个断点,点击 go,你几乎会立即中断。让我们来看看:
0:000> bu 73611142
0:000> g
0:000> kb1
ChildEBP RetAddr Args to Child
0101f220 75d87443 00120c6a 00000046 00000000 COMCTL32!MasterSubclassProc
第一个参数 (00120c6a) 是窗口句柄。对比 Spy++ 上的值,应该是一样的。第二个参数是消息。就我而言,它是 0x46,即 WM_WINDOWPOSCHANGING。
好的,我不关心所有这些消息,我只想打破我关心的消息。您关心的是 0X0111 (winuser.h) 的 WM_COMMAND
现在,输入以下内容(有点复杂的命令):
0:000> bu 73611142 "j poi(esp+4)==00120c6a AND poi(esp+8)==111 AND poi(esp+''; 'gc'"
breakpoint 0 redefined
您在 windows 过程上设置了一个断点,并告诉 WinDbg 仅在第一个参数(即 poi(esp+4) )是您的 Windows 句柄并且第二个参数是 111 时才中断。“gc”告诉 WinDBG 继续条件不满足时的执行。
现在可以调试反汇编了。如果你有符号,你的工作会更轻松,但这不是必需的。在任何情况下,请记住从符号服务器下载 Microsoft 精简符号,因此如果您正在调试的代码正在调用 Windows API,您可以看到它。
就是这样。如果您的要求不同(不同的窗口、不同的消息等),请修改此技术。如果您无法可靠地找到 Windows 过程,作为最后的手段,请考虑在 PostMessage 或 DispatchMessage 上放置一个断点(尽管您必须遵循该代码)。对于繁重的倒车使用IDA,它将反汇编可执行文件,并解决各种交叉引用。
假设您有 pdbs 并且它们没有剥离私有符号,那么您将在按钮处理程序上设置断点,如下所示:
bp myDLL!myWindowApp::onOKBtnClicked
如果您有 pdb,那么您可以使用 x 搜索可能的处理程序:
x myDLL!myWindowApp::*ok*
这假定您知道或可以猜出哪个 dll 和函数名称是什么,否则您可以使用 spy++、Win Spy++ 或 Win Detective 获取此信息以获取按钮的句柄并拦截窗口消息并从该信息中设置断点.