- 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成功: