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 挂钩技术的更多相关文章

  1. Android so注入( inject)和Hook(挂钩)的实现思路讨论

    本文博客:http://blog.csdn.net/qq1084283172/article/details/54095995 前面的博客中分析一些Android的so注入和Hook目标函数的代码,它 ...

  2. 禁用copy on write实现全局EAT HOOK

    以前写过一个,但是一不小心删除了,哎,就当再次复习复习吧. 首先抛出一个有意思的问题: 已知所有Windows可执行文件exe都会链接子系统ntdll.dll,那么真实内存中有几份ntdll.dll? ...

  3. pg3 bypass源码阅读 —— 学习x64内核hook跳板技术

    如之前描述的 pg3复杂了许多 先来看看都要hook哪些点 1.hook dpc和定时器分发器,防止seh路线触发pg KiTimerListExpire,KiRetireDpcList 看一下hoo ...

  4. EAT/IAT Hook

    标 题: EAT/IAT Hook 作 者: Y4ng 时 间: 2013-08-21 链 接: http://www.cnblogs.com/Y4ng/p/EAT_IAT_HOOK.html #in ...

  5. PE格式: 分析IatHook并实现

    Ring 3层的 IAT HOOK 和 EAT HOOK 其原理是通过替换IAT表中函数的原始地址从而实现Hook的,与普通的 InlineHook 不太一样 IAT Hook 需要充分理解PE文件的 ...

  6. Windows Hook技术

    0x01 简介 有人称它为“钩子”,有人称它为“挂钩”技术.谈到钩子,很容易让人联想到在钓东西,比如鱼钩就用于钓鱼.编程技术的钩子也是在等待捕获系统中的某个消息或者动作.钩子的应用范围非常广泛,比如输 ...

  7. Windows Dll Injection、Process Injection、API Hook、DLL后门/恶意程序入侵技术

    catalogue 1. 引言2. 使用注册表注入DLL3. 使用Windows挂钩来注入DLL4. 使用远程线程来注入DLL5. 使用木马DLL来注入DLL6. 把DLL作为调试器来注入7. 使用c ...

  8. hook 9大类

    HOOK技术主要分为两大类,一是内核层HOOK,一是用户层HOOK. 用户层HOOK也就是在ring3环境下hook kenerl32.dll.User3.dll.Gui32.dll.Advapi.d ...

  9. HOOK API (一)——HOOK基础+一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  10. windows、linux劫持技术

    windows系统以下能够利用detours劫持 realse  模式劫持,调试的程序不能够 函数劫持能够实现的效果. 函数的劫持原理 我们怎样实现-detours detours是微软亚洲研究院出品 ...

随机推荐

  1. Nginx--安装模块

    一 安装系统自带模块 #进入安装目录[root@localhost ~]# cd nginx-1.18.0/#查看原来的编译选项 [root@localhost nginx-1.18.0]# ngin ...

  2. 实战指南 | Serverless 架构下的应用开发

    作者 | 刘宇.田初东.卢萌凯.王仁达 UC Berkeley认为Serverless架构的出现过程类似于40多年前从汇编语言转向高级语言的过程,在未来Serverless架构的使用会飙升,或许服务器 ...

  3. sipp3.6带媒体测试方案

    概述 SIP压测工具sipp,免费,开源,功能足够强大,配置灵活,优点多. 本文档介绍sipp工具如何带媒体测试,并介绍如何制作可用的媒体文件(G729和PCMA). 环境 centos7.9 fre ...

  4. go 变量逃逸分析

    0. 前言 在 小白学标准库之 reflect 篇中介绍了反射的三大法则以及变量的逃逸分析.对于逃逸分析的介绍不多,大部分都是引自 Go 逃逸分析.不过后来看反射源码的过程中发现有一种情况 Go 逃逸 ...

  5. 一文搞清楚Java中的包、类、接口

    写在开头 包.类.接口.方法.变量.参数.代码块,这些都是构成Java程序的核心部分,即便最简单的一段代码里都至少要包含里面的三四个内容,这两天花点时间梳理了一下,理解又深刻了几分. Java中的包 ...

  6. 基于html5+javascript技术开发的房贷利率计算器,买房的码农们戳进来

    房贷计算器是一款专为购房者设计的实用工具应用,其主要功能是帮助用户详细计算房贷的还款金额.利息以及还款计划等.通过这款软件,用户可以更加便捷地了解到自己的还款情况和计划,从而更好地规划自己的财务.下面 ...

  7. Angular系列教程之路由守卫

    .markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...

  8. Shell-流程控制-if-then-elif

  9. Shell-获取终端输入-read

  10. [转帖]linux中的set -e 与set -o pipefail

    https://www.cnblogs.com/xingmuxin/p/8431970.html 1.set -e "Exit immediately if a simple command ...