导入表解析与IATHook

news2024/11/19 11:28:43
  • 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:
注入dll
继续运行程序,发现Hook成功:
注入成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/946144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【人工智能】—_贝叶斯网络、概率图模型、全局语义、因果链、朴素贝叶斯模型、枚举推理、变量消元

文章目录 频率学派 vs. 贝叶斯学派贝叶斯学派Probability&#xff08;概率&#xff09;:独立性/条件独立性&#xff1a;Probability Theory&#xff08;概率论&#xff09;:Graphical models &#xff08;概率图模型&#xff09;什么是图模型&#xff08;Graphical Models&…

【Vue3】transition-group 过渡列表

1. 基本使用 transition-group 和 transition 的用法基本上是一样的。 <template><div class"content"><button click"add">add</button><button click"pop">pop</button><div class"wrap"&…

Michael.W基于Foundry精读Openzeppelin第33期——EIP712.sol

Michael.W基于Foundry精读Openzeppelin第33期——EIP712.sol 0. 版本0.1 EIP712.sol 1. 目标合约2. 代码精读2.1 constructor(string memory name, string memory version)2.2 _domainSeparatorV4()2.3 _hashTypedDataV4(bytes32 structHash) 0. 版本 [openzeppelin]&#xff…

OpenVINO2023使用简介

1 下载安装 先在anaconda中创建一个虚拟环境&#xff0c;该环境的python版本为3.7&#xff0c;之所以使用python3.7&#xff0c;是因为我在3.9上安装过程中出现不少bug&#xff0c;后面新建了一个3.7的环境才解决&#xff0c;我不知道是否由于和我已有环境中某些包不兼容&…

222. 完全二叉树的节点个数 Python

文章目录 一、题目描述示例 1![在这里插入图片描述](https://img-blog.csdnimg.cn/8c74d1b796b74286999e09d4c6b7682f.png#pic_center)示例 2示例 3 二、代码三、解题思路 一、题目描述 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定…

【无监督学习】压缩即预测——Kolmogorov 复杂度作为终极压缩器

基于学习方法&#xff0c;机器学习大致可分为监督学习和无监督学习两种。在无监督学习中&#xff0c;我们需要用某种算法去训练无标签数据集&#xff0c;从而帮助模型找到这组数据的潜在结构。 为了进行无监督学习&#xff0c;在OpenAI成立早期&#xff0c;他们认为通过压缩可…

go gin 自定义验证

我们上一篇已经提到了gin中binding时候可以指定json字段大小等限制&#xff0c;但是那个错误却是英文的&#xff0c;现在想搞成中文的&#xff0c;以便前端可读&#xff0c;demo如下 package mainimport ("net/http""reflect""github.com/gin-gonic/…

知更鸟语音训练

现在哪还有人读小说、看视频&#xff0c;谁还用真人朗读呢&#xff1f; 现在给大家介绍&#xff0c;假人朗读是怎么来的&#xff0c;提供一些音频&#xff0c;进行训练&#xff0c;然后就能合成属于自己的音频了。这里只讲训练部分&#xff0c;使用请自己看github知更鸟&#…

javaee spring 静态代理

静态代理 package com.test.staticProxy;public interface IUsersService {public void insert(); }package com.test.staticProxy;//目标类 public class UsersService implements IUsersService {Overridepublic void insert() {System.out.println("添加用户");…

【C++作业】定义一个基类Animal,其中有一个虚函数Perform,用于在子类中实现不同的表演行为

1 动物园的讲解员和动物表演 以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c…

让你成为室内渲染大师!别再犯这6大错误

你是不是经常感叹自己仿佛用了个假软件&#xff1f; V-Ray室内渲染中这6个常见错误你一定不能犯&#xff0c;今天小编就带你逐一击破&#xff01; 案例项目为 Whistler House by SBD & Burgers Architecture 1.错误比例的纹理 材质纹理太小或太大都会让渲染看起来不真实…

公园可视联网报警器怎么样

公园可视联网报警器怎么样 公园可视联网报警器是一种用于保障公园安全的设备&#xff0c;具有以下几个优点&#xff1a; 1. 实时监控&#xff1a;可视联网报警器可以实时监控公园的各个角落&#xff0c;一旦发现可疑情况&#xff0c;及时报警并提供现场视频。 2. 防止犯罪&am…

前端基础1——HTML标记语言

文章目录 一、基本了解二、HTML常用标签2.1 文本格式化标签2.2 列表标签2.3 超链接标签2.4 图片标签2.5 表格标签2.6 表单标签2.6.1 提交表单2.6.2 下拉表单2.6.3 按钮标签 2.7 布局标签 一、基本了解 网页组成&#xff08;index.html页面&#xff09;&#xff1a; HTML标记语言…

一次讲清楚Linux Cron和 Spring Cron

定时任务是我们日常开发中经常用到的一个功能点&#xff0c;无论是Linux服务器上Crontab还是Spring task schedule&#xff0c;都会使用到cron表达式去实现定时任务的配置。不过&#xff0c;一定要注意&#xff0c;Linux cron表达式和Spring的cron表达式不一样&#xff0c;下面…

打开谷歌浏览器远程调试功能

谷歌浏览器远程调试功能 首先我们来启动Chrome的远程调试端口。你需要找到Chrome的安装位置&#xff0c;在Chrome的地址栏输入chrome://version就能找到Chrome的安装路径 开启远程控制命令 文件路径/chrome.exe --remote-debugging-port9222开启后的样子(注意要关闭其他谷歌浏…

你会使用druid数据库连接池吗???

1.下载架包。下载地址&#xff1a;https://note.youdao.com/ynoteshare/index.html?id61e2cc939390acc9c7e5017907e98044&typenote&_time1693296531722 2.将架包加入项目文件。 创建一个lib目录&#xff0c;将架包复制进去 右键点击lib目录&#xff0c;将其添加为库。…

秋招面试总结

八股 C中传引用和传指针的区别&#xff1a;参考 指针传参&#xff1a; 本质是值传递&#xff0c;形参的指针变量是个临时局部变量&#xff0c;用来接收外部实参指针变量保存的地址值除了解引用对地址内存进行操作外&#xff0c;形参指针变量的其他任何操作都不会影响到外面的实…

yolov5自定义模型训练一

要拿yolo来用到自己希望使用的场合就需要自己来训练模型权重&#xff0c;要训练模型权重需要足够的训练数据集&#xff0c;数据越多训练后的模型权重越准确。 数据集需要按yolov5的格式进行收集&#xff0c;收集图片后需要用标注工具进行标注&#xff0c;常用的有LabelImg软件…

Redis——》Pipeline

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

小学生演讲与口才教案设计

教案设计&#xff1a;小学生演讲与口才 教学目标&#xff1a; 1. 培养学生的演讲能力和口才表达能力。 2. 培养学生的自信心和沟通能力。 3. 提高学生的思维逻辑和语言组织能力。 教学重点&#xff1a; 教学重点一&#xff1a;演讲技巧的培养 演讲技巧是指在演讲过程中运…