首页
论坛
课程
招聘

ASProtect SKE 2.2 SDK中的API修复

2006-7-10 20:22 53661

ASProtect SKE 2.2 SDK中的API修复

2006-7-10 20:22
53661
【文章标题】: ASProtect SKE 2.2 SDK中的API修复
【文章作者】: kanxue
--------------------------------------------------------------------------------
【详细过程】

   有关ASProtect的SDK,近期论坛不少文章涉及到了,如cyto的文章(本文一些补丁代码参考了cyto文章)。SDK的修复VolX、shoooo等大侠更是轻车熟路。这2天也学习了一下SDK修复,有少许心得,现拿出来希望大家帮忙指正一下。

    ASProtect的SDK种类比较多,本文主要介绍如何修复ASProtect自带的一些API,如GetHardwareID,CheckKeyAndDecrypt,GetRegistrationKeys,GetModeInformation,GetRegistrationInformation 等。  
    学习SDK最好的方法是将ASProtect的帮助文档看一遍,并结合其样例掌握用法。

1.准备工作

   本文以ASProtect自带的样例Examples\Reg Trial\VC\ 来讨论。为了降低难度,我将样例中的REG_CRYPT_BEGIN1与REG_CRYPT_END1注释掉,这对标签是加密代码的,无key代码就不能解密,当然有key还得修复这段代码,修复方法类似stolen OEP。


//REG_CRYPT_BEGIN1 //注释掉,不加密如下代码
strcpy( caption, "Registered version!" );
SetWindowText( hwnd, caption );
GetModeInformation( 0, &ModeName, &mode_status );
SetWindowText( GetDlgItem(hwnd,IDCANCEL), "Close" );
ShowWindow(GetDlgItem(hwnd,IDC_BUYNOW), SW_HIDE);
ShowWindow(GetDlgItem(hwnd,IDC_REG_BUTTON), SW_HIDE);
wsprintf( buffer,"Key: %s\nName: \t\t%s\nMode Name: \t%s",UserKey, UserName, ModeName );
SetDlgItemText(hwnd, IDC_TEXT, buffer);
//REG_CRYPT_END1 //注释掉


   然后用VC 6.0编译Reg Trial样例,得到trial.exe文件,运行ASProtect主程序,打开该样例提供的reg_trial.aspr2项目文件,本文主要是讨论SDK修复,因此protectin Options全部不选。Modes部分reg_trial.aspr2己设置好,如图:



   然后点击Protect按钮将trial.exe加壳保护,生成的trial.exe无key运行是试用版,需要输入key才能为注册版。key可以在Activation keys栏生成:


  本例将加密标签REG_CRYPT_BEGIN1与REG_CRYPT_END1注释掉了,因此不存在解码问题。

2.用脚本脱壳

   非常感谢VolX能与大家分享他那强大的脚本!OD加载trial.exe后,用ODbgScript 1.4x插件跑VolX的脚本:Asprotect 2.XX SKE IAT Fixer 。
http://bbs.pediy.com/showthread.php?s=&threadid=24557


运行一会儿,脚本有一个提示:“Import table is fixed, you can dump the file now or later. check the address and size of IAT in log window”
点击确定后,再单击ODbgScript/Resume继续执行脚本,不一会儿就到OEP:“OEP found, no stolen code at the OEP!”。

00401470    55              push    ebp                              ; trial.00400000
00401471    8BEC            mov     ebp, esp
00401473    6A FF           push    -1

此时就可Dump取trial.exe程序了,并用ImportREC重建输入表:



这里会发现有一些函数不能识别,这些函数就是ASProtect自己的API,可以直接Cut,就可重建输入表了,得到dumped_.exe。

在OD里查看这些ASProtect的API,会发现它们与IAT其他函数靠在一起:

00405000  00AA7FD8
00405004  00AA7EC4
00405008  00AA7CCC
0040500C  00AA8024
00405010  00AA7BE0
00405014  00000000
00405018  7C801D77  kernel32.LoadLibraryA
0040501C  7C80AC28  kernel32.GetProcAddress
00405020  7C9379FD  ntdll.RtlReAllocateHeap

