一、准备工作
老规矩设置Ollydbg忽略所有异常,用IsDebug 1.4插件去掉Ollydbg的调试器标志。
侦壳:我用FI 4.01a 查一下 显示为 Armadillo 4.00 {glue}
二 、脱壳
1 避开密码检测
OD 载入 Shift+F9 运行,弹出输入密码提示,注意:这个练习是 PassWord 方式,而不是带 KEY 的方式。
如果是带 KEY 的 ARM 壳,没有 KEY 是无法脱壳的!
00449243 > 55 PUSH EBP //停在这里
00449244 8BEC MOV EBP,ESP
00449246 6A FF PUSH -1
00449248 68 402F4700 PUSH password.00472F40
0044924D 68 808F4400 PUSH password.00448F80
00449252 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
00449258 50 PUSH EAX
00449259 64:8925 0000000>MOV DWORD PTR FS:[0],ESP
00449260 83EC 58 SUB ESP,58
下断点 bp strlen (注意在 OD 里下断点的时候 OD 是区分 API 的大小写的) 然后回到程序输入假密码:123123 后点 OK 按钮
77C178A0 > 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] //中断在这里
77C178A4 F7C1 03000000 TEST ECX,3
77C178AA 74 14 JE SHORT msvcrt.77C178C0
77C178AC 8A01 MOV AL,BYTE PTR DS:[ECX]
77C178AE 41 INC ECX
77C178AF 84C0 TEST AL,AL
77C178B1 74 40 JE SHORT msvcrt.77C178F3
77C178B3 F7C1 03000000 TEST ECX,3
77C178B9 ^ 75 F1 JNZ SHORT msvcrt.77C178AC
中断后清除断点 alt+F9 返回
00BC49E9 85C0 TEST EAX,EAX //返回到这里
00BC49EB 59 POP ECX
00BC49EC 74 1A JE SHORT 00BC4A08
00BC49EE 8B0D E01EBE00 MOV ECX,DWORD PTR DS:[BE1EE0]
00BC49F4 8D85 00FFFFFF LEA EAX,DWORD PTR SS:[EBP-100]
00BC49FA 50 PUSH EAX
00BC49FB E8 7D77FEFF CALL 00BAC17D
00BC4A00 84C0 TEST AL,AL //测试标志位,修改al=1
00BC4A02 74 04 JE SHORT 00BC4A08
00BC4A04 6A 01 PUSH 1
00BC4A06 EB 4C JMP SHORT 00BC4A54 //跳走后正常运行
2 避开 IAT 加密
下断点 he GetModuleHandleA Shift+F9 运行中断后取消断点 Alt+F9 返回
7C80B529 > 8BFF MOV EDI,EDI //中断在这里
7C80B52B 55 PUSH EBP
7C80B52C 8BEC MOV EBP,ESP
7C80B52E 837D 08 00 CMP DWORD PTR SS:[EBP+8],0
此时堆栈内容如下:
0012928C 00BB5CE1 /CALL 到 GetModuleHandleA 来自 00BB5CDB
00129290 001293DC \pModule = "kernel32.dll"
清除断点 ALT + F9 返回
000BB5CE1 8B0D AC40BE00 MOV ECX,DWORD PTR DS:[BE40AC] //返回到这里
00BB5CE7 89040E MOV DWORD PTR DS:[ESI+ECX],EAX
00BB5CEA A1 AC40BE00 MOV EAX,DWORD PTR DS:[BE40AC]
00BB5CEF 391C06 CMP DWORD PTR DS:[ESI+EAX],EBX
00BB5CF2 75 16 JNZ SHORT 00BB5D0A
00BB5CF4 8D85 B4FEFFFF LEA EAX,DWORD PTR SS:[EBP-14C]
00BB5CFA 50 PUSH EAX
00BB5CFB FF15 BC62BD00 CALL DWORD PTR DS:[BD62BC] ; kernel32.LoadLibraryA
00BB5D01 8B0D AC40BE00 MOV ECX,DWORD PTR DS:[BE40AC]
00BB5D07 89040E MOV DWORD PTR DS:[ESI+ECX],EAX
00BB5D0A A1 AC40BE00 MOV EAX,DWORD PTR DS:[BE40AC]
00BB5D0F 391C06 CMP DWORD PTR DS:[ESI+EAX],EBX
00BB5D12 0F84 2F010000 JE 00BB5E47 //改JE为 JMP
00BB5D18 33C9 XOR ECX,ECX
00BB5D1A 8B07 MOV EAX,DWORD PTR DS:[EDI]
00BB5D1C 3918 CMP DWORD PTR DS:[EAX],EBX
00BB5D1E 74 06 JE SHORT 00BB5D26
00BB5D20 41 INC ECX
00BB5D21 83C0 0C ADD EAX,0C
00BB5D24 ^ EB F6 JMP SHORT 00BB5D1C
在 00C15D12 处改 JE 为 JMP 然后按回车跟随
00BB5E47 83C7 0C ADD EDI,0C //跟随到这里
00BB5E4A 89BD 78FDFFFF MOV DWORD PTR SS:[EBP-288],EDI
00BB5E50 83C6 04 ADD ESI,4
00BB5E53 395F FC CMP DWORD PTR DS:[EDI-4],EBX
00BB5E56 ^ 0F85 49FEFFFF JNZ 00BB5CA5
00BB5E5C EB 03 JMP SHORT 00BB5E61 //这里F2下断
00BB5E5E D6 SALC
00BB5E5F D6 SALC
00BB5E60 8F ??? ; 未知命令
然后 Shift+F9 运行中断后取消断点然后回到修改JMP的地方撤消刚才的修改,因为有效验:)
修改以后, ALT+M 打开内存镜象
选择~TEXT段设内存访问断点,F9运行
在次ALT+M 打开内存镜象 选择1000段~TEXT段设内存访问断点,F9运行
就到了OEP了 :)
三、修复IAT
完整转存后用 ImportREC v1.6F 修复IAT,OEP处填10CC 自动搜索IAT 获取输入表 显示无效函数
把无效指针全部CUT掉。修复抓取文件
最后可以给文件做个减肥。用 LordPE 打开脱壳后的文件。把 text1 adata data1 reloc1 padtat 这5个区段删除掉。然后重建PE文件
正常运行 收工
[课程]Android-CTF解题方法汇总!