cwinapimemorycreateprocessbase-address

Finding the base address after creating suspended process


i'm trying to learn how to do process hollowing / replacement (for the sake of learning). I've created a 32bit process in a suspended state, afterwards i need the base address of that process in order to later unmap from memory and replace with something else.

From my research i can get it from the PEB of the process, which includes that address. also from what i understood the PEB is always located in the ebx register, and the entrypoint is located in the eax register.

HOWEVER, when i get the context for the main thread (which holds the content of the registers) it's all zero which makes no sense to me, but it doesn't fail.

SECOND PROBLEM. when i read the process memory i get error 299 (12B) which from what i understand occurs when trying to read memory of a 64bit from 32bit (but remember that i'm running a 32bit process).

#include <Windows.h>
#include <tchar.h>
#include <stdio.h>

void end_program(LPPROCESS_INFORMATION pinfo, LPSTARTUPINFO stinfo)
{
    TerminateProcess(pinfo->hProcess, 1);
    CloseHandle(pinfo->hProcess);
    CloseHandle(pinfo->hThread);
    CloseHandle(stinfo->hStdError);
    CloseHandle(stinfo->hStdInput);
    CloseHandle(stinfo->hStdOutput);
    system("pause");
}

void main()
{
    // Create process suspended
    PROCESS_INFORMATION process_info;
    STARTUPINFO start_info;
    ZeroMemory(&process_info, sizeof(process_info));
    ZeroMemory(&start_info, sizeof(start_info));
    TCHAR path[100] = TEXT("C:\\Windows\\SysWOW64\\svchost.exe");
    if (!CreateProcess(NULL, path, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &start_info, &process_info))
    {
        printf("Failed creating process: error 0x%p", GetLastError());
        return;
    }
    printf("PID: %i Handle: 0x%p\r\n", process_info.dwProcessId, process_info.hProcess);

    // Get context of thread
    CONTEXT context;
    ZeroMemory(&context, sizeof(context));
    if (!GetThreadContext(process_info.hThread, &context))
    {
        printf("Failed getting context: error 0x%p\r\n", GetLastError());
        end_program(&process_info, &start_info);
        return;
    }
    printf("Context recieved!\r\n");

    // Get base address
    PVOID base_address;
    ZeroMemory(&base_address, sizeof(base_address));
    if (!ReadProcessMemory(process_info.hProcess, (BYTE)(context.Ebx + 8), &base_address, sizeof(PVOID), NULL))
    {
        printf("Error reading file: error 0x%p\r\n", GetLastError());
        end_program(&process_info, &start_info);
        return;
    }

    // Bugs that haven't been uncovered yet goes here




    // End of program
    end_program(&process_info, &start_info);
}

note 1: research said that the PEB with offset of 8 bytes is the base address.

note 2: tried to snapshot all process but same error, also tried enumprocessmodules, same error occurs.

note 3: everything i found online is for finding the base address of a running process, which i tried and succeeded, but since no modules are loaded yet in suspended (as it appears in taskmanager since there's no name for the process, could be wrong though), it doesn't work for me.

note 4: i'm also kind of new to coding in C, so sorry if something looks odd.

any help will be gladly appriciated. if you have other ways to get base address i'd love to hear. sorry if the code the a little messy, or if i wasn't clear. i'll do my best to explain...

forgot to add: my system is Windows 10 64bit

Edit: Fixed the problem. needed to do context.ContextFlags=CONTEXT_INTEGER. that allowed me to read. also the readprocess memory failed because i gave it wrong address to read from (basically 0+8=8) which i assume was for a 64bit process


Solution

  • You never set context.ContextFlags, you must set it to CONTEXT_INTEGER before calling GetThreadContext().

    Here's a sample code:

    #if defined(_WIN64)
        WOW64_CONTEXT context;
        memset(&context, 0, sizeof(WOW64_CONTEXT));
        context.ContextFlags = CONTEXT_INTEGER;
        Wow64GetThreadContext(pi.hThread, &context);
    #else   
        CONTEXT context;
        memset(&context, 0, sizeof(CONTEXT));
        context.ContextFlags = CONTEXT_INTEGER;
        GetThreadContext(pi.hThread, &context);
    #endif
    

    Taken from hasherezade's excellent runpe implementation