Чтение нарушения прав доступа при попытке запустить pe-файл из памяти - PullRequest
0 голосов
/ 29 мая 2020

Я взял известный пример запуска исполняемого файла pe из памяти. Но когда я пытаюсь запустить его, я получаю нарушение доступа к памяти в функции WriteProcessMemory ().

Я использую последнюю версию Visual Studio 2019 и Windows 10 x64 OS. В настройках Visual Studio я выбираю отладку и сборку x86. Приложение, которое я пытаюсь запустить (simpleMessageBox.exe), совпадает с отладкой x86. Вот моя полная программа:

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <Windows.h> // WinAPI header
#include <TlHelp32.h> // WinAPI Process API

std::vector<uint8_t> getFileContents(const char* filePath)
{
    std::vector<uint8_t> rawData;

    std::ifstream stream(filePath, std::ios::in);
    rawData = std::vector<uint8_t>(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>());

    return rawData;
}

int RunPortableExecutable(void* Image)
{
    IMAGE_DOS_HEADER* DOSHeader; // For NT DOS Header symbols
    IMAGE_NT_HEADERS* NtHeader; // For Nt Header objects & symbols
    IMAGE_SECTION_HEADER* SectionHeader;

    PROCESS_INFORMATION PI;
    STARTUPINFOA SI;

    CONTEXT* CTX;

    DWORD* ImageBase; // Base address of the image
    void* pImageBase; // Point to the image base

    int count;
    char CurrentFilePath[1024];

    DOSHeader = PIMAGE_DOS_HEADER(Image); // Initialize variable
    NtHeader = (PIMAGE_NT_HEADERS)((char*)DOSHeader + DOSHeader->e_lfanew);

    GetModuleFileNameA(0, CurrentFilePath, 1024); // Path to current executable
    if (DOSHeader->e_magic == IMAGE_DOS_SIGNATURE) // Check if image is a PE file
    {
        ZeroMemory(&PI, sizeof(PI)); // Null the memory
        ZeroMemory(&SI, sizeof(SI)); // Null the memory

        if (CreateProcessA(CurrentFilePath, NULL, NULL, NULL, FALSE,
        CREATE_SUSPENDED, NULL, NULL, &SI, &PI)) // Create a new instance of current
           //process in suspended state, for the new image.
        {
            // Allocate memory for the context.
            CTX = LPCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE));
            CTX->ContextFlags = CONTEXT_FULL; // Context is allocated

            if (GetThreadContext(PI.hThread, LPCONTEXT(CTX))) //if context is in thread
            {
                // Read instructions
                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);

                // Write the image to the process
                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);
                }
                WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&NtHeader->OptionalHeader.ImageBase), 4, 0);

                // Move address of entry point to the eax register
                CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint;
                SetThreadContext(PI.hThread, LPCONTEXT(CTX)); // Set the context
                ResumeThread(PI.hThread); //´Start the process/call main()

                return 0; // Operation was successful.
            }
        }
    }
}

int main()
{
    auto rawPEData = getFileContents("C:\\Users\\..\\simpleMessageBox.exe");
    auto runError = RunPortableExecutable(&rawPEData[0]);
    return runError;
}

Благодарю за любую помощь. Заранее спасибо.

...