hook编程的问题
看来还是初学者。
代码贴出来吧,这样想解答也是莫名其妙
看了你的代码,
头部改为如下样子:
#include"stdafx.h"
#include
#include"Hook.h"
——记住,“#include"stdafx.h"”要放在所有其它#include的前面。
具体的挂钩子的操作你都还没做,要做的工作还很多啊。。。,多在网上搜搜资料吧
本回答由提问者推荐
什么是HOOK功能?
HOOKAPI是一个永恒的话题,如果没有HOOK,许多技术将很难实现,也许根本不能实现。这里所说的API,是广义上的API,它包括DOS下的中断,WINDOWS里的API、中断服务、IFS和NDIS过滤等。比如大家熟悉的即时翻译软件,就是靠HOOKTextOut()或ExtTextOut()这两个函数实现的,在操作系统用这两个函数输出文本之前,就把相应的英文替换成中文而达到即时翻译;IFS和NDIS过滤也是如此,在读写磁盘和收发数据之前,系统会调用第三方提供的回调函数来判断操作是否可以放行,它与普通HOOK不同,它是操作系统允许的,由操作系统提供接口来安装回调函数。
甚至如果没有HOOK,就没有病毒,因为不管是DOS下的病毒或WINDOWS里的病毒,都是靠HOOK系统服务来实现自己的功能的:DOS下的病毒靠HOOKINT21来感染文件(文件型病毒),靠HOOKINT13来感染引导扇区(引导型病毒);WINDOWS下的病毒靠HOOK系统API(包括RING0层的和RING3层的),或者安装IFS(CIH病毒所用的方法)来感染文件。因此可以说“没有HOOK,就没有今天多姿多彩的软件世界”。
由于涉及到专利和知识产权,或者是商业机密,微软一直不提倡大家HOOK它的系统API,提供IFS和NDIS等其他过滤接口,也是为了适应杀毒软件和防火墙的需要才开放的。所以在大多数时候,HOOKAPI要靠自己的力量来完成。
HOOKAPI有一个原则,这个原则就是:被HOOK的API的原有功能不能受到任何影响。就象医生救人,如果把病人身体里的病毒杀死了,病人也死了,那么这个“救人”就没有任何意义了。如果你HOOKAPI之后,你的目的达到了,但API的原有功能失效了,这样不是HOOK,而是REPLACE,操作系统的正常功能就会受到影响,甚至会崩溃。
HOOKAPI的技术,说起来也不复杂,就是改变程序流程的技术。在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的尾部,比如HOOKCreateFilaA(),如果你在API尾部HOOKAPI,那么此时你就不能写文件,甚至不能访问文件;HOOKRECV(),如果你在API头HOOK,此时还没有收到数据,你就去查看RECV()的接收缓冲区,里面当然没有你想要的数据,必须等RECV()正常执行后,在RECV()的尾部HOOK,此时去查看RECV()的缓冲区,里面才有想要的数据;
4,上下文的问题,有些HOOK代码不能执行某些操作,否则会破坏原API的上下文,原API就失效了;
5,同步问题,在HOOK代码里尽量不使用全局变量,而使用局部变量,这样也是模块化程序的需要;
6,最后要注意的是,被替换的CPU指令的原有功能一定要在HOOK代码的某个地方模拟实现。
下面以ws2_32.dll里的send()为例子来说明如何HOOK这个函数:
Exportedfn():send-Ord:0013h
地址机器码汇编代码
:71A21AF455pushebp//将被HOOK的机器码(第1种方法)
:71A21AF58BECmovebp,esp//将被HOOK的机器码(第2种方法)
:71A21AF783EC10subesp,00000010
:71A21AFA56pushesi
:71A21AFB57pushedi
:71A21AFC33FFxoredi,edi
:71A21AFE813D1C20A371931CA271cmpdwordptr[71A3201C],71A21C93//将被HOOK的机器码(第4种方法)
:71A21B080F84853D0000je71A25893
:71A21B0E8D45F8leaeax,dwordptr[ebp-08]
:71A21B1150pusheax
:71A21B12E869F7FFFFcall71A21280
:71A21B173BC7cmpeax,edi
:71A21B198945FCmovdwordptr[ebp-04],eax
:71A21B1C0F85C4940000jne71A2AFE6
:71A21B22FF7508push[ebp+08]
:71A21B25E826F7FFFFcall71A21250
:71A21B2A8BF0movesi,eax
:71A21B2C3BF7cmpesi,edi
:71A21B2E0F84AB940000je71A2AFDF
:71A21B348B4510moveax,dwordptr[ebp+10]
:71A21B3753pushebx
:71A21B388D4DFCleaecx,dwordptr[ebp-04]
:71A21B3B51pushecx
:71A21B3CFF75F8push[ebp-08]
:71A21B3F8D4D08leaecx,dwordptr[ebp+08]
:71A21B4257pushedi
:71A21B4357pushedi
:71A21B44FF7514push[ebp+14]
:71A21B478945F0movdwordptr[ebp-10],eax
:71A21B4A8B450Cmoveax,dwordptr[ebp+0C]
:71A21B4D51pushecx
:71A21B4E6A01push00000001
:71A21B508D4DF0leaecx,dwordptr[ebp-10]
:71A21B5351pushecx
:71A21B54FF7508push[ebp+08]
:71A21B578945F4movdwordptr[ebp-0C],eax
:71A21B5A8B460Cmoveax,dwordptr[esi+0C]
:71A21B5DFF5064call[eax+64]
:71A21B608BCEmovecx,esi
:71A21B628BD8movebx,eax
:71A21B64E8C7F6FFFFcall71A21230//将被HOOK的机器码(第3种方法)
:71A21B693BDFcmpebx,edi
:71A21B6B5Bpopebx
:71A21B6C0F855F940000jne71A2AFD1
:71A21B728B4508moveax,dwordptr[ebp+08]
:71A21B755Fpopedi
:71A21B765Epopesi
:71A21B77C9leave
:71A21B78C21000ret0010
下面用4种方法来HOOK这个API:
1,把API入口的第一条指令是PUSHEBP指令(机器码0x55)替换成INT3(机器码0xcc),然后用WINDOWS提供的调试函数来执行自己的代码,这中方法被SOFTICE等DEBUGER广泛采用,它就是通过BPX在相应的地方设一条INT3指令来下断点的。但是不提倡用这种方法,因为它会与WINDOWS或调试工具产生冲突,而汇编代码基本都要调试;
2,把第二条movebp,esp指令(机器码8BEC,2字节)替换为INTF0指令(机器码CDF0),然后在IDT里设置一个中断门,指向我们的代码。我这里给出一个HOOK代码:
leaebp,[esp+12]//模拟原指令movebp,esp的功能
pushfd//保存现场
pushad//保存现场
//在这里做你想做的事情
popad//恢复现场
popfd//恢复现场
iretd//返回原指令的下一条指令继续执行原函数(71A21AF7地址处)
这种方法很好,但缺点是要在IDT设置一个中断门,也就是要进RING0。
3,更改CALL指令的相对地址(CALL分别在71A21B12、71A21B25、71A21B64,但前面2条CALL之前有一个条件跳转指令,有可能不被执行到,因此我们要HOOK71A21B64处的CALL指令)。为什么要找CALL指令下手?因为它们都是5字节的指令,而且都是CALL指令,只要保持操作码0xE8不变,改变后面的相对地址就可以转到我们的HOOK代码去执行了,在我们的HOOK代码后面再转到目标地址去执行。
假设我们的HOOK代码在71A20400处,那么我们把71A21B64处的CALL指令改为CALL71A20400(原指令是这样的:CALL71A21230)
而71A20400处的HOOK代码是这样的:
71A20400:
pushad
//在这里做你想做的事情
popad
jmp71A21230//跳转到原CALL指令的目标地址,原指令是这样的:call71A21230
这种方法隐蔽性很好,但是比较难找这条5字节的CALL指令,计算相对地址也复杂。
4,替换71A21AFE地址上的cmpdwordptr[71A3201C],71A21C93指令(机器码:813D1C20A371931CA271,10字节)成为
call71A20400
(机器码:E8XXXXXXXX9090909090,10字节)
在71A20400的HOOK代码是:
pushad
movedx,71A3201Ch//模拟原指令cmpdwordptr[71A3201C],71A21C93
cmpdwordptr[edx],71A21C93h//模拟原指令cmpdwordptr[71A3201C],71A21C93
pushfd
//在这里做你想做的事
popfd
popad
这种方法隐蔽性最好,但不是每个API都有这样的指令,要具体情况具体操作。
以上几种方法是常用的方法,值得一提的是很多人都是改API开头的5个字节,但是现在很多杀毒软件用这样的方法检查API是否被HOOK,或其他病毒木马在你之后又改了前5个字节,这样就会互相覆盖,最后一个HOOKAPI的操作才是有效的,所以提倡用第3和第4种方法。
什么是hook编程?vb可以进行hook编程吗?
计算机编程术语解释什么是:API函数;hook技术;rootkit技术
本书以加密与解密为切入点,讲述了软件安全领域许多基础知识和技能,如调试技能、逆向分析、加密保护、外壳开发、虚拟机设计等。读者在掌握本书的内容,很容易在漏洞分析、安全编程、病毒分析、软件保护等领域扩展,这些知识点都是相互的,彼此联系。国内高校对软件安全这块领域教育重视程度还不够,许多方面还是空白,而近年来许多企业对软件安全技术人才需求量越来越大