|
高手就飘过吧,接触脱壳有一段时间了,对于脱壳有一些感悟,愿与大家一起分享,对于一般的加密壳,修复正确的iat一般
都是这两种方法,一是在到达oep之前就改magic jump 或者 patch code修复;二是 到达oep之后,查看加密之后的函数调用,
根据其解密的方式编写代码还原,然后IR修复。下面我以UltraProtect加壳的记事本为例,其实这个壳不用这么复杂的,我只是
借这个实例说一下这两种方法,下面实例分析一下:
第一种方法:在到达oep之后修复
这种方法主要是先到达oep,可以用两次内存断点法,最后一次异常法,等等。。。当然了有stolen code 等其他的保护方式要另当别论了,小菜我水平太烂
不忽略内存访问异常
0040D000 > 60 pushad ;加壳后程序入口
0040D001 F9 stc ;F8一下,命令行下断:hr esp 主要是找stolen code,不在本文讨论之列 F9 运行
0040D002 87D6 xchg esi,edx
0040D004 72 03 jb short UltraPro.0040D009
0040D006 73 01 jnb short UltraPro.0040D009
0040D008 7A 81 jpe short UltraPro.0040CF8B
0040D00A F7 ??? ; Unknown command
0040D00B 4A dec edx
0040D00C C49F 9DE80***00 es ebx,fword ptr ds:[edi+1E89D] ; Modification of segment register
0040D012 0000 add byte ptr ds:[eax],al
0040D014 E8 83C40***66 call 66***49C
0040D019 D3EA shr edx,cl
004****5719 CD 01 int 1 ;到达此处
00***71B 40 inc eax ;F2下断 shift + F9 运行 断在此处 取消F2断点 F9
00***71C 40 inc eax
00***71D 0BC0 or eax,eax
00***71F 75 05 jnz short UltraPro.004****5726
004****5721 90 nop
004****5722 90 nop
004****5723 90 nop
004****5724 90 nop
004****5725 61 popad
004****5726 33C0 xor eax,eax
004****5728 64:8F00 pop dword ptr fs:[eax]
00***72B 58 pop eax
00***72C 60 pushad
00***72D E8 000****0000 call UltraPro.004****5732
00***54C9 55 push ebp ;stolen code 1
00***54CA 8BEC mov ebp,esp ;stolen code 2
00***54CC 83EC 44 sub esp,44 ;stolen code 3
00***54CF 60 pushad
00***54D0 60 pushad
00***54D1 E8 000****0000 call UltraPro.00***54D6
此时取消开始下好的硬件 单步F7走到00***54d6 对code段下断然后F9 运行 来到这里:
00***10D2 56 push esi
00***10D3 FF15 E46***00 call dword ptr ds:[4063E4] ; UltraPro.0040D1BA
00***10D9 8BF0 mov esi,eax
00***10DB 8A00 mov al,byte ptr ds:[eax]
00***10DD 3C 22 cmp al,22
00***10DF 75 1B jnz short UltraPro.00***10FC
00***10E1 56 push esi
00***10E2 FF15 F46***00 call dword ptr ds:[4064F4] ; UltraPro.0040D4C6
补上stolen code 如下:
00***10CC 55 push ebp ;可以在这里新建起源 再dump 不建也可以
00***10CD 8BEC mov ebp,esp
00***10CF 83EC 44 sub esp,44
00***10D2 56 push esi
00***10D3 FF15 E46***00 call dword ptr ds:[4063E4] ; UltraPro.0040D1BA
00***10D9 8BF0 mov esi,eax
00***10DB 8A00 mov al,byte ptr ds:[eax]
00***10DD 3C 22 cmp al,22
00***10DF 75 1B jnz short UltraPro.00***10FC
00***10E1 56 push esi
00***10E2 FF15 F46***00 call dword ptr ds:[4064F4] ; UltraPro.0040D4C6
LoadPE转存它
我们看到iat加密了
00***10CC 55 push ebp
00***10CD 8BEC mov ebp,esp
00***10CF 83EC 44 sub esp,44
00***10D2 56 push esi
00***10D3 FF15 E46***00 call dword ptr ds:[4063E4] ; 这里enter键 跟进
00***10D9 8BF0 mov esi,eax
00***10DB 8A00 mov al,byte ptr ds:[eax]
00***10DD 3C 22 cmp al,22
00***10DF 75 1B jnz short UltraPro.00***10FC
00***10E1 56 push esi
00***10E2 FF15 F46***00 call dword ptr ds:[4064F4] ; UltraPro.0040D4C6
结果如下:
0040D1BA 68 DD43C07E push 7EC043DD ;在这里我们右键 此处新建eip
0040D1BF 81***24 E06C4102 xor dword ptr ss:[esp],2416CE0
0040D1C6 C3 retn ;走到这里出现 返回到 7C812F3D (kernel32.GetCommandLineA)
说明正确的函数已被解出
同样的方法我们可以看看其它函数的解密方式,发现都是这样的,我们开始patch 代码修复吧,在patch之前我们确定一下加密函数的范围,打开IR选中进程,oep 填 10cc, 获取输入表,显示无效的
我们可以看到加密的iat有两段 635c ~63F0, 6414 ~6500,找片空地写下如下代码:
以上面的例子:
0040D1BA 68 DD43C07E push 7EC043DD
0040D1BF 81***24 E06C4102 xor dword ptr ss:[esp],2416CE0
0040D1C6 C3 retn
说明一下这段代码:
00***04FD4 C7C0 146****4000 mov eax,UltraPro.004****6414 ;加密函数开始的地址,另外一段将这里改成00***35c
00***04FDA 8B18 mov ebx,dword ptr ds:[eax]
00***04FDC 43 inc ebx
00***04FDD 90 nop
00***04FDE 8B0B mov ecx,dword ptr ds:[ebx];7EC043DD 给ecx
00***04FE0 81C3 070****0000 add ebx,7 ;定位到2416CE0
00***04FE6 330B xor ecx,dword ptr ds:[ebx] ;解码
00***04FE8 8908 mov dword ptr ds:[eax],ecx ;正确函数地址写入
00***04FEA 81C0 040****0000 add eax,4 ;处理下一个
00***04FF0 81F8 046****4000 cmp eax,UltraPro.004****6504 ;比较是否处理完,另外一段将这里改成00***63f4
00***04FF6 ^ 72 E1 jb short UltraPro.00***04FD9 ;没处理完则继续
00***04FF8 90 nop ;
00***04FF9 90 nop
我选在00***04fd4 大家可以选在别处,然后在00***04fd4处新建起源,在00***04ff8处下硬件执行断点,执行这段程序,处理完成后
改一下上面说的两个地址,处理完成之后只有一个无效的,很显然这个是 MessageBoxA
填上之后 全部有效,IR修复dump的文件可以运行。
第二种方法:在到达oep之前修复iat
这种关键是定位处理iat的关键代码,常见的方法是先到达oep然后查找iat的范围,对其下硬件写入断点,基本可以定位到iat处理的地方。也可以结合getprocaddress loadlibrarya等函数来确定,但是不一定有效。
忽略所有异常
对rdata段下断,F9运行,
00***18A0F 8B46 0C mov eax,dword ptr ds:[esi+C] ;来到此处 很明显了,这里是取dll的名字
00***18A12 0BC0 or eax,eax
00***18A14 0F84 C00***00 je UltraPro.00***18BDA ;判断所有dll处理完毕
00***18A1A 8366 0C 00 and dword ptr ds:[esi+C],0 ;取出之后清零
00***18A1E 03C2 add eax,edx ; UltraPro.004****0000 加上基址
00***18A20 8BD8 mov ebx,eax
00***18A22 56 push esi
00***18A23 57 push edi
00***18A24 50 push eax
00***18A25 8BF3 mov esi,ebx ; UltraPro.004****6592
00***18A27 8BFB mov edi,ebx
00***18A29 AC lods byte ptr ds:[esi]
00***18A2A C0C0 03 rol al,3
00***18A2D AA stos byte ptr es:[edi]
00***18A2E 803F 00 cmp byte ptr ds:[edi],0
00***18A31 ^ 75 F6 jnz short UltraPro.00***18A29 ;解出dll名
00***18A33 58 pop eax
00***18A34 5F pop edi
00***18A35 5E pop esi
00***18A36 50 push eax ; UltraPro.004****6592
00***18A37 FF95 489C4100 call dword ptr ss:[ebp+419C48] ; kernel32.GetModuleHandleA
00***18A3D 0BC0 or eax,eax
00***18A3F 75 43 jnz short UltraPro.00***18A84
00***18A41 90 nop
00***18A42 90 nop
00***18A43 90 nop
00***18A44 90 nop
00***18A45 53 push ebx
00***18A46 FF95 4C9C4100 call dword ptr ss:[ebp+419C4C] ;调用loadlibrarya
00***18A4C 0BC0 or eax,eax
00***18A4E 75 34 jnz short UltraPro.00***18A84
00***18A50 90 nop
00***18A51 90 nop
00***18A52 90 nop
00***18A53 90 nop
00***18A54 8B95 EA61***00 mov edx,dword ptr ss:[ebp+4061EA]
00***18A5A 0195 E41B4000 add dword ptr ss:[ebp+401BE4],edx
00***18A60 0195 E81B4000 add dword ptr ss:[ebp+401BE8],edx
00***18A66 6A 00 push 0
00***18A68 FFB5 E41B4000 push dword ptr ss:[ebp+401BE4]
00***18A6E FFB5 E81B4000 push dword ptr ss:[ebp+401BE8]
00***18A74 6A 00 push 0
00***18A76 FF95 549C4100 call dword ptr ss:[ebp+419C54]
00***18A7C 6A 00 push 0
00***18A7E FF95 509C4100 call dword ptr ss:[ebp+419C50]
00***18A84 60 pushad
00***18A85 2BC0 sub eax,eax
00***18A87 8803 mov byte ptr ds:[ebx],al
00***18A89 43 inc ebx
00***18A8A 3803 cmp byte ptr ds:[ebx],al ;擦除dll名字
00***18A8C ^ 75 F9 jnz short UltraPro.00***18A87
00***18A8E 61 popad
00***18A8F 8985 E26***00 mov dword ptr ss:[ebp+4061E2],eax
00***18A95 C785 E66***00 00***00>mov dword ptr ss:[ebp+4061E6],0
00***18A9F 8B95 EA61***00 mov edx,dword ptr ss:[ebp+4061EA]
00***18AA5 8B06 mov eax,dword ptr ds:[esi] ;取originalfirstthunk
00***18AA7 0BC0 or eax,eax
00***18AA9 75 07 jnz short UltraPro.00***18AB2
00***18AAB 90 nop
00***18AAC 90 nop
00***18AAD 90 nop
00***18AAE 90 nop
00***18AAF 8B46 10 mov eax,dword ptr ds:[esi+10]
00***18AB2 03C2 add eax,edx
00***18AB4 0385 E66***00 add eax,dword ptr ss:[ebp+4061E6]
00***18ABA 8B18 mov ebx,dword ptr ds:[eax]
00***18ABC 8B7E 10 mov edi,dword ptr ds:[esi+10] ;取firstthunk
00***18ABF 03FA add edi,edx
00***18AC1 03BD E66***00 add edi,dword ptr ss:[ebp+4061E6]
00***18AC7 85DB test ebx,ebx
00***18AC9 0F84 FD00***00 je UltraPro.00***18BCC
00***18ACF F7C3 000****0080 test ebx,800****0000 ;判断是不是序号方式
00***18AD5 75 1D jnz short UltraPro.00***18AF4
00***18AD7 90 nop
00***18AD8 90 nop
00***18AD9 90 nop
00***18ADA 90 nop
00***18ADB 03DA add ebx,edx
00***18ADD 83C3 02 add ebx,2
00***18AE0 56 push esi
00***18AE1 57 push edi
00***18AE2 50 push eax
00***18AE3 8BF3 mov esi,ebx
00***18AE5 8BFB mov edi,ebx
00***18AE7 AC lods byte ptr ds:[esi]
00***18AE8 C0C0 03 rol al,3
00***18AEB AA stos byte ptr es:[edi]
00***18AEC 803F 00 cmp byte ptr ds:[edi],0
00***18AEF ^ 75 F6 jnz short UltraPro.00***18AE7 ;解出函数名
00***18AF1 58 pop eax
00***18AF2 5F pop edi
00***18AF3 5E pop esi
00***18AF4 81E3 FFFFFF0F and ebx,0FFFFFFF
00***18AFA 53 push ebx
00***18AFB FFB5 E26***00 push dword ptr ss:[ebp+4061E2]
00***18B01 FF95 449C4100 call dword ptr ss:[ebp+419C44] ;getprocaddress
00***18B07 3B9D EA61***00 cmp ebx,dword ptr ss:[ebp+4061EA]
00***18B0D 7C 0F jl short UltraPro.00***18B1E
00***18B0F 90 nop
00***18B10 90 nop
00***18B11 90 nop
00***18B12 90 nop
00***18B13 60 pushad
00***18B14 2BC0 sub eax,eax
00***18B16 8803 mov byte ptr ds:[ebx],al
00***18B18 43 inc ebx
00***18B19 3803 cmp byte ptr ds:[ebx],al
00***18B1B ^ 75 F9 jnz short UltraPro.00***18B16 ;擦除操作
00***18B1D 61 popad
00***18B1E 0BC0 or eax,eax
00***18B20 ^ 0F84 2EFFFFFF je UltraPro.00***18A54
00***18B26 3B85 549C4100 cmp eax,dword ptr ss:[ebp+419C54] ; USER32.MessageBoxA
是否是特殊的函数
00***18B2C 75 0A jnz short UltraPro.00***18B38
00***18B2E 90 nop
00***18B2F 90 nop
00***18B30 90 nop
00***18B31 90 nop
00***18B32 8D85 8D67***00 lea eax,dword ptr ss:[ebp+40***78D]
00***18B38 56 push esi
00***18B39 FFB5 E26***00 push dword ptr ss:[ebp+4061E2]
00***18B3F 5E pop esi
00***18B40 39B5 C12***00 cmp dword ptr ss:[ebp+4020C1],esi ;比较是否是kernel32.dll 是则加密
00***18B46 74 15 je short UltraPro.00***18B5D ;nop掉 不让它加密
00***18B48 90 nop
00***18B49 90 nop
00***18B4A 90 nop
00***18B4B 90 nop
00***18B4C 39B5 C52***00 cmp dword ptr ss:[ebp+4020C5],esi ; 比较是否user32.dll 是则加密
00***18B52 74 09 je short UltraPro.00***18B5D ;nop掉 不让它加密
00***18B54 90 nop
00***18B55 90 nop
00***18B56 90 nop
00***18B57 90 nop
00***18B58 EB 63 jmp short UltraPro.00***18BBD ;不加密路线
00***18B5A 90 nop
00***18B5B 90 nop
00***18B5C 90 nop
00***18B5D 80BD 6FCB4000 00 cmp byte ptr ss:[ebp+40CB6F],0
00***18B64 74 57 je short UltraPro.00***18BBD
00***18B66 90 nop
00***18B67 90 nop
00***18B68 90 nop
00***18B69 90 nop
00***18B6A EB 07 jmp short UltraPro.00***18B73 ;加密路线
00***18B6C 90 nop
00***18B6D 90 nop
00***18B6E 90 nop
00***18B6F 0100 add dword ptr ds:[eax],eax
00***18B71 0000 add byte ptr ds:[eax],al
00***18B73 8BB5 AF62***00 mov esi,dword ptr ss:[ebp+4062AF]
00***18B79 83C6 0D add esi,0D
00***18B7C 81EE DF1B4000 sub esi,UltraPro.00***01BDF
00***18B82 2BF5 sub esi,ebp
00***18B84 83FE 00 cmp esi,0
00***18B87 7F 34 jg short UltraPro.00***18BBD
00***18B89 90 nop
00***18B8A 90 nop
00***18B8B 90 nop
00***18B8C 90 nop
00***18B8D 8BB5 AF62***00 mov esi,dword ptr ss:[ebp+4062AF]
00***18B93 53 push ebx
00***18B94 50 push eax
00***18B95 E8 A4A5FFFF call UltraPro.00***13E ;加密
00***18B9A 8BD8 mov ebx,eax
00***18B9C 58 pop eax
00***18B9D 33C3 xor eax,ebx
00***18B9F C606 68 mov byte ptr ds:[esi],68
00***18BA2 8946 01 mov dword ptr ds:[esi+1],eax
00***18BA5 C746 05 813****2400 mov dword ptr ds:[esi+5],24***81
00***18BAC 895E 08 mov dword ptr ds:[esi+8],ebx
00***18BAF C646 0C C3 mov byte ptr ds:[esi+C],0C3
00***18BB3 5B pop ebx
00***18BB4 8BC6 mov eax,esi
00***18BB6 8385 AF62***00 0D add dword ptr ss:[ebp+4062AF],0D
00***18BBD 5E pop esi
00***18BBE 8907 mov dword ptr ds:[edi],eax ;函数地址写入
00***18BC0 8385 E66***00 04 add dword ptr ss:[ebp+4061E6],4 ;继续下一个函数
00***18BC7 ^ E9 D3FEFFFF jmp UltraPro.00***18A9F
00***18BCC 83C6 14 add esi,14
00***18BCF 8B95 EA61***00 mov edx,dword ptr ss:[ebp+4061EA]
00***18BD5 ^ E9 35FEFFFF jmp UltraPro.00***18A0F ;继续下一个dll
00***18BDA 60 pushad ;这里F4
00***18BDB E8 000****0000 call UltraPro.00***18BE0
00***18BE0 5E pop esi
00***18BE1 83EE 06 sub esi,6
然后对code 下断,F9即可到达
00***10D2 56 push esi
00***10D3 FF15 E46***00 call dword ptr ds:[4063E4] ; UltraPro.0040D1BA
00***10D9 8BF0 mov esi,eax
00***10DB 8A00 mov al,byte ptr ds:[eax]
00***10DD 3C 22 cmp al,22
00***10DF 75 1B jnz short UltraPro.00***10FC
00***10E1 56 push esi
00***10E2 FF15 F46***00 call dword ptr ds:[4064F4] ; UltraPro.0040D4C6
补上stolen code LoadPE 转存程序,IR修复,同样有一个无效的,显然是MessageBoxA,填上,修复程序可以运行
总结:这是我学脱壳来对iat处理的心得体会,希望对像我一样的的菜鸟有帮助。 |
|