WinDBG

 

Random stuff

 

!process 0 0

 

PROCESS 8606b020  SessionId: 0  Cid: 0e88    Peb: 7ffdf000  ParentCid: 065c

    DirBase: 3545f000  ObjectTable: e1244418  HandleCount:  95.

    Image: OPSCAN.EXE

 

PROCESS 86268020  SessionId: 0  Cid: 08cc    Peb: 7ffdf000  ParentCid: 0544

    DirBase: 3a4fb000  ObjectTable: e1943658  HandleCount: 188.

    Image: WINWORD.EXE

Displays basic stuff on each process running.  The parameter Process is the address of the EPROCESS structure in memory.

 

To display the Eprocess structure in XP we use

 

lkd> dt nt!_EPROCESS  8606b020

   +0x000 Pcb              : _KPROCESS

   +0x06c ProcessLock      : _EX_PUSH_LOCK

….

   +0x255 WorkingSetAcquiredUnsafe : UChar

   +0x258 Cookie           : Uint4B

 

The undocumented EPROCESS structure in XP has the pid at 0x130 and the  image file name at 0x174.

 

We can also use the command to do the same thing

 

dt _EPROCESS 852d88b8

 

The value after Cid is the process is of our process in hex. We have winword or word running on our machine that has a pid of 2252 or 0x8cc. We used task manager to back check.

 

The PEB is the process environment block which is the same for all and begins at 7ffdf000. This is followed by the parent Cid or the parent of the pid that created this process.

 

The object table is the process object address.

 

lkd> !process winword.exe

PROCESS 852f7318  SessionId: 0  Cid: 0ef4    Peb: 7ffd7000  ParentCid: 0544

    DirBase: 07292000  ObjectTable: e12fcfb8  HandleCount:  62.

    Image: windbg.exe

    VadRoot 860963a0 Vads 67 Clone 0 Private 2312. Modified 688. Locked 1.

    DeviceMap e1f02f60

    Token                             e10676a0

    ElapsedTime                       00:29:57.524

    UserTime                          00:00:25.066

    KernelTime                        00:00:01.301

    QuotaPoolUsage[PagedPool]         40212

    QuotaPoolUsage[NonPagedPool]      2800

    Working Set Sizes (now,min,max)  (3564, 50, 345) (14256KB, 200KB, 1380KB)

    PeakWorkingSetSize                3585

    VirtualSize                       45 Mb

    PeakVirtualSize                   46 Mb

    PageFaultCount                    6073

    MemoryPriority                    BACKGROUND

    BasePriority                      8

    CommitCharge                      2742

 

        THREAD 85358bd0  Cid 0ef4.0ef8  Teb: 7ffdf000 Win32Thread: e10aee70 WAIT: (WrUserRequest) UserMode Non-Alertable

            86094d18  SynchronizationEvent

 

        THREAD 860637e0  Cid 0ef4.06b0  Teb: 7ffde000 Win32Thread: e126dcf8 RUNNING on processor 0

        THREAD 85370020  Cid 0ef4.0ae0  Teb: 7ffdc000 Win32Thread: 00000000 WAIT: (WrLpcReceive) UserMode Non-Alertable

            86455bf8  Semaphore Limit 0x7fffffff

 

The !process takes the name of the process as a parameter and displays details of that one process.

 

!process 852f7318

 

This displays more information about a process and as we can see 852f7318 is the address of the EPROCESS structure.

 

!process ef4

 

The process id of winword  is ef4 on our machine and thus we can use either the name of the process or the process id or the eprocess structure.

 

!process ef4 0

 

shows us minimal information about the process and

 

!process ef4 7

 

gives us more.

 

The first five bits decide how much information to show.

lkd> !object \Device\PhysicalMemory

Object: e1001958  Type: (867c0458) Section

    ObjectHeader: e1001940

    HandleCount: 0  PointerCount: 3

    Directory Object: e100f748  Name: PhysicalMemory

 

lkd> dt nt!_OBJECT_HEADER e1001958

   +0x000 PointerCount     : 83886080

   +0x004 HandleCount      : 18

   +0x004 NextToFree       : 0x00000012

   +0x008 Type             : 0x00000201 _OBJECT_TYPE

   +0x00c NameInfoOffset   : 0 ''

   +0x00d HandleInfoOffset : 0 ''

   +0x00e QuotaInfoOffset  : 0 ''

   +0x00f Flags            : 0x5 ''

   +0x010 ObjectCreateInfo : 0x00000020 _OBJECT_CREATE_INFORMATION

   +0x010 QuotaBlockCharged : 0x00000020

   +0x014 SecurityDescriptor : 0xe100b440

   +0x018 Body             : _QUAD

 

