- IAT:导入地址表
// PE文件解析.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <Windows.h>//函数向前声明 DWORD RvaToFoa(DWORD dwRva, const char* szBuffer); char* LoadFile(const char* szFilePath); void LoadDosHeader(const char* szBuffer); void LoadFileHeader(const char* szBuffer); void LoadOptionalHeader(const char* szBuffer); void LoadDirectories(const char*szBuffer); void LoadImportTable(const char* szBuffer); void LoadSectionHeader(const char* szBuffer);//数据目录表名称 const char* DataDirName[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]{"EXPORT""IMPORT""RESOURCE","EXCEPTION","SECURITY","BASERELOC","DEBUG","COPYRIGHT","ARCHITECTURE","GLOBALPTR","TLS","LOAD_CONFIG","BOUND_IMPORT","IAT","DELAY_IMPORT","COM_DESCRIPTOR" };int main() {const char* FileBuffer = LoadFile("C:\\Users\\lenovo\\Desktop\\目标程序.exe");printf("Dos Header:\r\n:");LoadDosHeader(FileBuffer);printf("File Header:");LoadFileHeader(FileBuffer);printf("OptionalHeader Header:");LoadOptionalHeader(FileBuffer);printf("Directories:\r\n");LoadDirectories(FileBuffer);printf("Sections Header:");LoadSectionHeader(FileBuffer);system("pause");return 0; }DWORD RvaToFoa(DWORD dwRva, const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&pNtHeaders->FileHeader;PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);if (dwRva < pFileHeader->SizeOfOptionalHeader) {return dwRva;}for (int i = 0; i < pFileHeader->NumberOfSections; i++) {if (dwRva > pSectionHeader->VirtualAddress&&dwRva <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData) {return dwRva - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}} }char* LoadFile(const char* szFilePath) {HANDLE hFile = CreateFileA(szFilePath, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE) {return FALSE;}DWORD dwFileSize = GetFileSize(hFile, NULL);char* szBuffer = new char[dwFileSize];memset(szBuffer, 0, dwFileSize);DWORD dwReadSize = 0;BOOL bRet = ReadFile(hFile, szBuffer, dwFileSize, &dwReadSize, NULL);if (bRet) {return szBuffer;}else {return NULL;} }void LoadDosHeader(const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;printf("Dos Tag:", pDosHeader->e_magic);printf("PE Headers offset:%X\r\n", pDosHeader->e_lfanew); }void LoadFileHeader(const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);printf("PE Tag:", pNtHeaders->Signature);PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&pNtHeaders->FileHeader;printf("区段数目:%08X\t\n", pFileHeader->NumberOfSections);printf("日期时间标志:%08X\t\n", pFileHeader->TimeDateStamp);printf("可选PE头大小:%08X\t\n", pFileHeader->SizeOfOptionalHeader);printf("特征值:%08X\t\n", pFileHeader->Characteristics); }void LoadOptionalHeader(const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;printf("入口点:%08X\t\n", pOptionalHeader->AddressOfEntryPoint);printf("镜像地址:%08X\t\n", pOptionalHeader->ImageBase);printf("镜像大小:%08X\t\n", pOptionalHeader->SizeOfImage);printf("代码基址:%08X\t\n", pOptionalHeader->BaseOfCode);printf("内存对齐:%08X\t\n", pOptionalHeader->SectionAlignment);printf("文件对齐:%08X\t\n", pOptionalHeader->FileAlignment);printf("标志:%08X\t\n", pOptionalHeader->Magic);printf("子系统:%08X\t\n", pOptionalHeader->Subsystem);printf("部首大小:%08X\t\n", pOptionalHeader->SizeOfHeaders);printf("校验和:%08X\t\n", pOptionalHeader->CheckSum);printf("数据目录表的个数:%08X\t\n", pOptionalHeader->NumberOfRvaAndSizes); }void LoadDirectories(const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {printf("Name:%s\r\n", DataDirName[i]);printf("VirtualAddress:0x%X\r\n", pOptionalHeader->DataDirectory[i].VirtualAddress);printf("Size:0x%X\r\n\r\n",pOptionalHeader->DataDirectory[i].Size);} }void LoadImportTable(const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;PIMAGE_DATA_DIRECTORY pImportDir = pOptionalHeader->DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToFoa(pImportDir->VirtualAddress, szBuffer) + szBuffer);while (pImport->Name != NULL) {char* szModuleName = (char*)(RvaToFoa(pImport->Name, szBuffer) + szBuffer);printf("模块名称:%s\r\n", szModuleName);printf("日期时间标志:%08X\r\n", pImport->TimeDateStamp);printf("ForwarderChain:%08X\r\n", pImport->ForwarderChain);printf("FirstThunk:%08X\r\n", pImport->FirstThunk);printf("OriginaFirstThunk:%08X\r\n", pImport->OriginalFirstThunk);//IAT表:PIMAGE_THUNK_DATA pIAT = (PIMAGE_THUNK_DATA)(RvaToFoa(pImport->OriginalFirstThunk, szBuffer) + szBuffer);DWORD dwIndex = 0;while (pIAT->u1.Ordinal != 0) {printf("ThunkRVA:%08X\r\n", pImport->OriginalFirstThunk + dwIndex);printf("ThunkOffset:%08X\r\n", RvaToFoa(pImport->OriginalFirstThunk, szBuffer) + dwIndex);dwIndex += 4;if ((pIAT->u1.Ordinal & 0x80000000) != 1) {PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)(RvaToFoa(pIAT->u1.AddressOfData, szBuffer) + szBuffer);__try {printf("API名称:%s\r\n", pName->Name);printf("HINT:%04X\r\n", pName->Hint);}__except (EXCEPTION_EXECUTE_HANDLER) {int nOun = pIAT->u1.Function - 0x80000000;char szNameBuffer[MAX_PATH] = { 0 };sprintf(szNameBuffer, "序号:%Xh %dd", nOun, nOun);printf("API名称:%s\r\n",szNameBuffer);printf("HINT:-\r\n");}printf("ThunkValue:%08X\r\n\r\n", pIAT->u1.Function);}pIAT++;}pImport++;}}void LoadSectionHeader(const char * szBuffer) {PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)szBuffer;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(szBuffer + pDosHeader->e_lfanew);PIMAGE_FILE_HEADER pFileHeader = (PIMAGE_FILE_HEADER)&pNtHeaders->FileHeader;PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeaders->OptionalHeader;PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);for (int i = 0; i < pFileHeader->NumberOfSections; i++) {printf("Section %d:\r\n", i);char szName[9] = { 0 };memcpy(szName, pSectionHeader[i].Name, 8);printf("VOffset(虚拟相对地址):%08X\r\n", pSectionHeader[i].VirtualAddress);printf("VSIZE(区段大小):%d\r\n", pSectionHeader[i].Misc.VirtualSize);printf("ROFFSET(文件偏移):%08X\r\n", pSectionHeader[i].PointerToRawData);printf("RSIZE(文件中区段的大小):%X\r\n", pSectionHeader[i].SizeOfRawData);printf("标记:%X\r\n\r\n", pSectionHeader[i].Characteristics);} }
IATHook
dllmain:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"//LPVOID OldMessageBoxW = NULL;
typedef int
(WINAPI *FuncMessageBoxW)(_In_opt_ HWND hWnd,_In_opt_ LPCWSTR lpText,_In_opt_ LPCWSTR lpCaption,_In_ UINT uType);
FuncMessageBoxW OldMessageBoxW = NULL;int
WINAPI
MyMessageBoxW(_In_opt_ HWND hWnd,_In_opt_ LPCWSTR lpText,_In_opt_ LPCWSTR lpCaption,_In_ UINT uType) {return OldMessageBoxW(hWnd, L"我的MessageBox", L"提示", NULL);
}VOID IATHook() {//保存原来的函数地址OldMessageBoxW = (FuncMessageBoxW)GetProcAddress(GetModuleHandle(L"user32.dll"), "MessageBoxW");//这里GetModuleHandle如果传入参数位NULL,那么就会获取.exe的基址//获取头部信息PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)&pNtHeader->OptionalHeader;//获取导出表地址偏移(这里时进程中获取的内存,所以我们之际使用RVA就可以)DWORD dwImportTable = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader + dwImportTable);PIMAGE_THUNK_DATA pFirstThunk;while (pImport->Characteristics && pImport->FirstThunk != NULL) {pFirstThunk = (PIMAGE_THUNK_DATA)(pImport->FirstThunk + (DWORD)pDosHeader);while (*(DWORD*)pFirstThunk != NULL) {if (*(DWORD*)pFirstThunk == (DWORD)OldMessageBoxW) {DWORD dwOldProtect = 0;VirtualProtectEx(GetCurrentProcess(), pFirstThunk, 0x8, PAGE_EXECUTE_READWRITE, &dwOldProtect);DWORD dwFuncAddr = (DWORD)MyMessageBoxW;memcpy(pFirstThunk, (DWORD*)&dwFuncAddr, 4);VirtualProtectEx(GetCurrentProcess(), pFirstThunk, 0x8, PAGE_EXECUTE_READWRITE, &dwOldProtect);}pFirstThunk++;}pImport++;}
}BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:IATHook();break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;}return TRUE;
}
Hook检测:
我们首先运行目标程序:
#include <iostream>
#include <Windows.h>int main()
{MessageBox(NULL, L"WdIg111", L"提示", NULL);system("pause");MessageBox(NULL, L"WdIg222", L"提示", NULL);
}
然后注入dll:
继续运行程序,发现Hook成功: