eat hook原来eat hook原来
EAT与IAT比较类,我相信会IAT的肯定很多,起初我想写在C#上面 不过与
C# 遍历DLL导出函数的方法很相,只是两者在内存中的映射方式不同而已
Heh,首先我们需要把DLL映射到地址内存空间去 否则没有办法去置换函数,
当然EAT有一些缺点,它必须在软件调用GetProcAddress函数之前替换DLL中
的函数,所以则出现了对GetProcAddress函数的一个Hook,否则只可改变
GetProcAddress返回的内容、是不是感到很惆怅
EAT全称为“Export address table”其核心则是利用PE与DLL的一些相关特性
实现的一个技术 首先我们通过LoadLibraryA函数把一个有效的DLL映射到内
存中,PE文件中第一个字节是MS-DOS信息头即IMAGE_DOS_HEADER
IMAGE_NT_HEADER= (pDosHearder pDosHearder->e_lfanew);
//IMAGE_NT_HEADER::OptionalHeader
pOptionalHeader =(pDosHearder pDosHearder->e_lfanew 24);
上面是x86的一个OptionalHeader的对称,这里是不想再多做一次转换直接
跳过去会很快捷、所以加上24但恰好指向OptionalHeader、而我们只需要
它其它的对我们而言根本没有任何用、所以跳过就可以
既然是EAT,我们看第一个字母全名为Export那么我们肯定要去找包含导出的DLL函数的
PE中的数据目录,恰好有那么一个IMAGE_DIRECTORY_ENTRY_EXPORT但是拿出来
的地址是RVA / 相对虚拟地址所以你必须要ToVA / 到虚拟地址、但是DLL已经被映射到虚
拟内存中 所以我们不需要使用RvaToVa、我们只需要
(DWORD)pDosHearder
pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
(DWORD)hRemoteModule DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
则可以得到,PIMAGE_EXPORT_DIRECTORY pExportDirectory函数导出目录,但是我
们得到了它却不可以耍花架子,我们还有继续下面的代码否则没法混、
pAddressOfNames // 导出函数名
pAddressOfFunctions // 导出函数地址
pAddressOfNameOrdinals // 导出函数序列
上面定义三种不同的指针,但是都预先把地址进行了一个处理,这是为了方便后面的使用
而不必一直加上(DOWRD)hRemoteModule那样子会很累的、
pExportDirectory->NumberOfNames // 导出函数计数(Length)
LPCSTR strInsideName = (LPCSTR)((DWORD)hRemoteModule pAddressOfNames[i]);
上面是获取DLL导出的函数名,pAddressOfNames[i] 返回的地址为虚拟相对地址(Rva)
在这里只需要如下去做、则可以得到DLL导出的函数名是什么,当然这个是c_str风字
符串,你懂的'\0'结尾,_strlen对其有效,不过在本代码中也用不到_strlen、
下面是首先比较两个字符串是否相等,主要看看需要具体去Hook那个函数
for(inti=0;i<pExportDirectory->NumberOfNames;i)
{
LPCSTRstrInsideName=(LPCSTR)((DWORD)hRemoteModulepAddressOfNames[i]);
if(_stricmp(strInsideName,strMethodName)==0)
{
DWORDpflOldProtect;
VirtualProtect(&pAddressOfFunctions[*pAddressOfNameOrdinals],0x1000,PAGE_READWRITE,&pflOldProtect);
pAddressOfFunctions[*pAddressOfNameOrdinals]=(DWORD)newMethodAddress-(DWORD)hRemoteModule;
break;
}
pAddressOfNameOrdinals;
}
&pAddressOfFunctions[*pAddressOfNameOrdinals] 从上面的代码你应该看出了端倪
对的,DLL函数导出的地址你不可以直接通过&pAddressOfFunctions[i]解决问题,因
为在PE中,它是通过Ordinals定位函数位置,但是它与i=0; i是相序的、有点绕哈
VirtualProtect(&pAddressOfFunctions[*pAddressOfNameOrdinals],
0x1000, PAGE_READWRITE, &pflOldProtect);
上面是修改函数的内存保护,0x1000没有太大意义、填4 / 8也是可以的
pAddressOfFunctions[*pAddressOfNameOrdinals] =
(DWORD)newMethodAddress - (DWORD)hRemoteModule;
好吧,这里填写相对虚拟地址、指的是新的函数地址与这个模块的地址做一个加减
不管返回的是负数还是正数都可以,没有那么多讲究、后面这句话也是必要的
pAddressOfNameOrdinals; 你可以任性的把使用 *pAddressOfNameOrdinals
修改为pAddressOfNameOrdinals[i]但是绝对不可以不写,这是原则性上的问题、
HANDLEWINAPICB_GetModuleHandleW(LPCTSTRstrLibraryName)
{
returnNULL;
}
我们写一个Hook的处理函数,GetModuleHandleW函数的一个处理函数,什么都不
用写,只需要打个断点看看有没有执行就可以了,因为没有太大的意义重点在这里
int_tmain(intargc,_TCHAR*argv[])
{
EATHook("kernel32.dll","GetModuleHandleW",CB_GetModuleHandleW);
LPDWORDpfnGetModuleHandleW=(LPDWORD)GetProcAddress(GetModuleHandleA("kernel32"),"GetModuleHandleW");
_asm
{
push0
callpfnGetModuleHandleW
}
return0;
}
上面是利用EAT先把GetModuleHandleW函数进行挂钩,然后通过GetProcAddress
函数得到pfnGetModuleHandleW,为了方便不想使用函数指针,直接嵌入两行汇编
代码进去直接解决问题,然后F5调试,如果CB_GetModuleHandleW函数被执行 那
么恭喜你成功了,如果没有说明你出错了、哈哈
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/tongxinshuyu/article-43686-1.html
潜艇下潜
这是维护国家主权
警告后还不是滚出去了
枷锁在一根根往自己脖子上套