hook_api几种方法
APIHOOK的实现原理

APIHOOK的实现原理API Hooking(API挂钩)是一种常见的软件技术,用于修改或者扩展应用程序的行为,它通过“操纵”应用程序的API调用过程来实现这一目标。
API Hooking通常用于各种目的,例如:监视应用程序的行为、修复漏洞、收集数据等。
本文将介绍API Hook的实现原理及其相关概念。
1. API Hook概述API Hooking通过劫持和修改应用程序对动态链接库(DLL)中导出函数的调用来实现目标功能。
在Windows操作系统中,每个可执行文件都会使用一些API函数,这些函数由系统提供并存储在动态链接库中。
当应用程序调用这些函数时,操作系统会在库文件中查找并执行相应的函数代码。
API Hooking就是在应用程序和DLL之间插入一个中间层,通过改变函数调用的目标,来控制和改变应用程序的行为。
API Hooking的实现原理可以归纳为以下几个步骤:(1)定位目标函数:首先,需要确定要Hook的目标函数。
可以通过静态分析程序源代码、反汇编可执行文件、监视应用程序行为等方法来获取目标函数的地址或名称。
(2)获取目标函数的原始地址:通过动态链接库(DLL)中的导入表,可以获取到目标函数的原始地址。
导入表中保存了DLL中导出函数地址的引用。
(3)Hook目标函数:Hook目标函数的方式有多种,这里介绍两种常见的方式。
a. 钩子函数(Hook Function):通过将Hook函数替换为目标函数的调用,可以劫持目标函数的执行。
Hook函数在执行之前、中间或者之后可以执行额外的逻辑操作,并返回结果给应用程序。
b. IAT Hooking(Import Address Table Hooking):IAT是动态链接库中的导入表,包含了动态链接库中导出函数的地址。
通过修改IAT中目标函数的地址,将其指向Hook函数,即可实现Hook效果。
(4)重定向函数调用:Hook目标函数后,需要将应用程序中对目标函数的调用重定向到Hook函数。
hook api隐藏文件代码

//file_str(name,"F:\\temp2.txt");
return bReturn;
}
//----------------------------------------------------
#ifdef HookProA
//file_str("路径不匹配","F:\\temp1.txt");
}
/*
i=WideCharToMultiByte(CP_ACP,0,(WCHAR *)lpFindFileData->cFileName,wcslen((WCHAR *)lpFindFileData->cFileName),path,MAX_PATH,0,0);
HideName[i]='\0';
while(HideName[i]!='\\' && i>0)
i--;
i++;
j=0;
while(HideName[i]!='\0' && i<MAX_PATH)
path[i]='\0';
file_str(path,"F:\\temp2.txt");
*/
return hFind;
要实现Ring3下隐藏文件,最简单的方法就是HOOK掉Explorer进程里的FindFirstFile和FindNextFile函数,考虑到A和W两个版本,我们应该要HOOK四个函数,但是事实上,我们只要HOOK掉W版本的两个函数就可以了,因为用Dependency看下就能发现Explorer.exe并没有使用FindFirstFileA和FindNextFileA。HOOK API的方法有好多种,我这里用的是HOOK IAT法,也就是遍历Exeplorer进程中的所有模块,凡是模块的导入表中用到FindFirstFileW和FindNextFileW的,就修改FirstThunk数组中对应项的Function地址为MYFindFirstFileW和MYFindNextFileW的地址,再在MYFindFirstFileW函数中调用真实的FindFirstFileW地址,MYFindNextFileW函数类似。以下直接给出源程序,程序中为了安全也可以HOOK掉A版本的函数,只要把//#define HookProA行的注释符号去掉就行。
源程序程序破解之 API HOOK技术

gCallCounter ++;
}
#endif
return ret;
}
2)使用刚才提到的方法进行DLL导入
string hexData1 = toHexString((const char *)pbData, strlen((const char *)pbData));
int ret = sub_4026B0(pbData);
string hexData2 = toHexString((const char *)pbData, strlen((const char *)pbData));
gHooks.Add(_T("KERNEL32.DLL"), "DeviceIoControl", my_DeviceIoControl);
static int gCallCounter = 0;
BOOL WINAPI my_DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
// 指定DLL的某个函数进行HOOK
HANDLE Add(LPCTSTR lpszModule, LPCSTR lpcFuncName, void *pNewAddr, DWORD dwData = 0);
// 给定一个函数地址进行HOOK
API Hook应用简述

