【文章标题】: ASProtect 2.1x SKE dll文件脱壳+去除时间限制
【作 者】: jinwj
【软件名称】: scxb4.dll
【大 小】: 1.61MB
【加壳方式】: ASProtect 2.1x SKE->Alexey Solodovnikov
【编写语言】: Borland Delphi
【工 具】: Win2000、OllyDbg、PEiD、LordPE、RecImport。
【操作平台】: Win2000
--------------------------------------------------------------------------------
【详细过程】
这个scxb4.dll是bds2006的一个第三方插件,用来使bds2006支持符合微软scc api的版本控制软件。这个DEMO版有30天的时间限制。
用 PEid 0.94 显示为 ASProtect 2.1x SKE -> Alexey Solodovnikov
很奇怪,用loaddll.exe不能正常载入scxb4.dll,提示进程不能处理异常退出。用VC编个小程序测试,LoadLibrary后同样异常退出,不知是什么原因。
正好看到一篇文章,大概意思是说通过DLL卸载时找OEP简单多了,正好用在这里。
用flyDBG载入BDS2006(命令行"bds.exe -pDelphi"),ALT+O,忽略全部异常。
1D399001 S> 60 pushad
1D399002 E8 03000000 call SCXB4.1D39900A
1D399007 - E9 EB045D45 jmp 629694F7
1D39900C 55 push ebp
1D39900D C3 retn
1D39900E E8 01000000 call SCXB4.1D399014
1D399013 EB 5D jmp short SCXB4.1D399072
1D399015 BB EDFFFFFF mov ebx,-13
1D39901A 03DD add ebx,ebp
1D39901C 81EB 00903900 sub ebx,399000 ; ASCII "em@TObjectii"
一、找到OEP
F9 Run 直到bds正常运行。
HE 1D399001 ;SCXB4.DLL 代码入口点,关闭bds,DLL卸载时会再次中断在外壳入口处!可以跟下去走
到OEP了。
1D2881C0 55 push ebp ;OEP 入口点,此处下硬件断点,方便下次停住。
1D2881C1 8BEC mov ebp,esp
1D2881C3 83C4 C4 add esp,-3C
1D2881C6 B8 EC4C281D mov eax,SCXB4.1D284CEC
1D2881CB E8 DC94D7FF call SCXB4.1D0016AC
1D2881D0 E8 AB90D7FF call SCXB4.1D001280 ; jmp to
rtl100.System::Halt0
1D2881D5 8D40 00 lea eax,dword ptr ds:[eax]
1D2881D8 0000 add byte ptr ds:[eax],al
1D2881DA 0000 add byte ptr ds:[eax],al
1D2881DC 0000 add byte ptr ds:[eax],al
1D2881DE 0000 add byte ptr ds:[eax],al
二、发现IAT。
Ctrl+B:FF 25。
1D286000 - FF25 048B291D jmp dword ptr ds:[1D298B04] ;
rtl100.System::initialization
1D286006 8BC0 mov eax,eax
1D286008 832D 1010291D 01 sub dword ptr ds:[1D291010],1
1D28600F 73 07 jnb short SCXB4.1D286018
1D286011 33C0 xor eax,eax
1D286013 A3 1410291D mov dword ptr ds:[1D291014],eax
1D286018 C3 retn
1D286019 8D40 00 lea eax,dword ptr ds:[eax]
右键--->数据窗口跟随--->内存地址。
在数据窗口右键--->长型--->地址。
向上滚动来到IAT开始。
1D298B00 00000000
1D298B04 51F7A000 rtl100.System::initialization ;IAT开始
1D298B08 51F0A8EC rtl100.System::Finalization
1D298B0C 51F0A7D0 rtl100.System::LoadResString
1D298B10 51F0A318 rtl100.System::FreeMemory
1D298B14 51F0A188 rtl100.System::TInterfacedObject::_Release
........................
1D298E48 77E69129 KERNEL32.LocalAlloc
1D298E4C 00000000
1D298E50 77E06485 USER32.CreateWindowExA
1D298E54 77E1CD8D USER32.WindowFromPoint
1D298E58 F44143B6 ; IAT加密
1D298E5C 77E1C7C2 USER32.WaitMessage
1D298E60 77E051E0 USER32.WaitForInputIdle
1D298E64 77E09419 USER32.ValidateRect
..........................
1D29AFDC 51F6C2B4 rtl100.Widestrutils::WStrLen
1D29AFE0 00000000
1D29AFE4 51F5BD84 rtl100.Maskutils::FormatMaskText
1D29AFE8 51F5B13C rtl100.Maskutils::TEditMask ; IAT结束
1D29AFEC 00000000
1D29AFF0 591B99B6
三、测试IAT加密
Ctrl+F2重起OD,硬件中断在SCXB4.DLL代码入口点。
bp GetModuleHandleA,中断两次,F2 取消中断,Alt-F9返回(注意:下面的地址在每次重启机器后可
能不同)。
06AB34AC 85C0 test eax,eax ; KERNEL32.77E60000 返回到这里
06AB34AE 75 07 jnz short 06AB34B7
06AB34B0 53 push ebx
06AB34B1 FF95 F0314400 call dword ptr ss:[ebp+4431F0]
右键--->搜索--->文本字符串,在第一个85下双击,来到这里。
06A9D95B 68 F8DBA906 push 6A9DBF8 ; ASCII "85"
06A9D960 E8 4B7DFFFF call 06A956B0
06A9D965 A1 6CB8AA06 mov eax,dword ptr ds:[6AAB86C]
06A9D96A 8B00 mov eax,dword ptr ds:[eax]
06A9D96C E8 27BD0000 call 06AA9698 ;F4运行到这里,F7进入
06A9D971 84C0 test al,al
06A9D973 75 0A jnz short 06A9D97F
06A9D975 68 F8DBA906 push 6A9DBF8 ; ASCII "85"
06A9D97A E8 317DFFFF call 06A956B0
06A9D97F A1 34B9AA06 mov eax,dword ptr ds:[6AAB934]
光标定位到地址06A9D96C,F4运行,F7进入。
06AA97B3 50 push eax
06AA97B4 56 push esi
06AA97B5 E8 9EFCFFFF call 06AA9458 ;F4运行到这里,F7进入
06AA97BA 0FB707 movzx eax,word ptr ds:[edi]
06AA97BD 83C0 02 add eax,2
06AA97C0 03F8 add edi,eax
06AA97C2 8A1F mov bl,byte ptr ds:[edi]
向下拉动,光标定位到地址06AA97B5,F4运行,F7进入。
06AA948C 6933 C08A433B imul esi,dword ptr ds:[ebx],3B438AC0
06AA9492 3BF0 cmp esi,eax ;下F2断点
06AA9494 75 5E jnz short 06AA94F4
06AA9496 EB 01 jmp short 06AA9499
06AA9498 C7 ??? ; 未知命令
06AA9499 66:8B02 mov ax,word ptr ds:[edx]
在数据窗口定位IAT区段,Ctrl+G:1D298B04 (IAT头)。
在06AA9492地址连续F9,注意数据窗口第一个出现了,看寄存器ESI为12,继续F9。
====================================================
1D298AF4 00000000
1D298AF8 4A5976B7
1D298AFC 4CBF7535
1D298B00 00000000
1D298B04 51F7A000 rtl100.System::initialization
1D298B08 3536F873
1D298B0C 7F9E9F8D
1D298B10 10ADBDF3
====================================================
通过测试,12、46是没有加密,7c是加密,还有一种情况都不同于以上值,经测试是GetProcAddress。
四、IAT解密
Ctrl+F2重起,重复进行到06AA9492这个比较,F2断点,F9,中断,F2取消断点。
用OD的插件HideOD申请内存,我这里分配给06E80000。
修改06AA9494:
06AA9494 75 5E jnz short 06AA94F4 ;-->jmp 06E80000
F8步进,来到申请内存06E80000,键入以下补丁代码。
===============================
06E80000 - 0F84 9394C2FF je 06AA9499
06E80006 83FE 7C cmp esi,7C
06E80009 74 05 je short 06E80010
06E8000B 83FE 12 cmp esi,12
06E8000E 75 0A jnz short 06E8001A
06E80010 BE 12000000 mov esi,12
06E80015 - E9 DA94C2FF jmp 06AA94F4
06E8001A CC int3
06E8001B ^ EB F3 jmp short 06E80010
06E8001D 90 nop
0F 84 93 94 C2 FF 83 FE 7C 74 05 83 FE 12 75 0A BE 12 00 00 00 E9 DA 94 C2 FF CC EB F3 90
================================
HE 6A9D971以便IAT解密完毕可以停下。
Alt+O,取消忽略int3异常,定位数据窗口在IAT区段,F9运行,会停在06E8001B,单步运行,来到下面。
006AA95B9 8B45 FC mov eax,dword ptr ss:[ebp-4]
06AA95BC 50 push eax
06AA95BD 8B45 10 mov eax,dword ptr ss:[ebp+10]
06AA95C0 50 push eax
06AA95C1 53 push ebx
06AA95C2 E8 9DFCFFFF call 06AA9264
06AA95C7 8B55 0C mov edx,dword ptr ss:[ebp+C]
06AA95CA 8B12 mov edx,dword ptr ds:[edx]
06AA95CC 8902 mov dword ptr ds:[edx],eax
;记住edx=1d29932c,eax=KERNEL32.GetStringTypeExA
06AA95CE E9 95000000 jmp 06AA9668
1d29932c处应该是GetProcAddress,手工更改:
AB 0C E8 77 getprocaddress
F9继续,停在6A9D971,现在IAT已经全部解密了。
五、patch CALL XXXXXXXX
F9继续运行,停在OEP入口处。
CTRL+G来到6A9D971处,取消6A9D971处的硬件断点,查找mov eax,700,来到下面
06AA9028 8945 F0 mov dword ptr ss:[ebp-10],eax
06AA902B B8 00070000 mov eax,700
06AA9030 E8 0F95FDFF call 06A82544 ;改为-->jmp 06E80041,见下面patch代码
06AA9035 8945 E4 mov dword ptr ss:[ebp-1C],eax
在申请的内存06E80000处写上下面patch代码
06E80000 E8 00000000 call 06E80005
06E80005 5B pop ebx
06E80006 83EB 05 sub ebx,5
06E80009 8B93 00010000 mov edx,dword ptr ds:[ebx+100]
06E8000F 803A E8 cmp byte ptr ds:[edx],0E8
06E80012 0F85 94000000 jnz 06E800AC
06E80018 8B42 01 mov eax,dword ptr ds:[edx+1]
06E8001B 03C2 add eax,edx
06E8001D 83C0 05 add eax,5
06E80020 3B83 18010000 cmp eax,dword ptr ds:[ebx+118]
06E80026 0F85 80000000 jnz 06E800AC
06E8002C 90 nop
06E8002D 90 nop
06E8002E 90 nop
06E8002F 90 nop
06E80030 90 nop
06E80031 90 nop
06E80032 90 nop
06E80033 90 nop
06E80034 90 nop
06E80035 90 nop
06E80036 90 nop
06E80037 90 nop
06E80038 60 pushad
06E80039 89A3 08010000 mov dword ptr ds:[ebx+108],esp
06E8003F FFE2 jmp edx
06E80041 E8 00000000 call 06E80046
06E80046 5B pop ebx
06E80047 83EB 46 sub ebx,46
06E8004A 8993 0C010000 mov dword ptr ds:[ebx+10C],edx
06E80050 8BA3 08010000 mov esp,dword ptr ds:[ebx+108]
06E80056 61 popad
06E80057 8B8B 10010000 mov ecx,dword ptr ds:[ebx+110]
06E8005D 8B83 0C010000 mov eax,dword ptr ds:[ebx+10C]
06E80063 3901 cmp dword ptr ds:[ecx],eax
06E80065 0F85 0D000000 jnz 06E80078
06E8006B 66:C702 FF25 mov word ptr ds:[edx],25FF
06E80070 894A 02 mov dword ptr ds:[edx+2],ecx
06E80073 E9 34000000 jmp 06E800AC
06E80078 83C1 04 add ecx,4
06E8007B 3B8B 14010000 cmp ecx,dword ptr ds:[ebx+114]
06E80081 ^ 0F82 DCFFFFFF jb 06E80063
06E80087 FF83 1C010000 inc dword ptr ds:[ebx+11C]
06E8008D 90 nop
06E8008E 90 nop
06E8008F 90 nop
06E80090 90 nop
06E80091 90 nop
06E80092 90 nop
06E80093 90 nop
06E80094 90 nop
06E80095 90 nop
06E80096 90 nop
06E80097 90 nop
06E80098 90 nop
06E80099 90 nop
06E8009A 90 nop
06E8009B 90 nop
06E8009C 90 nop
06E8009D 90 nop
06E8009E 90 nop
06E8009F 90 nop
06E800A0 90 nop
06E800A1 90 nop
06E800A2 90 nop
06E800A3 90 nop
06E800A4 90 nop
06E800A5 90 nop
06E800A6 90 nop
06E800A7 90 nop
06E800A8 90 nop
06E800A9 90 nop
06E800AA 90 nop
06E800AB 90 nop
06E800AC 42 inc edx
06E800AD 3B93 04010000 cmp edx,dword ptr ds:[ebx+104]
06E800B3 ^ 0F82 56FFFFFF jb 06E8000F
06E800B9 - EB FE jmp short 06E800B9 ;下F2断点
E8 00 00 00 00 5B 83 EB 05 8B 93 00 01 00 00 80 3A E8 0F 85 94 00 00 00 8B 42 01 03 C2 83
C0 05
3B 83 18 01 00 00 0F 85 80 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 60 89 A3 08 01 00
00 FF
E2 E8 00 00 00 00 5B 83 EB 46 89 93 0C 01 00 00 8B A3 08 01 00 00 61 8B 8B 10 01 00 00 8B
83 0C
01 00 00 39 01 0F 85 0D 00 00 00 66 C7 02 FF 25 89 4A 02 E9 34 00 00 00 83 C1 04 3B 8B 14
01 00
00 0F 82 DC FF FF FF FF 83 1C 01 00 00 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 42 3B 93 04 01 00 00 0F 82 56 FF FF FF EB FE
这段代码可以贴在任何地址处而不用修改任何一个字节,但是它需要一些变量,你在运行之前要填上这
些变量。如果
你的代码被贴在06E80000,那么:
06E80000+100 程序代码段开始地址
06E80000+104 程序代码段结束地址+1
06E80000+108 ESP保存地址
06E80000+10C 保存解码API地址
06E80000+110 IAT开始地址
06E80000+114 IAT结束地址+4
06E80000+118 解码call地址
06E80000+11C 未找到API个数记录
你需要填的是目标程序的代码段开始地址、程序代码段结束地址+1、IAT开始地址、IAT结束地址+4和解
码call地址。
其余的就不用管了,我们这里:
程序代码段开始地址=1D001000
程序代码段结束地址+1=1D289000
IAT开始地址=1D298B04
IAT结束地址+4=1D29AFEC
解码call地址(AIP call)=06EA0000
填完后06E80000+100 开始的数据应该是这样:
00 10 00 1D 00 90 28 1D 04 8B 29 1D 00 00 00 00 04 8B 29 1D EC AF 29 1D 00 00 EA 06 00 00
00 00
然后回到我们的Patch代码处,在第一句上右键-〉此处新建EIP,F9运行,停在06E800B9处,F2取消断点
,这时AIP call都已经修复了。
取消06AA9494,06AA9030两处的修改,在OEP入口处右键-〉此处新建EIP,接着就是Dump+Imp修复了。
六、去除时间限制
备份原文件,copy dumped_.dll scxb4.dll,运行bds2006,发生内存写异常,scxb4.dll不能正常载
入,看来还有问题。
用flyDBG载入BDS2006(注意:scxb4.dll是脱壳后的),停在1D2881C0处后,HE 1D284AC9,1D284AC9
是scxb4.dll的输出函数入口,跟下去看看。
1D284AC9 55 push ebp
1D284ACA 68 5C4C281D push 1D284C5C
1D284ACF 64:FF30 push dword ptr fs:[eax]
1D284AD2 64:8920 mov dword ptr fs:[eax],esp
1D284AD5 E8 4AFFFFFF call 1D284A24
1D284ADA 57 push edi
1D284ADB 56 push esi
1D284ADC E8 80000000 call 1D284B61
1D284AE1 0BFD or edi,ebp
1D284AE3 81EF 261F18CB sub edi,CB181F26
1D284AE9 8D7C0C 18 lea edi,dword ptr ss:[esp+ecx+18]
1D284AED 2BF9 sub edi,ecx
1D284AEF 8D7C2F E4 lea edi,dword ptr ds:[edi+ebp-1C]
1D284AF3 2BFD sub edi,ebp
1D284AF5 8B3F mov edi,dword ptr ds:[edi]
1D284AF7 8DBC0F 27CDD7FF lea edi,dword ptr ds:[edi+ecx+FFD7CD27]
1D284AFE 2BF9 sub edi,ecx
1D284B00 8D7451 5C lea esi,dword ptr ds:[ecx+edx*2+5C]
1D284B04 8D740E A4 lea esi,dword ptr ds:[esi+ecx-5C]
1D284B08 2BF1 sub esi,ecx
1D284B0A 8B37 mov esi,dword ptr ds:[edi]
1D284B0C 81E6 FF000000 and esi,0FF
1D284B12 83EF 75 sub edi,75
1D284B15 BF 62314700 mov edi,473162 ; ASCII "
"...
1D284B1A 337C24 08 xor edi,dword ptr ss:[esp+8]
1D284B1E C1CF E5 ror edi,0E5
1D284B21 8DBC35 88104800 lea edi,dword ptr ss:[ebp+esi+481088]
1D284B28 8DBC08 EDFCEB4F lea edi,dword ptr ds:[eax+ecx+4FEBFCED]
1D284B2F 2BF9 sub edi,ecx
1D284B31 2BF8 sub edi,eax
1D284B33 8DB6 2B0214B0 lea esi,dword ptr ds:[esi+B014022B]
1D284B39 03F7 add esi,edi
1D284B3B 85F6 test esi,esi
1D284B3D 0F84 28000000 je 1D284B6B ;此处要跳,否则会出现内存写异常
1D284B43 BD B6AC4700 mov ebp,47ACB6
1D284B48 83DD 37 sbb ebp,37
1D284B4B 8D740B DE lea esi,dword ptr ds:[ebx+ecx-22]
1D284B4F 81E7 C8090384 and edi,840309C8
1D284B55 68 548C0323 push 23038C54
1D284B5A 6A 52 push 52
1D284B5C E9 0A000000 jmp 1D284B6B
1D284B61 037C24 18 add edi,dword ptr ss:[esp+18]
1D284B65 BF 2E9E4900 mov edi,499E2E
1D284B6A C3 retn
1D284B6B 5E pop esi
1D284B6C 5F pop edi
1D284B6D EB 7B jmp short 1D284BEA
修改1D284B3D处代码,必须要跳转。运行,正常了。
下面去除时间限制,CTRL+F2重新载入,到上面修改处继续跟踪,来到下面。
1D284C0B E8 00D6FBFF call 1D242210
1D284C10 E8 EBD6FBFF call 1D242300
1D284C15 E9 12000000 jmp 1D284C2C
改为
1D284C0B E8 00D6FBFF call 1D242210 ;全部改为90
1D284C10 E8 EBD6FBFF call 1D242300 ;全部改为90
1D284C15 EB 24 jmp short 1D284C3B
运行,时间提示没有了,保存,退出。
修改系统时间到过期时间以后,运行bds2006验证,试一下几个功能,OK,时间限制去除了。
七、后记
本来是不想写这篇文章的,第一次手工脱壳,水平真的是太菜,不想出来献丑了,权当是凑发帖数吧!文章里面基本没有自己的东西,patch代码也是抄别人的,在这里要感谢论坛里的牛人们,无数牛人的文章使我受益良多。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!