破解狼人 发表于 2010-10-31 22:22:22

PE_Admin[20090719]-免费全功能版脱壳[by hyperchem]

不知道是系统的问题 还是程序的问题,还是OD的问题,这个软件在我的OD中运行的速度巨慢无比。
在运行起来以后,查看第一个区段,也就是Code段的内容


引用
00401000             04 10               add al,10
00401002             40                  inc eax
00401003             0003                add byte ptr ds:,al
00401005             07                  pop es
00401006             42                  inc edx
00401007             6F                  outs dx,dword ptr es:
00401008             6F                  outs dx,dword ptr es:
00401009             6C                  ins byte ptr es:,dx
0040100A             65:61               popad
0040100C             6E                  outs dx,byte ptr es:
0040100D             0100                add dword ptr ds:,eax
0040100F             0000                add byte ptr ds:,al
00401011             0001                add byte ptr ds:,al
00401013             0000                add byte ptr ds:,al
00401015             0000                add byte ptr ds:,al
00401017             1040 00             adc byte ptr ds:,al
0040101A             05 46616C73         add eax,736C6146
0040101F             65:04 54            add al,54
00401022             72 75               jb short 00401099
00401024             65:8D40 00          lea eax,dword ptr gs:
00401028             2C 10               sub al,10
0040102A             40                  inc eax
0040102B             0002                add byte ptr ds:,al
0040102D             04 43               add al,43


发现这是个典型的Delphi程序。
下面我们来找OEP。
Delphi的程序的OEP很好找。依据以下几点:


引用
1,OEP的上面是初始化函数表
2,OEP的下面是Code段结束的00
3,OEP附近的第一个API调用时GetModuleHandleA


这个程序把原始程序的所有区段都合并到第一个区段去了,所以通过前两种方法中OEP的话,对于大多数人来说都是个体力活。
我们用第三种方法,因为程序N慢,所以对于我来说也是种煎熬~
重新载入,然后bp GetModuleHandleA 运行,然后就等到程序中断下来 看返回的地址是不是在第一个区段的范围内。

最后我们中断并返回到这里:00407374    53            push ebx
00407375    8BD8            mov ebx,eax
00407377    33C0            xor eax,eax
00407379    A3 C4005600   mov dword ptr ds:,eax
0040737E    6A 00         push 0
00407380    E8 2BFFFFFF   call 004072B0-------这里就是call GetModuleHandleA了
00407385    A3 68B65700   mov dword ptr ds:,eax
0040738A    A1 68B65700   mov eax,dword ptr ds:
0040738F    A3 D0005600   mov dword ptr ds:,eax
00407394    33C0            xor eax,eax
00407396    A3 D4005600   mov dword ptr ds:,eax
0040739B    33C0            xor eax,eax
0040739D    A3 D8005600   mov dword ptr ds:,eax
004073A2    E8 C1FFFFFF   call 00407368
004073A7    BA CC005600   mov edx,005600CC
004073AC    8BC3            mov eax,ebx
004073AE    E8 1DD7FFFF   call 00404AD0
004073B3    5B            pop ebx
004073B4    C3            retn熟悉Delphi朋友肯定知道这就是OEP处的第一个call了。 继续返回到上层0055F0EC >55            push ebp----------这就是OEP了
0055F0ED    8BEC            mov ebp,esp
0055F0EF    83C4 F0         add esp,-10
0055F0F2    B8 7CED5500   mov eax,0055ED7C
0055F0F7    E8 7882EAFF   call 00407374
0055F0FC    A1 DCA05700   mov eax,dword ptr ds:
0055F101    8B00            mov eax,dword ptr ds:
0055F103    E8 D03DF2FF   call 00482ED8
0055F108    A1 DCA05700   mov eax,dword ptr ds:
0055F10D    8B00            mov eax,dword ptr ds:
0055F10F    C640 5B 00      mov byte ptr ds:,0
0055F113    8B0D 44A15700   mov ecx,dword ptr ds:            ; 1.0057D1DCOEP找到了~ 我们下面看看IAT004072B0             90                  nop
004072B1         - E9 3E7CC500         jmp 0105EEF4----这里应该是Jmp GetModudleHandleA
004072B6             8BC0                mov eax,eax
004072B8             90                  nop
004072B9         - E9 027CC500         jmp 0105EEC0
004072BE             8BC0                mov eax,eax
004072C0             90                  nop
004072C1         - E9 CE7BC500         jmp 0105EE94
004072C6             8BC0                mov eax,eax
004072C8             90                  nop
004072C9         - E9 9A7BC500         jmp 0105EE68发现IAT已经被处理了。我们要修复。
好了,先说句题外话吧。在跟踪的过程,我发现程序的注册框是壳代码里面显示的,而且这个时候原程序的代码段和数据段都已经解码了,

也就是说这个时候还没有执行到OEP,数据没有初始化。这个是我们修复的最好时机。

