Search This Blog

Showing posts with label pseudo rgister. Show all posts
Showing posts with label pseudo rgister. Show all posts

Friday, 19 September 2014

WinDbg : The Difference Between The Dot (.) & The Arrow (->) In The dt Command


WinDbg : The Difference Between The Dot (.) & The Arrow (->) In The dt Command 


Commands used:

We have seen that the dot (.) after the name of a structure member name will make the dt command expand the sub-structure. 

kd> dt nt!_EPROCESS pcb.
   +0x000 Pcb  : 
      +0x000 Header : _DISPATCHER_HEADER
      +0x010 ProfileListHead : _LIST_ENTRY
      +0x018 DirectoryTableBase : Uint4B

<Output Snipped to Save Space>

The same seem to be achieved with the arrow (->) as well.

kd> dt nt!_EPROCESS pcb->*
   +0x000 Pcb   : 
      +0x000 Header : _DISPATCHER_HEADER
      +0x010 ProfileListHead : _LIST_ENTRY
      +0x018 DirectoryTableBase : Uint4B

<Output Snipped to Save Space>

So The question arises what then is the difference, if at all between these. Well, on the first level a single . is equivalent to ->*. The differences arise with multiple levels.

. (dot) will recursively expand structures within structures and can be used like ...... (dot dot dot dot). Four dots in a row will expand till the 4th level nested structure, while -> will deference a pointer and you may need a name for it. 

In the below examples we will be using the pseudo register $Proc. To learn more about pseudo registers, please read this post.

lkd> $nodot

lkd> dt nt!_EPROCESS @$proc -y pc.H
   +0x000 Pcb  :
      +0x000 Header : _DISPATCHER_HEADER

lkd> $single dot

lkd> dt nt!_EPROCESS @$proc -y pc.H.
   +0x000 Pcb   :
      +0x000 Header :
         +0x000 Type  : 0x3 ''
         +0x001 Absolute : 0 ''
         +0x002 Size  : 0x1b ''
         +0x003 Inserted : 0 ''
         +0x004 SignalState : 0n0
         +0x008 WaitListHead : _LIST_ENTRY [ 0x866dd6d0 - 0x866dd6d0 ]

lkd> $single dot is equivalent to ->*

lkd> dt nt!_EPROCESS @$proc -y pc.H->*
   +0x000 Pcb    :
      +0x000 Header :
         +0x000 Type   : 0x3 ''
         +0x001 Absolute : 0 ''
         +0x002 Size   : 0x1b ''
         +0x003 Inserted : 0 ''
         +0x004 SignalState : 0n0
         +0x008 WaitListHead : _LIST_ENTRY [ 0x866dd6d0 - 0x866dd6d0 ]

lkd> $double dot will expand _list_entry

lkd> dt nt!_EPROCESS @$proc -y pc.H..
   +0x000 Pcb    :
      +0x000 Header :
         +0x000 Type   : 0x3 ''
         +0x001 Absolute : 0 ''
         +0x002 Size   : 0x1b ''
         +0x003 Inserted : 0 ''
         +0x004 SignalState : 0n0
         +0x008 WaitListHead :  [ 0x866dd6d0 - 0x866dd6d0 ]
            +0x000 Flink  : 0x866dd6d0 _LIST_ENTRY [ 0x866dd6d0 - 0x866dd6d0 ]
            +0x004 Blink  : 0x866dd6d0 _LIST_ENTRY [ 0x866dd6d0 - 0x866dd6d0 ]

lkd> dt nt!_EPROCESS @$proc -y pc.H->W.
   +0x000 Pcb      :
      +0x000 Header   :
         +0x008 WaitListHead :  [ 0x866dd6d0 - 0x866dd6d0 ]
            +0x000 Flink    : 0x866dd6d0 _LIST_ENTRY [ 0x866dd6d0 - 0x866dd6d0 ]
            +0x004 Blink    : 0x866dd6d0 _LIST_ENTRY [ 0x866dd6d0 - 0x866dd6d0 ]

lkd> dt nt!_EPROCESS @$proc -y pc.H->W->*
   +0x000 Pcb       :
      +0x000 Header    :
         +0x008 WaitListHead :  [ 0x866dd6d0 - 0x866dd6d0 ]
            +0x000 Flink     : 0x866dd6d0 _LIST_ENTRY [ 0x866dd6d0 -
0x866dd6d0 ]
            +0x004 Blink     : 0x866dd6d0 _LIST_ENTRY [ 0x866dd6d0 -
0x866dd6d0 ]

