Загрузка двоичного файла Go в память и запуск с C

#c #go #executable #security

# #c #Вперед #исполняемый файл #Безопасность

Вопрос:

Я провожу некоторые независимые исследования в области кибербезопасности, пытаясь прочитать, загрузить исполняемый файл Windows в память и запустить его из памяти с использованием C . Используя некоторые видео и другие сообщения стека, я смог заставить его работать с очень простым приложением, которое я создал с использованием C , которое просто показывает одно всплывающее окно, и оно работает отлично. Тем не менее, я хочу выполнить тот же процесс, используя двоичный файл Golang, но всякий раз, когда я создаю простую программу Golang и пытаюсь использовать ее с помощью приведенного ниже кода, я получаю сообщение об ошибке приложения: «Приложению не удалось запустить правильно (0xc0000005). Нажмите OK, чтобы закрыть приложение «.

Большая часть моего опыта программирования связана с Golang и Python, поэтому этот код на C для меня довольно новый для этого последнего проекта по кибербезопасности, поэтому я был бы признателен за любую помощь!

Это мой код на C (код Go — это всего лишь один fmt.Println файл, встроенный в exe)

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

    PROCESS_INFORMATION PI;
    STARTUPINFOA SI;

    CONTEXT* CTX;

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

    int count;

    char CurrentFilePath[1024];

    DOSHeader = PIMAGE_DOS_HEADER(Image); // Initialize variable
    NtHeader = PIMAGE_NT_HEADERS(DWORD(Image)   DOSHeader->e_lfanew); // Initialize

    GetModuleFileNameA(0, CurrentFilePath, 1024); // Path to current executable

        if (NtHeader->Signature == IMAGE_NT_SIGNATURE) // Check if image is a PE file
        {
            ZeroMemory(amp;PI, sizeof(PI)); // Null the memory
            ZeroMemory(amp;SI, sizeof(SI)); // Null the memory

            if (CreateProcessA(CurrentFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, amp;SI, amp;PI)) //Create new instance of process in suspended state (for new image)
            {
                CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE)); // Allocate context memory
                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(amp;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(amp;NtHeader->OptionalHeader.ImageBase), 4, 0);

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

                    return 0;
                }
            }
        }
}

// Get the size of a file
long getFileSize(FILE* file)
{
    long lCurPos, lEndPos;
    lCurPos = ftell(file);
    fseek(file, 0, 2);
    lEndPos = ftell(file);
    fseek(file, lCurPos, 0);
    return lEndPos;
}

int main()
{
    const char* filePath = "printtest.exe";
    BYTE* fileBuf;            // Pointer to our buffered data
    FILE* file = NULL;        // File pointer

    if ((file = fopen(filePath, "rb")) == NULL)
        std::cout << "Could not open specified file" << std::endl;
    else
        std::cout << "File opened successfully" << std::endl;

    long fileSize = getFileSize(file);

    fileBuf = new BYTE[fileSize];

    fread(fileBuf, fileSize, 1, file);
    fclose(file);   // Almost forgot this 

    // This just logs some characters to verify it read in properly
    for (int i = 0; i < 300; i  )
        std::cout << fileBuf[i];
        //printf("%X ", fileBuf[i]);

    RunPortableExecutable(fileBuf);

    std::cin.get();
    delete[]fileBuf;

}