C 挂接IAT地址不正确
我正在尝试查找在测试应用程序中导入的wglGetProcAddress(OpenGl32.dll)的条目。出于某种原因,名为“wglGetProcAddress”的导入确实指向通过调用Opengl32.dll上的GetModuleHandle和GetProcAddress返回的相同函数 可执行文件已加载到内存中,是一个线程当前挂起的进程。以下代码正确读取该可执行文件导入的模块名称及其函数。因此,IAT不应包含RVA,因为它已加载C 挂接IAT地址不正确,c,hook,portable-executable,C,Hook,Portable Executable,我正在尝试查找在测试应用程序中导入的wglGetProcAddress(OpenGl32.dll)的条目。出于某种原因,名为“wglGetProcAddress”的导入确实指向通过调用Opengl32.dll上的GetModuleHandle和GetProcAddress返回的相同函数 可执行文件已加载到内存中,是一个线程当前挂起的进程。以下代码正确读取该可执行文件导入的模块名称及其函数。因此,IAT不应包含RVA,因为它已加载 HMODULE h = GetModuleHandle("OPEN
HMODULE h = GetModuleHandle("OPENGL32.dll");
DWORD expect_addr = (DWORD)GetProcAddress(h, "wglGetProcAddress");
PIMAGE_IMPORT_DESCRIPTOR import_desc = (PIMAGE_IMPORT_DESCRIPTOR)(pmem + import_dir);
while (import_desc->Name)
{
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(pmem + import_desc->OriginalFirstThunk);
while (thunk->u1.Function)
{
PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)(pmem + thunk->u1.AddressOfData);
printf("%s 0x%X\n", import->Name, thunk->u1.Function);
if ((DWORD)expect_addr == (DWORD)thunk->u1.Function)
{
printf("Found wglGetProcAddress\n");
}
else if (!strcmp((const char*)import->Name, "wglGetProcAddress"))
{
printf("Found wglGetProcAddress's import, but the function has a different value.\n");
}
++thunk;
}
++import_desc;
}
该原始值的GetProcAddress返回地址60XXC245,其中XX不同,但thunk->u1.Function始终返回0xA46D8。thunk->u1(函数、数据地址、序号和转发器字符串)中的所有内容都具有
相同的值。导入描述符和导入的名称正确无误。有人看到我遗漏了什么吗
编辑:
我正在尝试其他方法:我正在扫描pmem(内存中可执行文件的图像),查找我期望的IAT条目,但它也找不到:
HMODULE h = GetModuleHandle("OPENGL32.dll");
DWORD expect_addr = (DWORD)GetProcAddress(h, "wglGetProcAddress");
printf("Looking for 0x%X\n", expect_addr);
for (int i = 0; i < pmem_size - sizeof(DWORD); i++)
{
if (*(DWORD*)(pmem + i) == expect_addr)
{
printf("0x%X at 0x%X\n", *(DWORD*)(pmem + i), i);
}
}
hmoduleh=GetModuleHandle(“OPENGL32.dll”);
DWORD expect_addr=(DWORD)GetProcAddress(h,“wglGetProcAddress”);
printf(“查找0x%X\n”,预期地址);
对于(int i=0;i
已解决:我没有意识到这一点,但使用CREATE_SUSPENDED调用CreateProcess会阻止windows加载程序使用实际地址填充FIRSThunk。如果我让进程运行一秒钟,然后挂起线程,它就可以很好地钩住IAT地址。现在我必须寻找一种方法来解决这个问题。
u1。函数
表示与图像按名称导入的条目(如果设置了图像顺序标志
位,则表示顺序条目)的相对偏移量。这就是它与GetProcAddress
中的值不匹配的原因,因为它不是函数的地址,而是函数导入项的地址
当您找到与您的函数匹配的thunk时,您也需要使用此方法查找链接器更改的虚拟化地址,形成另一个thunk列表。更改代码以实现此目的会导致:
while (import_desc->Name)
{
PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((DWORD)GetModuleHandle(NULL) + import_desc->OriginalFirstThunk);
int i = 0;
while (thunk->u1.Function)
{
PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)((DWORD)GetModuleHandle(NULL) + thunk->u1.AddressOfData);
void** p = (void**)((DWORD)GetModuleHandle(NULL) + import_desc->FirstThunk);
printf("%s 0x%X\n", import->Name, p[i]);//thunk->u1.Function);
if ((DWORD)expect_addr == (DWORD)p[i])
{
printf("Found wglGetProcAddress\n");
}
else if (!strcmp((const char*)import->Name, "wglGetProcAddress"))
{
printf("Found wglGetProcAddress's import, but the function has a different value.\n");
}
++thunk;
}
++import_desc;
}
为了获得IAT条目,我做了一些不同的事情:
inline const void** GetImportAddress(HMODULE hModule, IMAGE_IMPORT_DESCRIPTOR* pTable, size_t nThunk)
{
const void** pAddressBlock = (const void**)((DWORD)hModule + pTable->FirstThunk);
return &pAddressBlock[nThunk];
}
const void** GetImport(HMODULE hModule, const char* szDll, const char* szFunction)
{
const char* szDllName = NULL;
IMAGE_IMPORT_DESCRIPTOR* pTable = GetImportDescriptor(hModule);
while(pTable->Characteristics != 0 && (szDllName = GetImportTableName(hModule,pTable)) != NULL)
{
if(!lstrcmpiA(szDll,szDllName))
{
IMAGE_THUNK_DATA* pThunkData = GetThunk(hModule,pTable);
if(pThunkData != NULL)
{
size_t nThunk = 0;
while(pThunkData->u1.AddressOfData != 0)
{
if(pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
if(IMAGE_ORDINAL32(pThunkData->u1.Ordinal) == (DWORD)szFunction)
return GetImportAddress(hModule,pTable,nThunk);
}
else
{
IMAGE_IMPORT_BY_NAME* pImport = GetImport(hModule,pThunkData);
if(!lstrcmpA(szFunction,(const char*)pImport->Name))
return GetImportAddress(hModule,pTable,nThunk);
}
nThunk++;
pThunkData++;
}
}
}
pTable++;
}
return NULL;
}
它与GetProcAddress中的值不匹配。如何找到地址块?@Dmi:我添加了我在许多项目中使用的代码,用于执行IAT钩子和查找,应该可以提供您正在查找的数据块,但是如果我使用const void**addr=GetImportAddress(pmem,n),其中n是数据块索引,*addr再次给我0xA46D8。@Dmi:a用您的代码的固定版本重新编写它一点,该版本可以正常工作(它从您遇到的相同问题开始)。您可以从FirstOriginalThunk打印IAT偏移量,而不是从FirstThunk打印虚拟化地址。哦,我没有意识到这一点,但使用CREATE_SUSPENDED调用CreateProcess会阻止windows加载程序使用实际地址填充FirstThunk/