lkd> dt nt!_EPROCESS @$proc -y pc.H->W..
   +0x000 Pcb       :
      +0x000 Header    :
         +0x008 WaitListHead :  [ 0x866dd6d0 - 0x866dd6d0 ]
            +0x000 Flink     :
            +0x004 Blink     :
Cannot find specified field members



Thursday, 18 September 2014

WinDbg : .for Command For Looping

WinDbg : .for Command For Looping 


Many a times we need to perform the same operation over multiple times in the debugger. The .for command will help ease the task. It helps us define loops, much like we do in the C-style for loop.

The .for token behaves like the for keyword in C, except that multiple increment commands must be separated by semicolons, not by commas.

The syntax is: 
.for (InitialCommand ; Condition ; IncrementCommands) { Commands }

We usually use pseudo-registers or registers to create the initialCommand and the condition of the loop. As an example lets revisit the topic of heaps. In this post we said that to display all the members of the ProcessHeaps array we need a loop. Taking the relevant portion of text from that post for the benefit of the reader, we see that the ProcessHeaps can be displayed with the following command.

kd> .for (r $t0 = 0; @$t0 < 0x4; r $t0 = @$t0 + 1){dt _HEAP poi(0x77c77500 + ((@$t0)*4)) - y SegmentSignature}
ntdll!_HEAP
   +0x008 SegmentSignature : 0xffeeffee
ntdll!_HEAP
   +0x008 SegmentSignature : 0xffeeffee
ntdll!_HEAP
   +0x008 SegmentSignature : 0xffeeffee
ntdll!_HEAP
   +0x008 SegmentSignature : 0xffeeffee

So what is happening here. We are using the pseudo-register $t0 and setting it to initial value 0 with the command r $t0 = 0. Remember the rule about *NOT* having to use the at (@) sign with the left hand operand of the r command. The rule is described in the post here. Next we create the condition of the loop by setting it to execute till it is less than 0x4. This is done by the statement @$t0 < 0x4. Then comes the increment to the value, which is done with the statement r $t0 = @$t0 + 1. Once again we see that the left hand operand for r doesn't need the at (@) sign, however, the same one in the right hand side needs it.

After this, inside the curly braces is the command to execute, which in this case is being used to print the SegmentSignature member of the _HEAP structure. Also note, that the pointer is incremented by 4 bytes (the size of pointers on an x86 machine. Since the register $t0 is a counter this will be used to calculate the indices of the array.

WinDbg : The r (register) command

WinDbg : The r (register) command

To access the registers currently in the system we use the register (r) command.

kd> r
eax=827411fc ebx=91387b02 ecx=00000001 edx=00000000 esi=82733d20 edi=00000000
eip=826495cb esp=91387b24 ebp=91387b3c iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00000202
nt!KiTrap0E+0x2cf:

826495cb 833d04db768200  cmp     dword ptr [nt!KiFreezeFlag (8276db04)],0 ds:0023:8276db04=00000000

To see the value of a specific register use it's name with r.

kd> r eax

eax=827411fc

The r command can be used to both read and write into registers.

r can also be used to access pseudo-registers and read and write them. The debugger always interprets its first argument as a register or pseudo-register. (An at (@) sign is not required or permitted.) If there is a second argument for the r command, it is interpreted according to the default expression syntax. 

If the default expression syntax is C++, we must use the following command to copy the $t2 pseudo-register to the $t1 pseudo-register.

0:000> r $t1 = @$t2 

Notice that even though both t1 and t2 are registers, the at (@) is only needed in the right hand side.

To write a value to a register or pseudo-register, we do the following:

0:000> r $t0 = 7

for a normal register

0:000> r eax = 7

or to put MyVar multiplied by 128 into a pseudo register.

0:000> r $t1 = 128*poi(MyVar)

A pseudo-register is always typed as an integer, unless the ? switch is used together with the r command. Using this switch, the pseudo-register acquires the type of whatever is assigned to it. 

For example, the following command assigns the UNICODE_STRING** type and the 0x0012FFBC value to $t15

0:000> r? $t15 = * (UNICODE_STRING*) 0x12ffbc

R is a very versatile command, and has several switches and customizations. Please consult the WinDbg manual if you need any thing specific.

WinDbg : Pseudo Registers

WinDbg : Pseudo Registers  

Yet another powerful tool provided by WinDbg are the pseudo registers. These registers, as the name suggests, can hold temporary values. Pseudo registers can be: 
  • Automatic : WinDbg sets the values for the automatic pseudo registers automatically to certain useful values.
  • User defined : These are integer variables which the user has to read or write to. 
All pseudo registers, whether automatic or user defined, begin with the dollar ($) sign.

Note: When using the MASM expression evaluator we need to add an at (@) sign in front of the dollar ($) sign. This tells the debugger that the following token is a register or pseudo-register and not a symbol. Omitting the at @) sign makes the debugger look up the symbol table, making it slower in response.

