Неверный адрес IAT - PullRequest
       14

Неверный адрес IAT

5 голосов
/ 15 марта 2012

Я пытаюсь найти запись для wglGetProcAddress (OpenGl32.dll), импортированного в тестовое приложение. По какой-то причине импорт с именем «wglGetProcAddress» указывает на ту же функцию, возвращаемую путем вызова GetModuleHandle и GetProcAddress для Opengl32.dll.

Исполняемый файл загружен в память и является процессом, поток которого в настоящий момент приостановлен. Следующий код правильно читает имена модулей и их функции, импортированные этим исполняемым файлом. Следовательно, 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 из этого исходного значения возвращает адрес 60XXC245, где XX изменяется, но thunk-> u1.Function всегда возвращает 0xA46D8. Все в thunk-> u1 (Function, AddressOfData, Ordinal и ForwarderString) имеет такое же значение. Имена дескрипторов импорта и импорта правильные. Кто-нибудь видит, чего мне не хватает?

Edit: Я пытаюсь что-то еще: я сканирую 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);
    }
}

решено: Я не понял этого, но вызов CreateProcess с помощью CREATE_SUSPENDED не позволяет загрузчику Windows заполнить FirstThunk действительными адресами. Если я позволю процессу запуститься на секунду, а затем приостановить поток, он отлично перехватит адрес IAT. Теперь мне нужно искать способ исправить это.

1 Ответ

3 голосов
/ 15 марта 2012

u1.Function представляет относительное смещение записи IMAGE_IMPORT_BY_NAME (или порядковой записи, если установлен бит IMAGE_ORDINAL_FLAG). вот почему он не соответствует значению GetProcAddress, потому что это не адрес функции, а адрес функции запись импорта .

Когда вы нашли, что thunk соответствует вашей функции, вам нужно использовать этот поиск виртуального адреса, измененного компоновщиком, формируя список other 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;
}
...