【Target】: AsLoad (c) 2003 by GlObAl & [NtSC]

简介:作用解决试用日期限制注册,对 ASProtect v1.2 试用日期限制的有效,readme中说可以high点,我没有试

【小注】:想了解一下Loader,找到了这个;这个壳我未玩过,不等于这个壳很先进,但它的处理方式有些哈哈!这个可能是私人壳或者是一些壳的早期版本。。。有人知道可以通知我。。。呵呵

PEid 没检到什么,它的输入表 就只有那么一个API GetModuleHandleA,一定有动作的。。。
开头你不能用 Esp 定律
开头你不能用硬件断点,被它占用作小解码,占用很长的一段非法指令时间,全跟要吐血的...

开头用 int3 断点要小心噢,在 se 入口处下断要当心;
API断点要小心下到准确无误的地址。

bp GetProcAddress
bp GetModuleHandleA
bp LoadLibraryA

这样你会死得很惨,它并不检你是否有bp api,由于它做惯“小偷”,你不能这样去下断,否则自食其果!
bp api + some offset 就可以了,offset 要定位准确噢!

用OD调试,你无需隐藏调试器标志,它不检这个!

废话连篇,动手呀。。。
我用的是自己的 DIY 版 OD,在 XP 下调试。。。
OD设置忽略所有异常,全部打勾。。。
bp LoadLibraryA +9


00401A82   pushad   // 停在入口
00401A83   call 00401A88                    ; AsLoad.00401A88
00401A88   pop ebp
00401A89   sub ebp,4078BB
00401A8F   pushad
00401A90   xor eax,eax
00401A92   call 00401B8B                     ; AsLoad.00401B8B

Shift + F9
中断后堆栈报告如下:
0012FF6C    00404BEC   ASLOAD.00404BEC
0012FF70    00401FA9   ASLOAD.00401FA9
0012FF74    003705B4   返回到 003705B4               // Ctrl + G 此地址下断,Shift + F9
0012FF78    003705A3   返回到 003705A3 来自 003705AE

// 下面组织得比较乱。。。
// call 370020 是解密数据
// 特殊的 api 被壳 Hook 和 Stolen了,并加入了花花,而且很铺张地每个用上 64 K内存 -> 即10000h
// 壳会动态解码后运行完又加密,小花样,加密解密都用同一个 call 00371147

00370556   push 4
00370558   push 1000
0037055D   mov eax,dword ptr ss:[ebp+409533]
00370563   add eax,10000                        ; UNICODE "=::=::\"
00370568   push eax
00370569   push 0
0037056B   call dword ptr ss:[ebp+4096AF]     //[ebp+4096AF] = 390000  实际是 kernel32.VirtualAlloc 最后 jmp 77E5981B

00370585   call 00371147                     // 公用的 加密/解码 Call -> 不可轻易F8
0037058A   popad
0037058B   pushad
0037058C   lea eax,dword ptr ss:[ebp+408378]
00370592   mov ecx,47
00370597   call 00371147
0037059C   popad
0037059D   pushad
0037059E   call 003705AE

003705AE   call dword ptr ss:[ebp+409553]  //[ebp+409553] = 3B0000 实际是 LoadLibraryA
003705B4   mov dword ptr ss:[ebp+409547],eax
003705BA   call 003705CB
003705BF   dec ebp
003705C0   jnb short 00370636

003705CB  push eax                          // 模块入口
003705CC  call dword ptr ss:[ebp+40954F]    // [ebp+40954F] = 003D0000 实际是GetProcAddress
003705D2  pushad
003705D3  lea eax,dword ptr ss:[ebp+408378]
003705D9  mov ecx,47
003705DE  call 00371147  //加密壳代码

003705E4  cmp dword ptr ss:[ebp+4097E7],1  // ??
003705EB  jnz 00370721
003705F1  mov dword ptr ss:[ebp+40954B],eax
003705F7  mov eax,dword ptr ss:[ebp+40954B]
003705FD  lea edi,dword ptr ss:[ebp+40954B]
00370603  call 003711CB

// 块解码好像会比较块数据开头是否为 "JC"
00370784   >popad
00370785   >xchg eax,ecx
00370786   >cmp dword ptr ss:[ebp+4096A7],0
0037078D   >je short 003707A1
0037078F   >mov edi,dword ptr ss:[ebp+4096A7]
00370795   >add edi,dword ptr ss:[ebp+4097DF]
0037079B   >mov ecx,dword ptr ss:[ebp+4096AB]
003707A1   >rep movs byte ptr es:[edi],byte ptr ds:[esi] 迁回解码后的Code节 401000
003707A3   >pushad
003707A4   >mov ecx,30
003707A9   >lea eax,dword ptr ss:[ebp+408560]
003707AF   >call 00371147