3.修复SDK

  如果此时运行脱壳后的文件dumped_.exe,就会异常,因为程序里会调用ASProtect的API函数:

00404A18   $- FF25 0C504000 jmp     [40500C]  //F2下断点
00404A1E   $- FF25 08504000 jmp     [405008]  //F2下断点
00404A24   $- FF25 04504000 jmp     [405004]  //F2下断点
00404A2A   $- FF25 00504000 jmp     [405000]  //F2下断点
00404A30   $- FF25 10504000 jmp     [405010]  //F2下断点
00404A36   $- FF25 A8504000 jmp     [<&kernel32.RtlUnwind>]          ;  ntdll.RtlUnwind

  接下来就是要猜这些API函数了,运行加壳的trial.exe,来到OEP后,对00404A18~00404A36这段代码下断点。再运行程序,首先会中断在00404A30这行。

00404A18  - FF25 0C504000   jmp     [40500C]
00404A1E  - FF25 08504000   jmp     [405008]
00404A24  - FF25 04504000   jmp     [405004]
00404A2A  - FF25 00504000   jmp     [405000]
00404A30  - FF25 10504000   jmp     [405010]     //首先中断这行
00404A36  - FF25 A8504000   jmp     [4050A8]                         ; ntdll.RtlUnwind

然后查看堆栈,对返回地址设断:

0012FA84   004011AA  返回到 trial.004011AA 来自 trial.00404A30
0012FA88   00000000
0012FA8C   004086C0  trial.004086C0
0012FA90   004086C4  trial.004086C4

对004011AA 设断后,会来到:

00401196  |.  53            push    ebx
00401197  |.  56            push    esi
00401198  |.  57            push    edi
00401199  |.  68 C4864000   push    004086C4
0040119E  |.  68 C0864000   push    004086C0
004011A3  |.  6A 00         push    0
004011A5  |.  E8 86380000   call    00404A30
004011AA  |.  8B3D C0864000 mov     edi, [4086C0]  //来到这里

此时EAX=1,结合源码及ASProtect帮助文档,可以猜出这个是GetRegistrationInformation。
用这种方法就可确定其他几个函数:

00404A18  - FF25 0C504000   jmp     [40500C]                         ; GetHardwareID
00404A1E  - FF25 08504000   jmp     [405008]                         ; CheckKeyAndDecrypt
00404A24  - FF25 04504000   jmp     [405004]                         ; GetTrialDays
00404A2A  - FF25 00504000   jmp     [405000]                         ; GetModeInformation
00404A30  - FF25 10504000   jmp     [405010]                         ; GetRegistrationInformation
00404A36  - FF25 A8504000   jmp     [4050A8]                         ; ntdll.RtlUnwind

其中带key脱壳后,只有GetRegistrationInformation与GetModeInformation被调用(其他函数确定,请删除注册文件aspr_keys.ini尝试),因此只需要修复这2个函数即可。

3.1 构造 GetRegistrationInformation函数的参数及返回值

函数原型:
GetRegistrationInformation( 0, &Key, &Name );  

dumped_.exe程序中的代码:
00401199  |.  68 C4864000   push    004086C4   //&Name
0040119E  |.  68 C0864000   push    004086C0   //&Key
004011A3  |.  6A 00         push    0
004011A5  |.  E8 86380000   call    00404A30

00404A30   $ /FF25 10504000 jmp     [405010]                         ;  GetRegistrationInformation

找一段空地写下如下代码:

00404A41         mov     eax, [esp+8]
00404A45         mov     dword ptr [eax], 00404A5E        ;  ASCII "78787878" //参数Key
00404A4B         mov     eax, [esp+C]
00404A4F         mov     dword ptr [eax], 00404A68        ;  ASCII "pediy"   //参数Name
00404A55         mov     eax, 1                           //返回值
00404A5A         retn    0C