Note2 : If a symbol exists with the same name as the pseudo-register, then the at(@) sign MUST be added. If the C++ expression evaluator is being used, the at (@) sing must be used ALWAYS. There are a few exceptions to this rule, and those would be covered in the post related to the registers (r command).

Here is a list of the automatic pseudo-registers supported (taken from the WInDbg Help).

Pseudo-register
Description
$ea 
The effective address of the last instruction that was executed. If this instruction does not have 
an effective address, the debugger displays "Bad register error". If this instruction has two 
effective addresses, the debugger displays the first address.
$ea2 
The second effective address of the last instruction that was executed. If this instruction does 
not have two effective addresses, the debugger displays "Bad register error".
$exp 
The last expression that was evaluated.
$ra 
The return address that is currently on the stack.
This address is especially useful in execution commands. For example, g @$ra continues until 
the return address is found (although gu (Go Up) is a more precise effective way of 
"stepping out" of the current function).
$ip 
The instruction pointer register.
x86-based processors: The same as eip
Itanium-based processors: Related to iip. (For more information, see the note following this 
table.) 
x64-based processors: The same as rip
$eventip 
The instruction pointer at the time of the current event. This pointer typically matches $ip
unless you switched threads or manually changed the value of the instruction pointer.
$previp 
The instruction pointer at the time of the previous event. (Breaking into the debugger counts 
as an event.)
$relip 
An instruction pointer that is related to the current event. When you are branch tracing, 
this pointer is the pointer to the branch source.
$scopeip 
The instruction pointer for the current local context (also known as the scope).
$exentry 
The address of the entry point of the first executable of the current process.
$retreg 
The primary return value register.
x86-based processors: The same as eax
Itanium-based processors: The same as ret0
x64-based processors: The same as rax
$retreg64 
The primary return value register, in 64-bit format.
x86 processor: The same as the edx:eax pair. 
$csp 
The current call stack pointer. This pointer is the register that is most representative of call 
stack depth.
x86-based processors: The same as esp
Itanium-based processors: The same as bsp
x64-based processors: The same as rsp
$p 
The value that the last d* (Display Memory) command printed.
$proc 
The address of the current process (that is, the address of the EPROCESS block). 
$thread 
The address of the current thread. In kernel-mode debugging, this address is the address 
of the ETHREAD block. In user-mode debugging, this address is the address of the thread 
environment block (TEB).
$peb 
The address of the process environment block (PEB) of the current process.
$teb 
The address of the thread environment block (TEB) of the current thread.
$tpid 
The process ID (PID) for the process that owns the current thread. 
$tid 
The thread ID for the current thread.
$bpNumber
The address of the corresponding breakpoint. For example, $bp3 (or $bp03) refers to the 
breakpoint whose breakpoint ID is 3. Number is always a decimal number. If no breakpoint 
has an ID of Number$bpNumber evaluates to zero. For more information about breakpoints, 
see Using Breakpoints.
$frame
The current frame index. This index is the same frame number that the .frame (Set Local
 Context) command uses.
$dbgtime
The current time, according to the computer that the debugger is running on.
$callret
The return value of the last function that .call (Call Function) called or that is used in an 
.fnret /s command. The data type of $callret is the data type of this return value.
$lastclrex 
Managed debugging only: The address of the last-encountered common language runtime (CLR) exception object. 
$ptrsize
The size of a pointer. In kernel mode, this size is the pointer size on the target computer.
$pagesize
The number of bytes in one page of memory. In kernel mode, this size is the page size on 
the target computer.

Note: Not all of these are available all the time. Example, the $teb and $peb are user mode concepts and wouldn't be available in the kernel mode unless the process context is properly set. Also, these are not available with mini dumps.

There are 20 User Defined pseudo-registers possible. They are named $t0, $t1...$t19. To write to a pseudo register we must use the register (r) command, described here.