API Hook应用简述东软移动互联网事业部卜少峰1.概述windows系统下的编程,消息message的传递是贯穿其始终的。
hook与消息有着非常密切的联系,它的中文含义是“钩子”,这样理解起来我们不难得出“hook是消息处理中的一个环节,用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过程前,处理某些特定的消息”。
这也是hook分为不同种类的原因。
hook的这个本领,使它能够将自身的代码“融入”被hook住的程序的进程中,成为目标进程的一个部分。
在windows2000以后的系统中,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。
这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是hook的出现给我们开拓了解决此类问题的道路。
在windows系统下编程,会接触到api函数的使用,常用的api函数大概有2000个左右。
最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样API Hook就自然而然的出现了。
我们可以通过API Hook,改变一个系统api的原有功能。
基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数。
2.API Hook的基本方法如何进行API Hook,常用的方法有如下四种:1、使用注册表HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs2、调用SetWindowsHookEx(WH_GETMESSAGE, …, 0)设置全局的消息钩子;3、使用CreateRemoteThread函数在目标进程中创建远程线程4、如果你只是要挂接某个特定进程的并且情况允许你自己来创建此进程,你可以调用CreateProcess(…, CREATE_SUSPENDED)创建子进程并暂停运行,然后修改入口代码使之调用LoadLibrary加载自己的DLL。
易语言HookAPI 技巧

