But what if I want to place a breakpoint on a data dump that has a size of greater than 4 bytes. For example, I want to do this to see what location within the region would be first accessed. Normally, there is no way to do this because of the lack of the support IA32 architecture provides. Software solution is possible but not implemented in debuggers such as in Ollydbg and in Windbg.
What you could do in these circumstances is to guess where the code parsing the data starts, and place a breakpoint on the execution flow, so when you break in the debugger you can trace the code from that point and watch the data flow. This is likely to be tedious process because you spend time stepping through code you are not interested. The other ideas tend to be even more tedious, and require prepration work (hooking etc.) We shouldn't forget that the reason we want to place breakpoint on memory region is usually to narrow down the scope of total debugging.
Some time ago I've seen how Armadillo protection uses debugge/debugger process to mark encrypted pages and when there is an access to the page it gets decrypted and executed on-the-fly. Also, EMET (Enhanced Mitigation Experience Toolkit) in the heap spray mitigation function uses to mark certain pages as unaccessible so the system cannot allocate memory to that address. This has inspired me how to write a plugin that allows me to place data breakpoint on arbitrary memory region. Yay!
Using
VirtualProtect
it's possible to disable all access to the memory page in the process address space. I however don't use VirtualProtect
in the plugin but use VirtualProtectEx
instead because the extended version allows me to disable all access to the memory in specified process rather than the current process.The prototype has been developed as an extension command for Windbg. It requires two parameters describing the breakpoint: the address and the size of the region. When data is accessed within this region the we break in the debugger.
When the extension command runs it locates the base address of the memory page the specified region belongs to. Next,
PAGE_NOACCESS
protection flag is set for the memory page. This allows us to filter any access to the memory page via exception handling.When the target runs in the debugger, and if there is an attempt to read from the protected page it results in an access violation. Due to this, the exception event callback implemented in the Windbg extension is executed. This callback verifies if the address of inaccessible data is within the region of the data breakpoint. If it is we restore the original protection flags for the page and break in the debugger - breakpoint hit. Otherwise, we restore the original protection flag to execute the single instruction previously generated the exception. Then we restore the protection flags do disable all access and continue to run the application until there is an attempt to read from the protected page resulting in an access violation.
The exception information is stored in
EXCEPTION_RECORD
structure which is available in the exception even callback function. Exception->ExceptionAddress
is the address where the exception occurred. Exception->ExceptionInformation[1]
is the address of the inaccessible data. More information on exception is available here.Before I run the plugin command I also run
sxn av
so if access violation occurs we don't break in the debugger but get notification of the exception. Thus we let the event callback handle the exception.When the memory page is too big - irrespectively of the breakpoint size - it might be possible it's being accessed too many times. In this case, the debugging tends to be extremely slow because of the frequent context switches between the target process and the debugger.
An enhancement of this plugin would be to let the execution continue when a data is accessed but to record each address being accessed so we can trace the memory access for certain memory regions.