2012-03-14 73 views
5

我試圖找到wglGetProcAddress(OpenGl32.dll)在測試應用程序中導入的條目。出於某種原因,名稱爲「wglGetProcAddress」的導入確實指向通過在Opengl32.dll上調用GetModuleHandle和GetProcAddress返回的相同函數。掛鉤IAT地址不正確

可執行文件已加載到內存中,並且是其線程當前暫掛的進程。以下代碼正確讀取由該可執行文件導入的名稱模塊及其功能。因此,IAT不應該包含RVA,因爲它已經被加載。從該原始值

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的返回,其中XX改變地址60XXC245,但thunk-> u1.Function總是返回0xA46D8。 thunk-> u1(Function,AddressOfData,Ordinal和ForwarderString)中的所有內容都具有相同的值 。導入描述符和導入的名稱正確。有沒有人看到我失蹤?

編輯: 我想別的東西:我對我的期望是IAT入口掃描PMEM(在內存中的可執行文件的圖像),但它並沒有找到,要麼:

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); 
    } 
} 

解決方案:我沒有意識到它,但調用CreateProcess與CREATE_SUSPENDED可以防止窗口加載器填充FirstThunk實際地址。如果我讓進程運行一秒鐘然後暫停線程,它將IAT地址完全掛鉤。現在我必須去尋找解決方法。

回答

3

u1.Function表示與IMAGE_IMPORT_BY_NAME條目(如果設置了IMAGE_ORDINAL_FLAG位,則序數條目)的相對偏移量。這就是爲什麼它與GetProcAddress的值不匹配,因爲它不是函數的地址,它的函數地址爲,導入項目爲

當你發現的thunk符合功能,你需要使用這個太查找鏈接器改變了虛擬地址,形成其他 thunk的列表。改變你的代碼,以便它不這樣yeilds:

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; 
} 
+0

它不會從GetProcAddress的價值相匹配。我如何找到地址塊? – Dmi 2012-03-14 20:45:04

+0

@Dmi:我添加了我在許多項目中使用的代碼來完成IAT鉤子和查找,應該給你你正在尋找的 – Necrolis 2012-03-14 20:54:36

+0

謝謝,但是如果我使用const void ** addr = GetImportAddress(pmem,n)where n是塊索引,* addr再次給我0xA46D8。 – Dmi 2012-03-14 21:02:56