2012-03-14 16 views
5

Estoy tratando de localizar la entrada de wglGetProcAddress (OpenGl32.dll) importada en una aplicación de prueba. Por algún motivo, la importación cuyo nombre es "wglGetProcAddress" apunta a la misma función devuelta al llamar a GetModuleHandle y GetProcAddress en Opengl32.dll.Enlazar la dirección IAT es incorrecta

El archivo ejecutable se ha cargado en la memoria y es un proceso con su hilo actualmente suspendido. El siguiente código lee correctamente los nombres de los módulos y sus funciones importadas por ese ejecutable. Por lo tanto, el IAT no debe contener RVA desde que se ha cargado.

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 a partir de ese valor original devuelve la dirección 60XXC245 donde XX es variable, pero thunk-> u1.Function siempre devuelve 0xA46D8. Todo en thunk-> u1 (Function, AddressOfData, Ordinal y ForwarderString) tiene el mismo valor. Los nombres de los descriptores de importación y las importaciones son correctos. ¿Alguien ve lo que me estoy perdiendo?

Editar: Estoy intentando otra cosa: estoy escaneando pmem (imagen del ejecutable en la memoria) para lo que espero es la entrada de IAT, pero no encuentra que:

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

SOLUCIONADO: No me di cuenta, pero llamar CreateProcess con CREATE_SUSPENDED impide que el cargador de Windows llene FirstThunk con las direcciones reales. Si dejo que el proceso se ejecute por un segundo y luego suspender el hilo, engancha perfectamente la dirección IAT. Ahora tengo que ir a buscar una forma de arreglar eso.

Respuesta

3

u1.Function representa el desplazamiento relativo a la entrada IMAGE_IMPORT_BY_NAME (o la entrada ordinal si se establece el bit IMAGE_ORDINAL_FLAG). es por eso que no coincide con el valor de GetProcAddress, porque no es la dirección de la función, es la dirección de la entrada de importación.

Cuando haya encontrado el thunk que concuerda con su función, necesita usar esto también buscar la dirección virtualizada alterada por el enlazador, formar el otra lista de thunk. alterando su código por lo que este 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; 
} 

Para conseguir las entradas IAT, hago las cosas un poco diferente:

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

no coincide con el valor de GetProcAddress. ¿Cómo encontraría el bloque de direcciones? – Dmi

+0

@Dmi: Agregué el código que uso en muchos de mis proyectos para hacer búsquedas y búsquedas de IAT, debería darle lo que está buscando – Necrolis

+0

Gracias, pero si uso const void ** addr = GetImportAddress (pmem, n) donde n es el índice de fragmento, * addr me da 0xA46D8 nuevamente. – Dmi

Cuestiones relacionadas