TA的每日心情 | 慵懒 2018-6-6 15:51 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
原文来自看雪学院:http://bbs.pediy.com/showthread.php?t=28790&tcatid=11
标 题: ASProtect SKE 2.2 SDK中的API修复
作 者: kanxue
时 间: 2006-07-10,20:22
链 接: http://bbs.pediy.com/showthread.php?t=28790
【文章标题】: 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
例子下载
[ 本帖最后由 glts 于 2007-8-25 20:10 编辑 ] |
|