易语言HookAPI 技巧易语言Hook的代码有很多,Hook的跳转代码也很简单,不多说,主要注意的有:1.可以保存原API函数的API头到自己申请的地址,Hook跳转的地址仍然是自己的子程序,但如果保存了API头,就可以call addr 实现不恢复Hook调用原函数。
.版本2.如果真(FuncAddress =0 或HookFuncAddr =0)返回(0).如果真结束hHook =VirtualAlloc (0, 14, 位或(#MEM_COMMIT, #MEM_RESERVE), #PAGE_EXECUTE_READWRITE).如果真(hHook =0)返回(0).如果真结束RtlMoveMemory_1 (hHook, 到字节集(FuncAddress), 4)JmpCode =hHook +4RtlMoveMemory (JmpCode, FuncAddress, 5)RtlMoveMemory_1 (JmpCode +5, { 233 } +到字节集(到整数(FuncAddress + 5 -JmpCode -10)), 5)VirtualProtect (FuncAddress, 5, #PAGE_EXECUTE_READWRITE, OldProtect)RtlMoveMemory_1 (FuncAddress, { 233 } +到字节集(到整数(HookFuncAddr -FuncAddress -5)), 5)VirtualProtect (FuncAddress, 5, OldProtect, 0)返回(JmpCode)2.Hook recv函数等的技巧,这类函数的特点是,某个参数是具有缓冲区性质的,并在函数调用完成后参数会直接传递数据,所以结合上面的代码,就可以这样了:ret=Call(jmpcode,para1,para2.etc)这时候,再对参数para1等进行处理,才可以获得数据3.Anti-Hook的躲避技巧,部分程序会有检测API头5字节,所以我们只需要在Hookaddr上面加上一段偏移(大于5)即可躲避。
windows下hook第三方库函数的方法

windows下hook第三方库函数的方法在Windows下,要hook第三方库函数,你可以使用一种称为API hooking的技术。
API hooking允许你拦截和修改系统库函数的调用,以便在需要时注入自定义代码。
以下是一种常用的方法,用于在Windows上hook第三方库函数:1. 导入所需函数:首先,在你的代码中导入`windows.h`头文件,并使用`GetProcAddress`函数获取你想要hook的库函数的地址。
2. 创建hook函数:创建一个自定义的hook函数,该函数将代替原始库函数的调用。
该函数应该与原始库函数拥有相同的参数和返回值。
3. 修改函数指针:使用`DetourTransactionBegin`、`DetourUpdateThread`和`DetourAttach`等函数修改目标库函数的指针,将其指向你的自定义hook函数。
4. 启用hook:使用`DetourTransactionCommit`函数启用hook,使得目标函数调用时会转向你的hook函数。
以下是一个简单的示例代码,演示了如何hook第三方库函数:```c++#include <windows.h>#include <detours.h>// 定义原始库函数的指针类型typedef BOOL(WINAPI* OriginalFunc)(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName);// 声明自定义的hook函数BOOL WINAPI MyCustomFunc(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName){// 在这里可以添加你的自定义代码// 例如:记录日志、修改参数、以及其他操作// 调用原始库函数return ((OriginalFunc)RealFunc)(lpAppName, lpKeyName, lpString, lpFileName);}int main(){// 获取原始库函数的地址OriginalFunc RealFunc =(OriginalFunc)GetProcAddress(GetModuleHandle(L"user32.dll"), "WritePrivateProfileStringA");// 开始hook过程DetourTransactionBegin();DetourUpdateThread(GetCurrentThread());DetourAttach(&(PVOID&)RealFunc, MyCustomFunc);DetourTransactionCommit();// 调用原始库函数WritePrivateProfileStringA("Section", "Key", "Value", "config.ini");// 卸载hookDetourTransactionBegin();DetourUpdateThread(GetCurrentThread());DetourDetach(&(PVOID&)RealFunc, MyCustomFunc);DetourTransactionCommit();return 0;}```请注意,这只是一个示例,实际的hook过程可能会更加复杂。
hook api几种方法

:71A21B72 8B4508 mov eax, dword ptr [ebp+08]
:71A21B75 5F pop edi
:71A21B76 5E pop esi
:71A21B77 C9 leave
:71A21B78 C21000 ret 0010
下面用4种方法来HOOK这个API:
:71A21B62 8BD8 mov ebx, eax
:71A21B64 E8C7F6FFFF call 71A21230 //将被HOOK的机器码(第3种方法)
:71A21B69 3BDF cmp ebx, edi
:71A21B6B 5B pop ebx
:71A21B6C 0F855F940000 jne 71A2AFD1
假设我们的HOOK代码在71A20400处,那么我们把71A21B64处的CALL指令改为CALL 71A20400(原指令是这样的:CALL 71A21230)
而71A20400处的HOOK代码是这样的:
71A20400:
pushad
//在这里做你想做的事情
:71A21B42 57 push edi
:71A21B43 57 push edi
:71A21B44 FF7514 push [ebp+14]
:71A21B47 8945F0 mov dword ptr [ebp-10], eax
:71A21B4A 8B450C mov eax, dword ptr [ebp+0C]
4,上下文的问题,有些HOOK代码不能执行某些操作,否则会破坏原API的上下文,原API就失效了;
5,同步问题,在HOOK代码里尽量不使用全局变量,而使用局部变量,这样也是模块化程序的需要;
APIHook的几种实现

APIHook的⼏种实现所谓的API Hook,就是利⽤某种技术将API的调⽤转为我们⾃⼰定义的函数的调⽤。
这种技术在实际项⽬⾥⾯的应⽤也是很⼴泛的。
最近,我在做关于我们项⽬的⾃动化测试的时候,就遇到了这种情况。
在写测试代码之前,我们对测试代码有⼀些要求。
1. 不能因为测试代码⽽修改原代码。
2. 原有的模块是以dll格式输出的,在做测试的时候,要测的类和函数也只能使⽤dll的导出类或者函数,⽽不能将源⽂件重新编译。
由于这些限制,导致测试⽤例往往不能在普通的机器上运⾏。
⽐如这样⼀个函数:int func(){//Some initializing codesint hardware_code = get_hardware_code();if (is_valid_code(hardware_code)){//}//return ret;}此处,函数get_hardware_code()是与特定平台相关的,在普通PC上运⾏肯定⽆法获得正确的结果。
如果拿不到正确的结果,也就不能对函数func()进⾏测试了。
于是,我们就可以利⽤API Hook技术,在测试代码⾥⾯,把所有对get_hardware_code()的调⽤换成我们⾃定义的函数mock_get_hardware_code()的调⽤,这样,在我们⾃⼰定义的函数⾥⾯,可以返回⼀个有效的代码以保证原代码能够正确的往下执⾏。
经过研究,API Hook有这么⼏种⽅法。
1. 改写函数的⾸地址。
这个是在《Windows核⼼编程》⾥⾯⼤师提到的API Hook的⽅法之⼀。
原理就是,⾸先获得要被Hook的函数的地址(⽐如get_hardware_code()),然后将其⾸地址之后的若⼲字节(通常是5个字节)改成⼀条jmp指令,⽽jmp的⽬标地址就是⾃定义函数的地址(此处为mock_get_hardware_code())。
这样,当函数每次执⾏⽬标函数的时候,就会跳转到我们⾃定义的函数⾥⾯去。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
HOOK API是一个永恒的话题,如果没有HOOK,许多技术将很难实现,也许根本不能实现。
这里所说的API,是广义上的API,它包括DOS下的中断,WINDOWS里的API、中断服务、IFS和NDIS过滤等。
比如大家熟悉的即时翻译软件,就是靠HOOK TextOut()或ExtTextOut ()这两个函数实现的,在操作系统用这两个函数输出文本之前,就把相应的英文替换成中文而达到即时翻译;IFS和NDIS过滤也是如此,在读写磁盘和收发数据之前,系统会调用第三方提供的回调函数来判断操作是否可以放行,它与普通HOOK不同,它是操作系统允许的,由操作系统提供接口来安装回调函数。
甚至如果没有HOOK,就没有病毒,因为不管是DOS下的病毒或WINDOWS里的病毒,都是靠HOOK系统服务来实现自己的功能的:DOS下的病毒靠HOOK INT 21来感染文件(文件型病毒),靠HOOK INT 13来感染引导扇区(引导型病毒);WINDOWS下的病毒靠HOOK系统API(包括RING0层的和RING3层的),或者安装IFS(CIH病毒所用的方法)来感染文件。
因此可以说“没有HOOK,就没有今天多姿多彩的软件世界”。
由于涉及到专利和知识产权,或者是商业机密,微软一直不提倡大家HOOK它的系统API,提供IFS和NDIS等其他过滤接口,也是为了适应杀毒软件和防火墙的需要才开放的。
所以在大多数时候,HOOK API要靠自己的力量来完成。
HOOK API有一个原则,这个原则就是:被HOOK的API的原有功能不能受到任何影响。
就象医生救人,如果把病人身体里的病毒杀死了,病人也死了,那么这个“救人”就没有任何意义了。
如果你HOOK API之后,你的目的达到了,但API的原有功能失效了,这样不是HOOK,而是REPLACE,操作系统的正常功能就会受到影响,甚至会崩溃。
HOOK API的技术,说起来也不复杂,就是改变程序流程的技术。
在CPU的指令里,有几条指令可以改变程序的流程:JMP,CALL,INT,RET,RETF,IRET等指令。
理论上只要改变API入口和出口的任何机器码,都可以HOOK,但是实际实现起来要复杂很多,因为要处理好以下问题:1,CPU指令长度问题,在32位系统里,一条JMP/CALL指令的长度是5个字节,因此你只有替换API里超过5个字节长度的机器码(或者替换几条指令长度加起来是5字节的指令),否则会影响被更改的小于5个字节的机器码后面的数条指令,甚至程序流程会被打乱,产生不可预料的后果;2,参数问题,为了访问原API的参数,你要通过EBP或ESP来引用参数,因此你要非常清楚你的HOOK代码里此时的EBP/ESP的值是多少;3,时机的问题,有些HOOK必须在API的开头,有些必须在API的尾部,比如HOOK CreateFilaA(),如果你在API尾部HOOK API,那么此时你就不能写文件,甚至不能访问文件;HOOK RECV(),如果你在API头HOOK,此时还没有收到数据,你就去查看RECV()的接收缓冲区,里面当然没有你想要的数据,必须等RECV()正常执行后,在RECV()的尾部HOOK,此时去查看RECV()的缓冲区,里面才有想要的数据;4,上下文的问题,有些HOOK代码不能执行某些操作,否则会破坏原API的上下文,原API就失效了;5,同步问题,在HOOK代码里尽量不使用全局变量,而使用局部变量,这样也是模块化程序的需要;6,最后要注意的是,被替换的CPU指令的原有功能一定要在HOOK代码的某个地方模拟实现。
下面以ws2_32.dll里的send()为例子来说明如何HOOK这个函数:Exported fn(): send - Ord:0013h地址机器码汇编代码:71A21AF4 55 push ebp //将被HOOK的机器码(第1种方法):71A21AF5 8BEC mov ebp, esp //将被HOOK的机器码(第2种方法):71A21AF7 83EC10 sub esp, 00000010:71A21AFA 56 push esi:71A21AFB 57 push edi:71A21AFC 33FF xor edi, edi:71A21AFE 813D1C20A371931CA271 cmp dword ptr [71A3201C], 71A21C93 //将被HOOK 的机器码(第4种方法):71A21B08 0F84853D0000 je 71A25893:71A21B0E 8D45F8 lea eax, dword ptr [ebp-08]:71A21B11 50 push eax:71A21B12 E869F7FFFF call 71A21280:71A21B17 3BC7 cmp eax, edi:71A21B19 8945FC mov dword ptr [ebp-04], eax:71A21B1C 0F85C4940000 jne 71A2AFE6:71A21B22 FF7508 push [ebp+08]:71A21B25 E826F7FFFF call 71A21250:71A21B2A 8BF0 mov esi, eax:71A21B2C 3BF7 cmp esi, edi:71A21B2E 0F84AB940000 je 71A2AFDF:71A21B34 8B4510 mov eax, dword ptr [ebp+10] :71A21B37 53 push ebx:71A21B38 8D4DFC lea ecx, dword ptr [ebp-04] :71A21B3B 51 push ecx:71A21B3C FF75F8 push [ebp-08]:71A21B3F 8D4D08 lea ecx, dword ptr [ebp+08] :71A21B42 57 push edi:71A21B43 57 push edi:71A21B44 FF7514 push [ebp+14]:71A21B47 8945F0 mov dword ptr [ebp-10], eax :71A21B4A 8B450C mov eax, dword ptr [ebp+0C] :71A21B4D 51 push ecx:71A21B4E 6A01 push 00000001:71A21B50 8D4DF0 lea ecx, dword ptr [ebp-10] :71A21B53 51 push ecx:71A21B54 FF7508 push [ebp+08]:71A21B57 8945F4 mov dword ptr [ebp-0C], eax :71A21B5A 8B460C mov eax, dword ptr [esi+0C]:71A21B5D FF5064 call [eax+64]:71A21B60 8BCE mov ecx, esi:71A21B62 8BD8 mov ebx, eax:71A21B64 E8C7F6FFFF call 71A21230 //将被HOOK的机器码(第3种方法):71A21B69 3BDF cmp ebx, edi:71A21B6B 5B pop ebx:71A21B6C 0F855F940000 jne 71A2AFD1:71A21B72 8B4508 mov eax, dword ptr [ebp+08]:71A21B75 5F pop edi:71A21B76 5E pop esi:71A21B77 C9 leave:71A21B78 C21000 ret 0010下面用4种方法来HOOK这个API:1,把API入口的第一条指令是PUSH EBP指令(机器码0x55)替换成INT 3(机器码0xcc),然后用WINDOWS提供的调试函数来执行自己的代码,这中方法被SOFT ICE等DEBUGER广泛采用,它就是通过BPX在相应的地方设一条INT 3指令来下断点的。
但是不提倡用这种方法,因为它会与WINDOWS或调试工具产生冲突,而汇编代码基本都要调试;2,把第二条mov ebp,esp指令(机器码8BEC,2字节)替换为INT F0指令(机器码CDF0),然后在IDT里设置一个中断门,指向我们的代码。
我这里给出一个HOOK代码:lea ebp,[esp+12] //模拟原指令mov ebp,esp的功能pushfd //保存现场 32位标志寄存器入栈pushad //保存现场所有通用寄存器入栈//在这里做你想做的事情popad //恢复现场popfd //恢复现场iretd //返回原指令的下一条指令继续执行原函数(71A21AF7地址处)这种方法很好,但缺点是要在IDT设置一个中断门,也就是要进RING0.3,更改CALL指令的相对地址(CALL分别在71A21B12、71A21B25、71A21B64,但前面2条CALL之前有一个条件跳转指令,有可能不被执行到,因此我们要HOOK 71A21B64处的CALL 指令)。
为什么要找CALL指令下手?因为它们都是5字节的指令,而且都是CALL指令,只要保持操作码0xE8不变,改变后面的相对地址就可以转到我们的HOOK代码去执行了,在我们的HOOK代码后面再转到目标地址去执行。
假设我们的HOOK代码在71A20400处,那么我们把71A21B64处的CALL指令改为CALL 71A20400(原指令是这样的:CALL 71A21230)而71A20400处的HOOK代码是这样的:71A20400:pushad//在这里做你想做的事情popadjmp 71A21230 //跳转到原CALL指令的目标地址,原指令是这样的:call 71A21230这种方法隐蔽性很好,但是比较难找这条5字节的CALL指令,计算相对地址也复杂。
4,替换71A21AFE地址上的cmp dword ptr [71A3201C], 71A21C93指令(机器码:813D1C20A371931CA271,10字节)成为 call 71A20400nopnopnopnopnop(机器码:E8 XX XX XX XX 90 90 90 90 90,10字节)在71A20400的HOOK代码是: pushadmov edx,71A3201Ch //模拟原指令cmp dword ptr [71A3201C], 71A21C93cmp dword ptr [edx],71A21C93h //模拟原指令cmp dword ptr [71A3201C], 71A21C93 pushfd//在这里做你想做的事popfdpopadret这种方法隐蔽性最好,但不是每个API都有这样的指令,要具体情况具体操作。