Archive for October, 2009

Useful pseudo registers

Thursday, October 22nd, 2009

The debugger defines a set of pseudo registers, which can be used in expressions and always evaluate to certain special values. The full list of pseudo registers can be found here, but thought I’d highlight a few in their own post.

Always remember to prefix the pseudo register name with the @ symbol so that WinDBG knows you’re specifying a register name. If you don’t, be prepared to be punished when you fat finger the register name and WinDBG goes into a tailspin trying to resolve it!

$pagesize

This register contains the page size for the target platform. Most of us are only using the x86 and x64 so this will always evaluate out to 4K, but if you’re scripting better to use the pseudo register to be future proof.

$thread

The current ETHREAD address.

$peb

The current Process Environment Block addres.

$teb

The current Thread Environment Block address.

$ptrsize

The pointer size of the target machine.

$p

This one I love. $p contains the result of the previous Display Memory (d) command. For example, I can dump out a memory block and then evaluate a new expression using the contents of the memory location:

ppseudo

Back before the dps command was introduced this was the easiest way to evaluate a jump through a driver’s Import Address Table when you didn’t have symbols for the driver:

lnvsdps

Debugger Command Program example bug

Thursday, October 15th, 2009

Under the Debugger Command Program Examples section of the debugger documentation, there’s a nifty example script that will walk the current process list and print the process name and address. Only problem is that if you run the script you’ll get the following:

procprg1

Luckily the fix to the script is easy, the name of the alias defined doesn’t match the name of the alias used. In order to fix the script, the following line:

.echo ${$ImageName} at ${$Procc}

Simply needs to be changed to:

.echo ${$ImageName} at ${Procc}

And you’re done!

procprgfx

Thread specific breakpoints

Wednesday, October 14th, 2009

Thread specific breakpoints are a feature that I wasn’t aware of for a while but have become an important part of my debugging toolbox.

As it turns out, the bp command takes a /t switch, which allows you to specify the address of the thread object that you want to set the breakpoint for. By that I mean that the breakpoint will only fire if the address specified is executed by the thread specified. This is helpful if you have a routine in your driver called from multiple threads and you’re trying to narrow down the behavior of a particular thread. Example usage would be:

bp /t 86033858  ntfs!ntfscommoncreate

This will set a breakpoint on an incredibly hot routine in the system (the open handler for NTFS) but will only break into the debugger if the breakpoint is hit by thread 0×86033858.

As an added tip, this command can be combined with the $thread pseudo register, which always evaluates to the current thread:

bp /t @$thread ntfs!ntfscommoncreate

Why is that extension command failing? (.show_sym_failures)

Wednesday, October 7th, 2009

There are a couple of interesting commands that can provide insight into symbol issues that you’re having. Perhaps you’re running an extension command that is failing mysteriously even though you’re sure that you have symbols loaded? Enter .show_sym_failures and .show_read_failures, which spit error messages out when a symbol can’t be resolved or read. They are to be documented in a future release of the WinDBG docs, but until then:

.show_sym_failures
/s           Enable Display of Symbol Lookup Failures
/S           Disable Display of Symbol Lookup Failures

/t           Enable Display of Type Lookup Failures
/T           Disable Display of Type Lookup Failures

.show_read_failures
/v           Enable Display of Read Errors
/V           Disable Display of Read Errors

!pool broken for Special Pool allocations

Wednesday, October 7th, 2009

Driver Verifier has a Special Pool option, which causes your pool allocations to come out of special pool and get all sorts of added checking. This includes things such as guard pages at the end of your allocations to avoid buffer overruns, checks against accessing buffers after you free them, etc. Unfortunately the !pool command in WinDBG appears to be broken when given a special pool address on Windows XP. I haven’t had the chance to investigate further on newer O/S platforms, so it’s possible that there are also some issues there.

The extension command appears to have two issues:

1) The size shown as the allocation size is really the allocation size minus 8. Take for example a verified driver that does the following:

	a = ExAllocatePoolWithTag(NonPagedPool, 4, 'xxxx');
       	b = ExAllocatePoolWithTag(NonPagedPool, 8, 'xxxx');
       	c = ExAllocatePoolWithTag(NonPagedPool, 16, 'xxxx');

A !pool on a, b, and c shows the following (respectively):

1: kd> !pool 0x82a5aff8
Pool page 82a5aff8 region is Special pool
*82a5b000 size: fffffffc non-paged special pool, Tag is xxxx
	Owning component : Unknown (update pooltag.txt)
1: kd> !pool 0x824eeff8
Pool page 824eeff8 region is Special pool
*824ef000 size:    0 non-paged special pool, Tag is xxxx
	Owning component : Unknown (update pooltag.txt)
1: kd> !pool 0x82940ff0
Pool page 82940ff0 region is Special pool
*82940ff8 size:    8 non-paged special pool, Tag is xxxx
	Owning component : Unknown (update pooltag.txt)

2) The pool header addresses are incorrect. Take a in the example above:

1: kd> !pool 0x82a5aff8
Pool page 82a5aff8 region is Special pool
*82a5b000

That address given as the pool header is actually the guard page and not the header:

1: kd> dt nt!_pool_header 82a5b000
	+0x000 PreviousSize     : ??
	+0x000 PoolIndex        : ??
	+0x002 BlockSize        : ??
	+0x002 PoolType         : ??
	+0x000 Ulong1           : ??
	+0x004 ProcessBilled    : ????
	+0x004 PoolTag          : ??
	+0x004 AllocatorBackTraceIndex : ??
	+0x006 PoolTagHash      : ??
	Memory read error 82a5b006

The pool header in this case is the page rounded down to page size, not up to:

1: kd> dt nt!_pool_header 0x82a5a000
	+0x000 PreviousSize     : 0y000000100 (0x4)
	+0x000 PoolIndex        : 0y0100000 (0x20)
	+0x002 BlockSize        : 0y001010001 (0x51)
	+0x002 PoolType         : 0y0000000 (0)
	+0x000 Ulong1           : 0x514004
	+0x004 ProcessBilled    : 0x78787878 _EPROCESS
	+0x004 PoolTag          : 0x78787878
	+0x004 AllocatorBackTraceIndex : 0x7878
	+0x006 PoolTagHash      : 0x7878

As you can see, the tag is the correct “xxxx” that we specified in the allocation:

1: kd> .formats 0x78787878
	Evaluate expression:
	Hex:     78787878
	Decimal: 2021161080
	Octal:   17036074170
	Binary:  01111000 01111000 01111000 01111000
	Chars:   xxxx
	Time:    Tue Jan 17 20:38:00 2034
	Float:   low 2.01583e+034 high 0
	Double:  9.98586e-315