解析绑定导入表
一、綁定導入表的作用
有些windows程序,如notepad,為了提高加載速度,會直接把DLL中的函數地址寫入到IAT表,省去了加載時的計算。但是這樣會有兩個問題,第一,當DLL沒有占住ImageBase時,IAT中的地址就是錯的;第二,當鏈接的DLL被修改了,那IAT里寫的地址也是錯的。遇到這兩種情形之一,加載時就必須修復IAT了。
對于第二種情形,DLL是否被修改,是根據比較DLL的時間戳和綁定導入表中的記錄的DLL時間戳來判斷的,如果不一致,說明DLL被修改了。
加載程序時,操作系統根據導入表中的時間戳來判斷程序是否使用了綁定導入。當時間戳為0,表示不使用綁定導入表;當時間戳為0xFFFFFFFF,說明該程序使用綁定導入。
對于使用綁定導入的程序,綁定導入表存儲在最后一個節表后面,如圖示:
二、綁定導入表的結構
綁定導入表結構:
typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {DWORD TimeDateStamp;WORD OffsetModuleName;WORD NumberOfModuleForwarderRefs; // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows } IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR;TimeDateStamp 是時間戳,用于和DLL中的時間戳比較,判斷DLL是否已經發生變化;
OffsetModuleName 是當前模塊名距離第一個 _IMAGE_BOUND_IMPORT_DESCRIPTOR 的偏移。
NumberOfModuleForwarderRefs 是該模塊依賴的模塊數量;
依賴模塊結構:
typedef struct _IMAGE_BOUND_FORWARDER_REF {DWORD TimeDateStamp;WORD OffsetModuleName;WORD Reserved; } IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;除了第三個屬性保留,其他與 _IMAGE_BOUND_IMPORT_DESCRIPTOR 相同。
三、打印綁定導入表
// 打印綁定導入表 VOID PrintBoundImportTable(LPVOID pFileBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)(pDosHeader->e_lfanew + (DWORD)pDosHeader + 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER));PIMAGE_SECTION_HEADER pSectionHeader = \(PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);// 判斷方式一/*if (NULL == pOptionHeader->DataDirectory[11].VirtualAddress){printf("該程序綁定導入表為空\n");return;}*/// 判斷方式二PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + \RvaToFoa(pFileBuffer, pOptionHeader->DataDirectory[1].VirtualAddress));if (pImportTable->TimeDateStamp == 0){printf("該程序沒有綁定導入\n");return;}PIMAGE_BOUND_IMPORT_DESCRIPTOR pBoundImportTable = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + \RvaToFoa(pFileBuffer, pOptionHeader->DataDirectory[11].VirtualAddress));PIMAGE_BOUND_IMPORT_DESCRIPTOR pFirstBoundImportTable = pBoundImportTable; while (pBoundImportTable->TimeDateStamp || pBoundImportTable->OffsetModuleName || pBoundImportTable->NumberOfModuleForwarderRefs){// 打印時間戳、模塊名、依賴模塊數量puts("-------------------------------------------");printf("%s\n", (LPCSTR) ((DWORD)pFirstBoundImportTable + pBoundImportTable->OffsetModuleName));printf("TimeDateStamp:%x\n", pBoundImportTable->TimeDateStamp); printf("NumberOfModuleForwarderRefs:%d\n", pBoundImportTable->NumberOfModuleForwarderRefs);// 遍歷依賴模塊PIMAGE_BOUND_FORWARDER_REF pBFR = (PIMAGE_BOUND_FORWARDER_REF)((DWORD)pBoundImportTable + \sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR));for (int i = 0; i < pBoundImportTable->NumberOfModuleForwarderRefs; i++){printf("\t%s\n", (LPCSTR)((DWORD)pFirstBoundImportTable + pBFR[i].OffsetModuleName));printf("\tTimeDateStamp:%x\n", pBFR[i].TimeDateStamp);}pBoundImportTable = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pBoundImportTable + \sizeof(IMAGE_BOUND_IMPORT_DESCRIPTOR) + \pBoundImportTable->NumberOfModuleForwarderRefs * sizeof(IMAGE_BOUND_FORWARDER_REF));}}打印notepad的綁定導入表運行結果
四、完整代碼
https://blog.csdn.net/Kwansy/article/details/106234264
總結
- 上一篇: 解析导入表和IAT表
- 下一篇: 导入表注入原理和C语言实现