A very brief look into the PEB memory structure found, aiming to get a bit more comfortable with WinDBG and walking memory structures.
Basics
First of, checking what members the _PEB structure actually entails:
dt _peb
There are many fields in the structure among which there are ImageBaseAddresss and ProcessParameters which are interesting to us for this lab:
Getting the PEB address of the process:
0:001> r $peb$peb=000007fffffd5000
The _PEB structure can now be overlaid on the memory pointed to by the $peb to see what values the structure members are holding/pointing to:
0:001> dt_peb@$peb
_PEB structure is now populated with the actual data pulled from the process memory:
Let's check what's in memory at address 0000000049d40000 - pointed to by the ImageBaseAddress member of the _peb structure:
0:001> db 0000000049d40000 L100
Exactly! This is the actual binary image of the running process:
Another way of finding the ImageBaseAddress is:
0:001> dt _pebntdll!_PEB//snip+0x010 ImageBaseAddress : Ptr64 Void//snip0:001> dd @$peb+0x010 L2000007ff`fffd5010 49d40000 00000000// 49d40000 00000000 is little-endian byte format - need to invert0:001> db 0000000049d40000 L100
Convenience
We can forget about all of the above and just use:
!peb
This gets us a nicely formatted PEB information of some of the key members of the structure:
Finding Commandline Arguments
One of the interesting fields the PEB holds is the process commandline arguments. Let's find them:
0:001> dd 0x00000000`002a1f40+70+8 L200000000`002a1fb8002a283c000000000:001> du 00000000002a283c00000000`002a283c""C:\Windows\system32\cmd.exe" "
Since we now know where the commandline arguments are stored - can we modify them? Of course.
Forging Commandline Arguments
0:001> eu 00000000002a283c"cmdline-logging? Are You Sure?"
_PEB_LDR_DATA
Getting a list of loaded modules (exe/dll) by the process:
// get the first _LIST_ENTRY structure address0:001> dt _peb @$peb ldr->InMemoryOrderModuleList*ntdll!_PEB+0x018 Ldr : +0x020 InMemoryOrderModuleList : _LIST_ENTRY [ 0x00000000`002a2980-0x00000000`002a1e40 ]// walking the list manually and getting loaded module infodt _LIST_ENTRY 0x00000000`002a2980// cmd moduledt _LDR_DATA_TABLE_ENTRY 0x00000000`002a2980dt _LIST_ENTRY 0x00000000`002a2980// ntdll moduledt _LDR_DATA_TABLE_ENTRY 0x00000000`002a2a70dt _LIST_ENTRY 0x00000000`002a2a70// kernel32 moduledt _LDR_DATA_TABLE_ENTRY 0x00000000`002a2df0...loop...
If we check the loaded modules with !peb, it shows we were walking the list correctly:
Here is another way to find the first _LDR_DATA_TABLE_ENTRY:
dt _peb @$pebdt _PEB_LDR_DATA 0x00000000`774ed640
dt _LDR_DATA_TABLE_ENTRY 0x00000000`002a2980
A nice way of getting a list of linked-list structure addresses is by providing address of the first list_entry structure to the command dl and specifying how many list items it should print out: