4.4 EAT Hook 挂钩技术
EAT(Export Address Table)用于修改动态链接库(DLL)中导出函数的调用。与IAT Hook不同,EAT Hook是在DLL自身中进行钩子操作,而不是修改应用程序的导入表。它的原理是通过修改DLL的导出函数地址,将原本要导出的函数指向另一个自定义的函数。这样,在应用程序调用DLL的导出函数时,实际上会执行自定义的函数。
EAT Hook的步骤通常包括以下几个步骤:
- 获取目标DLL的基址:通过模块加载和遍历PE文件的导出表,找到目标DLL的基址。
- 定位导出函数:根据导出函数的名称或序号,在导出表中找到目标函数的位置。
- 保存原始函数地址:将目标函数的地址保存下来,以便后续恢复。
- 修改导出函数地址:将目标函数在导出表中对应的地址修改为自定义函数的地址。
- 实现自定义函数:编写自定义的函数,该函数会在被钩子函数被调用时执行。
- 调用原始函数:在自定义函数中,可以选择是否调用原始的被钩子函数。
与IAT不同是EAT存放的不是函数地址,而是导出函数地址的偏移,使用时需要加上指定Dll的模块基地址,当Hook挂钩之后,所有试图通过导出表获取函数地址的行为都会受到影响,EATHook并不会直接生效,它只能影响Hook之后对该函数地址的获取。
实现导出表劫持的详细流程如下所示:
- 首先获取到DOS头,并加上偏移得到NT头,再通过Nt头得到数据目录表基地址。
- 数据目录表
DataDirectory中的第0个成员指向导出表的首地址,直接拿到导出表的虚拟地址。 - 循环查找导出表的导出函数是否与我们的函数名称一致,一致则取出导出函数地址。
- 设置导出函数位置读写属性,将新的导出函数地址写入到该位置
根据上述流程,读者可以很容易的写出导出表劫持代码,如下所示则是完整的代码片段,当运行EATHook时,进程内如果再次获取MessageBox函数的内存地址时则会返回MyMessageBox自定函数地址,此时功能将被替换。
#include <windows.h>
#include <cstdio>
#include <tchar.h>
// 导出表劫持
BOOL EATHook(LPCTSTR szDllName, LPCTSTR szFunName, LPVOID NewFun)
{
DWORD addr = 0, index = 0, dwProtect = 0;
// 装入模块
HMODULE DllBase = LoadLibrary(szDllName);
if (NULL == DllBase)
{
return(FALSE);
}
// 得到Dos头NT头数据目录表
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)DllBase;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptHeader = (PIMAGE_OPTIONAL_HEADER)(&pNtHeader->OptionalHeader);
// 得到导出表的虚拟地址
PIMAGE_EXPORT_DIRECTORY pExpDes = (PIMAGE_EXPORT_DIRECTORY)
((PBYTE)DllBase + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
// 获取导出表的函数地址,函数名称,函数序号
PULONG pAddressOfFunctions = (PULONG)((PBYTE)DllBase + pExpDes->AddressOfFunctions);
PULONG pAddressOfNames = (PULONG)((PBYTE)DllBase + pExpDes->AddressOfNames);
PUSHORT pAddressOfNameOrdinals = (PUSHORT)((PBYTE)DllBase + pExpDes->AddressOfNameOrdinals);
// 循环查找
for (int i = 0; i < pExpDes->NumberOfNames; ++i)
{
index = pAddressOfNameOrdinals[i];
// 得到导出函数名
LPCTSTR pFuncName = (LPTSTR)((PBYTE)DllBase + pAddressOfNames[i]);
// 对比函数名
if (!_tcscmp((LPCTSTR)pFuncName, szFunName))
{
// 返回地址
addr = pAddressOfFunctions[index];
break;
}
}
// 设置读写属性
VirtualProtect(&pAddressOfFunctions[index], 0x1000, PAGE_READWRITE, &dwProtect);
// 设置导出函数
pAddressOfFunctions[index] = (DWORD)NewFun - (DWORD)DllBase;
// 写出替换
WriteProcessMemory(GetCurrentProcess(), &pAddressOfFunctions[index],
(LPCVOID)((DWORD)NewFun - (DWORD)DllBase), sizeof(NewFun), &dwProtect);
return(TRUE);
}
// 自定义导出函数
int __stdcall MyMessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
printf("hello lyshark \n");
return(0);
}
typedef int (WINAPI* LPFNMESSAGEBOX)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
int main(int argc, char *argv[])
{
// 对MessageBoxA进行Eat Hook
EATHook("USER32.dll", "MessageBoxA", MyMessageBox);
// 模拟下次调用后就是执行我们的Hook代码
LoadLibrary("USER32.dll");
HMODULE hDll = GetModuleHandle("USER32.dll");
LPFNMESSAGEBOX lpMessageBox = (LPFNMESSAGEBOX)GetProcAddress(hDll, "MessageBoxA");
lpMessageBox(NULL, "Hello, EAT Hook", "Info", MB_OK);
system("pause");
return(0);
}
上述代码被运行后,针对外部调用MessageBoxA函数都会转向到MyMessageBox函数上,至此传入的参数将会失效,如下图所示;

4.4 EAT Hook 挂钩技术的更多相关文章
- Android so注入( inject)和Hook(挂钩)的实现思路讨论
本文博客:http://blog.csdn.net/qq1084283172/article/details/54095995 前面的博客中分析一些Android的so注入和Hook目标函数的代码,它 ...
- 禁用copy on write实现全局EAT HOOK
以前写过一个,但是一不小心删除了,哎,就当再次复习复习吧. 首先抛出一个有意思的问题: 已知所有Windows可执行文件exe都会链接子系统ntdll.dll,那么真实内存中有几份ntdll.dll? ...
- pg3 bypass源码阅读 —— 学习x64内核hook跳板技术
如之前描述的 pg3复杂了许多 先来看看都要hook哪些点 1.hook dpc和定时器分发器,防止seh路线触发pg KiTimerListExpire,KiRetireDpcList 看一下hoo ...
- EAT/IAT Hook
标 题: EAT/IAT Hook 作 者: Y4ng 时 间: 2013-08-21 链 接: http://www.cnblogs.com/Y4ng/p/EAT_IAT_HOOK.html #in ...
- PE格式: 分析IatHook并实现
Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...
- Windows Hook技术
0x01 简介 有人称它为“钩子”,有人称它为“挂钩”技术.谈到钩子,很容易让人联想到在钓东西,比如鱼钩就用于钓鱼.编程技术的钩子也是在等待捕获系统中的某个消息或者动作.钩子的应用范围非常广泛,比如输 ...
- Windows Dll Injection、Process Injection、API Hook、DLL后门/恶意程序入侵技术
catalogue 1. 引言2. 使用注册表注入DLL3. 使用Windows挂钩来注入DLL4. 使用远程线程来注入DLL5. 使用木马DLL来注入DLL6. 把DLL作为调试器来注入7. 使用c ...
- hook 9大类
HOOK技术主要分为两大类,一是内核层HOOK,一是用户层HOOK. 用户层HOOK也就是在ring3环境下hook kenerl32.dll.User3.dll.Gui32.dll.Advapi.d ...
- HOOK API (一)——HOOK基础+一个鼠标钩子实例
HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...
- windows、linux劫持技术
windows系统以下能够利用detours劫持 realse 模式劫持,调试的程序不能够 函数劫持能够实现的效果. 函数的劫持原理 我们怎样实现-detours detours是微软亚洲研究院出品 ...
随机推荐
- three.js 视频融合
MixVideo.js代码: //视频融合 import * as THREE from '../build/three.module.js'; import { API } from '../js. ...
- 【CJsonObject】C++ JSON 解析器使用教程
能选封装的尽量不使用底层的 一.CJsonObject 简介 CJsonObject 是 Bwar 基于 cJSON 全新开发一个 C++ 版的 JSON 库. CJsonObject 的最大优势是轻 ...
- shardingsphere 5.1.1 分库分表
1. mysql配置: application-dubboService = spring-csc-campaign-agent-context.xml kafka.topics.redisAcces ...
- 活动回顾|阿里云 Serverless 技术实践营 Serverless +AI 专场
8月25日"阿里云Serverless技术实践营( Serverless + AI 专场)"北京站圆满落幕.活动受众以关注 Serverless +AI 技术的开发者.企业决策人. ...
- webgl创建一个点
- 解决刷新页面丢失vuex数据
- Vue中如何使用sass实现换肤(更换主题)功能
Vue中如何使用sass实现换肤(更换主题)功能 https://blog.csdn.net/m0_37792354/article/details/82012278
- 驾校考试系统 考试模块的 UI效果图
初始系统界面 判断题 单选题 多选题
- java 对象作为成员变量
public class Main { private int uplimit; private int value; public Main(int uplimit){ this.uplimit = ...
- Vue第三篇 Vue组件
01-组件的全局注册 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...