问外国有哪些达到“魔改”级别的武器装备?
-
馒头没有馅儿
当执行完我们自定义的hook函数之后,又从被hook函数的首部开始执行,被hook函数一进入就被跳转了。而本文,则要实现在某个函数体内部任意地方进行hook并跳转,执行完我们的函数之后,再回到原来的位置继续向下执行完未执行的逻辑。那么,初看这种方式似乎与前面写的两篇hook没有什么差别,都是hook,都是跳转然后回到被hook的函数。但仔细一想,你会发现本文要实现的方式要比前面两种hook复杂,因为hook的地方是函数体内任意地方,那么回来的时候就不是直接调用被hook的函数了,而是要回到之前hook的地方去。这期间就涉及到hook函数的返回地址问题和被hook函数的返回地址问题。说了这么多,可能还是有点晕,先不管为什么要这么做,也不管这种hook方式能有什么用途(在本文最后会说明用途),下面我们先写一些代码,在实践中来想一想这种方式有什么用途,并且与之前的两篇hook进行比较。首先,我们需要一个自定义的hook函数,这个函数也就是被hook函数被hook后跳转到的地方,这个hook函数负责hook与unhook,还可以监视寄存器,监视内存,也可以管理hook的次数,以供我们灵活的hook需求。直接贴代码吧:
[cpp]view plaincopyprint?include
include
pragma warning(d**able:4311)
pragma warning(d**able:4312)
define hook_bytes 5
typedef unsigned int uint;uint hookaddr=0;char old_code[hook_bytes];char new_code[hook_bytes];void printreg**ters(void);bool hook(void)
{
dword dwflag;if(virtualprotect((void*)hookaddr,hook_bytes,page_execute_readwrite,&dwflag))
{
memcpy(old_code,(void*)hookaddr,hook_bytes);memcpy((void*)hookaddr,new_code,hook_bytes);virtualprotect((void*)hookaddr,hook_bytes,dwflag,&dwflag);return true;}
return false;}
void unhook(void)
{
dword dwflag;if(virtualprotect((void*)hookaddr,hook_bytes,page_execute_readwrite,&dwflag))
{
memcpy((void*)hookaddr,old_code,hook_bytes);virtualprotect((void*)hookaddr,hook_bytes,dwflag,&dwflag);}
}
namespace global
{
uint geax=0;uint gebx=0;uint gecx=0;uint gedx=0;uint gesp=0;uint gebp=0;uint gesi=0;uint gedi=0;uint gret=0;临时的返回地址
uint gtmp=0;一些临时的值保存
uint gpar=0;被hook函数的正常返回地址
uint gcnt=1;当前hook的次数
uint gmax=0;最大hook次数,为0表示一直hook
bool bent=0;是否为第一次进入hook函数
}
void_declspec(naked)hook_jmp(void)
{
asm
{
entry:
pushad
{
cmp global:bent,0/如果没有进入则表示需要unhook
je_first
cmp global:gmax,0/如果为0,则一直启用hook逻辑
je_second
mov eax,global:gcnt
cmp eax,global:gmax/如果当前hook次数没有达到最大次数,则继续
jl_second
mov global:gcnt,1/reset state
mov global:bent,0/reset state
mov global:gmax,0/reset state
mov eax,global:gpar/被hook函数的正常返回地址
mov global:gret,eax/准备跳转到被hook函数的上层调用,结束hook
popad
jmp_ret
}
first:
保存相关重要寄存器值
{
popad
mov global:geax,eax
mov global:gebx,ebx
mov global:gecx,ecx
mov global:gedx,edx
mov global:gesp,esp
mov global:gebp,ebp
mov global:gesi,esi
mov global:gedi,edi
}
第一次进入,unhook并监视相关状态
pushad
{
mov global:bent,1/记录状态
mov edi,global:gebp/被hook函数的ebp
mov eax,[edi+4]/被hook函数的返回地址(其上层调用地址)
mov global:gpar,eax/保存返回地址
mov esi,_entry/将被hook函数的返回地址修改为
mov[edi+4],esi/本函数的首地址,以便执行完被hook函数的
剩余逻辑之后能够返回到本函数,决定是否
还需要hook。call printreg**ters/打印寄存器值[测试],或者其他
call unhook/unhook
mov eax,hookaddr/获得被hook的内存地址
mov global:gret,eax
}
popad
pop global:gtmp/移除本函数的返回地址,并将hook的地址设置
jmp_ret/为本函数的返回地址,从而实现跳转
second:
第二次进入,继续hook,这次进入是被hook函数ret返回的,没有新的ret地址被压栈
{
mov global:bent,0/设置状态
add global:gcnt,1/增加hook计数
call hook/hook
mov eax,global:gpar/将被hook函数的返回地址设置为本函数的
mov global:gret,eax/返回地址,从而实现正常的函数流程
}
popad
ret:
push global:gret/修改本函数的返回地址
ret
}
}
void sethookbytes(uint addr)
{
hookaddr=addr;new_code[0]=(char)0xe8;call 指令机器码
(uint&)new_code[1]=(uint)hook_jmp-addr-5;计算跳转偏移
}
void printreg**ters(void)
{
printf("eax=0x%08x/n",global:geax);printf("ebx=0x%08x/n",global:gebx);printf("ecx=0x%08x/n",global:gecx);printf("edx=0x%08x/n",global:gedx);printf("esp=0x%08x/n",global:gesp);printf("ebp=0x%08x/n",global:gebp);printf("esi=0x%08x/n",global:gesi);printf("edi=0x%08x/n",global:gedi);}
如上,hook_jmp函数即为我们自定义的hook函数,当被hook函数被hook之后,就会跳转到这个函数里,执行相关逻辑,上面我加了很详细的注释。应该很容易看懂。还是先看怎么使用这套方法,再来细说,代码如下:
[cpp]view plaincopyprint?void testhook(void)
{
printf("th** ** a hook test 1./n");printf("th** ** a hook test 2./n");printf("th** ** a hook test 3./n");printf("th** ** a hook test 4./n");printf("_/n");}
int main(void)
{
uint hook_addr=0x0042ec7b;sethookbytes(hook_addr);global:gmax=2;if(hook())
{
testhook();testhook();testhook();}
system("pause");return 0;}
如上,testhook函数即为被hook的函数,在main函数中,0x0042ec7b则为testhook函数里的第二个printf调用的地址,在你的机器上可能不一样。这里只是测试之用。testhook函数具体反汇编代码如下:
[cpp]view plaincopyprint?void testhook(void)
{
0042ec50 push ebp
0042ec51 mov ebp,esp
0042ec53 sub esp,0c0h
0042ec59 push ebx
0042ec5a push esi
0042ec5b push edi
0042ec5c lea edi,[ebp-0c0h]
0042ec62 mov ecx,30h
0042ec67 mov eax,0cccccccch
0042ec6c rep stos dword ptr es:[edi]
printf("th** ** a hook test 1./n");0042ec6e push offset string"th** ** a hook test 1./n"(487e24h)
0042ec73 call@ilt+4550(_printf)(42d1cbh)
0042ec78 add esp,4
printf("th** ** a hook test 2./n");0042ec7b push offset string"th** ** a hook test 2./n"(487e08h)
0042ec80 call@ilt+4550(_printf)(42d1cbh)
0042ec85 add esp,4
printf("th** ** a hook test 3./n");0042ec88 push offset string"th** ** a hook test 3./n"(487dech)
0042ec8d call@ilt+4550(_printf)(42d1cbh)
0042ec92 add esp,4
printf("th** ** a hook test 4./n");0042ec95 push offset string"th** ** a hook test 4./n"(487dd0h)
0042ec9a call@ilt+4550(_printf)(42d1cbh)
0042ec9f add esp,4
printf("_/n");0042eca2 push offset string"_./n"(487db4h)
0042eca7 call@ilt+4550(_printf)(42d1cbh)
0042ecac add esp,4
}
0042ecaf pop edi
0042ecb0 pop esi
0042ecb1 pop ebx
0042ecb2 add esp,0c0h
0042ecb8 cmp ebp,esp
0042ecba call@ilt+3570(_rtc_checkesp)(42cdf7h)
0042ecbf mov esp,ebp
0042ecc1 pop ebp
0042ecc2 ret
我们hook的就是第18行(0042ec7b)那句代码,sethookbytes构建了一个5字节的call语句,0xe8为call指令的机器码,后面4个字节是call的偏移量(目标地址-当前地址-call指令占用的5个字节)。在main函数中,构建了hook的5个字节之后,设置了hook次数,如main函数那段代码的第15行:global:gmax=2,则会hook两次。然后是main函数那段代码的第16行,调用hook函数,将5个字节的call指令写入0042ec7b中,并保存了0042ec7b中原来的代码到old_code中。之后,我们便可以调用testhook函数进行测试hook的流程了。最终输出结果为:
th** ** a hook test 1.
eax=0x00000017
ebx=0x7ffdc000
ecx=0x8df97741
edx=0x00499148
esp=0x0012fd84
ebp=0x0012fe54
esi=0x00000000
edi=0x0012fe54
th** ** a hook test 2.
th** ** a hook test 3.
th** ** a hook test 4.
th** ** a hook test 1.
eax=0x00000017
ebx=0x7ffdc000
ecx=0x8df97741
edx=0x00499148
esp=0x0012fd84
ebp=0x0012fe54
esi=0x00000000
edi=0x0012fe54
th** ** a hook test 2.
th** ** a hook test 3.
th** ** a hook test 4.
th** ** a hook test 1.
th** ** a hook test 2.
th** ** a hook test 3.
th** ** a hook test 4.
可以看出,前面两次调用testhook函数时,都执行了hook_jmp函数,并调用了printreg**ters函数将寄存器打印了出来,之后又回到testhook中,继续输出后面的3句字符...
-
问 哪些武器装备是**特有的?
提问时间:2024-05-12 10:38:56
答 sy-400武器系统,这个自己都不好意思叫它火箭炮了。我想不通,垂直发射,射程280km的东西,你叫他火箭炮?顺带提一句,国内有一种火箭炮产品和sy-400在国...
-
问 **有哪些国际一流的武器装备?
提问时间:2024-05-12 03:49:04
答 国际一流的武器?**三百种有没有?魂舞大漠看法是有的,现在销售出去的不多,给世人的印象好像**武器还不成,要在我们作为负责任的大国,从不插手敏感地区事务,外销武...
-
问 **有哪些国际一流的武器装备?
提问时间:2024-05-12 01:12:10
答 自军改以来,国内陆海空军、火箭军、战略支援部队五大军种并驾齐驱,又有所重点地快速发展。所谓10年陆军、50年空军、百年海军,说明海军发展的艰辛和困难,但将近二十...
-
问 魔兽世界国服爆的高级武器装备像国外那样唯一的吗?
提问时间:2024-05-12 14:27:33
答 wow里所有的史诗级装备都不可能让一个服就一件的!因为wow现在最重要的还是团队。所谓的唯一,是指你的人物只能拿一件!不可以重复拥有2件的。当然也有bug的,比...
-
问 **有哪些非常著名的武器和装备?
提问时间:2024-05-12 08:45:13
答 谈到**著名的武器装备,不得不提,最新款j20空优战斗机,这款战斗机的产生,在内部技术方面因为美军同代战斗机出现的比较早,在技术方面已经完成了对美军战斗机的超越...
-
问 永恒之塔 魔族装备外形改造的外形有哪些种?
提问时间:2024-05-12 10:56:58
答 展开全部.只要是装备 就能改。你55的装备也可以改成20级装备的样子。但金属只能改金属的 布甲只能改 布甲的。帽子随意。像时装那样的外形 就不分职业了 神庙的就...
-
问 高达德尔塔改武器装备有哪些
提问时间:2024-05-12 18:06:59
答 msn-001x 德尔塔改的**是强化了msn-001a1 德尔塔plus的智能光束步**后的长距离米加粒子炮,具有更高出力和射程。nitro系统控制的增加的两...