贪玩蓝月手游怎样快速提升战力 战力提升攻略

贪玩蓝月手游

梅英谢 梅英谢
回答
  • Jasmine Jasmine

    hook api是一个永恒的话题,如果没有hook,许多技术将很难实现,也许根本不能实现。这里所说的api,是广义上的api,它包括dos下的中断,windows里的api、中断服务、ifs和nd**过滤等。比如大家熟悉的即时翻译软件,就是靠hook textout()或exttextout()这两个函数实现的,在操作系统用这两个函数输出文本之前,就把相应的英文替换成中文而达到即时翻译;ifs和nd**过滤也是如此,在读写磁盘和收发数据之前,系统会调用第三方提供的回调函数来判断操作是否可以放行,它与普通hook不同,它是操作系统允许的,由操作系统提供接口来安装回调函数。甚至如果没有hook,就没有病毒,因为不管是dos下的病毒或windows里的病毒,都是靠hook系统服务来实现自己的功能的:dos下的病毒靠hook int 21来感染文件(文件型病毒),靠hook int 13来感染引导扇区(引导型病毒);windows下的病毒靠hook系统api(包括ring0层的和ring3层的),或者安装ifs(cih病毒所用的方法)来感染文件。因此可以说“没有hook,就没有今天多姿多彩的软件世界”。由于涉及到专利和知识产权,或者是商业机密,微软一直不提倡大家hook它的系统api,提供ifs和nd**等其他过滤接口,也是为了适应杀毒软件和防火墙的需要才开放的。所以在大多数时候,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 le**e
    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/保存现场
    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
    在这里做你想做的事情
    popad
    jmp 71a21230/跳转到原call指令的目标地址,原指令是这样的:call 71a21230
    这种方法隐蔽性很好,但是比较难找这条5字节的call指令,计算相对地址也复杂。4,替换71a21afe地址上的cmp dword ptr[71a3201c],71a21c93指令(机器码:813d1c20a371931ca271,10字节)成为
    call 71a20400
    nop
    nop
    nop
    nop
    nop
    (机器码:e8 xx xx xx xx 90 90 90 90 90,10字节)
    在71a20400的hook代码是:
    pushad
    mov edx,71a3201ch/模拟原指令cmp dword ptr[71a3201c],71a21c93
    cmp dword ptr[edx],71a21c93h/模拟原指令cmp dword ptr[71a3201c],71a21c93
    pushfd
    在这里做你想做的事
    popfd
    popad
    ret
    这种方法隐蔽性最好,但不是每个api都有这样的指令,要具体情况具体操作。以上几种方法是常用的方法,值得一提的是很多人都是改api开头的5个字节,但是现在很多杀毒软件用这样的方法检查api是否被hook,或其他病毒木马在你之后又改了前5个字节,这样就会互相覆盖,最后一个hook api的操作才是有效的,所以提倡用第3和第4种方法。

类似问答
精品推荐

友情链接

友链互换QQ:

谷财 备案编号:蜀ICP备11019336号-3商务合作:235-677-2621

Copyright 2009-2020 Chengdu Sanzilewan Technology Co.,Ltd all rights reserve

抵制不良游戏 拒绝盗版游戏 注意自我保护 谨防受骗上当 适度游戏益脑 沉迷游戏伤身 合理安排时间 享受健康生活