00404A5E  37 38 37 38 37 38 37 38 00 00 70 65 64 69 79 00  78787878..pediy.

再将00405010改成如下:
00405010  41 4A 40 00                                      AJ@.

这样jmp     [405010] 就能跳到00404A41 执行了。

3.2 构造GetModeInformation函数的参数及返回值

函数原型:
GetModeInformation( 0, &ModeName, &mode_status );

dumped_.exe程序中的代码:
00401205    52              push    edx       //&mode_status
00401206    68 CC864000     push    004086CC  //&ModeName
0040120B    6A 00           push    0
0040120D    E8 18380000     call    00404A2A // call GetModeInformation
……
00404A2A  - FF25 00504000   jmp     [405000]                         ; GetModeInformation

找一段空地写下如下代码:

00404A79       mov     eax, [esp+8]
00404A7D       mov     dword ptr [eax], 00404A8D        ;  ASCII "Registered"  //参数ModeName
00404A83       mov     eax, 1
00404A88       retn    0C

00404A8D  52 65 67 69 73 74 65 72 65 64 00 00 00 00 00 00  Registered......

再将00405000改成如下:
00405000  79 4A 40 00         

这样jmp     [405000]  就能跳到00404A79 执行了

--------------------------------------------------------------------------------

                                                      2006年07月10日 20:10:21

[推荐]看雪企服平台,提供项目众包、渗透测试、安全分析、定制项目开发、APP等级保护等安全服务!

上传的附件:
最新回复 (93)
小虾 10 2006-7-10 20:35
2
0
第一个学习。
nbw 24 2006-7-10 20:37
3
0
学习!
monkeycz 11 2006-7-10 20:38
4
0
学习!
freecat 1 2006-7-10 20:39
5
0
学习
liuyilin 2006-7-10 20:41
6
0
还是学习
wofan[OCN] 21 2006-7-10 20:42
7
0
对于好文是不顶不行了
hbqjxhw 16 2006-7-10 20:44
8
0
我说我第二个学习呢,没想到看完了,一下到了第八楼了
libozi 2006-7-10 20:44
9
0
支持,学习中!
windycandy 5 2006-7-10 21:07
10
0
学习并不断成长ing.............
chinadev 2006-7-10 22:09
11
0
好文不断~
cyto 31 2006-7-10 22:27
12
0
看完后有一种茅塞顿开的感觉。
坛主的这篇文章真是及时雨。
谢谢!
sbright 2 2006-7-10 23:10
13
0
收藏!!!!
Bewaar 2006-7-11 00:07
14
0
老大的文章每次都有一种里程碑似的指导意义,学习了。
血草 1 2006-7-11 01:01
15
0
此时EAX=1,结合源码及ASProtect帮助文档,可以猜出这个是GetRegistrationInformation。
用这种方法就可确定其他几个函数:

都用猜来判断下面的API吗?
kanxue 8 2006-7-11 08:31
16
0
最初由 血草 发布

都用猜来判断下面的API吗?


经验很重要,根据参数及返回值来判断。
闲云 2006-7-11 10:31
17
0
顶,学习中!!!
daxia200N 6 2006-7-11 12:53
18
0
最初由 kanxue 发布
经验很重要,根据参数及返回值来判断。

做个通用版本的api ida签名,也许更容易些。
whg3249 2006-7-11 13:03
19
0
看学老大就是牛,学习收藏
海风月影 17 2006-7-12 18:08
20
0
由KANXUE版主的教程看来,GetRegistrationInformation是ASP SDK中一个重要函数,
几乎每一个用到SDK的程序都要修复这个函数(由源代码可见,它是第一个被调用的)
但是,对于 构造 GetRegistrationInformation函数的参数及返回值
有一点不解:

