导入表解析与IATHook

  • IAT:导入地址表
    // PE文件解析.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #define  _CRT_SECURE_NO_WARNINGS
    #include 
    #include 
    
    //函数向前声明
    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 
#include 

int main()
{
    
	MessageBox(NULL, L"WdIg111", L"提示", NULL);
	system("pause");
	MessageBox(NULL, L"WdIg222", L"提示", NULL);
}

然后注入dll:
导入表解析与IATHook_第1张图片
继续运行程序,发现Hook成功:
导入表解析与IATHook_第2张图片

你可能感兴趣的:(滴水逆向三期PE文件结构学习,windows,安全)