直接运行程序,弹出注册框以后,用OD附加这个程序。然后开始我们的修复IAT的过程。
跟入上面的Jmp,看到下面的代码。0105EEF4             E8 03C675FF         call PE_Adm_1.007BB4FC
0105EEF9         - FF25 FFEE0501       jmp dword ptr ds:                     ; SHELL32.7D8559B8跟进上面的call,清理下代码,得到下面的代码007BB502             9C                  pushfd
007BB503             50                  push eax
007BB504             53                  push ebx
007BB50A             E8 DDB6F8FF         call 00746BEC                                  ; jmp to kernel32.GetCurrentThread
007BB50F             9C                  pushfd
007BB510             58                  pop eax
007BB511             A3 94458400         mov dword ptr ds:,eax
007BB51C             E8 47000000         call 007BB568
007BB521             31C0                xor eax,eax
007BB523             A0 B0458400         mov al,byte ptr ds:
007BB528             83F8 00             cmp eax,0
007BB52B             75 34               jnz short 007BB561
007BB52D             8B4424 0C         mov eax,dword ptr ss:---------注意这里
007BB531             89C3                mov ebx,eax
007BB533             83C0 02             add eax,2
007BB536             8B00                mov eax,dword ptr ds:
007BB538             8B00                mov eax,dword ptr ds:
007BB53A             31D8                xor eax,ebx
007BB53C             894424 0C         mov dword ptr ss:,eax
007BB540             8B00                mov eax,dword ptr ds:
007BB542             3C CC               cmp al,0CC
007BB544             74 14               je short 007BB55A
007BB546             80FC CC             cmp ah,0CC
007BB549             74 0F               je short 007BB55A
007BB54B             C1E8 10             shr eax,10
007BB54E             3C CC               cmp al,0CC
007BB550             74 08               je short 007BB55A
007BB552             80FC CC             cmp ah,0CC
007BB555             74 03               je short 007BB55A
007BB557             EB 08               jmp short 007BB561
007BB559         - E9 C605B045         jmp 462BBB24
007BB55E             8400                test byte ptr ds:,al
007BB560             015B 58             add dword ptr ds:,ebx
007BB563             9D                  popfd
007BB564             C3                  retn这里面ESP+C里面放的是
0105EEF4             E8 03C675FF         call PE_Adm_1.007BB4FC
这个call的返回地址,也就是0105EEF9
007BB533             83C0 02             add eax,2
007BB536             8B00                mov eax,dword ptr ds:
007BB538             8B00                mov eax,dword ptr ds:
这三条指令的作用就是获取下面这个7D8559B8的
0105EEF9         - FF25 FFEE0501       jmp dword ptr ds:                     ; SHELL32.7D8559B8

007BB53A             31D8                xor eax,ebx----这个就是用上面的地址跟返回地址异或,就得到真正API地址了。

可以分析下,所有的IAT都是这样处理的,所以写个脚本修复下就OK了!mov eip,00401000-----------代码开始
mov tmp0,01750000----------这个是我用StrongOD分配的内存,用来存放IAT的

Loop:
mov tmp1,eip
find tmp1,#90E9#-----------查找nop Jmp
cmp $RESULT,0
je Finish
mov tmp2,$RESULT
mov tmp3,$RESULT
add tmp2,1
GCI tmp2,DESTINATION
cmp $RESULT,01040000--------
jb continue
cmp $RESULT,01910000--------因为jmp的地址不在一个内存段上,所以这两个值就是内存段的上限和下限值
jg continue
mov tmp4,$RESULT
add tmp4,5
GCI tmp4,DESTINATION--------因为是哪里用的是FF25这样的jmp型,所以直接用GCI就可以获取异或后的API地址了
cmp $RESULT,0
je continue
mov tmp5,$RESULT
xor tmp5,tmp4---------------异或解开
mov ,tmp5,4
mov ,#FF25#,2---------修复IAT调用为Jmp dword ptr ds:[]
add tmp3,2
mov ,tmp0,4
add tmp0,4
jmp continue

continue:
mov eip,tmp2
jmp Loop

Finish:
ret跑完脚本以后,IAT就差不多全部修复了~
还剩三处没有修复,因为处理的方法不同的说004078C0    90            nop
004078C1- E9 7AA17C77   jmp version.GetFileVersionInfoA
004078C6    8BC0            mov eax,eax
004078C8    90            nop
004078C9- E9 21A17C77   jmp version.GetFileVersionInfoSizeA
004078CE    8BC0            mov eax,eax
004078D0    90            nop
004078D1- E9 D49F7C77   jmp version.VerQueryValueA使用的是直接Jmp的~ 这三个手动修复下就可以了!

然后用UIF把IAT移动回程序内,DUmp进程,ImportREC重建输入表(还记得OEP是什么吧?)。

至此脱壳完成!

建议:

1,不要向System32下释放dll文件,否则很容易被主动掉!
2,不要给dll加WinUPack这样的壳,因为这个壳是病毒常用的,很容易被误杀。
3,IAT加密还需加强的说~
4,资源的处理不要只修改一个索引。
页: [1]
查看完整版本: PE_Admin[20090719]-免费全功能版脱壳[by hyperchem]