【目    标】:Security Officer for Windows 6.7.1.1
【工    具】:flyodbg1.1、LORDPE、ImportREC,WinHex
【任    务】:脱壳、修复
【操作平台】:Windows XP sp2
【作    者】: mirrormask
【相关链接】: google
【简要说明】:老婆经常偷玩游戏,近日又迷上英雄无敌,荒废学业。某天突发奇志,要金盆洗手,要我找一用户控制软件,功能要求是在她的用户界面下,只能进入学习资料文件夹。于是找到一名为Security Officer for Windows的冬冬,方便之处不能细数。可是只有30天试用期。想我也在看雪受诸位高手熏陶多时,向老婆夸下海口,要在30天内解除软件限制,使她的学习环境得到保证.找来高手文章,边学边练,12日后,神功初成,软柿子涅扁。
【详细过程】:

peid:ASProtect 2.1x SKE -> Alexey Solodovnikov

od,大概32次异常后下code段内存断点,shift-f9,断下

00529D3C    55                    push ebp  ;这里
00529D3D    8BEC                  mov ebp,esp
00529D3F    83C4 F0               add esp,-10
00529D42    B8 4C975200           mov eax,wso.0052974C
00529D47    E8 88CFEDFF           call wso.00406CD4


做了一个只有32 个esto 的odscript脚本(别的指令不会)。简陋,但方便。
无stolen code,窃喜。

1、iat初步分析
粗跟一下,会看到call进入壳里了。
00406C10    E8 EB93DA00           call 011B0000  ;可能是其他数值


搜索命令 call 011B0000,发现从 40123c开始,类似 

/*40123C*/  jmp dword ptr ds:[530***]

形式的语句,他们本应整齐排列,530***就应是iat位置。但被call 011B0000这类指令打断,api调用被加密。d 530000,发现从5301b4到5309a0处是iat表,但是iat表被加密,比如:
005301F0  *5C B4 FB 1B    AD 9C 80 7C    *C8 2D E7 47   11 03 81 7C  \贷瓬|?鏕亅
*处就是加密后的iat

2、找到api解密代码位置

通过学习loveboom的《ASPROTECT 2.x 脱壳系列》,知道api解密后call 011B0000会被修改,在

00406C10    E8 EB93DA00           call 011B0000

下内存写入断点
00FC5CEE    8902                  mov dword ptr ds:[edx],eax ;断在这里
00FC5CF0    EB 01                 jmp short 00FC5CF3

对00FC5CEE 以上几个call分析(见loveboom文一)
00FC5C9E    8D4D E0               lea ecx,dword ptr ss:[ebp-20]
00FC5CA1    8B45 F4               mov eax,dword ptr ss:[ebp-C]
00FC5CA4    8B40 3C               mov eax,dword ptr ds:[eax+3C]
00FC5CA7    8B55 FC               mov edx,dword ptr ss:[ebp-4] ;
00FC5CAA    E8 D1130000           call 00FC7080  ;edi中为api地址。

跟进

00FC7080    55                    push ebp
00FC7081    8BEC                  mov ebp,esp
00FC7083    83C4 E4               add esp,-1C
00FC7086    53                    push ebx
00FC7087    56                    push esi
00FC7088    57                    push edi
00FC7089    894D F4               mov dword ptr ss:[ebp-C],ecx
00FC708C    8955 F8               mov dword ptr ss:[ebp-8],edx
00FC708F    8945 FC               mov dword ptr ss:[ebp-4],eax
00FC7092    33C0                  xor eax,eax
00FC7094    8945 F0               mov dword ptr ss:[ebp-10],eax
00FC7097    B8 00070000           mov eax,700
00FC709C    E8 A3B4FDFF           call 00FA2544

跟进

00FA2544    85C0                  test eax,eax
00FA2546    74 0A                 je short 00FA2552
00FA2548    FF15 1890FC00         call dword ptr ds:[FC9018] ;;edi中为api地址。

loveboom说,此处下断点不会被检测到,就拿此处开刀!

3、还原iat
重新加载wso.ese,到达oep后,把
00FA2548    FF15 1890FC00         call dword ptr ds:[FC9018]
改为  call 0e000033

先申请一块内存(用od插件memory manage):
 地址=0E000000
 大小=00010000 (65536.)


写下如下代码:

0E000000   mov dword ptr ds:[E001000],532D40 ;532D40开始,原iat所在区块是连续空白区,下一个区块也是空白,作为预留空间,存放解密后api地址
0E00000A   mov edx,401000                    ;搜索“call 11b0000“的起始地质
0E00000F   cmp byte ptr ds:[edx],0E8         ;是否为call指令?
0E000012   jnz short 0E000028                ;继续搜索
0E000014   mov eax,dword ptr ds:[edx+1]        ;计算调用地址
0E000017   add eax,edx
0E000019   add eax,5
0E00001E   cmp eax,11B0000                   ;调用地址=11b0000?(11b0000可变)
0E000023   jnz short 0E000028                 ;继续搜索
0E000025   pushad                             ;保存堆栈,观察堆栈变化
0E000026   jmp edx                            ;执行call 11b0000,进入api解密.如0E000033处下代码断点
0E000028   inc edx
0E000029   cmp edx,52A000                     ;代码段结束?
0E00002F  ^jb short 0E00000F                   ;继续搜索
0E000031  -jmp short 0E000031                 ;方便dump
0E000033   mov ecx,dword ptr ds:[E001000]      ;中断在此处,[E001000]中是为iat预留的地址
0E000039   nop
           ...                               ; 39~~~~6c之间为nop,,
