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.