4

我在这里找到了一个修复导入表的工具,但是在 C/C++ 中首先构建的没有导入表的 PE 可执行文件如何?

4

2 回答 2

7

只是不要使用 CRT,不要使用任何导入的函数。

#pragma comment(linker, "/entry:start")
int start()
{
   return 42; 
}

要使用 WinAPI 函数,找到 kernel32 base,解析它的导出目录并找到 LoadLibrary() 函数(你应该已经有类似 GetProcAddress() 的东西来找到 LoadLibrary())

这可能看起来像这样:

// compile as console application, "release" configuration with /MT /GS-
#include <Windows.h>
#pragma comment(linker, "/entry:start")
void start()
{
    HMODULE kernel32base = *(HMODULE*)(*(DWORD*)(*(DWORD*)(*(DWORD*)(*(DWORD*)(__readfsdword(0x30) + 0x0C) + 0x14))) + 0x10);

    DWORD base = (DWORD)kernel32base;
    IMAGE_NT_HEADERS* pe = PIMAGE_NT_HEADERS(base + PIMAGE_DOS_HEADER(base)->e_lfanew);
    IMAGE_EXPORT_DIRECTORY* exportDir = PIMAGE_EXPORT_DIRECTORY(base + pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    DWORD* namePtr = (DWORD*)(base + exportDir->AddressOfNames);
    WORD* ordPtr = (WORD*)(base + exportDir->AddressOfNameOrdinals);
    for(; strcmp((const char*)(base + *namePtr), "GetProcAddress"); ++namePtr, ++ordPtr)
        ;
    DWORD funcRVA = *(DWORD*)(base + exportDir->AddressOfFunctions + *ordPtr * 4);

    typedef FARPROC (WINAPI *GetProcAddress_t)(HMODULE, const char*);
    GetProcAddress_t GetProcAddress = (GetProcAddress_t)(base + funcRVA);

    HANDLE (WINAPI *GetStdHandle)(DWORD);
    *(FARPROC*)&GetStdHandle = GetProcAddress(kernel32base, "GetStdHandle");

    HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);

    BOOL (WINAPI *WriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
    *(FARPROC*)&WriteFile = GetProcAddress(kernel32base, "WriteFile");

    const char* greeting = "Hello world!\n";

    DWORD written;
    WriteFile(stdout, greeting, strlen(greeting), &written, NULL);
}
于 2010-10-11T05:24:28.100 回答
0

要从现有的可执行模块中删除导入,您应该解析它的导入目录以获取其导入,然后生成并添加代码以获取这些导入,然后删除导入目录。

于 2010-10-11T05:30:27.087 回答