遇事不决,OPENAI
查看导出表信息
E:\IDE\VisualStudio2019\community>dumpbin /exports C:\Windows\System32\version.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30145.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Windows\System32\version.dll
File Type: DLL
Section contains the following exports for VERSION.dll
00000000 characteristics
927B71E6 time date stamp
0.00 version
1 ordinal base
17 number of functions
17 number of names
ordinal hint RVA name
1 0 00001080 GetFileVersionInfoA
2 1 00002190 GetFileVersionInfoByHandle
3 2 00001DF0 GetFileVersionInfoExA
4 3 00001040 GetFileVersionInfoExW
5 4 00001010 GetFileVersionInfoSizeA
6 5 00001E00 GetFileVersionInfoSizeExA
7 6 00001050 GetFileVersionInfoSizeExW
8 7 00001060 GetFileVersionInfoSizeW
9 8 00001070 GetFileVersionInfoW
10 9 00001E10 VerFindFileA
11 A 00002360 VerFindFileW
12 B 00001E20 VerInstallFileA
13 C 00002F80 VerInstallFileW
14 D VerLanguageNameA (forwarded to KERNEL32.VerLanguageNameA)
15 E VerLanguageNameW (forwarded to KERNEL32.VerLanguageNameW)
16 F 00001020 VerQueryValueA
17 10 00001030 VerQueryValueW
Summary
1000 .data
1000 .pdata
2000 .rdata
1000 .reloc
1000 .rsrc
3000 .text
可以发现verson.dll有2个转发函数
VerLanguageNameA (forwarded to KERNEL32.VerLanguageNameA)
VerLanguageNameW (forwarded to KERNEL32.VerLanguageNameW)
导出表结构
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
DWORD AddressOfFunctions; // RVA from base of image
DWORD AddressOfNames; // RVA from base of image
DWORD AddressOfNameOrdinals; // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
关键判断:
如果functionRVA 位于导出表地址范围内(IMAGE_DATA_DIRECTORY),则该地址指向格式为 <MODULE>.<ExportName> 的转发字符串,
if (arFuncs[i] >= pExportEntry->VirtualAddress && arFuncs[i] < pExportEntry->VirtualAddress+pExportEntry->Size)
{
//function address is RVA to Forwarder String; e.g. NTDLL.RtlDecodePointer
}
else
{
//function address is RVA to actual code within current module
}
chatgpt 给的代码
第一次并没有给出正确代码,需要去不断纠正,比如指针运算的错误……
#include <windows.h>
#include <iostream>
#include <string>
FARPROC GetExportFunction(HMODULE Module, LPCSTR Name) {
if (Module == NULL) {
std::cerr << "Invalid module handle" << std::endl;
return NULL;
}
if (Name == NULL) {
std::cerr << "Invalid function name" << std::endl;
return NULL;
}
// 获取导出函数地址
PIMAGE_DOS_HEADER pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(Module);
PIMAGE_NT_HEADERS pNTHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<BYTE*>(Module) + pDosHeader->e_lfanew);
PIMAGE_EXPORT_DIRECTORY pExportDir = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<BYTE*>(Module) + pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* functions = reinterpret_cast<DWORD*>(reinterpret_cast<BYTE*>(Module) + pExportDir->AddressOfFunctions);
WORD* ordinals = reinterpret_cast<WORD*>(reinterpret_cast<BYTE*>(Module) + pExportDir->AddressOfNameOrdinals);
DWORD* names = reinterpret_cast<DWORD*>(reinterpret_cast<BYTE*>(Module) + pExportDir->AddressOfNames);
for (DWORD i = 0; i < pExportDir->NumberOfNames; ++i) {
const char* functionName = reinterpret_cast<const char*>(reinterpret_cast<BYTE*>(Module) + names[i]);
if (strcmp(functionName, Name) == 0) {
// 找到导出函数
DWORD functionRVA = functions[ordinals[i]];
if (functionRVA >= pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress &&
functionRVA < pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
// 转发函数
const char* forwarderString = reinterpret_cast<const char*>(reinterpret_cast<BYTE*>(Module) + functionRVA);
// 解析转发字符串,加载相应的 DLL
std::string strForwarder(forwarderString);
size_t dotPos = strForwarder.find('.');
if (dotPos != std::string::npos) {
std::string dllName = strForwarder.substr(0, dotPos);
std::string functionName = strForwarder.substr(dotPos + 1);
HMODULE hForwardModule = LoadLibraryA(dllName.c_str());
if (hForwardModule != NULL) {
// 递归调用 GetExportFunction 获取导出函数地址
FARPROC forwardFunction = GetExportFunction(hForwardModule, functionName.c_str());
FreeLibrary(hForwardModule); // 加载后释放模块
return forwardFunction;
} else {
std::cerr << "Failed to load the forwarded DLL: " << dllName << std::endl;
return NULL;
}
} else {
std::cerr << "Invalid forwarder string: " << forwarderString << std::endl;
return NULL;
}
} else {
// 非转发函数
return reinterpret_cast<FARPROC>(reinterpret_cast<BYTE*>(Module) + functionRVA);
}
}
}
return NULL;
}
int main() {
// 使用示例
HMODULE hModule = LoadLibraryA("YourLibrary.dll");
if (hModule != NULL) {
FARPROC functionAddress = GetExportFunction(hModule, "YourFunctionName");
if (functionAddress != NULL) {
// 使用获取的函数地址
// 例如:reinterpret_cast<YourFunctionType>(functionAddress)(arguments);
} else {
std::cerr << "Failed to get the function address" << std::endl;
}
FreeLibrary(hModule);
} else {
std::cerr << "Failed to load the library" << std::endl;
}
return 0;
}
更多信息:
https://ferreirasc.github.io/PE-Export-Address-Table/
https://www.cnblogs.com/revercc/p/16703647.html
https://stackoverflow.com/questions/44279216/how-can-i-resolve-the-forwarded-api-from-the-iat-on-pe
P.S.
标签:cast,--,PE,Module,reinterpret,EXPORT,转发,DIRECTORY,DWORD From: https://www.cnblogs.com/DirWang/p/17826582.htmlAI是大势所趋,"滚滚长江东逝水,浪花淘尽英雄"