本帖最后由 smallyou93 于 2009-12-28 19:51 编辑
本文是由ximo大牛的指导下完成,学到了很多东西,感谢ximo,膜拜ximo
脱壳目标:TPPpack加过的记事本(TPPpack主程序见附件,在tut发现的..)
1.SEH + AntiDRx01013010 > $ E8 00000000 call 01013015 ; EP
01013015 $ 5D pop ebp
01013016 . 81ED F58F4000 sub ebp, 0x408FF5
0101301C . 60 pushad
0101301D . 33F6 xor esi, esi ; ESI清零
0101301F . E8 11000000 call <SEH_1>
00495024 8B6424 08 mov esp, dword ptr [esp+0x8] ; Drx清零
01013035 > $ 64:FF35 00000000 push dword ptr fs:[0]
0101303C . 64:8925 00000000 mov dword ptr fs:[0], esp
01013043 . AD lods dword ptr [esi] ; 造成第一次内存访问异常.Dr7清零
01013044 . 90 nop
01013024 . 8B6424 08 mov esp, dword ptr [esp+0x8] ; 异常出口
01013028 . 64:8F05 00000000 pop dword ptr fs:[0]
0101302F . 58 pop eax
01013030 . 61 popad
01013031 . EB 13 jmp short 01013046
01013046 ? 60 pushad
01013047 ? 33FF xor edi, edi ; edi清零
01013049 . E8 00000000 call <SEH_2>
0101304E >/$ 830424 10 add dword ptr [esp], 0x10
01013052 |. 64:8B07 mov eax, dword ptr fs:[edi]
01013055 |. 50 push eax
01013056 |. 64:8927 mov dword ptr fs:[edi], esp
01013059 |. C607 00 mov byte ptr [edi], 0x0 ; 再次造成内存访问异常.Dr7清零
0101305C |. 90 nop
0101305D |. 90 nop
0101305E |. 8B7C24 0C mov edi, dword ptr [esp+0xC] ; DRx全部清零
01013062 |. 33C0 xor eax, eax ; eax清零
01013064 |. 8947 04 mov dword ptr [edi+0x4], eax
01013067 |. 8947 08 mov dword ptr [edi+0x8], eax
0101306A |. 8947 0C mov dword ptr [edi+0xC], eax
0101306D |. 8947 10 mov dword ptr [edi+0x10], eax
01013070 |. 8387 B8000000 27 add dword ptr [edi+0xB8], 0x27
01013077 |. 33C0 xor eax, eax
01013079 \. C3 retn ; 返回到ntdll.7C9232A8
0101307A 1F db 1F
Dr0,Dr1,Dr2,Dr3是存放中断的地址,Dr6,Dr7是控制状态的(比如硬件写入断点还是执行等等),被清零了,你下的硬件断点信息全被清掉了,因此下的硬件断点也就失效了
2.Stolen code
bp VirtualProtect 解码后返回
alt+m 在x001000下内存访问断点 shift+f9就到fake oep了01007568 /$ 68 BA750001 push 010075BA ; 断在这里
向上一拉,全是00...01007398 CC int3
01007399 CC int3
0100739A CC int3
0100739B CC int3
0100739C CC int3
0100739D 00 db 00 ; 这里才是oep
--------------------------------------(省去一部分)--------------------------------------
01007562 00 db 00
01007563 CC int3
01007564 CC int3
01007565 CC int3
01007566 CC int3
01007567 CC int3
01007568 /$ 68 BA750001 push 010075BA ; 断在这里
100739D 到 1007562 的代码都被壳抽取到壳中了
大小0x1c6
3.IAT加密
bp GetModuleHandleA+20
观察堆栈0013FF90 0049783D 返回到 TPPpack.0049783D
0013FF94 1001E235 ASCII "KERNEL32.dll" <---第一次
....(shift+f9若干次后)...
0013FF10 1000C135 返回到 1000C135 来自 kernel32.GetModuleHandleA
0013FF14 1001B997 ASCII "KERNEL32"
0013FD20 1000572B 返回到 1000572B 来自 kernel32.GetModuleHandleA
0013FD24 006518C0 ASCII "ntdll.dll" <---返回时机了.alt+f9
取消断点返回1000C12A 68 97B90110 push 0x1001B997 ; ASCII "KERNEL32"
1000C12F FF15 D7730110 call dword ptr [0x100173D7] ; kernel32.GetModuleHandleA
1000C135 85C0 test eax, eax ; 返回到这里
1000C137 74 15 je short 1000C14E
Ctrl+B 搜索
3D ?? ?? ?? ?? 74 ?? 3D ?? ?? ?? ?? 74 ?? 3D ?? ?? ?? ?? 74 ?? 3D ?? ?? ?? ??10005B6E FF15 08710110 call dword ptr [0x10017108] ; kernel32.GetProcAddress
10005B74 894424 18 mov dword ptr [esp+0x18], eax
10005B78 EB 08 jmp short 10005B82
10005B7A 1122 adc dword ptr [edx], esp
10005B7C 334455 66 xor eax, dword ptr [ebp+edx*2+0x66]
10005B80 ^ 77 88 ja short 10005B0A
10005B82 8B4424 54 mov eax, dword ptr [esp+0x54]
10005B86 3D 53F14A7A cmp eax, 0x7A4AF153
10005B8B 74 19 je short 10005BA6 ; nop
10005B8D 3D 4DE75D66 cmp eax, 0x665DE74D
10005B92 74 12 je short 10005BA6 ; nop
10005B94 3D 5FF05127 cmp eax, 0x2751F05F
10005B99 74 0B je short 10005BA6 ; nop
10005B9B 3D 59F04E75 cmp eax, 0x754EF059
10005BA0 0F85 70010000 jnz 10005D16 ; magic jmp
10005BA0的jnz改成jmp即可跳过iat加密
4.AntiDump
bp VirtualProtect 解码后返回10008531 FF15 C1790110 call dword ptr [0x100179C1] ; kernel32.VirtualProtect
10008537 83C7 01 add edi, 0x1 ; 返回到这里
Ctrl+B 搜索
8B 94 24 6C 01 00 001000874B 8B9424 6C010000 mov edx, dword ptr [esp+0x16C] ; 此处下断
10008752 8D4C24 18 lea ecx, dword ptr [esp+0x18]
10008756 51 push ecx
10008757 6A 01 push 0x1
10008759 6A 64 push 0x64
1000875B 52 push edx
1000875C FF15 92130210 call dword ptr [0x10021392] ; 跟进
004A1AD4 8BFF mov edi, edi
004A1AD6 55 push ebp
004A1AD7 8BEC mov ebp, esp
004A1AD9 FF75 14 push dword ptr [ebp+0x14]
004A1ADC FF75 10 push dword ptr [ebp+0x10]
004A1ADF FF75 0C push dword ptr [ebp+0xC]
004A1AE2 FF75 08 push dword ptr [ebp+0x8]
004A1AE5 6A FF push -0x1
004A1AE7 E8 75FFFFFF call 004A1A61 ; F7
004A1A61 8BFF mov edi, edi
004A1A63 55 push ebp
004A1A64 8BEC mov ebp, esp
004A1A66 56 push esi
004A1A67 8B35 C4124A00 mov esi, dword ptr [0x4A12C4] ; ntdll.ZwProtectVirtualMemory
004A1A6D 57 push edi
004A1A6E FF75 18 push dword ptr [ebp+0x18]
004A1A71 8D45 10 lea eax, dword ptr [ebp+0x10]
004A1A74 FF75 14 push dword ptr [ebp+0x14]
004A1A77 50 push eax
004A1A78 8D45 0C lea eax, dword ptr [ebp+0xC]
004A1A7B 50 push eax
004A1A7C FF75 08 push dword ptr [ebp+0x8]
004A1A7F FFD6 call esi ; ntdll.ZwProtectVirtualMemory
看一下ZwProtectVirtualMemory参数#define PAGE_NOACCESS 0x01
#define PAGE_READONLY 0x02
#define PAGE_READWRITE 0x04
#define PAGE_WRITECOPY 0x08
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
再看回头那段代码1000874B 8B9424 6C010000 mov edx, dword ptr [esp+0x16C]
10008752 8D4C24 18 lea ecx, dword ptr [esp+0x18]
10008756 51 push ecx
10008757 6A 01 push 0x1 ; 参数为1,也就是NOACCESS
10008759 6A 64 push 0x64
那这样就好办了,只要把10008757改成push 40就可以过Anti Dump
5.寻找被偷的代码
bp VirtualProtect 解码后返回
Ctrl+B 搜索
8B 94 24 6C 01 00 00
把改成10007E76 6A 40 push 0x40 //先干掉antidump,方便找回被偷的代码
Ctrl+B 搜索
B8 01 00 00 00 C2 04 00 CC CC CC CC CC CC CC CC CC CC CC CC CC1000831D B8 01000000 mov eax, 0x1 ; 断在这里
10008322 C2 0400 retn 0x4 ; 返回
10008325 CC int3
10008326 CC int3
10008327 CC int3
10008328 CC int3
10008329 CC int3
1000832A CC int3
1000832B CC int3
右键,查找,命令,jmp eax,下断,shift+f9,取消断点(一般是很大的跳转.如果不是大跳转,多找几次)010153CB - FFE0 jmp eax ; F7
跟进后就是被偷的代码了!
直接用二进制复制吧
复制到100739D那里后,还需要修正一下call的地址006AFE00 6A 70 push 0x70 //被偷的代码
006AFE02 68 98180001 push 0x1001898
006AFE07 E8 5C779500 call pack_NOT.01007568 <---call 1
...........
006AFEAB E8 44779500 call pack_NOT.010075F4 <---call 2
...........
006AFEC4 E8 14779500 call pack_NOT.010075DD <---call 3
006AFEC9 68 10900001 push 0x1009010
006AFECE 68 0C900001 push 0x100900C
006AFED3 E8 FA769500 call pack_NOT.010075D2 <---call 4
...........
006AFF09 E8 C4769500 call pack_NOT.010075D2 <---call 5
...........
006AFF6F E8 C2299500 call pack_NOT.01002936 <--- call 6
...........
006AFF99 E8 28769500 call pack_NOT.010075C6 <--- call 7
........
006AFFC0 E8 DE759500 call pack_NOT.010075A3 <--- call 8
006AFFC5 C3 retn
总结一下脱壳步骤:
1.bp GetModuleHandleA+20
2.返回干掉iat加密
3.再次断在VirtualProtect那里,解码后返回干掉AntiDump
4.找被偷的代码
5.alt+m,在test(x01000)下内存访问断点,来到fake oep,向上拉,粘贴一下被偷的代码
6.修正一下call的地址,LORDPE+IMPREC修复之.脱壳完成 |