Board logo

标题: [转帖]妙用Second段内存断点大法——比泰软件防盗版战士2005J V1.00脱壳 [打印本页]

作者: yongmin    时间: 2006-10-22 10:57     标题: [转帖]妙用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的调试器标志。

CODE:[Copy to clipboard]7C921231   C3                 retn
//进入Ollydbg后暂停在系统断点
Alt+B 察看断点窗口,会发现Ollydbg默认在BSLicense.exe的EP处设置了断点
点右键,删除这个断点,否则会导致解码出错!
现在Alt+M 显示内存窗口,在第2个区段00401000段“设置内存写入断点”。
F9运行,中断下来,取消断点。Ctrl+F9执行到返回

CODE:[Copy to clipboard]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主程序输入表的处理部分了。
下面这段可能看着比较郁闷,你可以比较一下加壳程序运行流程和下面修改后的运行流程,这样容易理解点。

CODE:[Copy to clipboard]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处。

CODE:[Copy to clipboard]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中“二进制复制”如下:

CODE:[Copy to clipboard]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在“整个段块”搜索命令序列:

CODE:[Copy to clipboard]
add esp,4
xor eax,eax
pop edi
pop esi
pop ebp
pop ebx
add esp,230
retn 4

CODE:[Copy to clipboard]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!

CODE:[Copy to clipboard]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,正常运行!
作者: chinanic    时间: 2006-10-22 19:07     标题: [转帖]妙用Second段内存断点大法——比泰软件防盗版战士2005J V1.00脱壳

汗,防盗软件,结果自己被盗了。。




欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/) Powered by Discuz! 7.2