以下是源代码:

  GetRegistrationInformation( 0, &UserKey,  &UserName );

  if ((UserKey != NULL) && (strlen(UserKey) > 0))
  {


GetRegistrationInformation这个函数并没有返回值,后面的判断也没用到返回值,
只是用到UserKey,为什么构造 GetRegistrationInformation函数的参数及返回值时要有个返回值 MOV EAX,1


00404A41         mov     eax, [esp+8]
00404A45         mov     dword ptr [eax], 00404A5E        ;  ASCII "78787878" //参数Key
00404A4B         mov     eax, [esp+C]
00404A4F         mov     dword ptr [eax], 00404A68        ;  ASCII "pediy"   //参数Name
00404A55         mov     eax, 1                           //返回值
00404A5A         retn    0C



确实有点不解,在ASProtect help中,作者的例子是:


 For Delphi:  
 
  
 
 Var  
 
   Key  : PChar;  
 
   Name : PChar;  
 
  
 
 begin  
 
   GetRegistrationInformation( 0, Key, Name );  
 
   MessageBox(0,StrPas(Key) + #13#10 + StrPas(Name),'Key/Name:',0);  
 
 end;   
 
  
 
 For C++:  
 
  
 
 {  
 
 char* Key = "";  
 
 char* Name = "";  
 
  
 
 GetRegistrationInformation( 0, &Key, &Name );  
 
 printf( " Key: %s\n Name: %s\n", Key, Name );  
 
 }  



也没用到返回值
kanxue 8 2006-7-12 18:16
21
0
最初由 海风月影 发布
对于 构造 GetRegistrationInformation函数的参数及返回值 有一点不解:


你跟踪加壳程序,带key与不带key都跟一下,你会发现有key时这函数返回1,否则返回0.
当然此例中返回任何值都不影响程序功能。
海风月影 17 2006-7-12 22:57
22
0
最初由 kanxue 发布
你跟踪加壳程序,带key与不带key都跟一下,你会发现有key时这函数返回1,否则返回0.
当然此例中返回任何值都不影响程序功能。


也就是说,可以把程序写出这样了:


IsReg=GetRegistrationInformation( 0, &UserKey,  &UserName );

  if (IsReg) 
 {
  ...
 }



去试试看
木头 2006-7-13 22:49
23
0
跟着老大的文章练习,很受益!
hbqjxhw 16 2006-7-14 01:33
24
0
#include "stdafx.h"
#include "resource.h"
#include <shellapi.h>
#include "include/aspr_api.h"
#include "include/asprotect.h"
#pragma comment(lib,"include/aspr_ide.lib")
kanxue楼主这几个文件在哪找?
snowshow 2006-7-14 02:02
25
0
chasgone 2 2006-7-14 18:31
26
0
真是好文章,老大真厉害
swordkok 1 2006-7-14 22:28
27
0
终于等到了,学习!
aspr的帮助文档哪里有?
偶下的版本都没有带。。。。
chinadev 2006-7-15 06:40
28
0
此时EAX=1,结合源码及ASProtect帮助文档,可以猜出这个是GetRegistrationInformation。

我跟踪了下这个
00404A2A  - FF25 00504000   jmp     [405000]
在00401212处eax的值仍然是1
为什么它是GetModeInformation?而不是GetRegistrationInformation?
kanxue 8 2006-7-15 10:43
29
0
最初由 chinadev 发布
我跟踪了下这个
00404A2A - FF25 00504000 jmp [405000]
在00401212处eax的值仍然是1
为什么它是GetModeInformation?而不是GetRegistrationInformation?


参数可以区别开来:
GetModeInformation( 0, &ModeName, &mode_status );
这个参数:&mode_status

00401205  |.  52            push    edx //指向0012FA5C
00401206  |.  68 CC864000   push    004086CC
0040120B  |.  6A 00         push    0
0040120D  |.  E8 18380000   call    00404A2A

0012FA5C  00 04 00 00 E2 02 00 00 52 65 67 69 73 74 65 72  ...?..Register
0012FA6C  65 64 20 76 65 72 73 69 6F 6E 21 00 00 00 00 00  ed version!.....

kanxue 8 2006-7-15 10:48
30
0
最初由 hbqjxhw 发布
#include "stdafx.h"
#include "resource.h"
#include <shellapi.h>
#include "include/aspr_api.h"
#include "include/asprotect.h"
kanxue楼主这几个文件在哪找?
........

下载一个ASProtect SKE 2.2 Release原版,安装,在Examples目录下。
kkangs 2006-7-17 19:59
31
0
good! thanks~
lidou 1 2006-7-18 16:07
32
0
最初由 Bewaar 发布
老大的文章每次都有一种里程碑似的指导意义,学习了。


nod..
学习..
发现Aspr2.2好象又强壮了不少
yalcm 2006-7-19 12:49
33
0

强强强强
enjon 2006-9-25 12:21
34
0
你们个个怎么哪么牛啊。佩服,哎,我不知道要学到何年何月去了
邪秀才 2 2006-9-28 14:58
35
0
看雪一发帖,都是精品中的精品,只有学习的份了
叶孓落落 2006-10-26 12:13
36
0
收藏啦...
hcfhcf 2006-12-5 18:14
37
0
如果此时运行脱壳后的文件dumped_.exe,就会异常,因为程序里会调用ASProtect的API函数:

00404A18   $- FF25 0C504000 jmp     [40500C]  //F2下断点
00404A1E   $- FF25 08504000 jmp     [405008]  //F2下断点
00404A24   $- FF25 04504000 jmp     [405004]  //F2下断点
00404A2A   $- FF25 00504000 jmp     [405000]  //F2下断点
00404A30   $- FF25 10504000 jmp     [405010]  //F2下断点

请问这个00404A18这些地址是怎么找出来的?
cyto 31 2006-12-6 07:25
38
0
当你修复IAT的时候,是不是有几个无效函数,而且地址n整齐?
那就是了.
hcfhcf 2006-12-7 20:02
39
0
但是那几个的地址跟这地址不一样,是不是一定要运行脱壳程序出错后看堆椎的返回???我现在脱的一个文件运行后不会出错(没有反应),所以在堆栈里看不到这个地址了
mervynlove 2006-12-7 20:42
40
0
又是一篇极品好文啊 学习了
scship 2006-12-7 23:31
41
0
留名学习ing。。。
棒棒糖 2006-12-8 01:15
42
0
到下面练习了几次,终于有所领悟,多谢kanxue 老师的指点:)
棒棒糖 2006-12-8 01:17
43
0
Ctrl+B找FF25
或直接Ctrl+F找:jmp dword ptr ds:[405000]
我是利用后者.
qiweixue 19 2006-12-8 08:50
44
0
哇卡卡厄....
顶..老大厄
linex 7 2006-12-8 10:12
45
0
对于DLL文件中的SDK还要改重定位吗?请高人指教一下
cyto 31 2006-12-8 13:50
46
0
最初由 linex 发布
对于DLL文件中的SDK还要改重定位吗?请高人指教一下


曾经碰到同样的疑问,目前没找到重定位的方法,我只是修改call的地址解决,不过这样也许要修好多地方.
见过Volx的某个dll脱壳后文件,他的SDK重定位没问题,我的就是无法重定位,可能是重定位表的原因吧.
linex 7 2006-12-8 13:57
47
0
现在也只有靠修改偏移量解决了,手动修改重定位表太麻烦,不懂
王仁军 10 2006-12-8 15:23
48
0
先做个记号,然后回去试试,不行了再来学习
VolX 4 2006-12-9 20:39
49
0
最初由 cyto 发布
曾经碰到同样的疑问,目前没找到重定位的方法,我只是修改call的地址解决,不过这样也许要修好多地方.
见过Volx的某个dll脱壳后文件,他的SDK重定位没问题,我的就是无法重定位,可能是重定位表的原因吧.


以前是用别的方法改, 现在是改重定位表.
々火狼々 2007-5-6 15:55
50
0
对于好文是不顶不行了!
游客
登录 | 注册 方可回帖
返回