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

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

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

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

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

如果我在 运行 时修改 IAT 中的一个条目,使其指向不同的 library/function,那么在我的原始 C++ 中对该函数的所有调用也会发生变化。我只想改变其中的一些。或者让某个Win32API函数根本不出现在IAT中,而是直接被代码段引用

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

I would like only some of them to change. Or to make it such that a certain Win32 API function does not even appear in the IAT at all, but it is directly referenced by the code segment.

How can I do that?

为此,您必须在 运行 时使用 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);