type
status
date
slug
summary
tags
category
icon
password
When generating assembly code for a function call, the C/C++ compiler needs to consider whether the function is part of the current executable or an external DLL.
- Function within the same executable: to call a function from the same executable or DLL, the compiler can determine its location at compile time. Therefore, it generates a direct call instruction with an immediate operand. This operand is a relative or absolute address depending on the context (hardcode E8 or FF15).
For example, a call to a function within the same module might look like:
- Function from a DLL: When the function is part of a DLL, the compiler can't determine the function's address at compile time because the DLL is loaded into memory by the PE loader at runtime, and its base address can change due to Address Space Layout Randomization (ASLR). In this case, the compiler generates an indirect call instruction through a memory operand.
This memory location is an entry in the Import Address Table (IAT) that the loader fills in with the function's actual address when it loads the DLL into memory. The resulting assembly code might look something like:
In this post, we will ignore C++ virtual functions. For these so-called virtual functions, the compiler uses an indirect calling method similar to the IAT table. This involves concepts such as virtual tables and virtual pointers. we will cover this topic in future blogs.
Now, let’s take a deeper look at the IAT table, and how it works closely with the import & export table to get the job done.
how IAT works?
IAT stands for "Import Address Table". The IAT is used for storing function addresses that are imported from DLLs (Dynamically Linked Libraries).
Before a program is run (at load-time), the IAT is filled with placeholder values, typically Relative Virtual Addresses (RVAs), which point to entries in the Import Lookup Table (ILT). Each entry in the ILT contains the name or ordinal of a function in a specific DLL. At this stage, the IAT does not contain the actual memory addresses of the functions because the DLLs have not been loaded into memory yet.
An Windows program only have one executable file, and that executable file usually uses multiple DLLs. When a program is loaded into memory (during runtime), it goes through the IAT table for each of these EXE/DLLs, and replaces these placeholder values with the actual memory addresses of the imported functions. The loader determines where each DLL will reside in memory, loads the DLLs, use the corresponding DLL’s export table to find the memory addresses of the functions being imported, and then writes these addresses into the IAT.
So, before runtime, the IAT contains relative addresses pointing to the ILT. During runtime, the IAT contains the actual memory addresses of the functions being imported from DLLs.
- 作者:Zack Yang
- 链接:https://zackyang.blog/article/iat-table
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章
C++ Virtual Table Implementation Details
Injecting a DLL into a Windows Executable By Modifying PE Import Table
Injecting a Simple Message Box at the Startup of a Windows Application
How C/C++ Compiler Generate Assembly Code For Switch Statement
How C/C++ Compiler Generate x86 Assembly Code For Large Return Values
C/C++ Runtime Memory Layout