The !object extension displays stuff about any system object like /device/physicalmemory.  The value e1001958 tells us the address of the object.  The dt command displays the object header for the object starting at e10001958.

 

We ran the !handle extension which gave us a list of handles like

 

lkd> !handle

processor number 0, process 852ddb80

PROCESS 852ddb80  SessionId: 0  Cid: 048c    Peb: 7ffd8000  ParentCid: 0a74

    DirBase: 37ecc000  ObjectTable: e132a438  HandleCount:  46.

    Image: windbg.exe

 

New version of handle table at e13aa000 with 46 Entries in use

0004: Object: e100b7e0  GrantedAccess: 000f0003

Object: e100b7e0  Type: (867c0ad0) KeyedEvent

    ObjectHeader: e100b7c8

        HandleCount: 45  PointerCount: 46

        Directory Object: e1005ab8  Name: CritSecOutOfMemoryEvent

 

0008: Object: e1a8f7b8  GrantedAccess: 00000003

Object: e1a8f7b8  Type: (867c6040) Directory

    ObjectHeader: e1a8f7a0

        HandleCount: 45  PointerCount: 80

        Directory Object: e1001230  Name: KnownDlls

 

We then ran the object extension on some of the objects starting address to get the following listing

 

lkd> !object 853c2978

Object: 853c2978  Type: (867e9040) File

    ObjectHeader: 853c2960

    HandleCount: 1  PointerCount: 1

    Directory Object: 00000000  Name: \WINDOWS\Symbols\ntoskrnl.pdb\32962337F0F646388B39535CD8DD70E82\ntoskrnl.pdb {HarddiskVolume1}

 

lkd> !peb

PEB at 7ffdf000

 

The !peb extension gives us the peb or the process environment block. We can find the peb of any process using the command

 

!peb 7ffdf000

 

g.c

main()

{

fopen("a.c","w");

getch();

}

 

!handle 0 F 85f2a020

 

where 85f2a020 is the EPROCESS structure address of g.exe

 

07e8: Object: 852bdf90  GrantedAccess: 00120196 (Inherit)

Object: 852bdf90  Type: (867e9040) File

    ObjectHeader: 852bdf78

        HandleCount: 1  PointerCount: 1

        Directory Object: 00000000  Name: \vm\a.c {HarddiskVolume1}

 

The handle extension allows us to see all the handles that a process has opened.

 

New Stuff

To set windbg working click on menu File, Symbol File Path and in the multi line text box write the following SRV*c:\windows\symbols*http://msdl.microsoft.com/download/symbols which will cache all the symbols in windows/symbols.

Also set the environment variable _NT_SYMBOL_PATH to c:\windows\symbols

 

Converting a virtual address to a physical address.

 

We first write a program d.c in c:\vm as follows.

 

d.c

#include <windows.h>

void *p;

main()

{

p = VirtualAlloc(0,24,MEM_COMMIT,PAGE_READWRITE);

strcpy(p,"Vijay Mukhi");

printf("%08x %s\n",p,p);

getch();

}

 

00340000 Vijay Mukhi

 

We use method VirtualAlloc to allocate 24 virtual committed memory locations that we can read and write. The value of p returned is  00340000. We copy my name over the freshly allocated memory locations. The byte index of the virtual memory is the lower 12 bits which is 000.

 

In kd we use the !process extension to give us the directory base.

 

!process 0 0

 

PROCESS 852ac020  SessionId: 0  Cid: 0b68    Peb: 7ffde000  ParentCid: 01b8

    DirBase: 010bb000  ObjectTable: e15cfa38  HandleCount:   7.

    Image: d.exe

 

The Dir Base of image d.exe is 010bb000 and the page frame number is by righting the above bits by 12 which gives us 010bb. We use the !vtop extension which requires two parameters the page frame number 010bb and the virtual address 00340000.  The DirBase is the physical address of the processes page directory. Normally as the last 10 bits are always 0 the DirBase gives us the physical address of the page directory table.

 

lkd> !vtop 010bb 340000

Pdi 0 Pti 340

00340000 Transition 0a94b000 (0a94b)

 

The number 0a94b000 is the physical address as the first 12 bits of the virtual; address is 0. If not zero add to the physical address which is at the start of the page to get the real address.

 

lkd> !dc 0a94b000

# a94b000 616a6956 754d2079 0069686b 00000000 Vijay Mukhi.....

 

The extension !dc displays the bytes at the physical memory.

 

e.c

#include <windows.h>

void *p,*q;

main()

{

p = VirtualAlloc(0,24,MEM_COMMIT,PAGE_READWRITE);

strcpy(p,"Vijay Mukhi");

printf("%08x %s\n",p,p);

q = VirtualAlloc(0,24,MEM_COMMIT,PAGE_READWRITE);

strcpy(q,"sonal Mukhi");

printf("%08x %s\n",q,q);

getch();

}

 

