Patching IAT

Introduction

When building Position Independent Code (PIC), the term patching refers to fixing import addresses when the PE is loaded into memory based on their RVA and the Image base address of the PE when it's loaded into a memory buffer.


BOOL FixImportAddressTable(IN PIMAGE_DATA_DIRECTORY pEntryImportDataDir, IN PBYTE pPeBaseAddress) {
    for (SIZE_T i =0; i < pEntryImportDataDir->Size; i+=sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
        PIMAGE_IMPORT_DESCRIPTOR currentImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(pPeBaseAddress + pEntryImportDataDir->VirtualAddress + i);

        if (currentImportDescriptor->FirstThunk == 0 && currentImportDescriptor->OriginalFirstThunk == 0)
            break;

        LPSTR cDllName = (LPSTR)(pPeBaseAddress + currentImportDescriptor->Name);
        HANDLE hModule = NULL;

        // See if we can load DLL
        hModule = LoadLibraryA(cDllName);
        if (hModule == NULL) {
            wprintf(L"Failed to Load Library %s GetLastError: %d", cDllName, GetLastError());
            return FALSE;
        }

        // Iterate through imported functions via IAT & INT
        SIZE_T     ImgThunkSize                    = 0x00;    // Used to move to the next function (iterating through the IAT and INT)
        ULONG_PTR pFuncAddress = 0;
        PIMAGE_IMPORT_BY_NAME pImgImportByName = NULL;

        while (TRUE) {

            PIMAGE_THUNK_DATA pFirstThunk = (PIMAGE_THUNK_DATA)(pPeBaseAddress + currentImportDescriptor->FirstThunk + ImgThunkSize);
            PIMAGE_THUNK_DATA pOriginalFirstThunk = (PIMAGE_THUNK_DATA)(pPeBaseAddress + currentImportDescriptor->OriginalFirstThunk + ImgThunkSize);

            if (pOriginalFirstThunk->u1.Function == 0 && pFirstThunk->u1.Function == 0) {
                break;
            }

            if (IMAGE_SNAP_BY_ORDINAL(pOriginalFirstThunk->u1.Ordinal)) {
                if ( !(pFuncAddress = (ULONG_PTR)GetProcAddress(hModule, (LPCSTR)IMAGE_ORDINAL(pOriginalFirstThunk->u1.Ordinal))) ) {
                    printf("[!] Could Not Import !%s#%d \n", cDllName, (int)pOriginalFirstThunk->u1.Ordinal);
                    return FALSE;
                }
            }
                // Import function by name
            else {
                pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pPeBaseAddress + pOriginalFirstThunk->u1.AddressOfData);
                if ( !(pFuncAddress = (ULONG_PTR)GetProcAddress(hModule, pImgImportByName->Name)) ) {
                    printf("[!] Could Not Import !%s.%s \n", cDllName, pImgImportByName->Name);
                    return FALSE;
                }
            }

            // Install the function address in the IAT
            pFirstThunk->u1.Function = (ULONGLONG)pFuncAddress;

            ImgThunkSize += sizeof(IMAGE_THUNK_DATA);

        }

    }
    return TRUE;
}

Last updated