我找到了修复导入表的工具here,但是如果没有在 c/c++ 中首先构建导入表,PE 是如何可执行的呢?
只是不要使用 CRT,也不要使用任何导入的函数。
#pragma comment(linker, "/entry:start")
int start()
{
return 42;
}
要使用 WinAPI 函数,请找到 kernel32 基址,解析它的导出目录并找到 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);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)