Debugging/bypassing BSOD without source code

巧了我就是萌 提交于 2019-12-05 18:23:53
fileoffset
nv4_disp+90fd0
bd0a2fd0 39b8f8000000    cmp     dword ptr [eax+0F8h],edi

This is the important part. Looking at this, it is most probable that eax is invalid, hence attempting to access an invalid memory address.

What you need to do is load nv4_disp.dll into IDA (you can get a free version), check the image base that IDA loads nv4_disp at and hit 'g' to goto address, try adding 90fd0 to the image base IDA is using, and it should take you directly to the offending instruction (depending on section structure).

From here you can analyze the control flow, and how eax is set and used. If you have a good kernel level debugger you can set a breakpoint on this address and try and get it to hit.

Analysing the function, you should attempt to figure out what the function does, what eax is meant to be pointing to at that point, what its actually pointing to, and why. This is the hard part and is a great part of the difficulty and skill of reverse engineering.

Found a solution.

Problem:
Logging is unreliable since messages (when dumped to file) disappear during bsod, packets are sometimes lost when logging over network, and there's slowdown due to logging.

Solution:
Instead of logging to file or over network, configure system to produce full physical memory dump on BSOD and log all messages into any memory buffer. It'll be faster. Once system crashed, it'll dump entire memory into file, and it'll be possible to either view contents of log-file buffer using WinDBG's dt (if you have debug symbols) command, or you'll be able to search and locate logfile stored in memory using "memory" view.

I used circular buffer of std::strings to store messages and separate array of const char* to make things easier to read in WinDBG, but you could simply create huge array of char and store all messages within it in plaintext.

Details:
Entire process on winxp:

  1. Ensure that minimum page file size is equal or larger than total amount of RAM + 1 megabytes. (Right Click "My Computer"->Properties->Advanced->Performance->Advanced->Change)
  2. Configure system to produce complete memory dump on BSOD (RIght click "My Computer'->Properties->Advanced->Startup and Recovery->Settings->Write Debugging Information . Select "Complete memory dump" and specify path you want).
  3. Ensure that disk (where the file will be written) has required amount of free space (total amount of RAM on your system.
  4. Build app/dll (the one that does logging) with debug symbol, and Trigger BSOD.
  5. Wait till memory dump is finished, reboot. Feel free to swear at driver developer while system writes memory dump and reboots.
  6. Copy MEMORY.DMP system produced to a safe place, so you won't lose everything if system crashes again.
  7. Launch windbg.
  8. Open Memory Dump (File->Open Crash Dump).
  9. If you want to see what happened, use !analyze -v command.
  10. Access memory buffer that stores logged messages using one of those methods:
    1. To see contents of global variable, use dt module!variable where "module" is name of your library (without *.dll), and "variable" is name of variable. You can use wildcards. You can use address without module!variable
    2. To see contents of one field of the global variable (if global variable is a struct), use dt module!variable field where "field" is variable member.
    3. To see more details about varaible (content of arrays and substructures) use dt -b module!variable field or dt -b module!variable
    4. If you don't have symbols, you'll need to search for your "logfile" using memory window.

At this point you'll be able to see contents of log that were stored in memory, plus you'll have snapshot of the entire system at the moment when it crashed.

Also...

  1. To see info about process that crashed the system, use !process.
  2. To see loaded modules use lm
  3. For info about thread there's !thread id where id is hexadecimal id you saw in !process output.

It looks like the crash may either be caused by a bad pointer, or heap corruption. You can tell this because the crash occurs in a memory-freeing function (DxDdDestroySurface). Destroying surfaces is something that you absolutely need to do - you can't just stub this out, the surface will still get freed when the program exits, and if you disable it inside the kernel, you'll run out of on-card memory very quickly and crash that way, as well.

You can try to figure out what sequence of events leads up to this heap corruption, but there's no silver bullet here - as fileoffset suggested, you'll need to actually reverse engineer the driver to see why this happens (it may help to compare drivers before and after the offending driver version as well!)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!