003708B1  popad
003708B2  push 4
003708B4  push 1000
003708B9  push 10000                                        ; UNICODE "=::=::\"
003708BE  push 0
003708C0  call dword ptr ss:[ebp+4096AF] // 申请空间
003708C6  xchg eax,edi
003708C7  call 00371110
003708CC  pushad
003708CD  xchg eax,esi
003708CE  mov ecx,11380
003708D3  mov eax,F6305196
003708D8  xor byte ptr ds:[esi+ecx],al
003708DB  rol eax,cl
003708DD  xor eax,ecx
003708DF  loopd short 003708D8
003708E1  popad
003708E2  add eax,800
003708E7  push edi
003708E8  push edi
003708E9  push eax
003708EA  call 00370020 // 过了这个Call 可以看到 edi 地址是 API 信息
003708EF  pushad
003708F0  mov ecx,4F
003708F5  lea eax,dword ptr ss:[ebp+40868D] 
003708FB  call 00371147  //加密

00370949  test eax,80000000
0037094E  jnz short 00370986
00370950  push edi
00370951  push edi
00370952  push dword ptr ss:[ebp+409517]
00370958  call dword ptr ss:[ebp+40954F]
0037095E  mov dword ptr ds:[ebx],eax
00370960  pushad
00370961  cmp dword ptr ss:[ebp+40969F],1 // 是否需要加密 API ?当然不加密,[ebp+40969F] -> set zero ★★★
00370968  jnz short 00370971
0037096A  xchg edi,ebx
0037096C  call 00370B9A
00370971  popad


00370D62   pop dword ptr fs:[0]  // se 出口,下面是 Iat 处理
00370D68   add esp,4
00370D6B   pushad

00370D90   lods dword ptr ds:[esi]          // 不用加密的处理?
00370D91   and dword ptr ds:[esi-4],0
00370D95   or eax,eax
00370D97   je short 00370DB7
00370D99   xchg eax,ebx
00370D9A   add ebx,dword ptr ss:[ebp+4097DF]
00370DA0   lods dword ptr ds:[esi]
00370DA1   and dword ptr ds:[esi-4],0
00370DA5   add eax,dword ptr ss:[ebp+4097DF]
00370DAB   add eax,dword ptr ss:[ebp+4096D3]
00370DB1   mov ebx,dword ptr ds:[ebx]
00370DB3   mov dword ptr ds:[eax],ebx
00370DB5   jmp short 00370D90


00370DDD   lods dword ptr ds:[esi]         //  FF25 Jmp [] 加密的处理,这里壳处理成Jmp api地址偏移量,即:E9 + offset 的5字节跳转形式
00370DDE   and dword ptr ds:[esi-4],0
00370DE2   or eax,eax
00370DE4   je short 00370E09
00370DE6   xchg eax,ebx
00370DE7   add ebx,dword ptr ss:[ebp+4097DF]
00370DED   lods dword ptr ds:[esi]
00370DEE   and dword ptr ds:[esi-4],0
00370DF2   add eax,dword ptr ss:[ebp+4097DF]
00370DF8   add eax,dword ptr ss:[ebp+4096D3]
00370DFE   mov ebx,dword ptr ds:[ebx]
00370E00   sub ebx,eax
00370E02   sub ebx,4
00370E05   mov dword ptr ds:[eax],ebx
00370E07   jmp short 00370DDD


00370E2F   lods dword ptr ds:[esi]         //  FF15  Call [] 加密的处理 ? 我这里没有这情况。。。
00370E30   and dword ptr ds:[esi-4],0
00370E34   or eax,eax
00370E36   je short 00370E63
00370E38   xchg eax,ebx
00370E39   add ebx,dword ptr ss:[ebp+4097DF]
00370E3F   lods dword ptr ds:[esi]
00370E40   and dword ptr ds:[esi-4],0
00370E44   add eax,dword ptr ss:[ebp+4097DF]
00370E4A   add eax,dword ptr ss:[ebp+4096D3]
00370E50   mov byte ptr ds:[eax-1],0E8
00370E54   mov ebx,dword ptr ds:[ebx]
00370E56   sub ebx,eax
00370E58   sub ebx,4
00370E5B   mov dword ptr ds:[eax],ebx
00370E5D   mov byte ptr ds:[eax+4],90
00370E61   jmp short 00370E2F


// 可以改良一下,就能还原正常可识别的 Jmp [] Iat ★★★
00370DEE   add eax,dword ptr ss:[ebp+4097DF]  
00370DF4   add eax,dword ptr ss:[ebp+4096D3]
00370DFA   inc eax
00370DFB   mov dword ptr ds:[eax],ebx
00370DFD   dec eax
00370DFE   dec eax
00370DFF   mov word ptr ds:[eax],25FF
00370E04   nop
00370E05   nop
00370E06   nop
00370E07   jmp short 00370DDD

03 85 DF 97 40 00 03 85 D3 96 40 00 40 89 18 48 48 66 C7 00 FF 25 90 90 90