00340000 Vijay Mukhi

00350000 sonal Mukhi

 

!process 0 0

 

PROCESS 852ac020  SessionId: 0  Cid: 0d04    Peb: 7ffd4000  ParentCid: 01b8

    DirBase: 3ba0e000  ObjectTable: e2ae52d8  HandleCount:   7.

    Image: e.exe

 

lkd> !vtop 3ba0e 350000

Pdi 0 Pti 350

00350000 3a7cd000 pfn(3a7cd)

 

lkd> !dc 3a7cd000

#3a7cd000 616e6f73 754d206c 0069686b 00000000 sonal Mukhi.....

 

We once again run the program d.exe and then the command

 

!process 0 0

 

This gives us a list of all processes running and our program d.exe  has a dir base of 0026a000. We then find extract the pfn which is 0026a. We run the command

 

!ptov 0026a

 

this gives us a list of two columns where the first is the physical address of the memory and the second is the virtual address of all memory allocated. The display is too large and hence we click on Edit, Open/Close log file to open log file after specifying the name in our case C:\a.txt. We then run the above command and we see in a.txt that virtual address 950000 has a physical address of 7aa9000 which we display using the command

 

!dc 7aa9000

 

It is also a good idea to choose menu View Verbose output. Pressing Ctrl-Break will stop the listing but we were not fast enough.

 

lkd> !pte 00340000

               VA 00340000

PDE at   C0300000        PTE at C0000D00

contains 32512067      contains 00000000

pfn 32512 ---DA--UWEV 

 

The !pte command gives us the PDE and PTE of any virtual address. The virtual address for the page directory entry will always start at 0xC0300000. In our case our PDE index is 0.  In the flags D stands for Dirty, U for user mode, V for a valid page and W for writable.

 

lkd> !process 0af4 1

Searching for Process with Cid == af4

PROCESS 85f9e270  SessionId: 0  Cid: 0af4    Peb: 7ffdf000  ParentCid: 0160

    DirBase: 31918000  ObjectTable: e2368658  HandleCount:   7.

    Image: d.exe

    VadRoot 8534b770 Vads 22 Clone 0 Private 44. Modified 0. Locked 0.

 

lkd> !vad 8534b770

VAD     level      start      end    commit

85f42168 ( 1)         10       11         2 Private      READWRITE

86433920 ( 2)         20       20         1 Private      READWRITE

8532c6c0 ( 3)         30      12f         3 Private      READWRITE

85f4f4f0 ( 4)        130      132         0 Mapped       READONLY

86073220 ( 5)        140      23f         3 Private      READWRITE

8604c3f8 ( 6)        240      24f         6 Private      READWRITE

85165598 ( 7)        250      25f         0 Mapped       READWRITE

852fb890 ( 8)        260      275         0 Mapped       READONLY

8510acc8 ( 9)        280      2bc         0 Mapped       READONLY

851476e8 (10)        2c0      300         0 Mapped       READONLY

852dcbc8 (11)        310      315         0 Mapped       READONLY

858b1660 (12)        320      32f         8 Private      READWRITE

8666f758 (13)        330      332         0 Mapped       READONLY

86485848 (14)        340      340         1 Private      READWRITE

8534b770 ( 0)        400      408         4 Mapped  Exe  EXECUTE_WRITECOPY

86529e38 ( 3)        410      50f         8 Private      READWRITE

8605eb28 ( 2)      7c800    7c8f3         5 Mapped  Exe  EXECUTE_WRITECOPY

85142368 ( 1)      7c900    7c9af         5 Mapped  Exe  EXECUTE_WRITECOPY

852cc9d0 ( 3)      7f6f0    7f7ef         0 Mapped       EXECUTE_READ

85180420 ( 2)      7ffb0    7ffd3         0 Mapped       READONLY

8630e520 ( 4)      7ffde    7ffde         1 Private      READWRITE

85290618 ( 3)      7ffdf    7ffdf         1 Private      READWRITE

 

Total VADs:    22  average level:    6  maximum depth: 14

 

The VAD extension gives us the vad map if we pass it the root of the vad that we get from the process command.

 

lkd> !pte 340000

               VA 00340000

PDE at   C0300000        PTE at C0000D00

contains 32512067      contains 00000000

pfn 32512 ---DA--UWEV   

 

lkd> !pfn 32512

    PFN 00032512 at address 81F4A9B0

    flink       0000000C  blink / share count 0000008D  pteaddress C0300000

    reference count 0001   Cached     color 0

    restore pte 00000080  containing page        039A7C  Active     M      

    Modified  

 

D2.c

