【目标软件】 Processguard
【下载地址】 http://www.diamondcs.com.au/processguard/pgsetup_3300b4.exe
【脱壳工具】 OllyIce及相关工具
【作者声明】 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【调试过程】
现在好多软件作者为了防止被脱壳,而设置了各式各样的自校验,有明有暗,有强有弱。最近刚搞定了一个小软件,感觉难度中等,把调试过程写出来,与大家分享,高手略过.
一、脱壳:
未知壳,不过用Esp定律可轻松脱掉。OD载入后这样的:
代码:
004DC027 > 60 PUSHAD
004DC028 EB 0A JMP SHORT 004DC034
004DC02A 44 INC ESP
004DC02B 6961 6D 6F6E644>IMUL ESP,[ECX+6D],43646E6F
004DC032 53 PUSH EBX
004DC033 00EB ADD BL,CH
004DC035 02EB ADD CH,BL
004DC037 05 E8F9FFFF ADD EAX,-618
004DC03C FF58 2D CALL FAR FWORD PTR [EAX+2D] ; 远调用
注意忽略所有异常,F7走一步,下断hr ESP,F9运行后到达这里:
代码:
004DC14C 50 PUSH EAX
004DC14D B8 DE690100 MOV EAX,169DE
004DC152 35 28314000 XOR EAX,403128
004DC157 8BD8 MOV EBX,EAX
004DC159 58 POP EAX
004DC15A FFE3 JMP EBX //这里F7进去,到达这里
004158F6 B8 C4B64D00 MOV EAX,004DB6C4
004158FB 50 PUSH EAX
004158FC 64:FF35 0000000>PUSH DWORD PTR FS:[0]
00415903 64:8925 0000000>MOV FS:[0],ESP
去除ESP硬件断点,再F4一下,到达OEP
代码:
004158F6 55 PUSH EBP
004158F7 8BEC MOV EBP,ESP
004158F9 6A FF PUSH -1
004158FB 68 30744100 PUSH 00417430
00415900 68 805A4100 PUSH 00415A80 ; JMP 到 msvcrt._except_handler3
00415905 64:A1 00000000 MOV EAX,FS:[0]
0041590B 50 PUSH EAX
0041590C 64:8925 0000000>MOV FS:[0],ESP
00415913 83EC 68 SUB ESP,68
00415916 53 PUSH EBX
00415917 56 PUSH ESI
00415918 57 PUSH EDI
现在DUMP下来吧,用IM自动搜索一下IAT,找到了,可是里面有一个无效函数指针。
代码:
00417118 7C82DE40 kernel32.lstrlenW
0041711C 7C82F2FB kernel32.GetLocalTime
00417120 00380425 //这个是什么呢?
00417124 7C82C1BA kernel32.CloseHandle
00417128 7C82C0C0 kernel32.GetDriveTypeW
0041712C 7C8024A8 kernel32.Sleep
好,我们来跟踪一下它,在00417120 处下个内存访问断点,F9运行一下,断在这里:
代码:
00412A7D A1 20714100 MOV EAX,[417120] //进EAX
00412A82 A3 3C574200 MOV [42573C],EAX //写入 [42573C]
00412A87 A1 70714100 MOV EAX,[417170]
00412A8C 68 D0824100 PUSH 004182D0 ; UNICODE "Initializing ProcessGuard"
继续跟踪,在42573C处下内存访问断点,断在这里:
代码:
00412AFC 8135 3C574200 2>XOR DWORD PTR [42573C],894ADF25
00412B06 68 705D4200 PUSH 00425D70
00412B0B 68 7C814100 PUSH 0041817C ; UNICODE "Reboots"
00412B10 BE 48014200 MOV ESI,00420148 ; UNICODE "SOFTWARE\Diamond Computer Systems\ProcessGuard v3.0"
不管它继续F9,过几次XOR以后到达这里:
00412DFD FF15 3C574200 CALL [42573C] //开始调用地址了
00412E03 3BC3 CMP EAX,EBX
00412E05 74 59 JE SHORT 00412E60
00412E07 FFD0 CALL EAX
这时注意一下堆栈和寄存器,情况是这样的:
代码:
堆栈:
0012F010 7C800000 kernel32.7C800000
0012F014 0012FF10 ASCII "IsDebuggerPresent"
0012F018 00000000
0012F01C 001420D1
寄存器:
EAX 0012FF10 ASCII "IsDebuggerPresent"
ECX 0014D6D8
EDX 7C9B9D60 ntdll.7C9B9D60
EBX 00000000
ESP 0012F010
EBP 0012FF24
ESI 00000000
EDI 0012FF22
EIP 00412DFD procguar.00412DFD
下面我们F8一次,执行完这个函数,看看堆栈和寄存器的变化:
代码:
堆栈:
0012F018 00000000
0012F01C 001420D1
0012F020 00000000
寄存器:
EAX 7C824860 kernel32.IsDebuggerPresent
ECX 000008E4
EDX 00000001
EBX 00000000
ESP 0012F018
EBP 0012FF24
ESI 00000000
EDI 0012FF22
EIP 00412E03 procguar.00412E03
看到了吗?EAX值是什么?猜到了这个函数是什么了吧,对,GetProcAddress嘛,好像很多壳都是偷个这函数的。
好了,修正这个函数指针,脱壳完成。
二、修正自校验
运行软件后,还是有点问题,一点允许保护就异常退出,看来还有暗桩。弄了几次都不成功,后来想到是不是刚才修正的函数的问题,于是在401720处再次下内存访问断点,断在了这里:
代码:
00409CD5 . 8B35 20714100 MOV ESI,[<&kernel32.GetProcAddress>] ; kernel32.GetProcAddress
00409CDB . 8D45 DC LEA EAX,[EBP-24]
00409CDE . 50 PUSH EAX ; /ProcNameOrOrdinal
00409CDF . FF35 58574200 PUSH DWORD PTR [425758] ; |hModule = 7C800000 (kernel32)
00409CE5 . C645 E6 57 MOV BYTE PTR [EBP-1A],57 ; |
00409CE9 . C645 E1 65 MOV BYTE PTR [EBP-1F],65 ; |
00409CED . C645 DD 72 MOV BYTE PTR [EBP-23],72 ; |
00409CF1 . C645 DF 61 MOV BYTE PTR [EBP-21],61 ; |
00409CF5 . C645 E3 69 MOV BYTE PTR [EBP-1D],69 ; |
00409CF9 . C645 E4 6C MOV BYTE PTR [EBP-1C],6C ; |
00409CFD . C645 DE 65 MOV BYTE PTR [EBP-22],65 ; |
00409D01 . C645 DC 43 MOV BYTE PTR [EBP-24],43 ; |
00409D05 . C645 E5 65 MOV BYTE PTR [EBP-1B],65 ; |
00409D09 . 885D E7 MOV [EBP-19],BL ; |
00409D0C . C645 E0 74 MOV BYTE PTR [EBP-20],74 ; |
00409D10 . C645 E2 46 MOV BYTE PTR [EBP-1E],46 ; |
00409D14 . FFD6 CALL ESI //这里是CreateFileW
00409D16 . 8945 1C MOV [EBP+1C],EAX
00409D19 . 8D45 CC LEA EAX,[EBP-34]
00409D1C . 50 PUSH EAX ; /ProcNameOrOrdinal
00409D1D . FF35 58574200 PUSH DWORD PTR [425758] ; |hModule = 7C800000 (kernel32)
00409D23 . C645 D0 46 MOV BYTE PTR [EBP-30],46 ; |
00409D27 . C645 CE 61 MOV BYTE PTR [EBP-32],61 ; |
00409D2B . C645 D1 69 MOV BYTE PTR [EBP-2F],69 ; |
00409D2F . C645 CD 65 MOV BYTE PTR [EBP-33],65 ; |
00409D33 . C645 D2 6C MOV BYTE PTR [EBP-2E],6C ; |
00409D37 . C645 CC 52 MOV BYTE PTR [EBP-34],52 ; |
00409D3B . C645 D3 65 MOV BYTE PTR [EBP-2D],65 ; |
00409D3F . C645 CF 64 MOV BYTE PTR [EBP-31],64 ; |
00409D43 . 885D D4 MOV [EBP-2C],BL ; |
00409D46 . FFD6 CALL ESI //这里是:ReadFile
00409D48 . 8945 C8 MOV [EBP-38],EAX
00409D4B . 8D45 F0 LEA EAX,[EBP-10]
00409D4E . 50 PUSH EAX ; /ProcNameOrOrdinal
00409D4F . FF35 58574200 PUSH DWORD PTR [425758] ; |hModule = 7C800000 (kernel32)
00409D55 . C645 F8 69 MOV BYTE PTR [EBP-8],69 ; |
00409D59 . C645 F0 47 MOV BYTE PTR [EBP-10],47 ; |
00409D5D . C645 FA 65 MOV BYTE PTR [EBP-6],65 ; |
00409D61 . C645 F2 74 MOV BYTE PTR [EBP-E],74 ; |
00409D65 . C645 F1 65 MOV BYTE PTR [EBP-F],65 ; |
00409D69 . C645 F9 7A MOV BYTE PTR [EBP-7],7A ; |
00409D6D . 885D FB MOV [EBP-5],BL ; |
00409D70 . C645 F3 46 MOV BYTE PTR [EBP-D],46 ; |
00409D74 . C645 F6 65 MOV BYTE PTR [EBP-A],65 ; |
00409D78 . C645 F5 6C MOV BYTE PTR [EBP-B],6C ; |
00409D7C . C645 F7 53 MOV BYTE PTR [EBP-9],53 ; |
00409D80 . C645 F4 69 MOV BYTE PTR [EBP-C],69 ; |
00409D84 . FFD6 CALL ESI //这里是:GetFileSize
00409D86 . 8945 0C MOV [EBP+C],EAX
00409D89 . 8D45 A4 LEA EAX,[EBP-5C]
00409D8C . 50 PUSH EAX ; /ProcNameOrOrdinal
00409D8D . FF35 58574200 PUSH DWORD PTR [425758] ; |hModule = 7C800000 (kernel32)
00409D93 . C645 B5 57 MOV BYTE PTR [EBP-4B],57 ; |
00409D97 . C645 AE 69 MOV BYTE PTR [EBP-52],69 ; |
00409D9B . C645 AC 65 MOV BYTE PTR [EBP-54],65 ; |
00409D9F . C645 B1 4E MOV BYTE PTR [EBP-4F],4E ; |
00409DA3 . C645 A7 4D MOV BYTE PTR [EBP-59],4D ; |
00409DA7 . C645 A6 74 MOV BYTE PTR [EBP-5A],74 ; |
00409DAB . C645 AA 75 MOV BYTE PTR [EBP-56],75 ; |
00409DAF . C645 A8 6F MOV BYTE PTR [EBP-58],6F ; |
00409DB3 . 885D B6 MOV [EBP-4A],BL ; |
00409DB6 . C645 A5 65 MOV BYTE PTR [EBP-5B],65 ; |
00409DBA . C645 A4 47 MOV BYTE PTR [EBP-5C],47 ; |
00409DBE . C645 AF 6C MOV BYTE PTR [EBP-51],6C ; |
00409DC2 . C645 B4 65 MOV BYTE PTR [EBP-4C],65 ; |
00409DC6 . C645 AB 6C MOV BYTE PTR [EBP-55],6C ; |
00409DCA . C645 A9 64 MOV BYTE PTR [EBP-57],64 ; |
00409DCE . C645 AD 46 MOV BYTE PTR [EBP-53],46 ; |
00409DD2 . C645 B3 6D MOV BYTE PTR [EBP-4D],6D ; |
00409DD6 . C645 B2 61 MOV BYTE PTR [EBP-4E],61 ; |
00409DDA . C645 B0 65 MOV BYTE PTR [EBP-50],65 ; |
00409DDE . FFD6 CALL ESI //这里是:GetModuleFileNameW
00409DE0 . 395D 1C CMP [EBP+1C],EBX
00409DE3 . 8BD0 MOV EDX,EAX
00409DE5 . 0F84 AD000000 JE 00409E98
00409DEB . 395D C8 CMP [EBP-38],EBX
00409DEE . 0F84 A4000000 JE 00409E98
00409DF4 . 395D 0C CMP [EBP+C],EBX
00409DF7 . 0F84 9B000000 JE 00409E98
00409DFD . 3BD3 CMP EDX,EBX
00409DFF . 0F84 93000000 JE 00409E98 //上面4个是检验是否正确的得到了4个函数的地址
00409E05 . 33C0 XOR EAX,EAX
00409E07 . 66:899D 7CFDF>MOV [EBP-284],BX
00409E0E . B9 81000000 MOV ECX,81
00409E13 . 8DBD 7EFDFFFF LEA EDI,[EBP-282]
00409E19 . F3:AB REP STOS DWORD PTR ES:[EDI]
00409E1B . 66:AB STOS WORD PTR ES:[EDI]
00409E1D . 68 04010000 PUSH 104
00409E22 . 8D85 7CFDFFFF LEA EAX,[EBP-284]
00409E28 . 50 PUSH EAX
00409E29 . 53 PUSH EBX
00409E2A . FFD2 CALL EDX //CALL GetModuleFileNameW
00409E2C . 53 PUSH EBX
00409E2D . 53 PUSH EBX
00409E2E . 6A 03 PUSH 3
00409E30 . 53 PUSH EBX
00409E31 . 6A 01 PUSH 1
00409E33 . 68 00000080 PUSH 80000000
00409E38 . 8D85 7CFDFFFF LEA EAX,[EBP-284]
00409E3E . 50 PUSH EAX
00409E3F . FF55 1C CALL [EBP+1C] //CALL CreateFileW
00409E42 . 3BC3 CMP EAX,EBX
00409E44 . 8945 C4 MOV [EBP-3C],EAX
00409E47 . 74 4F JE SHORT 00409E98
00409E49 . 83F8 FF CMP EAX,-1
00409E4C . 74 4A JE SHORT 00409E98
00409E4E . 53 PUSH EBX
00409E4F . 50 PUSH EAX
00409E50 . FF55 0C CALL [EBP+C] //CALL GetFileSize
00409E53 . 8BF0 MOV ESI,EAX
00409E55 . 56 PUSH ESI
00409E56 . E8 4BBA0000 CALL <JMP.&msvcrt.??2@YAPAXI@Z>
00409E5B . 8BF8 MOV EDI,EAX
00409E5D . 3BFB CMP EDI,EBX
00409E5F . 59 POP ECX
00409E60 . 74 36 JE SHORT 00409E98
00409E62 . 53 PUSH EBX
00409E63 . 8D45 1C LEA EAX,[EBP+1C]
00409E66 . 50 PUSH EAX
00409E67 . 56 PUSH ESI
00409E68 . 57 PUSH EDI
00409E69 . FF75 C4 PUSH DWORD PTR [EBP-3C]
00409E6C . FF55 C8 CALL [EBP-38] //CALL ReadFile
00409E6F . FF75 C4 PUSH DWORD PTR [EBP-3C] ; /hObject
00409E72 . FF15 24714100 CALL [<&kernel32.CloseHandle>] ; \CloseHandle
00409E78 . 8D46 FC LEA EAX,[ESI-4]
00409E7B . 57 PUSH EDI
00409E7C . E8 E79B0000 CALL 00413A68 //这里是进行计算
00409E81 . 3B4437 FC CMP EAX,[EDI+ESI-4] //比较结果
00409E85 . 59 POP ECX
00409E86 . 8945 1C MOV [EBP+1C],EAX
00409E89 74 06 JE SHORT 00409E91 //不跳就OVER了
00409E8B . 61 POPAD
00409E8C . E9 230B0000 JMP 0040A9B4
00409E91 > 57 PUSH EDI
如果有兴趣可以跟进去计算一下,我是直接将409E89 处JE改为JMP了,结果正常运行了。程序还有一处自校验,跟这里差不多,不啰嗦了。
三、破解:
不多说了,很简单的。感觉写脱文比脱壳还费劲,写得不好,将就着看吧。