自校检是许多软件的保护手段之一,对软件加个简单的壳再增加自校检在一定程序上可以抵挡住一大部分新手,不过,对许多人来说,这个保护已经很弱了。可是,搜索论坛,居然没有一篇系统的文章。不知道是大家太忙了还是因为要守住点秘密。其实大部分技术应该拿出来交流才好,只有交流才有进步。就象老王的EPE,netsowell一次一次的脱壳文章,才促使老王一次一次的升级,保护强度也越来越强。废话一堆,不讲了。下面讲几种常见的解决自校检方法,写的粗略,希望大家补充。 1、通用对比法。就是将已经触发自校检的程序与原来正常的程序进行关键跳转对比,这种方法比较通用,大部分的自校检可以通过此方法解决(如果软件有防多开窗口的限制,需 要先解决这个问题。)附件中的sample1.EXE是一个加了ASPACK的自校检程序,修改任何代码或大小等都会触发校检提示软件被修改。dumped.EXE是脱壳后的文件,由于触发校检运行后出现“文件被非法修改”的提示,现在我们来解决脱壳后文件的自校检问题。打开脱壳后的程序dumped.EXE,下断BP CreateFileA,F9两次后出现出错提示。CTRL+F2重新载入dumped.EXE,下断BP reateFileA,F9一次。这时另开一个OD打开原来的程序sample1.EXE,用脚本到达OEP,命令中也下断BP CreateFileA,F9一次,这时两个OD停在同一个地方,然后在两个OD中逐步单步跟踪,碰到JE、JNE、JBE...之类的关键跳转要对比一下两者的区别。 7C801A24 > 8BFF MOV EDI,EDI ; BP CreateFileA断在这里,ALT+F9返回 7C801A26 55 PUSH EBP ================= 0040111C |. 3BF4 CMP ESI,ESP ; 都停在这里,逐步F8,进行关键跳转的对比 0040111E |. E8 0D030000 CALL crcdumpe.00401430 00401123 |. 8985 E0FEFFFF MOV DWORD PTR SS:[EBP-120],EAX 00401129 |. 83BD E0FEFFFF>CMP DWORD PTR SS:[EBP-120],-1 00401130 |. 75 07 JNZ SHORT crcdumpe.00401139
逐步F8,跟到下面的代码时,发现两个跳转不一样: 0040120C /75 07 JNZ SHORT crc.00401215 ; 原版这个地方信息窗口提示:跳转没有实现 0040120E |B8 01000000 MOV EAX,1 00401213 |EB 02 JMP SHORT crc.00401217 00401215 \33C0 XOR EAX,EAX ======================= 0040120C |. /75 07 JNZ SHORT crcdumpe.00401215 ; 脱壳版这个地方信息窗口提示:跳转已经实现,NOP掉 0040120E |. |B8 01000000 MOV EAX,1 00401213 |. |EB 02 JMP SHORT crcdumpe.00401217 00401215 |> \33C0 XOR EAX,EAX
这时将脱壳版0040120C处代码NOP掉后另存为dumpedFIX.EXE。试着运行一下,如果正常完事,还不行的话继续跟踪下去。该例只改这一处。
2、跟踪退出函数。附件中sample2也是个自校检程序,修改任何一处软件会自动退出。我们试着用UltraEdit将sample2.EXE的最后一个字节改为01后另存为sample2-change.EXE,这时运行sample2-change就会自动退出,我们就是要从退出函数入手。软件退出一般都是调用ExitProcess、PostQuitMessage之类的,我们用OD载入sample2-change.EXE,从输入表中我们可以看出软件是调用ExitProcess退出的。于是在OD中下断BP ExitProcess,F9运行,断下后看堆栈信息: 0012FEB8 004015B5 /CALL 到 ExitProcess 来自 sample2-.004015AF //从这里我们可以看出ExitProcess的调用地方是在004015AF 0012FEBC 00000000 \ExitCode = 0 0012FEC0 20DFA6E6 在OD中CTRL+G,输入004015AF: 004015AF |. FF15 AC514200 CALL DWORD PTR DS:[<&KERNEL32.ExitProces>; \就在这里,向上找这个子CALL的首部 004015B5 |> 8BE5 MOV ESP,EBP 004015B7 |. 5D POP EBP 004015B8 \. C3 RETN ======================================= 004014E0 /$Content$nbsp; 55 PUSH EBP ; 找到这里,注意信息栏的内容 004014E1 |. 8BEC MOV EBP,ESP 004014E3 |. 51 PUSH ECX 004014E4 |. 833D F8354200>CMP DWORD PTR DS:[4235F8],1 004014EB |. 75 11 JNZ SHORT sample2-.004014FE 信息栏的内容: Local Calls from 0040146B, 0040148B, 004014A9, 004014C9 也就是说有四个地方调用ExitProcess退出,因为程序的退出按钮和关闭的叉号也是调用ExitProcess函数的,一般都会在前面几个,我们在内容上右击,“前往CALL来自0040146B” 0040146B |. E8 70000000 CALL sample2-.004014E0 ; \到这里,同样查找首部 00401470 |. 83C4 0C ADD ESP,0C 00401473 |. 5D POP EBP 00401474 \. C3 RETN ============ 00401460 /$Content$nbsp; 55 PUSH EBP ; 在这里,信息栏提示:Local Calls from 00401072, <ModuleEntryPoint>+11A 00401461 |. 8BEC MOV EBP,ESP 00401463 |. 6A 00 PUSH 0 ; /Arg3 = 00000000 00401465 |. 6A 00 PUSH 0 ; |Arg2 = 00000000 在Local Calls from 00401072上右击,前往CALL来自00401072: 00401048 |. E8 BDFFFFFF CALL sample2-.0040100A 0040104D |. 85C0 TEST EAX,EAX 0040104F |. 74 1F JE SHORT sample2-.00401070 ; 是从这里跳过去的,NOP掉 00401051 |. 8BF4 MOV ESI,ESP 00401053 |. 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL 00401055 |. 68 28004200 PUSH sample2-.00420028 ; |Title = "提示" 0040105A |. 68 1C004200 PUSH sample2-.0042001C ; |Text = "正常运行!" 0040105F |. 6A 00 PUSH 0 ; |hOwner = NULL 00401061 |. FF15 B4524200 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA 00401067 |. 3BF4 CMP ESI,ESP 00401069 |. E8 82050000 CALL sample2-.004015F0 0040106E |. EB 07 JMP SHORT sample2-.00401077 00401070 |> 6A 00 PUSH 0 00401072 |. E8 E9030000 CALL sample2-.00401460 ; 就是这里了,最终会调用ExitProcess,向上看是从哪里跳过来 00401077 |> 33C0 XOR EAX,EAX
[1] [2] 下一页 |