在网上下了个svk加壳的试炼品,用peid一查显示为:SVKP 1.3x -> Pavol Cerven,用扩展扫描显示为svk1.43,不管了,好歹我看过几篇教程,那
就开工吧,如果有不周详的地方,请多指教,谢谢。
0.用OD加载,忽略所有异常,按一下F7,执行完pushad语句,记下esp的值13FFA4备用(后面要用到esp定律)
00405000 > 60 pushad
00405001 E8 00000000 call 00405006 //停在这里
00405006 5D pop ebp
00405007 81ED 06000000 sub ebp, 6
0040500D EB 05 jmp short 00405014
0040500F B8 49DCCE05 mov eax, 5CEDC49
00405014 64:A0 23000000 mov al, fs:[23]
0040501A EB 03 jmp short 0040501F
1.下断 bp GetModuleHandleA+5 (之所以要加5不用我解释了吧),shift+f9通过异常,直到在GetModuleHandleA+5处断了下来:
7C80B529 ker> 8BFF mov edi, edi //GetModuleHandleA
7C80B52B 55 push ebp
7C80B52C 8BEC mov ebp, esp
7C80B52E 837D 08 00 cmp dword ptr [ebp+8], 0 //断在这里
7C80B532 74 18 je short 7C80B54C
7C80B534 FF75 08 push dword ptr [ebp+8]
7C80B537 E8 682D0000 call 7C80E2A4
7C80B53C 85C0 test eax, eax
2.取消断点,执行到用户代码
055556AE /76 00 jbe short 055556B0
055556B0 \5B pop ebx //返回这里
055556B1 5E pop esi
055556B2 5F pop edi
055556B3 5D pop ebp
055556B4 0BC0 or eax, eax
055556B6 75 2F jnz short 055556E7
3.搜索命令:"cmp dword ptr [ebx], const" (const是OD中保留的关键字,代表常数),搜到特殊函数比较处
05555778 813B CC971025 cmp dword ptr [ebx], 251097CC
0555577E 0F84 41170000 je 05556EC5
05555784 813B C5B1662D cmp dword ptr [ebx], 2D66B1C5
0555578A 0F84 62180000 je 05556FF2
05555790 813B 9404B2D9 cmp dword ptr [ebx], D9B20494
05555796 0F84 AA1C0000 je 05557446
0555579C 813B A41A86D0 cmp dword ptr [ebx], D0861AA4
055557A2 0F84 58210000 je 05557900
055557A8 813B 706586B1 cmp dword ptr [ebx], B1866570
055557AE 0F84 C1240000 je 05557C75
055557B4 813B 0E46769B cmp dword ptr [ebx], 9B76460E
055557BA 0F84 36280000 je 05557FF6
055557C0 813B DB0793E6 cmp dword ptr [ebx], E69307DB
055557C6 0F84 76280000 je 05558042
055557CC 813B 627B6CA5 cmp dword ptr [ebx], A56C7B62
055557D2 0F84 BA280000 je 05558092
055557D8 813B 664E96BB cmp dword ptr [ebx], BB964E66
055557DE 0F84 00290000 je 055580E4
055557E4 813B 4506D75B cmp dword ptr [ebx], 5BD70645
055557EA 0F84 43290000 je 05558133
055557F0 813B 0DE0FC1D cmp dword ptr [ebx], 1DFCE00D
055557F6 0F84 83290000 je 0555817F
055557FC 813B 31DD0F00 cmp dword ptr [ebx], 0FDD31
05555802 0F84 C6290000 je 055581CE
05555808 813B 95B75126 cmp dword ptr [ebx], 2651B795
0555580E 0F84 132A0000 je 05558227
05555814 813B B482F64B cmp dword ptr [ebx], 4BF682B4
0555581A 0F84 582A0000 je 05558278
05555820 813B 0F1ACF4C cmp dword ptr [ebx], 4CCF1A0F
05555826 0F84 972A0000 je 055582C3
0555582C 813B 4A7687DF cmp dword ptr [ebx], DF87764A
05555832 0F84 FC2D0000 je 05558634
05555838 813B B8B8B2FB cmp dword ptr [ebx], FBB2B8B8
0555583E 0F84 56320000 je 05558A9A
05555844 813B 8E5D2D57 cmp dword ptr [ebx], 572D5D8E
0555584A 0F84 86320000 je 05558AD6
05555850 60 pushad
05555851 8B03 mov eax, [ebx]
05555853 8985 D8550200 mov [ebp+255D8], eax
05555859 8B95 33010200 mov edx, [ebp+20133]
0555585F 8B42 3C mov eax, [edx+3C]
将其中的十多处je const全部nop掉,这是我用脚本做的,所以不觉得麻烦(更简单的方法把第一个je改为jmp 5555850)
4.搜索命令序列:mov [edi], eax ;popad ,将找到的地方改为:popad;mod [edi],eax
05555B4F 8907 mov [edi], eax //找到这里
05555B51 61 popad
05555B52 8385 43010200 0>add dword ptr [ebp+20143], 4
05555B59 ^ E9 ADFBFFFF jmp 0555570B
改完后:
05555B4F 61 popad
05555B50 8907 mov [edi], eax
05555B52 8385 43010200 0>add dword ptr [ebp+20143], 4
05555B59 ^ E9 ADFBFFFF jmp 0555570B
在下面不远处你会看到xor eax,eax,在上面下个f2断点
05555B75 ^\E9 9DFAFFFF jmp 05555617
05555B7A 33C0 xor eax, eax //找到这里,下断
05555B7C 64:8F00 pop dword ptr fs:[eax]
05555B7F 83C4 04 add esp, 4
05555B82 C3 retn
f9运行,在xor eax,eax那一行断了下来,输入表处理完毕,取消断点
5.接下来,我们要找vm-oep了(由于svkp一般会抽取oep开始的代码,而改用vm代码取代,所以我们最好是能找到vm代码开始的地方,
才好分析被抽代码是什么,由于在vm代码开始的地方,堆栈,寄存器等的数值和程序开始处的值肯定是一样的(这是必须的,否则程序
会不正常),所以我们可以用到esp定律,姑且把vm代码开始的地方叫做vm-oep吧)
还记得程序开始处的ESP值吗?esp=13FFA4
下断点hr 13FFA4,按几次F9运行
0013FC40 60 pushad //第一次断在这
0013FC41 E8 03000000 call 0013FC49
0013FC46 D2EB shr bl, cl
0013FC48 0A58 EB or bl, [eax-15]
0013FC4B 0148 40 add [eax+40], ecx
0013FC4E EB 01 jmp short 0013FC51
0013FC54 E8 01000000 call 0013FC5A //第二次
0013FC59 E8 E8020000 call 0013FF46
0013FC5E 00CD add ch, cl
0013FC60 2083 04240B83 and [ebx+830B2404], al
0013FC66 44 inc esp
0013FC67 24 04 and al, 4
0013FC69 13C3 adc eax, ebx
0013FC6B E9 E8020000 jmp 0013FF58
0013FCFB E8 00000000 call 0013FD00 //第三次
0013FD00 5D pop ebp
0013FD01 E8 02000000 call 0013FD08
0013FD06 CD20 83042408 vxdcall 8240483
0013FD0C C3 retn
好的,取消硬件断点,在当前代码段搜索命令序列:jmp eax ;call const
找到一处,下F2断点,运行,断下后取消断点:
0013FF75 FFE0 jmp eax //找到这里,下断,这就是跳到vm-oep的地方
0013FF77 E8 01000000 call 0013FF7D
0013FF7C - E9 83C40484 jmp 8418C404
0013FF81 FF13 call [ebx]
0013FF83 0011 add [ecx], dl
6.按F7单步走一步,在这里DUMP,由于当前代码属于动态申请的内存,所以把当前区段也用loadpe dump下来备用:
055DE159 50 push eax //到这里,vm-oep,dump
055DE15A 55 push ebp
055DE15B 68 00000000 push 0
055DE160 B8 ADADB5D5 mov eax, D5B5ADAD
055DE165 E9 600C0000 jmp 055DEDCA
055DE16A 79 39 jns short 055DE1A5
055DE16C 5D pop ebp
在代码段下"内存访问断点"(不是F2断点),反复按ctrl+F11跟踪进入直到在代码段断下来:
0040174A E8 16010000 call 00401865 //断在这里
0040174F 391D 20304000 cmp [403020], ebx
00401755 75 0C jnz short 00401763
00401757 68 62184000 push 00401862
0040175C FF15 7C214000 call [40217C] ; msvcrt.__setusermatherr
00401762 59 pop ecx
00401763 E8 E8000000 call 00401850
00401768 68 14304000 push 00403014
0040176D 68 10304000 push 00403010
从40174A往上翻翻,全是nop,一直到4016E0,所以我们知道oep为4016E0
004016DE CC int3
004016DF CC int3
004016E0 90 nop
004016E1 90 nop
004016E2 90 nop
004016E3 90 nop
004016E4 90 nop
004016E5 90 nop
004016E6 90 nop
004016E7 90 nop
004016E8 90 nop
我晕,6A个字节被抽取了,我可没有那么多闲工夫来一个个恢复,干脆用流行的补区段方法修复算了。
用importrec获取输入表,全为有效的。
7.修复并完成,用loadpe将dump下的区段添加进dump下的程序,重建PE文件,用importrec修复输入表(oep填:51DE159(vmoep-CODEBASE))
运行,正常。大家帮忙测试下,看能不能跨平台。谢谢~~
[课程]Linux pwn 探索篇!