Windbg Tricks - Javascript Windbg Instrumentation
Moved from d0cs4vage.blogspot.com to here
This post is going to cover three levels of usefulness of windbg instrumentation via javascript : subpar, normal, and abnormal.
SUBPAR
The most basic way of instrumenting windbg via javascript is to set a
breakpoint on a simple function, such as Math.atan
, call Math.atan
at the
appropriate time in javascript to force windbg to break, and then do whatever
you need to do in windbg. Useful, yes, but it’s lame and gets extremely
tiring after the first time of doing it.
NORMAL
A better way to instrument windbg via javascript is to create a way for javascript to print a message in windbg (and trigger a break):
bu jscript!Js::Math::Atan ".printf \"DEBUG: %mu\\n\", poi(poi(esp+10)+c) ; g"
(If you want to break, remove the ; g
)
That’s cool, but what if you want to do something a little more complicated, like track all allocations of a specific size after certain javascript statements have been executed. With the previous method, the javascript would have to look something like this:
function log(msg) {
Math.atan(msg);
}
function track_all_allocations_and_frees_size_x20() {
Math.asin();
}
log("Executing main javascript");
execute_main_javascript();
log("Track all allocations and frees now");
track_all_allocations_and_frees_size_x20();
do_something_cool();
… and the windbg breakpoints would be something like this:
bu jscript!Js::Math::Atan ".printf \"DEBUG: %mu\\n\", poi(poi(esp+10)+c) ; g"
bu jscript!Js::Math::Asin "bp ntdll!RtlAllocateHeap .if(poi(esp+c) == 0x20) { .echo ALLOCATED ONE ; knL } ; g"
This is more useful, but is still very inflexible. For every new javascript<–>windbg binding you might want, you’d need to also modify your breakpoints in windbg.
ABNORMAL
Below is an abnormally useful way to instrument windbg with javascript:
bu jscript!Js::Math::Atan ".block { .shell -ci \".printf \\\"%mu\\\\n\\\", poi(poi(esp+10)+c)\" find /v \"13333333337\" > cmd_to_exec.txt & exit } ; $><cmd_to_exec.txt"
This lets you execute windbg commands directly from javascript. The breakpoint
basically does an eval("WINDBG_CMD")
with a string from memory. Broken down,
the breakpoint goes like this:
.block {
.shell -ci ".printf \"%mu\\n\", poi(poi(esp+10)+c)" find /v \"13333333337\" > cmd_to_exec.txt
}
$<>cmd_to_exec.txt
Using .block
helps to end the .shell
command, since semicolons
don’t work as statement endings for the .shell
command (see this
article
on msdn for more details).
find /v "13333333337" > cmd_to_exec.txt
simply saves what was printf’d to
the file cmd_to_exec.txt
. Specifically, the find command filters out all lines
from stdin that contain 13333333337
. Any string here will work as long as you
never expect to see it in a windbg command that you’d execute via javascript.
$<>cmd_to_exec.txt
runs the string we saved to cmd_to_exec.txt
as a
windbg script.
This method makes things much simpler. Going back to the first example, we can now do things like this:
function exec(cmd) {
Math.atan(cmd);
}
function log(msg) {
exec(".echo " + msg);
}
function track_allocations(size) {
exec('bp ntdll!RtlAllocateHeap ".if(poi(esp+c) == 0n' + size + '){ .echo ALLOCATED ONE ; knL } ; g" ; g');
}
log("Executing main javascript");
execute_main_javascript();
var alloc_size = 0x20;
log("Tracking allocations of size " + alloc_size.toString(0x10));
track_allocations(0x20);
do_something_cool();
Almost makes you wish you could write a javascript interface to windbg, doesn’t it?
UPDATE: I did end up writing something that did this: see bnarly:
Abnormally useful. Laters.