// StolenCode 形式为 5 字节长度,呵呵比较简单,可以完全还原。。。
// 下面过程是壳查表修复,因为壳是动态申请 Stolen 地址的。。。所以它要做这个工作
00370E88   lods dword ptr ds:[esi]           // 处理 StolenCode
00370E89   or eax,eax
00370E8B   je short 00370ED3
00370E8D   mov ebx,eax
00370E8F   lods dword ptr ds:[esi]
00370E90   add eax,ebx
00370E92   add eax,dword ptr ss:[ebp+4097DF]
00370E98   add eax,dword ptr ss:[ebp+4096D3]
00370E9E   add eax,5
00370EA1   cmp dword ptr ds:[esi+4],1      // 是否需要修正?
00370EA5   jnz short 00370EC5
00370EA7   cmp dword ptr ds:[eax],5355434B // 是否吻合要处理偏移位置的特征码?
00370EAD   je short 00370EB2
00370EAF   inc eax
00370EB0   jmp short 00370EA7
00370EB2   add esi,8
00370EB5   push esi
00370EB6   push eax
00370EB7   dec eax
00370EB8   sub eax,esi
00370EBA   neg eax
00370EBC   mov esi,eax
00370EBE   pop eax
00370EBF   sub esi,5
00370EC2   mov dword ptr ds:[eax],esi
00370EC4   pop esi
00370EC5   inc esi
00370EC6   cmp dword ptr ds:[esi],58585858 // 这里全是这种模式,是 StolenCode 标志?
00370ECC   jnz short 00370EC5
00370ECE   add esi,4
00370ED1   jmp short 00370E88


57 48 8B F8 33 C9 B1 05 F3 A4 5F 90 90 90
// 顺便补丁还原代码:
00370EB5   push esi
00370EB6   push edi                       // ★★★
00370EB7   dec eax
00370EB8   mov edi,eax
00370EBA   xor ecx,ecx
00370EBC   mov cl,5
00370EBE   rep movs byte ptr es:[edi],byte ptr ds:[esi]
00370EC0   pop edi
00370EC1   nop
00370EC2   nop
00370EC3   nop                            // ★★★
00370EC4   pop esi
00370EC5   inc esi


003710D5  stos dword ptr es:[edi]
003710D6  popad
003710D7  mov dword ptr ss:[esp+1C],edi
003710DB  popad
003710DC  jmp eax  // 前往 OEP 处理的花样 00AA0000
003710DE  popad
003710DF  retn


// 里面有很多花花,可以用 Esp 定律找 Stolen Code,也可以根据堆栈 “我猜我猜我猜猜猜”
00AA0000   push 401CDD //★★★
00AA0005   neg esi
00AA0008   cmp edi,edi
00AA000A   shld edi,eax,cl

00AA08E9   push dword ptr fs:[0]  //★★★
00AA08EF   mov esi,AB3919AB
00AA08F5   inc esi
00AA08F7   ror esi,3E

00AA11E6   mov dword ptr fs:[0],esp  //★★★
00AA11EC   not esi
00AA11EE   test esi,8BBE848D
00AA11F4   imul edi,esi,1DC84EAC

00AA1AEB   mov ecx,edi
00AA1AED   and edi,FFFF0000
00AA1AF3   sub ecx,edi
00AA1AF5   rep stos byte ptr es:[edi] // 移“花”植“草”
00AA1AF7   popad
00AA1AF8   popfd
00AA1AF9   push 401011               // 压入伪 OEP
00AA1AFE   retn

// 当 eip 等于 401011 时堆栈的情况,明显是安装了 seh 401CDD

0012FFBC    0012FFE0   指针到下一个 SEH 记录
0012FFC0    00401CDD   SE 句柄
0012FFC4    77E5EB69   返回到 kernel32.77E5EB69


// OEP定为 401000 吧,上面找到的长度要大,套不了,作如下修复刚好用完 00 字节
00401000    >push 401CDD  
00401005    >xor eax,eax
00401007    >push dword ptr fs:[eax]
0040100A    >mov dword ptr fs:[0],esp

哈哈,这次脱壳后又使我再次从壳盲的人群中挤了出来!
另外,我很想知道很多早期的壳在98下检测出OD调试器来,是怎么做的?
00401C05   and eax,FFFF0000
00401C0A   mov dword ptr ss:[ebp+4097DF],eax
00401C10   mov eax,dword ptr ss:[ebp+407889]
00401C16   and eax,FFFF0000
00401C1B   cmp word ptr ds:[eax],5A4D         //到达这里的指令, 很明显是只适用 NT 的获取模块基址的方式,好像不适用 98
00401C20   je short 00401C29                                  ; ASLOAD.00401C29
00401C22   sub eax,10000
00401C27   jmp short 00401C1B                                 ; ASLOAD.00401C1B
00401C29   mov dword ptr ss:[ebp+409543],eax
00401C2F   mov dword ptr ss:[ebp+40952B],eax

Written by askformore
 06.01.2005

Andy Law Advertising: 想要...就系你既...