我想知道如何确定 PE 标头中的导入函数是否是按顺序而不是按名称导入的,因为我遇到了执行此操作的可执行文件。这是按顺序导入所有函数的 DLL,除了一个(来自WS2_32.dll):
这就是我为导入所做的工作:
- 读取 PE 标头。
- 遍历数据目录并找到
IMAGE_DIRECTORY_ENTRY_IMPORT. 一旦
IMAGE_DIRECTORY_ENTRY_IMPORT找到,循环IMAGE_IMPORT_DESCRIPTORS。在每个 上
IMAGE_IMPORT_DESCRIPTORS,提取所有函数。
这是我提取函数的方法(仅适用于按名称导入的函数):
void extractFunctions(IMAGE_IMPORT_DESCRIPTOR dll, uintptr_t sectionStartAddrRaw) {
uintptr_t selectedFunctionImport = dll.Characteristics + sectionStartAddrRaw;
uintptr_t selectedFunctionImportIAT = dll.FirstThunk + sectionStartAddrRaw;
while (true) {
IMAGE_THUNK_DATA thunkPtrToImportByName = *(IMAGE_THUNK_DATA*)selectedFunctionImport;
selectedFunctionImport += sizeof(IMAGE_THUNK_DATA); //Next loop we'll loop over to the next IMAGE_THUNK_DATA.
if (thunkPtrToImportByName.u1.Function == NULL) { //Check if we need to exit the looping since there are no more functions to import.
break;
}
IMAGE_IMPORT_BY_NAME* functionImport = (IMAGE_IMPORT_BY_NAME*)(thunkPtrToImportByName.u1.Function + sectionStartAddrRaw);
Function function;
function.name = std::string(functionImport->Name); //Access violation here if the function needs to be imported by ordinal, instead of by name.
function.locationInIAT = selectedFunctionImportIAT;
function.locationInOriginalIAT = selectedFunctionImportIAT - sectionStartAddrRaw + header.OptionalHeader.ImageBase;
selectedFunctionImportIAT += sizeof(IMAGE_THUNK_DATA);
dlls.back().functions.push_back(function); //We assume that IMAGE_IMPORT_DESCRIPTOR dll is the last one in the dlls vector.]
}
}
我注意到ExeinfoPE按名称导入的每个函数 Hint/Ordinal都是0. 但是,在我的代码functionImport->Hint中始终设置为某些内容,无论函数是按名称还是顺序导入。
在IMAGE_IMPORT_DESCRIPTOR无法对里面是否该功能的信息IMAGE_IMPORT_DESCRIPTOR是按序号或名称导入,因为功能之一是通过名称进口,所有的人都按顺序导入。所以,我在这里完全没有想法。
以下是我正在使用的数据结构供您参考,因此无需谷歌:
typedef struct _IMAGE_THUNK_DATA {
union {
uint32_t* Function; // address of imported function
uint32_t Ordinal; // ordinal value of function
PIMAGE_IMPORT_BY_NAME AddressOfData; // RVA of imported name
DWORD ForwarderStringl // RVA to forwarder string
} u1;
} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; /* 0 for terminating null import descriptor */
DWORD OriginalFirstThunk; /* RVA to original unbound IAT */
} DUMMYUNIONNAME;
DWORD TimeDateStamp; /* 0 if not bound,
* -1 if bound, and real date\time stamp
* in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
* (new BIND)
* otherwise date/time stamp of DLL bound to
* (Old BIND)
*/
DWORD ForwarderChain; /* -1 if no forwarders */
DWORD Name;
/* RVA to IAT (if bound this IAT has actual addresses) */
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;
