If you've clicked on this document I'm assuming you already know what the PEB is (and thus you can skip this chapter) however for those that don't: PEB stands for Process Environment Block and it is a struct of data containing information about the current process. All native Windows processes have a PEB and it contains information like the beingDebugged
flag, all loaded Dynamic Link Libraries and many other process critical information.
For those that want the challenge of writing this yourself, this section will go over how we go from nothing to extracting any information we want from the PEB:
The first thing we require is the handle to the target process which requires getting the Process ID (PID). There are a few ways you can implement this depending on how this snippet is being implemented:
CreateToolhelp32Snapshot
and then string match for the process(s) you want then storing the returned th32ProcessID
valueOpenProcess
to retrieve a handle to the process. Once we have a handle we can use NtQueryInformationProcess
which returns the PROCESS_BASIC_INFORMATION
struct:
typedef struct _PROCESS_BASIC_INFORMATION { NTSTATUS ExitStatus; PPEB PebBaseAddress; ULONG_PTR AffinityMask; KPRIORITY BasePriority; HANDLE UniqueProcessId; HANDLE InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION, * PPROCESS_BASIC_INFORMATION;
As we can see the second entry returns us the base address of the PEB. Once we have this address we have two options for parsing PEB information:
We can finally use ReadProcessMemory
with our PEB address plus the offset we want and we're golden!
For those of you that tried defining the PEB structure and realized that it's an absolute pain, I'll now show you the easiest way to find the PEB offsets:
For this I'm going to be using WinDBG Preview which you can only download from the Microsoft store. If you don't have access to the Microsoft Store because you value your privacy and are using a stripped burner VM, you can also use the old original WinDBG. Once you lunch WinDBG you can attach to any process and then run the following command: !peb
:
Pressing the highlighted base address at the top will then show you all of the structures offsets. See below:
Here is an example (in C) which will read the beingDebugged
value from a specified process:
#include <windows.h> #include <winternl.h> #include <stdio.h> #include <stdint.h> // Manually defining NtQueryInformationProcess typedef NTSTATUS(NTAPI* _NtQueryInformationProcess)( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL ); _NtQueryInformationProcess NtQueryInfoProcess; int main() { HANDLE hProcess; DWORD processId = 1234; BYTE beingDebugged; PROCESS_BASIC_INFORMATION pbi; // Dynamically resolving NtQueryInformationProcess NtQueryInfoProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll"), "NtQueryInformationProcess"); if (NtQueryInfoProcess == NULL) { printf("Failed to resolve NtQueryInformationProcess\n"); return 0; } // Get handle to process using pid hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId); if (!hProcess) { printf("OpenProcess failed for pid: %i\n", processId); return 0; } // Get ProcessBasicInformation using the process handle in NtQueryInfoProcess NTSTATUS status = NtQueryInfoProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0); if (!NT_SUCCESS(status)) { printf("NTSTATUS had a failure code when trying NtQueryInfoProcess for pid: %i\n", processId); return 0; } // Offset from PEB->BeingDebugged is +0x02 if (!ReadProcessMemory(hProcess, (PVOID)((uint64_t)pbi.PebBaseAddress + 0x02), &beingDebugged, sizeof(beingDebugged), NULL)) { printf("ReadProcessMeory failed to read ProcessParameters offset for pid %i, Error:%i\n", processId, GetLastError()); return 0; } printf("Value in beingDebugged PEB flag is: %i\n", beingDebugged); return 1; }
Hopefully this example is simple enough to expand for your use case. This example is also held in a Github repository on my Github. As per usual any questions, shoot me a direct message on twitter!