我从Dr. Watson信息中获得最终用户的崩溃报告,我想用它们来找出发生崩溃的位置(即代码的哪一行)。
我不能只使用崩溃报告中的EIP,因为我们发布的exe是经过数字签名的,并且会更改所有偏移量。但是崩溃信息也有“CS:EIP的字节”,这是从EIP开始发生崩溃的前16个字节。它看起来像这样:
Bytes at CS:EIP:
85 c4 14 c3 8b ff 55 8b ec 6a 0a 6a 00 ff 75 08
这16个字节在exe中只出现一次。我只能使用HEX查看器在EXE中找到它们的偏移量,但是为了在调试期间跳转到那里并查看源代码中的哪一行,我需要在加载EXE后知道它们在内存中的偏移量。
在程序加载后扫描程序代码段的最佳方法是什么?我可以添加代码来查找EXE的基本偏移量所在的位置,然后循环使用它并使用memcmp查找字节模式的位置。
另外,如何找到EXE的基本偏移位置?
答案 0 :(得分:4)
我正在使用一种非常简单的方法解决同样的问题。
首先,我dumpbin我的可执行文件,用于查找代码段的物理(文件中)偏移量。
然后我从存储器地址中减去它,这些“魔术”字节位于二进制文件中。
然后我在调试器下运行程序,只需将此偏移量添加到代码段的虚拟地址。
.text name
10EE8E virtual size
1000 virtual address (00401000 to 0050FE8D)
10F000 size of raw data
--> 400 file pointer to raw data (00000400 to 0010F3FF) <--
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
答案 1 :(得分:2)
如果您使用类似ollydbg的内容,则可以在运行时扫描进程内存,并在查看找到的点时向其报告文件:行和源代码(只要pdb是正确链接)。如果您静态打开文件,它还允许您查看虚拟化地址。
答案 2 :(得分:1)
或者,如果您只是使用基本工具,则可以使用Visual Studio中的dumpbin
(a.k.a。link /dump /all
)或平台SDK。它可以为您提供十六进制转储和/或反汇编并应用所有重定位,并且还将选择PDB以向您的列表添加符号名称。所有人都说由于冲突,DLL可能在加载时被重定位到不同的地址,但你使用dumpbin /headers
来找出DLL的默认基本偏移量。
Watson博士不会给你EIP值,不仅仅是字节吗?自从我使用它已经有一段时间了。更好的解决方案是注册WinQual - 然后最终用户可以将其崩溃转储上传到Microsoft,您可以从那里收集它们,并且您可以获得实际的小型转储和堆转储。
答案 3 :(得分:1)
您所要做的就是将PE文件(.dll和.exe)和PDB文件放在符号服务器中,然后将调试器(windbg或VS)指向符号服务器和Microsoft的符号服务器。 PE文件和PDB文件将自动加载,将显示所有级别的调用堆栈的反汇编,并找到源文件。
如果您的PE文件已签名,那么您应该将签名的PE文件放在符号服务器中,但是如果您将未签名的文件放在符号服务器中,那么它们可能会正常加载(代码字节不受影响),可能还有一些校验和警告
对于奖励标记,您应该在将PDB添加到符号服务器之前运行源索引。这样,调试器可以从版本控制中检索源文件的正确版本 - 神奇。这真的不是那么难。我在我的爱好共享软件项目上做了所有这些步骤。
我博客的参考资料: https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/ https://randomascii.wordpress.com/2011/11/11/source-indexing-is-underused-awesomeness/
重申:这应该有效。我在许多不同的公司工作时看过客户机器上的数百个故障转储,由于符号服务器和源服务器,我只需要努力就可以得到机器代码,函数名,源代码,局部变量等。
答案 4 :(得分:0)
我在这里发布了一个我发现自己的可能解决方案,虽然它不是很优雅。我不确定使用GetModuleHandle作为基本偏移量是否正确,但它似乎正在处理我迄今为止尝试过的2-3个错误报告。
unsigned char buf[] = { 0x85, 0xc4, 0x14, 0xc3, 0x8b, 0xff, 0x55, 0x8b, 0xec, 0x6a, 0x0a, 0x6a, 0x00, 0xff, 0x75, 0x08 };
HMODULE hModule = GetModuleHandle(NULL);
char* ii;
for (ii = (char*) hModule; memcmp(ii, buf, sizeof(buf)); ii++);
char buf2[1000];
sprintf(buf2, "%p", ii);
MessageBox(0,buf2,0,0);