Question

I get crash reports from end users with Dr. Watson info and I want to use them to find out where the crash occured (i.e. on which line of the code).

I can't just use the EIP from the crash report because the exe we ship is digitally signed, and that changes all the offsets. However the crash info also has "bytes at CS:EIP", which is the first 16 bytes starting from EIP where the crash occured. It looks like this:

Bytes at CS:EIP:
85 c4 14 c3 8b ff 55 8b ec 6a 0a 6a 00 ff 75 08

Those 16 bytes occur exactly once in the exe. I can find their offset in the EXE using just a HEX viewer, but in order to jump there during debugging and see which line that is in the source, I need to know their offset in memory after the EXE is loaded.

What's the best way to scan the code segment of the program after it's loaded? Can I add code that finds where the base offset of the EXE is, and then cycle through that and use memcmp to find where the byte pattern occurs.

Also, how can I find where the base offset of the EXE is?

Was it helpful?

Solution

I'm using a very simple approach for the same problem.

First, I dumpbin my executable to find the physical (in file) offset of the code segment.

Then I subtract it from the memory address where these "magic" bytes are located in the binary.

Then I run the program under a debugger, and just add this offset to the virtual address of the code segment.

       .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

OTHER TIPS

If you use something like ollydbg, you can scan them process memory while its running and have it report back to you the file:line and source code when you view the found points (so long as the pdb's are linked correctly). It also allows you to view the virtualized address if you open up the file statically.

Or if you're just working with the basic tools, you can use dumpbin (a.k.a. link /dump /all) from Visual Studio or the platform SDK. It can give you a hex dump and / or a disassembly with all relocations applied, and will also pick up PDBs to add symbol names to your listings. That all said the DLL may have been relocated to a different address at load-time due to a clash, but you use dumpbin /headers to find out the default base offset of the DLL.

Doesn't Dr. Watson give you the EIP value, though, not just the bytes there? It's been a while since I've used it. A better solution is to sign up for WinQual - then end users can upload their crash dumps to Microsoft and you can collect them from there, and you get actual mini-dumps and heap dumps to look at.

All you have to do is put your PE files (.dll and .exe) and PDB files in a symbol server, then point the debugger (windbg or VS) at your symbol server plus Microsoft's symbol server. The PE files and PDB files will be automatically loaded up, disassembly will be shown for all levels of the call stack, and the source files will be found.

If your PE files are signed then you should put the signed PE files in your symbol server, although if you put the unsigned files in your symbol server then they will probably load fine (code bytes are unaffected) with perhaps some checksum warnings.

For bonus marks you should run source indexing prior to adding the PDBs to the symbol server. That way the debuggers can retrieve the correct version of the source file from version control -- magical. It's really not that hard. I do all these steps on my hobby shareware projects.

References from my blog: https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/ https://randomascii.wordpress.com/2011/11/11/source-indexing-is-underused-awesomeness/

To reiterate: this should just work. I've looked at hundreds of crash dumps from customer machines while working at many different companies and, because of symbol server and source server I get machine code, function names, source code, local variables, etc., with zero effort.

I'm posting here a possible solution I found myself, though it's not very elegant. I'm not sure if it's correct to be using GetModuleHandle as the base offset, but it seems to be working with the 2-3 error reports I've tried so far.

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top