可移植可执行文件是否可以直接绝对引用代码段中的外部库,而不是通过 IAT

Can a portable executable have direct absolute references to external libraries in the code segment, not via IAT?

本文关键字:外部 IAT 段中 代码 是否 可执行文件 引用 可移植      更新时间:2023-10-16

如果我从C++代码调用 Win32 API 函数,如以下示例所示:

fSuccess = WriteFile( 
  hPipe,                  // pipe handle 
  lpvMessage,             // message 
  cbToWrite,              // message length 
  &cbWritten,             // bytes written 
  NULL);                  // not overlapped 

然后,Visual C++编译器会将这些调用转换为对数据段中导入地址表 (IAT) 的绝对引用。IAT 本身将包含包含该 Win32 API 函数的外部库的实际绝对地址。在上面的 WriteFile 函数示例中,此外部库kernel32.dll

如果我在运行时修改 IAT 中的一个条目,使其指向不同的库/函数,那么我的原始C++中对该函数的所有调用也将更改。我只希望其中一些人改变。或者使某个 Win32 API 函数甚至根本不出现在 IAT 中,而是由代码段直接引用。

我该怎么做?我是否可以以某种方式强制编译器在代码段中包含对外部库的直接绝对引用,而不是通过 IAT 的间接引用?

我只希望其中一些人改变。或者使某个 Win32 API 函数甚至根本不出现在 IAT 中,而是由代码段直接引用。

我该怎么做?

为此,您必须在运行时使用 LoadLibrary()/GetModuleHandle()GetProcAddress()(或编译器的延迟加载包装器,如果有的话)动态访问函数,而不是在编译时静态链接到函数。 例如:

typedef BOOL (WINAPI *LPFN_WRITEFILE)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
LPFN_WRITEFILE lpWriteFile = (LPFN_WRITEFILE) GetProcAddress(GetModuleHandle("kernel32"), "WriteFile");
fSuccess = lpWriteFile( 
  hPipe,                  // pipe handle 
  lpvMessage,             // message 
  cbToWrite,              // message length 
  &cbWritten,             // bytes written 
  NULL);