妙用Second段内存断点大法――比泰软件防盗版战士2005J V1.00脱壳
下载页面: http://www.skycn.com/soft/10178.html
软件大小: 1052 KB
软件语言: 简体中文
软件类别: 国产软件 / 试用版 / 加密工具
应用平台: Win9x/NT/2000/XP
加入时间: 2005-01-10 15:14:20
下载次数: 2982
推荐等级: ****
开 发 商: http://WWW.bittide.com/
软件介绍: 比泰软件防盗版战士(BS-APC),是比泰科技(?2002-2005)出品的一个软件加密保护产品系列(含L版、A版、J版等产品线),它们为商业软件提供可靠的防盗版保护并支持数字化发行。|它采用比泰公司世界领先的“执行代码抽取加密”技术,软硬件结合,以“认证技术”保证软件“对象安全”、以“功能相关法”保证软件“入口安全”、以具有唯一性的计算机(物理)特征数据作为身份认证指纹,并以软件用户计算机本身的运算能力进行防盗版保护。|具有64位以上,到128位的加密安全强度。安全强度远胜传统的外壳加密式加密狗、API内嵌式加密狗,软件保护的功能范围及运行效率超过智能狗,且无须学习加密狗编程,不引入附加硬件维护问题。|适合对C/MFC/Visual C++(VC++)/Borland C++ Builder(BCB)、Delphi/Object Pascal、Power Builder(PB)、Authorware、Director等开发工具所编译程序的保护。|因为它是对真实指令进行代码抽取加密,因此暂不保护伪编译程序,如VB、VFP、C#、JAVA。
【作者声明】:只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【调试环境】:WinXP、Ollydbg V1.10、PEiD、LordPE、ImportREC
―――――――――――――――――――――――――――――――――
【脱壳过程】:
比泰软件防盗版战士是国产壳,有些特色。
壳首先通过ShareDll.dll对EXE主程序解码,包括重新定位IAT。
ShareDll.dll就是这个壳的特征!IAT处理有点繁琐。
OEP就是壳的EP,呵呵,不必寻找了。
简单写一下脱壳过程,希望作者能够继续完善这个壳,成长为新的猛壳。
―――――――――――――――――――――――――――――――――
一、两次Second段内存断点定位输入表处理部分
1、预处理
设置Ollydbg忽略所有异常选项。设置Ollydbg暂停在系统断点。
老规矩:用IsDebug 1.4插件去掉Ollydbg的调试器标志。
7C921231 C3 retn
//进入Ollydbg后暂停在系统断点
Alt+B 察看断点窗口,会发现Ollydbg默认在BSLicense.exe的EP处设置了断点
点右键,删除这个断点,否则会导致解码出错!
现在Alt+M 显示内存窗口,在第2个区段00401000段“设置内存写入断点”。
F9运行,中断下来,取消断点。Ctrl+F9执行到返回
10002C83 8908 mov dword ptr ds:[eax],ecx
//中断在这里
10002C85 8B4C24 2C mov ecx,dword ptr ss:[esp+2C]
10002C89 8950 04 mov dword ptr ds:[eax+4],edx
10002C8C 8B5424 30 mov edx,dword ptr ss:[esp+30]
10002C90 8948 08 mov dword ptr ds:[eax+8],ecx
10002C93 8950 0C mov dword ptr ds:[eax+C],edx
10002C96 75 AA jnz short Sharedll.10002C42
10002C98 5D pop ebp
10002C99 5B pop ebx
10002C9A 8D4C24 08 lea ecx,dword ptr ss:[esp+8]
10002C9E C74424 34 FFFFFFFF mov dword ptr ss:[esp+34],-1
10002CA6 C1E7 04 shl edi,4
10002CA9 E8 D2E4FFFF call Sharedll.10001180
10002CAE 8B4C24 2C mov ecx,dword ptr ss:[esp+2C]
10002CB2 8BC7 mov eax,edi
10002CB4 5F pop edi
10002CB5 5E pop esi
10002CB6 64:890D 00000000 mov dword ptr fs:[0],ecx
10002CBD 83C4 30 add esp,30
10002CC0 C2 1000 retn 10
//或者直接F4至这里
――――――――――――――――――――――――
2、第二次Second段内存断点定位输入表处理部分
现在再次在00401000段“设置内存写入断点”。F9运行,中断后取消断点。
OK,我们就来到了ShareDll.dll中对EXE主程序输入表的处理部分了。
下面这段可能看着比较郁闷,你可以比较一下加壳程序运行流程和下面修改后的运行流程,这样容易理解点。
10002A0B 8B4424 0C mov eax,dword ptr ss:[esp+C]
10002A0F C606 E9 mov byte ptr ds:[esi],0E9
//中断在这里,我们要在这里Patch,否则壳会把输入表搞的乱七八糟。
//修改为:jmp 10009900 ★ 跳到Patch代码
10002A12 2BC6 sub eax,esi
10002A14 83C0 FB add eax,-5
10002A17 8946 01 mov dword ptr ds:[esi+1],eax
10002A1A 8B5424 14 mov edx,dword ptr ss:[esp+14]
10002A1E 8B4424 20 mov eax,dword ptr ss:[esp+20]
//[esp+20]保存的是命令类型 ★
10002A22 3D 2D8B0000 cmp eax,8B2D
//分支①、8B2D ★
10002A27 893A mov dword ptr ds:[edx],edi
10002A29 0F8F 9C000000 jg Sharedll.10002ACB
10002A2F 0F84 86000000 je Sharedll.10002ABB
10002A35 3D 158B0000 cmp eax,8B15
//分支②、8B15 ★
10002A3A 7F 68 jg short Sharedll.10002AA4
10002A3C 74 38 je short Sharedll.10002A76
10002A3E 3D A1000000 cmp eax,0A1
//分支③、A1 ★
10002A43 74 1B je short Sharedll.10002A60
10002A45 3D 0D8B0000 cmp eax,8B0D
//分支④、8B0D ★
10002A4A 0F85 D9000000 jnz Sharedll.10002B29
10002A50 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002A54 8D46 06 lea eax,dword ptr ds:[esi+6]
10002A57 C601 8B mov byte ptr ds:[ecx],8B
10002A5A C641 01 0D mov byte ptr ds:[ecx+1],0D
10002A5E EB 24 jmp short Sharedll.10002A84
10002A60 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002A64 8D46 05 lea eax,dword ptr ds:[esi+5]
10002A67 C601 A1 mov byte ptr ds:[ecx],0A1
10002A6A 8B5424 14 mov edx,dword ptr ss:[esp+14]
10002A6E 8951 01 mov dword ptr ds:[ecx+1],edx
10002A71 83C1 05 add ecx,5
10002A74 EB 18 jmp short Sharedll.10002A8E
10002A76 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002A7A 8D46 06 lea eax,dword ptr ds:[esi+6]
10002A7D C601 8B mov byte ptr ds:[ecx],8B
10002A80 C641 01 15 mov byte ptr ds:[ecx+1],15
10002A84 8B5424 14 mov edx,dword ptr ss:[esp+14]
10002A88 8951 02 mov dword ptr ds:[ecx+2],edx
10002A8B 83C1 06 add ecx,6
10002A8E 2BC1 sub eax,ecx
10002A90 C601 E9 mov byte ptr ds:[ecx],0E9
10002A93 83E8 05 sub eax,5
10002A96 5F pop edi
10002A97 8941 01 mov dword ptr ds:[ecx+1],eax
10002A9A 5E pop esi
10002A9B 33C0 xor eax,eax
10002A9D 5B pop ebx
10002A9E 83C4 10 add esp,10
10002AA1 C2 0C00 retn 0C
10002AA4 3D 1D8B0000 cmp eax,8B1D
//分支⑤、8B1D ★
10002AA9 75 7E jnz short Sharedll.10002B29
10002AAB 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002AAF 8D46 06 lea eax,dword ptr ds:[esi+6]
10002AB2 C601 8B mov byte ptr ds:[ecx],8B
10002AB5 C641 01 1D mov byte ptr ds:[ecx+1],1D
10002AB9 EB C9 jmp short Sharedll.10002A84
10002ABB 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002ABF 8D46 06 lea eax,dword ptr ds:[esi+6]
10002AC2 C601 8B mov byte ptr ds:[ecx],8B
10002AC5 C641 01 2D mov byte ptr ds:[ecx+1],2D
10002AC9 EB B9 jmp short Sharedll.10002A84
10002ACB 3D 15FF0000 cmp eax,0FF15
//分支⑥、FF15 ★
10002AD0 7F 3D jg short Sharedll.10002B0F
10002AD2 74 2C je short Sharedll.10002B00
10002AD4 2D 358B0000 sub eax,8B35
10002AD9 74 15 je short Sharedll.10002AF0
10002ADB 83E8 08 sub eax,8
10002ADE 75 49 jnz short Sharedll.10002B29
10002AE0 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002AE4 8D46 06 lea eax,dword ptr ds:[esi+6]
10002AE7 C601 8B mov byte ptr ds:[ecx],8B
10002AEA C641 01 3D mov byte ptr ds:[ecx+1],3D
10002AEE EB 94 jmp short Sharedll.10002A84
10002AF0 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002AF4 8D46 06 lea eax,dword ptr ds:[esi+6]
10002AF7 C601 8B mov byte ptr ds:[ecx],8B
10002AFA C641 01 35 mov byte ptr ds:[ecx+1],35
10002AFE EB 84 jmp short Sharedll.10002A84
10002B00 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002B04 8D46 06 lea eax,dword ptr ds:[esi+6]
10002B07 C601 FF mov byte ptr ds:[ecx],0FF
10002B0A E9 71FFFFFF jmp Sharedll.10002A80
10002B0F 3D 25FF0000 cmp eax,0FF25
//分支⑦、FF25 ★
10002B14 75 13 jnz short Sharedll.10002B29
10002B16 8B4C24 10 mov ecx,dword ptr ss:[esp+10]
10002B1A 8D46 06 lea eax,dword ptr ds:[esi+6]
10002B1D C601 FF mov byte ptr ds:[ecx],0FF
10002B20 C641 01 25 mov byte ptr ds:[ecx+1],25
10002B24 E9 5BFFFFFF jmp Sharedll.10002A84
10002B29 5F pop edi
10002B2A C743 04 15270000 mov dword ptr ds:[ebx+4],2715
10002B31 5E pop esi
10002B32 83C8 FF or eax,FFFFFFFF
10002B35 5B pop ebx
10002B36 83C4 10 add esp,10
10002B39 C2 0C00 retn 0C
――――――――――――――――――――――――
3、Patch 处理:搞定输入表
现在我们要找2个地方
1、Patch代码存放地址 选择Patch代码存放的地址时候要小心,其他地方会引发异常。可以用playar兄弟的MemoryManage插件申请一段临时内存。一般在ShareDll.dll第2区段的末尾处可以存放临时数据。
2、跳转表存放地址 这里的地址要保证是不被占用的空白处,我选择放在00430660处。
10009900 53 push ebx
10009901 3E:8B5C24 70 mov ebx,dword ptr ds:[esp+70]; kernel32.7C800000
//[esp-70]处保存的是处理DLL的基址 ★
10009906 3B1D 00064300 cmp ebx,dword ptr ds:[430600]; kernel32.7C800000
//提前在[430600]处写入当前处理DLL的基址 ★
1000990C 74 0D je short Sharedll.1000991B
//这样比较前后2次处理的函数是否是同一个DLL的
1000990E 891D 00064300 mov dword ptr ds:[430600],ebx
10009914 8305 04064300 04 add dword ptr ds:[430604],4
//提前在[430604]处写入准备放跳转地址的地址00430660 ★ 呵呵,有点拗口了
1000991B 3B3D 08064300 cmp edi,dword ptr ds:[430608]; ntdll.RtlReAllocateHeap
//第一个函数过后在[430608]处写入第一个函数的地址
10009921 74 0D je short Sharedll.10009930
//这个壳把一个相同函数放好几个地方,比较烦
//比较前后2次处理的函数是否相同 ★
10009923 893D 08064300 mov dword ptr ds:[430608],edi
//保存不同函数地址的值
10009929 8305 04064300 04 add dword ptr ds:[430604],4
//跳转地址+4
10009930 3E:8B5C24 24 mov ebx,dword ptr ds:[esp+24]
//[esp+24]是壳放置的命令类型代码! ★
10009935 81FB A1000000 cmp ebx,0A1
//有一个单字节的,所以需要单独提出来
1000993B 74 11 je short Sharedll.1000994E
1000993D 86FB xchg bl,bh
//前后位调换
1000993F 891E mov dword ptr ds:[esi],ebx
//写入主程序
10009941 8B1D 04064300 mov ebx,dword ptr ds:[430604]; BSLicens.00430660
10009947 893B mov dword ptr ds:[ebx],edi
//正确函数写入 ★
10009949 895E 02 mov dword ptr ds:[esi+2],ebx
//跳转地址写入 ★
1000994C EB 0D jmp short Sharedll.1000995B
1000994E 891E mov dword ptr ds:[esi],ebx
10009950 8B1D 04064300 mov ebx,dword ptr ds:[430604]; BSLicens.00430660
10009956 893B mov dword ptr ds:[ebx],edi
10009958 895E 01 mov dword ptr ds:[esi+1],ebx
1000995B 5B pop ebx
1000995C E9 B990FFFF jmp Sharedll.10002A1A
//跳回去继续流程
从Ollydbg中“二进制复制”如下:
53 3E 8B 5C 24 70 3B 1D 00 06 43 00 74 0D 89 1D 00 06 43 00 83 05 04 06 43 00 04 3B 3D 08 06 43
00 74 0D 89 3D 08 06 43 00 83 05 04 06 43 00 04 3E 8B 5C 24 24 81 FB A1 00 00 00 74 11 86 FB 89
1E 8B 1D 04 06 43 00 89 3B 89 5E 02 EB 0D 89 1E 8B 1D 04 06 43 00 89 3B 89 5E 01 5B E9 B9 90 FF
FF
―――――――――――――――――――――――――――――――――
二、OEP+完成脱壳
Ctrl+S在“整个段块”搜索命令序列:
add esp,4
xor eax,eax
pop edi
pop esi
pop ebp
pop ebx
add esp,230
retn 4
10002963 85C0 test eax,eax
10002965 7C 0A jl short Sharedll.10002971
10002967 43 inc ebx
10002968 83C6 04 add esi,4
//找到这里
1000296B 3BDF cmp ebx,edi
1000296D 7C DE jl short Sharedll.1000294D
1000296F 33C0 xor eax,eax
10002971 5F pop edi
10002972 5E pop esi
10002973 5D pop ebp
10002974 5B pop ebx
10002975 C2 0C00 retn 0C
//这里下断,F9运行,中断后取消断点
当我们中断在10002975处后,输入表已经处理完毕了。
OEP就是壳的EP,我们可以直接G壳的EP。
还是再次使用Second段内存断点大法吧!
Alt+M 显示内存窗口,在第2个区段00401000段“设置内存访问断点”。
F9运行,直接中断在OEP!
0040F1A8 55 push ebp
//用LordPE完全Dump这个进程
0040F1A9 8BEC mov ebp,esp
0040F1AB 6A FF push -1
0040F1AD 68 60BC4200 push BSLicens.0042BC60
0040F1B2 68 3C314100 push BSLicens.0041313C
0040F1B7 64:A1 00000000 mov eax,dword ptr fs:[0]
0040F1BD 50 push eax
0040F1BE 64:8925 00000000 mov dword ptr fs:[0],esp
0040F1C5 83EC 58 sub esp,58
0040F1C8 53 push ebx
0040F1C9 56 push esi
0040F1CA 57 push edi
0040F1CB 8965 E8 mov dword ptr ss:[ebp-18],esp
0040F1CE FF15 F8074300 call dword ptr ds:[4307F8]; kernel32.GetVersion
运行ImportREC,选择这个进程。OEP不用修改,点IT AutoSearch,Get Import得到输入表,现在所有的函数都是有序有效的,FixDump,正常运行!
―――――――――――――――――――――――――――――――――
, _/
/| _.-~/ \_ , 青春都一晌
( /~ / \~-._ |\
`\\ _/ \ ~\ ) 忍把浮名
_-~~~-.) )__/;;,. \_ //'
/'_,\ --~ \ ~~~- ,;;\___( (.-~~~-. 换了破解轻狂
`~ _( ,_..--\ ( ,;'' / ~-- /._`\
/~~//' /' `~\ ) /--.._, )_ `~
" `~" " `" /~'`\ `\\~~\
" " "~' ""
UnPacked By : fly
2005-02-03 零点
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课