#include <windows.h>

void *p;

void abc(int i)

{

int x , y , z;

x = i & 0x00000fff;

y = i & 0x003ff000;

y = y >> 12;

z = i & 0xffC00000;

z = z >> 22;

printf("high 10 bits=%d:0x%x Middle 10 bits=%d:0x%x first 12 bits=%d:0x%x %08x\n",z,z,y,y,x,x,i);

}

main()

{

p = VirtualAlloc(0,24,MEM_COMMIT,PAGE_READWRITE);

strcpy(p,"Vijay Mukhi");

printf("%08x %s\n",p,p);

abc((unsigned int)p);

getch();

printf("%08x %s\n",p,p);

getch();

}

 

00340000 Vijay Mukhi

high 10 bits=0:0x0 Middle 10 bits=832:0x340 first 12 bits=0:0x0 00340000

00340000 AAAay Mukhi

 

We ran the above program and waited on the first getch method. Our  PTE is always 0x340. We then ran the command

 

!process 0 0

 

PROCESS 850fc6d8  SessionId: 0  Cid: 0a60    Peb: 7ffdf000  ParentCid: 0bb0

    DirBase: 1f151000  ObjectTable: e108b6a0  HandleCount:   7.

    Image: d2.exe

 

The physical address of the DirBase or Page Directory Table is 1f151000. All page table addresses would start with 000 as they represent a page of memory which is 4096 bytes large. We use the vtop command as

 

lkd> !vtop 1f151 340000

Pdi 0 Pti 340

00340000 34c1a000 pfn(34c1a)

 

Whether we specify the full 20 bit or 32 address of the PDE does not matter.  The Page Directory entry is 0 and the page table entry is 0x340 and the page frame number is 34c1a. As our byte offset or the first 12 bits of the virtual address are zero the physical address is 34c1a000.

 

lkd> !dc 34c1a000

#34c1a000 616a6956 754d2079 0069686b 00000000 Vijay Mukhi....

 

The dc extension that displays physical addresses simply confirms this.

 

lkd> !eb 34c1a000 41 41 41

lkd> !dc 34c1a000

#34c1a000 61414141 754d2079 0069686b 00000000 AAAay Mukhi.....

 

The eb extension lets us write to physical memory as bytes. We specify a series of bytes in hex separated by spaces or commas. The dc extension confirms this and then when we move out of the getch, we see that the bytes have actually changed.

 

We once again d.exe or d2.exe and get the same answer Page Directory Entry is 0 and Page Table Entry is 832 or 0x340.

 

00340000 Vijay Mukhi

high 10 bits=0:0x0 Middle 10 bits=832:0x340 first 12 bits=0:0x0 00340000

 

We then run the command

 

!process 0 0

 

this gives us a dirbase of 099ba000. This is the physical address of where the PDE begins. There is only one PDE per process and this value is stored in the CR3  register. As this is the physical address lets see  what the contents are.

 

lkd> !dd 099ba000

# 99ba000 1b645067 1fc44067 00000000 00000000

 

The dd extension unlike dc which displays bytes displays dwords instead. We see that we have two PTE enteries one for user space and the other one for kernel space. The value 1b645067 is actually 1b645 as the 20 bit page table address and 067 as the flags or permissions bits. Remember a page begins at a boundary of 4k and the first 12 bits are always zero.

 

Lets see what begins at this address.

 

lkd> !dd 1b645000

#1b645000 00000000 00000000 00000000 00000000

 

What we see are the 1024 DWORDS of the PTE, what we need to see is the entry at 832 or 0x340. We multiply this by 4 as each DWORD is 4 which gives us d00 and add it to the value 1b645000.  This gives us a value of 1b645d00.

 

lkd> !dd 1b645d00

#1b645d00 1edb2886 00000000 00000000 00000000

 

This shows us that the pfn or page frame number is 1edb2 and the flags are 886.

 

lkd> !dc 1edb2000

#1edb2000 616a6956 754d2079 0069686b 00000000 Vijay Mukhi.....

 

A dc on address 1edb2000 shows us vijay mukhi.

 

lkd> !vtop 099ba 340000

Pdi 0 Pti 340

00340000 Transition 1edb2000 (1edb2)

 

The vtop does what we did. It first extracts the offsets of the pdi and pti and then reads the pdi and pte to get at the physical address which it displays.

 

If we want to know what the bytes are at a certain variable we use the db command as

 

lkd> db PsLoadedModuleList

8055a420  a8 03 c1 89 d0 31 36 89-00 00 00 00 00 00 00 00

 

The above output confirms that the debugger understands the word PsLoadedModuleList and tells us that it starts at 8055a420. Our own code that reads the pcr conforms this. We can also see what the bytes present are.