0E00006c   nop
0E00006D   mov dword ptr ds:[ecx],edx        ; edx中是api解密后地址,放入预留的iat中
0E00006F   add dword ptr ds:[E001000],4      ;下一个iat地址
0E000076   mov dword ptr ds:[E002000],ecx    ;保存ecx
0E00007C   add esp,12C                       ;与0E000025处pushad对应的堆栈地址,12c可变
0E000082   popad                                        
0E000083   mov ebx,dword ptr ds:[E002000]    ;恢复ecx
0E000089   mov dword ptr ds:[edx+2],ebx       ;修改api调用地址为解密后地址
0E00008C   mov word ptr ds:[edx],25FF        ;修改calll 011b0000为jmp ********形式
0E000091   mov ebx,dword ptr ds:[E001000]     
0E000097   mov dword ptr ds:[ebx],0               ;iat保存后,下一dword填充00000000
0E00009D   nop
0E00009E   add dword ptr ds:[E001000],4      ;下一个iat预留地址
0E0000A5  ^jmp short 0E000028

二进制码为:
C7 05 00 10 00 0E 40 2D 53 00 BA 00 10 40 00 80 3A E8 75 14 8B 42 01 03 C2 05 05 00 00 00 3D 00
00 1B 01 75 03 60 FF E2 42 81 FA 00 A0 52 00 72 DE EB FE 8B 0D 00 10 00 0E 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 89 11 83 05 00 10 00 0E 04 89 0D 00 20 00 0E 81 C4 30 01
00 00 61 8B 1D 00 20 00 0E 89 5A 02 66 C7 02 FF 25 8B 1D 00 10 00 0E C7 03 00 00 00 00 90 83 05
00 10 00 0E 04 EB 81

代码是参照syscom <ASProtect.SKE.2.11 高速脫殼+(圖示) >中示范代码编写的,由于iat加密,进行了调整,将解密后api直接放入为其预留的iat空间,同时

0E000091   mov ebx,dword ptr ds:[E001000]     
0E000097   mov dword ptr ds:[ebx],0               ;解密api地址保存为之后面填充00000000

为了使imprec不出现误报,每一api解密后iat填充00000000

代码编写完毕后,使eip=0e000000,f9,片刻,f12暂停。

dump wso.exe 。
imprec抓取iat,oep=00129D3C,rva=130000,size=4000,get,cut无效指针

fix it,不能正常运行,od载入继续跟踪发现:

004012F4  - FF25 0C025300         jmp dword ptr ds:[53020C]

004070F0  - FF25 F4035300         jmp dword ptr ds:[5303F4]


两处均是GetProcAddress,imprec修正.
可以运行,但有点问题


4、暗桩修复
先来去掉日期提示nag:

0052947C   . /7E 1E               jle short wso.0052949C   ;修改为jmp short wso.0052949C
0052947E   . |A1 38CF5200         mov eax,dword ptr ds:[52CF38]
00529483   . |8B00                mov eax,dword ptr ds:[eax]
00529485   . |8B10                mov edx,dword ptr ds:[eax]
00529487   . |FF92 EC000000       call dword ptr ds:[edx+EC] ;nag窗口
0052948D   . |83F8 02             cmp eax,2  ;按try,eax=1;按quit,eax=2
00529490   . |75 0A               jnz short wso.0052949C


再来去掉about的异常
把00FA0000-00FD3000 区块(位置可能会变化,od跟踪确定) 用lordpe dump,装配进修复好的wso.exe.rebuild pe.过程如下:
先打开lordpe,选wso.exe进程,点右键,区域脱壳,选00FA0000-00FD3000 区块,保存00FA0000-00FD3000.dmp文件。
再用用lordpe的pe编辑器打开已修复的wso.exe,然后查看区段,在区段表最后一条点右键“从硬盘载入区段”,载入00FA0000-00FD3000.dmp文件。
在新增区段上点右键,“编辑区段头”将虚拟地址改为ba0000
保存,rebuild pe,ok

在把about的unregistered改一下,和正式版一样:)得到老婆夸奖,还将syscom,loveboom,fly等诸位大牛大大的敬仰了一把。:)

收功之后,英雄无敌目录locked,设置password,以为老婆学业从此蒸蒸日上,与时俱进,再无30日之忧。谁知某日凌晨醒来,惨叫之声不绝于耳,老婆的大天使正在斩妖除魔。不可能阿,我的防护天衣无缝,只有我才能进入游戏目录。老婆见我惊愕,羞涩的嫣然一笑,惭愧而又骄傲的告诉我“下次吧密码设复杂点儿“。
兄弟们,牢记教训阿。