Search code examples
c++winapiportable-executable

RunPE memory malfunction


Whenever executing my executable file, it works 80% of the time. The other 20% of the time, I receive a 0xc00000005 error from Windows. I believe this may be a memory problem, but I'm not sure how to fix it. I have spent too much time trying to figure out how I can fix this, so I am now coming here. I'm using Visual Studio.

I debugged the program and it's failing right here at the debug script named "Write process memory step 1: Failed."

if (WriteProcessMemory(PI.hProcess, pImageBase, Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL))
{
    for (count = 0; count < NtHeader->FileHeader.NumberOfSections; count++)
    {
        SectionHeader = PIMAGE_SECTION_HEADER(DWORD(Image) + DOSHeader->e_lfanew + 248 + (count * 40));

        WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + SectionHeader->VirtualAddress),
            LPVOID(DWORD(Image) + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, 0);
    }

RunPE function:

     /*             PE Execution Function               */
int RunPortableExecutable(void* Image)
{
    IMAGE_DOS_HEADER* DOSHeader;
    IMAGE_NT_HEADERS* NtHeader;
    IMAGE_SECTION_HEADER* SectionHeader;

    PROCESS_INFORMATION PI;
    STARTUPINFOA SI;

    DWORD* ImageBase;
    void* pImageBase;

    int count;
    char CurrentFilePath[1024];

    DOSHeader = PIMAGE_DOS_HEADER(Image);
    NtHeader = PIMAGE_NT_HEADERS(DWORD(Image) + DOSHeader->e_lfanew);

    GetModuleFileNameA(0, CurrentFilePath, 1024);
    if (NtHeader->Signature == IMAGE_NT_SIGNATURE)
    {
        ZeroMemory(&PI, sizeof(PI));
        ZeroMemory(&SI, sizeof(SI));

        if (CreateProcessA(CurrentFilePath, NULL, NULL, NULL, FALSE,
            CREATE_SUSPENDED, NULL, NULL, &SI, &PI))
        {
            LPCONTEXT CTX = LPCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
            CTX->ContextFlags = CONTEXT_FULL;

            if (GetThreadContext(PI.hThread, LPCONTEXT(CTX)))
            {
                if (ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&ImageBase), 4, 0))
                {
                    pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(NtHeader->OptionalHeader.ImageBase),
                    NtHeader->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);

                    if (WriteProcessMemory(PI.hProcess, pImageBase, Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL))
                    {
                        for (count = 0; count < NtHeader->FileHeader.NumberOfSections; count++)
                        {
                            SectionHeader = PIMAGE_SECTION_HEADER(DWORD(Image) + DOSHeader->e_lfanew + 248 + (count * 40));

                            if (WriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + SectionHeader->VirtualAddress),
                                LPVOID(DWORD(Image) + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, 0))
                            {
                                cout << "Write process memory in FOR statement. Success";
                            }
                            else cout << "Write process memory in FOR statement. Failed";
                        }

                        if (WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8),
                            LPVOID(&NtHeader->OptionalHeader.ImageBase), 4, 0))
                        {

                            CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint;
                            if (SetThreadContext(PI.hThread, LPCONTEXT(CTX)))
                            {
                                if (ResumeThread(PI.hThread))
                                {
                                cout << "Resume thread: Success";
                                }
                                else cout << "Resume thread: Failed";
                            }
                            else cout << "Set thread context: Failed";

                        }
                        else cout << "Write process memory step 2: Failed";
                    }
                    else cout << "Write process memory step 1: Failed";
                }
                else cout << "Read process memory: Failed";
            }
            else cout << "Get thread context: Failed";
        }
        else cout << "Create process: Failed";
    }
    else cout << "Get module file name: Failed";
    return 0;
}

Warnings messages:

Severity Code Description Project File Line Suppression State
Warning C6011 Dereferencing NULL pointer 'CTX'.
Line 39

Severity Code Description Project File Line Suppression State
Warning C6387 'CTX' could be '0': this does not adhere to the specification for the function 'GetThreadContext'. See line 39 for an earlier location where this can occur
Line 41

Severity Code Description Project File Line Suppression State
Warning C6387 'pImageBase' could be '0': this does not adhere to the specification for the function 'WriteProcessMemory'.
Line 48

Severity Code Description Project File Line Suppression State
Warning C6387 'CTX' could be '0': this does not adhere to the specification for the function 'SetThreadContext'. See line 39 for an earlier location where this can occur
Line 62


Solution

  • I solved the problem by setting the Randomized Base Address to No in the Linker/Advanced options tab.

    Then I added the NtUnmapViewofSection to my code

    *(DWORD_PTR*)&pNtUnmapViewOfSection = (DWORD_PTR)GetProcAddress(GetModuleHandleW(L"NTDLL.dll"), "NtUnmapViewOfSection");