WinDBG supports a set of pseudo registers, which are registers that don’t actually exist on the platform but contain interesting values during debugging.
For example, there is a $peb pseudo register that holds the address of the PEB for the current process. So, I can execute or script:
!peb @$peb
And know that I’ll always view the PEB of the current process. See the Pseudo-Register Syntax section of the WinDBG docs for a full list of all pseudo registers.
In addition to the debugger supplied pseudo registers, there are 20 user defined pseudo registers. The names of these user defined registers are $t0-$t19 and they can be used to hold any value you want. As a trivial example, I can store an integer value in there and recall it later:
Very useful in scripting situations, which hopefully I’ll get around to posting later…
That’s cool and all, but there’s another interesting feature to pseudo registers that is worth mentioning. Pseudo registers can be used with the r? command, which allows you to assign a type to the register along with the value. So, let’s set the $t0 register to be an EPROCESS this time:
With the above syntax the $t0 register is now an EPROCESS pointer at address 0×89635850.
Important note: r? uses the C++ expression evaluator, which treats all addresses as decimal by default! So the 0x prefix in the above is mandatory!
Now that $t0 is an EPROCESS pointer, what can we do? Well, we can start to dereference fields of it as if we were programming in C or C++. The only trick is that we need to make sure we’re using the C++ evaluator, since WinDBG defaults to the MASM evaluator. We can do this in one of two ways, we can either do an explicit override for our commands:
Or, we can change the current evaluator and omit the override:


Thanks for this. Examples of the C++ evaluator are always helpful.