API Hook基本原理和实现
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函数。
跨进程API Hook
跨进程API Hook(初稿)detrox什么是“跨进程API Hook”?众所周知Windows应用程序的各种系统功能是通过调用API函数来实现。
API Hook就是给系统的API附加上一段小程序,它能监视甚至控制应用程序对API函数的调用。
所谓跨进程也就是让自己的程序来控制别人程序的API调用了。
API Hook 理论通过对Win32 PE文件的分析(如果你还不熟悉PE文件格式,可以看看Iczelion的PE教程或者LUEVELSMEYER的<<The PE File Format>>)。
我们知道在PE文件中的IMPORT TABLE内存储着API函数的很多信息。
其中包括API的函数名,调用地址等等。
而操作系统在执行PE文件时会先将其映射到内存中。
在映射的同时还会把当前版本操作系统中API函数的入口地址写入IMPORT TABLE中一组与API调用相关的结构体内,用于该应用程序的API调用。
当应用程序调用API时,他会在自己内存映像里寻找API的入口地址,然后执行CALL指令。
如此一来,我们通过修改应用程序内存映像的IMPORT TABLE中API函数的入口地址,就可以达到重定向API 的目的。
将API地址改为我们自己函数的地址,这样我们的函数就可以完成对API的监视和控制了。
API Hook 的实现/* 1 */HANDLE hCurrent = GetModuleHandle(NULL);/* 2 */IMAGE_DOS_HEADER *pidh;/* 3 */IMAGE_NT_HEADERS *pinh;/* 4 */IMAGE_DATA_DIRECTORY *pSymbolTable;/* 5 */IMAGE_IMPORT_DESCRIPTOR *piid;/* 6 */pidh = (IMAGE_DOS_HEADER *)hCurrent;/* 7 */pinh = (IMAGE_NT_HEADERS *)((DWORD)hCurrent + pidh->e_lfanew); /* 8 */pSymbolTable = &pinh->OptionalHeader.DataDirectory[1];/* 9 */piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hCurrent + pSymbolTable->VirtualAddress);/*10 */do {/*11 */ IMAGE_THUNK_DATA *pitd,*pitd2;/*12 */ pitd = (IMAGE_THUNK_DATA *)((DWORD)hCurrent +piid->OriginalFirstThunk);/*13 */ pitd2 = (IMAGE_THUNK_DATA *)((DWORD)hCurrent +piid->FirstThunk);/*14 */ do {/*15 */ IMAGE_IMPORT_BY_NAME *piibn;/*16 */ piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)hCurrent + *((DWORD *)pitd));/*17 */ PROC *ppfn = (PROC *)(pitd2->u1.Function);/*18 */ if (!strcmp("MessageBoxW",(char *)piibn->Name)) {/*19 */ oldMsg = (MsgBoxType)(ppfn);/*20 */ DWORD addr = (DWORD)MyMessage;/*21 */ DWORD written = 0;/* 改变内存读写状态 *//*22 */ DWORD oldAccess;/*23 */VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldA ccess);/*24 */ APIAddress = (DWORD)&pitd2->u1.Function;/* 向内存映像写入数据 *//*25 */WriteProcessMemory(GetCurrentProcess(),&pitd2->u1.Function,&addr,sizeof(DWORD), &written);/*26 */ }/*27 */ pitd++;pitd2++;/*28 */ } while (pitd->u1.Function);/*29 */ piid++;/*30 */} while (piid->FirstThunk + piid->Characteristics+ piid->ForwarderChain + piid->Name + piid->TimeDateStamp);寻觅IMPORT TALBE在/*1*/中我们使用GetModuleHandle(NULL)来返回当前进程在内存中映像的基地址。
API_HOOK讲解1
第6章APIHOOKAPIHOOK始终是系统程序员关心的热门话题。
通过APIHOOK,可以对Win32API函数进行拦截,从而改变函数乃至程序的固有行为。
通过APIHOOK拦截可以解决十分棘手的难题。
本章主要介绍Win32API拦截、驱动程序服务函数的拦截、BrowserHelpObject实现、SPI接口的应用,并利用Detours库实现对DLL的绑定。
6.1 APIHOOK综述APIHOOK尽管能够提供非常强大的功能,但是遗憾的是,无论是DDK还是SDK都没有提供这方面的任何文档和例子。
使用APIHOOK前,用户首先应该弄清楚,究竟是拦截一个应用程序还是系统范围内的拦截。
系统的拦截往往需要实现对创建的新的进程进行监视。
对系统底层服务进行拦截,能够打破进程边界。
最简单的实现拦截的方法是实现一个代理的动态链接库。
这个动态链接库实现了目标拦截动态链接库的全部输出函数,但是它只是一个函数转发器,其函数功能还是通过间接地调用原来的目标动态链接库函数实现。
当程序或者系统调用目标动态链接库的时候,真正调用的是代理动态链接库。
代理动态链接库的输出函数会首先检查调用函数的入口参数,决定直接返回一个值,还是调用原来的函数。
可以把这个函数的返回结果作为返回值返回,也可以对调用结果进行二次处理。
由于这种方法需要对所有的函数进行处理,这个过程十分繁琐,而且并非所有的函数都提供了足够的文档,因此这种方法在某些情况下几乎是无法实现的。
这方面应用的例子有关于WinInet实现的程序,发表在1994年12月份的MSJ杂志上,网址是/MSJ/0997/hood0997.htm。
对API函数的拦截不外乎两种方式,要么在磁盘文件上实现,要么在内存中实现。
前者拦截在可执行程序加载以前,后者则是在程序加载之后。
两种方法基本上都是通过打补丁的方法实现的。
如果用户以前曾经研究过APIHOOK,也许听说过导入地址表补丁的概念。
它的很多优点使得这种WindowsAPIHOOK的方法成为最体面、最常见的方法之一。
hook技术原理
Hook技术是一种用于拦截API函数调用的技术,它通过修改系统API函数的内存地址,从而拦截系统函数的调用,实现对系统API函数的拦截和修改。
Hook技术的基本原理是将系统API函数的内存地址指向一个用户定义的函数,而不是指向实际的API函数。
当调用系统API函数时,系统将调用用户定义的函数,而不是原来的函数。
这样就可以实现对系统API函数的拦截和修改。
Hook技术的实现步骤如下:
1、首先,程序员需要查找和定位需要拦截的API函数的内存地址。
2、然后,程序员需要编写用户定义的函数,用来拦截和修改系统API函数的调用。
3、接着,程序员需要将系统API函数的内存地址指向用户定义的函数,从而实现API函数的拦截。
4、最后,程序员需要将系统API函数的原始内存地址保存起来,以便在不再需要拦截时,可以恢复原来的API函数调用行为。
Hook技术是一种强大的技术,可以用来实现各种功能,比如拦截软件的调用,拦截软件的输入输出,拦截系统函数的调用等。
Hook技术也可以用来实现防病毒,反垃圾邮件,防恶意程序,实现软件保护以及实现自定义控件等功能。
陷阱式APIHook的原理及其在截取串口数据中的应用
2024/9/29
8
NewCreateFile(文件名){ 还原CreateFile; Handle = CreateFile(文件名); 修改CreateFile; if(文件名==“COM2”) 保存Handle到共享内存变量ComHandle中
}
2024/9/29
9
NewWriteFile(文件句柄,数据){ if(文件句柄=ComHandle) 修改“数据”
GetMsgProc(){ }
2
目的进程载入 DLPSLIB.dll
(寄生程序)
同步修改ReadFile跳
转到NewReadFile
NewReadFile(){ }
2024/9/29
DLPSLIB.dll
目的进程载入dll时, dll就已经成为其一
部分了
SetDIPSHook{ SetWindowsHookEx(…)
2024/9/29
6
……
调用 Call ReadFile
1
……
4
自定义函数
NewReadFile(){ 还原ReadFile 调用ReadFile 修改ReadFile
ret
}
被劫持函数 ReadFile(){
……
2
ret
3
}
2024/9/29
……
调用 Call ReadFile
1
……
9
自定义函数 NewReadFile(){
1
……
9
自定义函数 NewReadFile(){
call ShadowReadFile(); 3
}
8
ShadowyReadFile(){
影子函数
源程序程序破解之 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
hook实现原理
hook实现原理Hook,即钩子,是一种在特定事件发生之前、之中或之后执行的代码。
在编程中,钩子技术被广泛应用于各种场景,如进程间通信、事件处理、性能监控等。
本文将介绍钩子的基本原理,以及在C++编程语言中使用钩子进行事件处理的实现方法。
一、钩子的基本原理钩子是一种特殊的函数,通常在特定事件发生时被系统调用。
钩子的实现原理通常是在系统调用事件发生之前,通过某种方式拦截事件的执行流程,并添加自定义的代码。
这种实现方式依赖于编程语言的底层机制,通常涉及到操作系统的内存管理、进程控制、中断处理等方面。
在C++中,钩子的实现通常需要借助操作系统提供的API函数或内核对象来实现。
钩子的注册和注销通常需要调用相应的API函数,以便在特定事件发生时触发钩子函数。
同时,钩子函数需要具备可移植性,以便在不同的操作系统和平台上使用。
1. 钩子注册和注销在C++中,钩子的注册和注销通常需要使用操作系统提供的API函数。
例如,在Windows操作系统中,可以使用SetWindowsHookEx()函数注册钩子,使用UnhookWindowsHookEx()函数注销钩子。
这些函数需要传递钩子函数的地址作为参数,以便在特定事件发生时执行钩子函数。
2. 钩子函数的执行当事件发生时,操作系统会根据注册的钩子函数列表,依次调用相应的钩子函数。
每个钩子函数会在事件发生的过程中添加自定义的代码,从而实现钩子的功能。
钩子函数的执行顺序和执行时机取决于注册时的顺序和条件。
3. 钩子的类型和用途钩子根据实现方式可以分为不同的类型,如键盘钩子、鼠标钩子、定时器钩子等。
不同类型的钩子适用于不同的场景,如键盘钩子可用于实现键盘快捷键功能,鼠标钩子可用于实现鼠标事件处理等。
根据用途不同,钩子可以应用于各种编程场景,如游戏开发、网络通信、应用性能监控等。
三、案例分析:C++游戏开发中的钩子实现在C++游戏开发中,钩子技术常用于事件处理和性能监控。
以下是一个简单的示例程序,展示了如何在游戏开发中使用钩子技术:1. 程序初始化时注册鼠标移动钩子在程序初始化时,使用系统API函数注册鼠标移动钩子。
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())。
这样,当函数每次执⾏⽬标函数的时候,就会跳转到我们⾃定义的函数⾥⾯去。
HOOKAPI(一)——HOOK基础+一个鼠标钩子实例
HOOKAPI(⼀)——HOOK基础+⼀个⿏标钩⼦实例HOOK API (⼀)——HOOK基础+⼀个⿏标钩⼦实例code: https:///hfl15/windows_kernel_development/tree/master/demo_source_code/MouseHook0x00 起因最近在做毕业设计,有⼀个功能是需要实现对剪切板的监控和进程的防终⽌保护。
原本想从内核层实现,但没有头绪。
最后决定从调⽤层⼊⼿,即采⽤HOOK API的技术来挂钩相应的API,从⽽实现预期的功能。
在这样的需求下,就开始学习了HOOK API。
0x01什么是HOOK APIHOOK(钩⼦,挂钩)是⼀种实现Windows平台下类似于中断的机制。
HOOK机制允许应⽤程序拦截并处理Windows消息或指定事件,当指定的消息发出后,HOOK程序就可以在消息到达⽬标窗⼝之前将其捕获,从⽽得到对消息的控制权,进⽽可以对该消息进⾏处理或修改,加⼊我们所需的功能。
钩⼦按使⽤范围分,可分为线程钩⼦和系统钩⼦,其中,系统钩⼦具有相当⼤的功能,⼏乎可以实现对所有Windows消息的拦截、处理和监控。
这项技术涉及到两个重要的API,⼀个是SetWindowsHookEx,安装钩⼦;另⼀个是UnHookWindowsHookEx,卸载钩⼦。
本⽂使⽤的HOOK API技术,是指截获系统或进程对某个API函数的调⽤,使得API的执⾏流程转向我们指定的代码段,从⽽实现我们所需的功能。
Windows下的每个进程均拥有⾃⼰的地址空间,并且进程只能调⽤其地址空间内的函数,因此HOOK API尤为关键的⼀步是,设法将⾃⼰的代码段注⼊到⽬标进程中,才能进⼀步实现对该进程调⽤的API进⾏拦截。
然⽽微软并没有提供HOOK API的调⽤接⼝,这就需要开发者⾃⼰编程实现,⼤家所熟知的防毒软件、防⽕墙软件等均采⽤HOOK API实现。
⼀般来说,HOOK API由两个组成部分,即实现HOOK API的DLL⽂件,和启动注⼊的主调程序。
软件逆向工程原理与实践第6章API钩取
第6章 API钩取
DEBUG_EVENT结构体的详细定义见表6-2。 dwDebugEventCode是调试事件类型码, 共有9种取值:
(1) CREATE_PROCESS_DEBUG_EVENT,值为3; (2) CREATE_THREAD_DEBUG_EVENT,值为2; (3) EXCEPTION_DEBUG_EVENT,值为1; (4) EXIT_PROCESS_DEBUG_EVENT,值为5; (5) EXIT_THREAD_DEBUG_EVENT,值为4; (6) LOAD_DLL_DEBUG_EVENT,值为6; (7) OUTPUT_DEBUG_STRING_EVENT,值为8; (8) RIP_EVENT,值为9; (9) UNLOAD_DLL_DEBUG_EVENT,值为7。
第6章 API钩取
6.3 修改IAT实现API钩取
通过更改PE文件的IAT,实际上能够将IAT中的API地址 更改为钩取函数的地址,这种方法实现起来较为简单,但对 于那些没有存在于IAT中的API,没有办法通过修改IAT来实 现对它们的钩取,因此对这种API的调用也就不会触发API 钩取。
通过修改IAT实现API钩取的基本原理见表6-3和表6-4。
第6章 API钩取
本节所指的调试器,不是OllyDbg这样的调试工具,而 是由用户编写的用来钩取的程序。这种程序与目标程序的关 系,可以看作调试者与被调试者之间的关系。通过调试钩取 API需要利用上述的断点机制,一般步骤如下:
(1) 将需要被钩取的进程置为被调试者; (2) 将被调试者的某API的第一个字节改为0xCC; (3) 在被调试者进程中该API被调用,被调试者挂起, 控制权转入调试器;
第6章 API钩取
第6章 API钩取
陷阱式APIHook的原理及其在截取串口数据中的应用共19页文档
2019/10/28
1
2019/10/28
2
利用API Hook技术将我们的程序代码注入其他进程
修改系统中的ReadFile、WriteFile、CreateFile和CloseHandle函 数
2019/10/28
3
1、Windows为了保护进程而不允许进程之间的访问。 2、使用API Hook 给目标进程设置一个特定消息Hook, 在发生这种消息的时候就会自动调用Hook函数。 3 、 Hook 函 数 只 能 存 在 与 DLL 中 , 因 为 只 有 DLL 可 以 “大家一起用”。
还原ReadFile
3
调用ReadFile
4
修改ReadFile
7
ret }
8
被劫持函数
ReadFile(){ jmp NewReadFile …… ret
}
25 6
7
截取串口数据,实际上就是利用上述原理修改系统的4个API: CreateFile、ReadFile、WriteFile和CloseHandle,利用 NewCreateFile截获串口打开时的设备句柄,在NewReadFile和 NewWriteFile中用串口设备句柄识别串口的读写操作并对其数据 进行观察控制。
还原WriteFile; WriteFile(文件句柄,数据); 修改WriteFile; }
2019/10/28
10
NewReadFile(文件句柄,数据){ 还原ReadFile; ReadFile(文件句柄,数据); 修改ReadFile;
if(文件句柄=ComHandle) 修改“数据”
}
陷阱式APIHook的原理及其在截取串口数据中的应用-精选文档
调用
自定义函数
…… Call ReadFile …… NewReadFile(){ call ShadowReadFile(); } ShadowyReadFile(){ ReadFile的前x条指令 jmp &(指令x+1) …… } ReadFile(){ jmp NewReadFile 指令x+1 …… ret }
2019/3/9
4
共享内存
控制进程
截获的数据放在 这里能够被任何 进程访问
只要两个函数的参 数一样,即堆栈结 构一样,就可以相 目标进程 互代替
…… Call ReadFile; ……
1
WinAPI WINMAIN(…){ … SetDIPSHook … }
SimpleDIP.exe
3 6 4
思考:能直 接跳转吗?
2019/3/9
自定义函数
3
4 7
8
2 3
被劫持函数 ReadFile(){ jmp NewReadFile …… ret }
2
5 6
7
截取串口数据,实际上就是利用上述原理修改系统的4个API: CreateFile、ReadFile、WriteFile和CloseHandle,利用 NewCreateFile截获串口打开时的设备句柄,在NewReadFile和 NewWriteFile中用串口设备句柄识别串口的读写操作并对其数据 进行观察控制。
,这对系统的稳定性造成极为恶劣的影响! 为了防止多个线程竞争使用API,不得不用互斥量对 其进行保护,这又严重影响了系统的执行效率。很多 时候这是不能容忍的。 对此而开发了一种只需要一次修改被劫持函数的方法 ——影子函数法
hook原理
hook原理
Hook原理是一种编程手段,它可以在不修改源代码的情况下,通过在应用程序的关键步骤之前或之后插入特定的代码,来实现对应用程序的功能增强、维护或检测。
Hook原理是一种“挂钩”机制,即在应用程序运行时,通过挂钩机制,将第三方软件插入原来的程序中,从而实现功能拓展,是一种常用的API和操作系统级别的编程技术。
Hook原理可以用来实现各种功能,如增强处理器性能、实现数据存储、实现调试技术、运行安全性检查、更新应用程序、保护数据和确保安全等等。
Hook原理的实现可以通过几种方法,包括直接在应用程序的关键函数上添加hook代码,将hook代码作为程序的一部分添加,或使用已有的应用程序接口(API)来实现hook原理。
首先,要实现hook原理,就必须在应用程序的关键函数上添加hook代码,即在函数的入口处和出口处添加hook 代码,以便在函数的入口处检查函数的参数,在函数的出口处检查函数的返回值,并在此基础上实现相应的功能增强。
其次,可以将hook代码作为应用程序的一部分添
加,即在调用函数的入口处添加hook代码,以便在调用函数之前和之后进行检查,实现相应的功能增强。
另外,也可以利用已有的应用程序接口(API)来实现hook原理。
API中有一组特殊的函数,可以在应用程序的关键步骤之前或之后插入特定的代码,以便实现功能增强、维护或检测。
比如,Windows系统中的SetWindowHookEx函数,可以让用户在应用程序的特定消息发生时,即时地收到消息,从而实现功能增强或检测。
以上就是hook原理的实现方式。
hook原理广泛应用于编程中,可以实现各种功能,有助于提高应用程序的性能和安全性。
Apihook
API拦截(API HOOK)技术及应用常用的API Hook(截取API,或函数钩子)有两种方式:陷阱式、改引入表式。
在Windows 9x、WindowsNT/2000这两个系统中的API Hook代码完全不同。
就Windows 9x而言,16位DLL与32位DLL的API Hook代码也完全不相同。
API HOOK入门API Hook是一项有趣而实用的Windows系统编程技术,应用领域十分广泛,屏幕取词、内码转换、屏幕翻译、中文平台、网络防火墙、串口红外通信或Internet通信的监视等,都涉及到了此项技术。
API Hook就是钩住API,钩就是绕弯的意思,即让API函数的调用先绕一个弯路,在它执行之前,先做一些“预处理”,这样我们就可以监视或定制某个Win32 API的调用,以实现一些特殊的功能。
至于具体可以实现些什么样的功能,就取决于程序设计者的想象力了。
在很多情况下,想监视或改变某个应用程序的一些特定的操作,但是该应用程序却没有提供相应的接口,而又几乎不可能得到其源代码。
因为大多数Windows应用程序的操作很大程度上依赖于API,所以可以采用API Hook的方式来试图监视和改变应用程序的行为。
常用的API Hook有两种方式:陷阱式和改引入表式。
API Hook的运行平台有三种:Windows 9x的16位DLL、Windows 9x的32位DLL和Windows NT/2000的32位DLL。
其关系如表7-1所示。
表7-1 API Hook的方式表示在VC下可以实现,在C++Builder/Delphi下很难实现;√表示可以实现。
表7-2列出了两种方式各自的优缺点。
陷井式API HOOK原理Windows NT/2000陷阱式API Hook的工作原理如图1所示。
其工作过程如下:(1)加载陷阱式API Hook时,需要定位至被截函数处(图中是BF501234),写入一条跳转指令(Jmp XXXX,二进制代码为E9XXXX),表示所有程序调用被截函数时都自动跳转到自定义函数。
DLL 注入hook API
二、API Hook 的原理 这里的 API 既包括传统的 Win32 APIs,也包括任何 Module 输出的函数调用。熟悉 PE 文件格 式的朋友都知道, PE 文件将对外部 Module 输出函数的调用信息保存在输入表中,即.idata 段。 下面首先介绍本段的结构。 输入表首先以一个 IMAGE_IMPORT_DESCRIPTOR(简称 IID)数组开始。每个被 PE 文件隐式链接 进来的 DLL 都有一个 IID.在这个数组中的最后一个单元是 NULL,可以由此计算出该数组的项数。 例如,某个 PE 文件从两个 DLL 中引入函数,就存在两个 IID 结构来描述这些 DLL 文件,并在两个 IID 结构的最后由一个内容全为 0 的 IID 结构作为结束。几个结构定义如下: IMAGE_IMPORT_DESCRIPTOR struct union{ DWORD Characteristics; ;00h DWORD OriginalFirstThunk; }; TimeDateStamp DWORD ;04h ForwarderChain DWORD ;08h Name DWORD ;0Ch FirstThunk DWORD ;10h IMAGE_IMPROT_DESCRIPTOR ends typedef struct _IMAGE_THUNK_DATA{ union{ PBYTE ForwarderString; PDWORD Functions; DWORD Ordinal; PIMAGE_IMPORT_BY_NAME AddressOfData; }u1; } IMAGE_IMPORT_BY_NAME 结构保存一个输入函数的相关信息: IMAGE_IMPORT_BY_NAME struct Hint WORD ? ;本函数在其所驻留 DLL 的输出表中的序号 Name BYTE ? ;输入函数的函数名,以 NULL 结尾的 ASCII 字符串 IMAGE_IMPORT_BY_NAME ends
python学习之hook钩子的原理和使用
python学习之hook钩⼦的原理和使⽤什么是钩⼦之前有转⼀篇关于回调函数的钩⼦函数、注册函数、回调函数,他们的概念其实是⼀样的。
钩⼦函数,顾名思义,就是把我们⾃⼰实现的hook函数在某⼀时刻挂接到⽬标挂载点上。
1. hook函数,就是我们⾃⼰实现的函数,函数类型与挂载点匹配(返回值,参数列表)2. 挂接,也就是hook或者叫注册(register),使得hook函数对⽬标可⽤3. ⽬标挂载点,也就是挂我们hook函数的地⽅(我们想在这个⽬标点实现我们⾃⼰的功能)先看⼀张图:hook的概念在windows的消息响应机制⾥⾯体现的尤为明显。
可能我们⼤家有写过windows桌⾯相关的程序(像MFC),⾥⾯有各种消息监听响应机制。
⽐如,要监听⿏标左键是否按下这个事件,我们要去实现⼀个onLeftKeyDown()之类的⽅法,该⽅法可以称为钩⼦函数。
同时,我们还要去注册钩⼦函数,MFC中是通过⼀组宏来实现的。
这样当⿏标左键按下后,就能调到我们定义的⽅法了。
为什么需要钩⼦⼤家思考⼀下上⾯这个例⼦,左键按下⽅法具体的逻辑是由框架⾃⾝去实现,还是由我们⽤户(调⽤者)去实现呢?显然应该由我们⾃⼰去实现。
要提供通⽤的框架能⼒,框架⾃⾝去实现该⽅法功能,是没有意义的,所以框架给提供⼀个挂载的point,把具体逻辑的实现交给⽤户就好了,灵活可⽤。
钩⼦使⽤hook是⼀个编程机制,与语⾔⽆关。
这⾥给个python的简单例⼦,帮助⼤家理解:import timeclass LazyPerson(object):def __init__(self, name): = nameself.watch_tv_func = Noneself.have_dinner_func = Nonedef get_up(self):print("%s get up at:%s" % (, time.time()))def go_to_sleep(self):print("%s go to sleep at:%s" % (, time.time()))def register_tv_hook(self, watch_tv_func):self.watch_tv_func = watch_tv_funcdef register_dinner_hook(self, have_dinner_func):self.have_dinner_func = have_dinner_funcdef enjoy_a_lazy_day(self):# get upself.get_up()time.sleep(3)# watch tv# check the watch_tv_func(hooked or unhooked)# hookedif self.watch_tv_func is not None:self.watch_tv_func()# unhookedelse:print("no tv to watch")time.sleep(3)# have dinner# check the have_dinner_func(hooked or unhooked)# hookedif self.have_dinner_func is not None:self.have_dinner_func()# unhookedelse:print("nothing to eat at dinner")time.sleep(3)self.go_to_sleep()def watch_daydayup(name):print("%s : The program ---day day up--- is funny" % name)def watch_happyfamily(name):print("%s : The program ---happy family--- is boring" % name)def eat_meat(name):print("%s : The meat is nice" % name)def eat_hamburger(name):print("%s : The hamburger is not so bad" % name)if __name__ == "__main__":lazy_tom = LazyPerson("Tom")lazy_jerry = LazyPerson("Jerry")# register hooklazy_tom.register_tv_hook(watch_daydayup)lazy_tom.register_dinner_hook(eat_meat)lazy_jerry.register_tv_hook(watch_happyfamily)lazy_jerry.register_dinner_hook(eat_hamburger)# enjoy a daylazy_tom.enjoy_a_lazy_day()lazy_jerry.enjoy_a_lazy_day()代码运⾏结果:Tom get up at:1509246940.32Tom : The program ---day day up--- is funnyTom : The meat is niceTom go to sleep at:1509246949.34Jerry get up at:1509246949.34Jerry : The program ---happy family--- is boringJerry : The hamburger is not so badJerry go to sleep at:1509246958.37以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
Windows下APIHook技术
Windows下APIHook技术1 前⾔在Micrisoft Windows中,每个进程都有⾃⼰的私有地址空间。
当我们⽤指针来引⽤内存的时候,指针的值表⽰的是进程⾃⼰的⾃制空间的⼀个内存地址。
进程不能创建⼀个指针来引⽤属于其他进程的内存。
独⽴的地址控件对开发⼈员和⽤户来说都是⾮常有利的。
对开发⼈员来说,系统更有可能捕获错误的内存读\写。
对⽤户⽽⾔,操作系统变得更加健壮。
当然这样的健壮性也是要付出代价的,因为它使我们很难编写能够与其他进程通信的应⽤程序或对其他进程进⾏操控的应⽤程序。
在《Windows 核⼼编程》第⼆⼗⼆章《DLL注⼊和API拦截》中讲解了多种机制,他们可以将⼀个DLL注⼊到另⼀个进程地址的空间中。
⼀旦DLL代码进⼊另⼀个地址空间,那么我们就可以在那个进程中随⼼所欲了。
本⽂主要介绍了如何实现替换Windows上的API函数,实现Windows API HOOK。
API HOOK的实现⽅法⼤概不下五六种。
本位主要介绍了其中的⼀种,即如何使⽤WIndows挂钩来注⼊DLL。
2 使⽤Windows挂钩来注⼊DLL2.1 简单windows消息HOOK2.1.1 SetWindowsHookEx这个是安装狗⼦的函数声明如下:HHOOK WINAPI SetWindowsHookEx(__in int idHook, \\钩⼦类型__in HOOKPROC lpfn, \\回调函数地址__in HINSTANCE hMod, \\实例句柄__in DWORD dwThreadId); \\线程ID,0表⽰所有让我们通过⼀个例⼦来学些下这个API。
进程A(⼀个游戏改建⼯具,需要接获键盘消息),安装了WH_KEYBOARD_LL挂钩,如下所⽰:HOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstDll, 0); 第⼀个参数表⽰挂钩类型,是⼀个低级键盘钩⼦。
API Hook基本原理和实现
API Hook基本原理和实现Hook是什么?Windows系统下的编程,消息message的传递是贯穿其始终的。
这个消息我们可以简单理解为一个有特定意义的整数,正如我们看过的老故事片中的“长江长江,我是黄河”一个含义。
windows中定义的消息给初学者的印象似乎是“不计其数”的,常见的一部分消息在winuser.h头文件中定义。
hook与消息有着非常密切的联系,它的中文含义是“钩子”,这样理解起来我们不难得出“hook是消息处理中的一个环节,用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过程前,处理某些特定的消息”。
这也是hook分为不同种类的原因。
hook的这个本领,使它能够将自身的代码“融入”被hook住的程序的进程中,成为目标进程的一个部分。
我们也知道,在windows2000以后的系统中,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。
这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是hook的出现给我们开拓了解决此类问题的道路。
API Hook是什么?在windows系统下编程,应该会接触到api函数的使用,常用的api函数大概有2000个左右。
今天随着控件,stl等高效编程技术的出现,api的使用概率在普通的用户程序上就变得越来越小了。
当诸如控件这些现成的手段不能实现的功能时,我们还需要借助api。
最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样api hook就自然而然的出现了。
我们可以通过api hook,改变一个系统api 的原有功能。
基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数。
api hook并不属于msdn上介绍的13类hook中的任何一种。
所以说,api hook并不是什么特别不同的hook,它也需要通过基本的hook提高自己的权限,跨越不同进程间访问的限制,达到修改api函数地址的目的。
Hook(钩子技术)基本知识讲解,原理
Hook(钩⼦技术)基本知识讲解,原理⼀、什么是HOOK(钩⼦) APIWindows消息传递机制,当在应⽤程序进⾏相关操作,例如点击⿏标、按下键盘,操作窗⼝等,操作系统能够感知这⼀事件,接着把此消息放到系统消息队列,然后到应⽤程序的消息序列中,应⽤程序通过Getmessage函数取出消息,然后调⽤DispatchMessage函数将这条消息调度给操作系统,操作系统会调⽤在设计窗⼝类时指定的应⽤程序窗⼝对这⼀消息进⾏处理,处理过程如图所⽰:在《VC深⼊详解》⼀书将钩⼦过程⽐喻为警察为了抓逃犯⽽设置的检查站,基本原理也确实与此类似。
就是在应⽤程序将信息传递给操作系统时(图中③的),对消息进⾏捕获和过滤,从⽽阻⽌消息发送到指定的窗⼝过程,最终完成对某些消息的屏蔽功能。
HOOK(钩⼦,挂钩)是⼀种实现Windows平台下类似于中断的机制。
HOOK机制允许应⽤程序拦截并处理Windows消息或指定事件,当指定的消息发出后,HOOK程序就可以在消息到达⽬标窗⼝之前将其捕获,从⽽得到对消息的控制权,进⽽可以对该消息进⾏处理或修改,加⼊我们所需的功能。
钩⼦按使⽤范围分,可分为线程钩⼦和系统钩⼦,其中,系统钩⼦具有相当⼤的功能,⼏乎可以实现对所有Windows消息的拦截、处理和监控。
这项技术涉及到两个重要的API,⼀个是SetWindowsHookEx,安装钩⼦;另⼀个是UnHookWindowsHookEx,卸载钩⼦。
对于Windows系统,它是建⽴在事件驱动机制上的,说⽩了就是整个系统都是通过消息传递实现的。
hook(钩⼦)是⼀种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往⽬标窗⼝的消息并进⾏处理。
所以说,我们可以在系统中⾃定义钩⼦,⽤来监视系统中特定事件的发⽣,完成特定功能,如屏幕取词,监视⽇志,截获键盘、⿏标输⼊等等。
程序员在讨论时也常说“可以先钩住再处理”,即执⾏某操作之前,优先处理⼀下,再决定后⾯的执⾏⾛向。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
API Hook基本原理和实现[图文]关键字:API Hook,消息,拦截API,钩子,wskjuf作者:wskjuf 更新:2007-12-23 08:18:25 浏览:18142注:本文主要为解决论坛上/forum/forum_posts.asp?TID=7281的提问而写的。
我搜索了一下互联网,将网络上几篇有代表性的api hook文章的精华进行了浓缩和适当简化,写成这篇介绍性文章。
另外也希望初学者能够认真思考本文采用的循序渐进的分析思路,如何解决了一个未知的问题。
文中借鉴的文献资料列于文末附录一节。
hook是什么?windows系统下的编程,消息message的传递是贯穿其始终的。
这个消息我们可以简单理解为一个有特定意义的整数,正如我们看过的老故事片中的“长江长江,我是黄河”一个含义。
windows中定义的消息给初学者的印象似乎是“不计其数”的,常见的一部分消息在winuser.h头文件中定义。
hook与消息有着非常密切的联系,它的中文含义是“钩子”,这样理解起来我们不难得出“hook是消息处理中的一个环节,用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过程前,处理某些特定的消息”。
这也是hook分为不同种类的原因。
hook的这个本领,使它能够将自身的代码“融入”被hook住的程序的进程中,成为目标进程的一个部分。
我们也知道,在windows2000以后的系统中,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。
这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是hook的出现给我们开拓了解决此类问题的道路。
api hook是什么?在windows系统下编程,应该会接触到api函数的使用,常用的api函数大概有2000个左右。
今天随着控件,stl等高效编程技术的出现,api的使用概率在普通的用户程序上就变得越来越小了。
当诸如控件这些现成的手段不能实现的功能时,我们还需要借助api。
最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样api hook就自然而然的出现了。
我们可以通过api hook,改变一个系统api的原有功能。
基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数。
api hook并不属于msdn上介绍的13类hook中的任何一种。
所以说,api hook并不是什么特别不同的hook,它也需要通过基本的hook提高自己的权限,跨越不同进程间访问的限制,达到修改api函数地址的目的。
对于自身进程空间下使用到的api函数地址的修改,是不需要用到api hook技术就可以实现的。
api hook和pe格式的关系api hook技术的难点,并不在于hook技术,初学者借助于资料“照葫芦画瓢”能够很容易就掌握hook的基本使用技术。
但是如何修改api函数的入口地址?这就需要学习pe可执行文件(.exe,.dll等)如何被系统映射到进程空间中,这就需要学习pe格式的基本知识。
windows已经提供了很多数据结构struct帮助我们访问pe格式,借助它们,我们就不要自己计算格式的具体字节位置这些繁琐的细节。
但是从api hook的实现来看,pe格式的访问部分仍然是整个编程实现中最复杂的一部分,对于经常crack的朋友不在此列。
假设我们已经了解了pe格式,那么我们在哪里修改api的函数入口点比较合适呢?这个就是输入符号表imported symbols table(间接)指向的输入符号地址。
下面对于pe格式的介绍这一部分,对于没有接触过pe格式学习的朋友应该是看不太明白的,但我已经把精华部分提取出来了,学习了pe格式后再看这些就很容易了。
pe格式的基本组成+-------------------+| DOS-stub | --DOS-头+-------------------+| file-header | --文件头+-------------------+| optional header | --可选头|- - - - - - - - - -|| || data directories | --(可选头尾的)数据目录| |+-------------------+| || section headers | --节头| |+-------------------+| || section 1 | --节1| |+-------------------+| || section 2 | --节2| |+-------------------+| || ... || |+-------------------+| || section n | --节n| |+-------------------+在上图中,我们需要从“可选头”尾的“数据目录”数组中的第二个元素——输入符号表的位置,它是一个IMAGE_DATA_DIRECTORY结构,从它中的VirtualAddress地址,“顺藤摸瓜”找到api函数的入口地点。
下图的简单说明如下:OriginalFirstThunk 指向IMAGE_THUNK_DATA结构数组,为方便只画了数组的一个元素,AddressOfData 指向IMAGE_IMPORT_BY_NAME结构。
IMAGE_IMPORT_DESCRIPTOR数组:每个引入的dll文件都对应数组中的一个元素,以全0的元素(20个bytes的0)表示数组的结束IMAGE_THUNK_DATA32数组:同一组的以全0的元素(4个bytes的0)表示数组的结束,每个元素对应一个IMAGE_IMPORT_BY_NAME结构IMAGE_IMPORT_BY_NAME:如..@Consts@initialization$qqrv. 表示Unmangled Borland C++ Function: qualified function __fastcall Consts::initialization()为了减少这个图的大小,不得已将汇编和c++的结构都用上了。
这个图是输入符号表初始化的情形,此时两个IMAGE_THUNK_DATA结构数组的对应元素都指向同一个IMAGE_IMPORT_BY_NAME结构。
程序加载到进程空间后,两个IMAGE_THUNK_DATA结构数组指向有所不同了。
看下图:// 本文转自 C++Builder研究 -/article.asp?i=1036&d=cf6de2始化的,“两个结构都指向同一个IMAGE_IMPORT_BY_NAME”,此时还没有api 函数地址当PE文件准备执行时,前图已转换成上图。
一个结构指向不变,另一个出现api 函数地址如果PE文件从kernel32.dll中引入10个函数,那么IMAGE_IMPORT_DESCRIPTOR 结构的 Name1域包含指向字符串"kernel32.dll"的RVA,同时每个IMAGE_THUNK_DATA 数组有10个元素。
(RVA是指相对地址,每一个可执行文件在加载到内存空间前,都以一个基址作为起点,其他地址以基址为准,均以相对地址表示。
这样系统加载程序到不同的内存空间时,都可以方便的算出地址) 上述这些结构可以在winnt.h头文件里查到。
具体编程实现我将手上的vc示例代码进行了适当修正,修改了一些资源泄漏的小问题,移植到c++builder6 & update4上,经过测试已经可以完成基本的api hook功能。
有几个知识点说明一下:1、 dll中共享内存变量的实现正常编译下的dll,它的变量使用到的内存是独立的。
比如你同时运行两个调用了某个dll的用户程序,试图对某一个在dll中定义的全局变量修改赋值的时候,两个程序里的变量值仍然是不同的。
共享的方法为:在.cpp文件(.h文件里如此设置会提示编译错误)的头部写上如上两行:#pragma option -zRSHSEG // 改变缺省数据段名#pragma option -zTSHCLASS // 改变缺省数据类名HINSTANCE hdll = NULL; // 用来保存该动态连接库的句柄HHOOK hApiHook = NULL; // 钩子句柄HHOOK hWndProc = NULL; // 窗口过程钩子用来拦截SendMessageint threadId = 0;另外建立一个与dll同名,不同后缀的def文件,如HookDll.def文件,写上:LIBRARY HookDll.dllEXPORTS;...SEGMENTSSHSEG CLASS 'SHCLASS' SHARED;end这样设置后在.cpp文件中定义的变量,如果进行了初始化,将进入“SHCLASS”共享内存段(如果不初始化,将不改变其默认段属性)。
上述的共享对于本示例代码并不是必须的,只是稍微演示了一下。
2、 api hook修改api函数入口点地址的时机很显然,我们必须通过hook进入目标进程的地址空间后,再在位于该地址空间里的hook消息处理过程里修改输入符号表“指向”的api函数入口点地址,退出hook前也必须在这个消息处理过程里恢复原来的地址。
只要我们牢记修改的过程发生在目标进程的地址空间中,就不会发生访问违例的错误了。
示例代码使用了WH_GETMESSAGE、WH_CALLWNDPROC两中hook来演示如何hook api,但WH_GETMESSAGE实际上并没有完成具体的功能。
为了让初学者尽快的掌握重点,我将代码进行了简化,是一个不健壮、不灵活的演示示例。
3、函数的内外部表现形式例如api函数MessageBox,这个形式是我们通常用到的,但到了dll里,它的名字很可能出现了两个形式,一个是MessageBoxA,另一个是MessageBoxW,这是因为系统需要适应Ansi和Unicode编码的两种形式,我们不在函数尾端添加“A”或“W”,是不能hook到需要的函数的。
4、辅助pe格式查看工具PE Explorer是一个非常好的查看pe资源的工具,通过它可以验证自己手工计算的pe地址,可以更快的掌握pe格式。
调试器ollydbg也是非常好的辅助工具,例如查看输入符号表中的api函数。
5、程序文件列表dll基本文件:Hook.h,Hook.cpp,HookDll.defclient验证方基本文件:HookTest.h,HookTest.cpp,ApiHookTest.cpp6、实现的功能对记事本的MessageBoxW函数进行了hook,先执行自定义的int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR M1, LPCWSTR M2, UINT M3) {return oldMessageBoxW(hWnd, M1, L"my api hook", M3);}从这里可以看到,由于目标进程空间中的执行线程并不知道你已经改变了api函数的实际入口地址,它在调用时仍旧将参数一成不变的压入堆栈(这个说法是汇编代码时看到的等价情形),事实上你已经提前接收到了函数调用的所有参数。