好友
阅读权限 40
听众
最后登录 1970-1-1
我是用户
发表于 2013-6-9 20:31
本帖最后由 我是用户 于 2013-6-23 13:48 编辑
【软件名称】: XX注册税务师考试锦囊
【作者邮箱】: 2714608453@qq.com
【下载地址】: 见附件
【加壳方式】: Mpress
【使用工具】: OD
【操作平台】: XP SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
1.查壳
对ESPlatform.exe和ESIExamPlatform.exe进行查壳.
如图1:
不过,我们通过区段名可以判断是用Mpress加壳的,将加壳程序脱入OD。
如图2:
看到pushad了有没有,我们用ESP定律脱去,顺利到达OEP。
如图3:
看入口点我们可以知道这是用VC8的程序,不信我们可以用PEID查壳.
ESPlatform.exe: VC8 -> Microsoft Corporation *
ESIExamPlatform.exe: VC8 -> Microsoft Corporation *
打开ESPlatform.exe:,出现CRC效验错误。
如图4:
2.去自效验
在此之前,我简要分析一下程度的流程,方便大家的理解。
正常启动:先启动ESPlatform.exe,然后再启动ESIExamPlatform.exe,两个程序相互保护, 必须同时存在。启动时ESPlatform.exe和ESIExamPlatform进行相互的CRC效验,
CRC不等则来启动.
但是主程序是ESIExamPlatform.exe,也就是我们要分析的程序,我们单独打开ESIExamPlatform会弹出提示.
如图5:
我们先来解决这个问题,将ESIExamPlatform拖入OD,记得我们所说的正常启动流程吗?因为我们两个程序都脱壳 了,在弹出“不能单独启动”这个提示前,ESIExamPlatform会对ESPlatform进行自效验。所以此时弹出错误.
如图6:
右键搜索字符串“《考试锦囊》CRC校验失败...",有两处,右键跟随。
如图7:
修改处如下:
[C] 纯文本查看 复制代码
00419DA1 |. /7C 1C jl short ESIExamP.00419DBF 改为nop
00419DB3 |. /74 0A je short ESIExamP.00419DBF 改为nop
00419DBD |. /75 62 jnz short ESIExamP.00419E21 改为jmp。
另一处处理方法如上所述,不在累述了。
然后保存,打开保存好的文件,此时弹出“不能单独启动“提示.修改的方法和前面一样,依旧是搜索字符串。
修改处如下:
[C] 纯文本查看 复制代码
00419EAF |. /0F84 AA000000 je ESIExamP.00419F5F 改为jmp
如图8:
打开保存好的文件,此时弹出错误。
如图9:
这是由程序通过SEH产生的一个异常,属于自效验,我们跳过就好。
相关代码如下:
[C] 纯文本查看 复制代码
00474B7A /$ 8BFF mov edi,edi
00474B7C |. 55 push ebp
00474B7D |. 8BEC mov ebp,esp
00474B7F |. 81EC 28030000 sub esp,0x328
00474B85 |. A1 A8694C00 mov eax,dword ptr ds:[0x4C69A8]
00474B8A |. 33C5 xor eax,ebp
00474B8C |. 8945 FC mov [local.1],eax
00474B8F |. 83A5 D8FCFFFF>and [local.202],0x0
00474B96 |. 53 push ebx
00474B97 |. 6A 4C push 0x4C
00474B99 |. 8D85 DCFCFFFF lea eax,[local.201]
00474B9F |. 6A 00 push 0x0
00474BA1 |. 50 push eax
00474BA2 |. E8 193A0000 call ESIExamP.004785C0
00474BA7 |. 8D85 D8FCFFFF lea eax,[local.202]
00474BAD |. 8985 28FDFFFF mov [local.182],eax
00474BB3 |. 8D85 30FDFFFF lea eax,[local.180]
00474BB9 |. 83C4 0C add esp,0xC
00474BBC |. 8985 2CFDFFFF mov [local.181],eax
00474BC2 |. 8985 E0FDFFFF mov [local.136],eax
00474BC8 |. 898D DCFDFFFF mov [local.137],ecx ; kernel32.7C864F18
00474BCE |. 8995 D8FDFFFF mov [local.138],edx ; ntdll.KiFastSystemCallRet
00474BD4 |. 899D D4FDFFFF mov [local.139],ebx
00474BDA |. 89B5 D0FDFFFF mov [local.140],esi
00474BE0 |. 89BD CCFDFFFF mov [local.141],edi
00474BE6 |. 66:8C95 F8FDF>mov word ptr ss:[ebp-0x208],ss
00474BED |. 66:8C8D ECFDF>mov word ptr ss:[ebp-0x214],cs
00474BF4 |. 66:8C9D C8FDF>mov word ptr ss:[ebp-0x238],ds
00474BFB |. 66:8C85 C4FDF>mov word ptr ss:[ebp-0x23C],es
00474C02 |. 66:8CA5 C0FDF>mov word ptr ss:[ebp-0x240],fs
00474C09 |. 66:8CAD BCFDF>mov word ptr ss:[ebp-0x244],gs
00474C10 |. 9C pushfd
00474C11 |. 8F85 F0FDFFFF pop [local.132]
00474C17 |. 8B45 04 mov eax,dword ptr ss:[ebp+0x4] ; ESIExamP.004757CA
00474C1A |. 8D4D 04 lea ecx,dword ptr ss:[ebp+0x4]
00474C1D |. C785 30FDFFFF>mov [local.180],0x10001
00474C27 |. 8985 E8FDFFFF mov [local.134],eax
00474C2D |. 898D F4FDFFFF mov [local.131],ecx ; kernel32.7C864F18
00474C33 |. 8B49 FC mov ecx,dword ptr ds:[ecx-0x4]
00474C36 |. 898D E4FDFFFF mov [local.135],ecx ; kernel32.7C864F18
00474C3C |. C785 D8FCFFFF>mov [local.202],0xC0000417
00474C46 |. C785 DCFCFFFF>mov [local.201],0x1
00474C50 |. 8985 E4FCFFFF mov [local.199],eax
00474C56 |. FF15 44B34900 call dword ptr ds:[<&kernel32.IsDebugger>; [IsDebuggerPresent
00474C5C |. 6A 00 push 0x0 ; /pTopLevelFilter = NULL
00474C5E |. 8BD8 mov ebx,eax ; |
00474C60 |. FF15 48B14900 call dword ptr ds:[<&kernel32.SetUnhandl>; \SetUnhandledExceptionFilter
00474C66 |. 8D85 28FDFFFF lea eax,[local.182]
00474C6C |. 50 push eax ; /pExceptionInfo = 00000001
00474C6D |. FF15 44B14900 call dword ptr ds:[<&kernel32.UnhandledE>; \UnhandledExceptionFilter
00474C73 |. 85C0 test eax,eax
00474C75 |. 75 0C jnz short ESIExamP.00474C83
00474C77 |. 85DB test ebx,ebx
00474C79 |. 75 08 jnz short ESIExamP.00474C83
00474C7B |. 6A 02 push 0x2
00474C7D |. E8 D8E50000 call ESIExamP.0048325A
00474C82 |. 59 pop ecx ; kernel32.7C864F18
00474C83 |> 68 170400C0 push 0xC0000417 ; /ExitCode = C0000417 (-1073740777.)
00474C88 |. FF15 34B34900 call dword ptr ds:[<&kernel32.GetCurrent>; |[GetCurrentProcess
00474C8E |. 50 push eax ; |hProcess = 00000001
00474C8F |. FF15 08B34900 call dword ptr ds:[<&kernel32.TerminateP>; \TerminateProcess
00474C95 |. 8B4D FC mov ecx,[local.1]
00474C98 |. 33CD xor ecx,ebp
00474C9A |. 5B pop ebx
00474C9B |. E8 B6E0FFFF call ESIExamP.00472D56
00474CA0 |. C9 leave
00474CA1 |. C3 retn
00474C56的IsDebuggerPresent判断是否处理调试状态,很常见的反调试
00474C60的SetUnhandledExceptionFilter设置顶层处理函数,即异常没有被处理时最后调用的函数.
00474C6D的UnhandledExceptionFilter的参数里有包含我们的错误信息.
如图10:
00124C30处的C0000417就是我们弹出的错误代码。
关于UnhandledExceptionFilter函数:
如果进程正处于调试之中,它将传递一个未处理的异常给调试器..否则它显示一个应用程序错误消息框.并导致异常处理程序被执行.这个函数只能从异常处理程序中的过滤器表达式中调用.
函数原型:
LONG WINAPI UnhandledExceptionFilter( __in struct _EXCEPTION_POINTERS* ExceptionInfo);
当一个异常到达Unhandled Exception Filter(kernel32!UnhandledExceptionFilter)并且程序没有被调试时,Unhandled Exception Filter将会调用在kernel32!SetUnhandledExceptionFilter()API作为参数指定的高层exception Filter
相关的知识,有兴趣的朋友可以百度一下,我其实也不怎么懂,也就不多说了。
理解原理不简单,但是跳过这个异常还是很容易的,堆栈回溯,往前找到00124F84 |0041B9E7 返回到 ESIExamP.0041B9E7 来自 ESIExamP.0047579E,返回到0041B9E7.
如图11:
修改如下:
[C] 纯文本查看 复制代码
0041B9D4 |. /74 14 je short ESIExamP.0041B9EA 改为jmp
再次保存,然后打开,又弹出错误:
如图12:
一大堆的弹窗有木有啊,有木有,在破这个软件的时候,我一般在他弹出三四个的时候就马上把进程杀掉,为了截图,他都打开了几十个ESPlatform.exe进程,还好我给虚拟机 分配了2G的内存,不然早就死机了。我们用xurte全部杀掉。自效验我们都已经解决了,为什么还会有CRC效验失败呢,还记得我们之前说的正常启动流程吗?在ESPlatform里还有一个自效验.我们把ESPlatform,然后搜索字符串,方法如上所述
如图13:
修改如下:
[C] 纯文本查看 复制代码
004015DF |. /74 22 je short ESPlatfo.00401603 改为nop
004015E9 |. /7C 18 jl short ESPlatfo.00401603 改为nop
004015F7 |. /74 0A je short ESPlatfo.00401603 改为nop
00401601 |. /75 3E jnz short ESPlatfo.00401641 改为jmp
保存好,然后运行ESIExamPlatform,程序正常打开。
如图14:
此时我们选中左边的习题集,出现错误。
如图15:
和上述一样的错误.
修改如下:
[C] 纯文本查看 复制代码
0042162B . /74 14 je short ESIExamP.00421641 改为jmp
保存,运行,错误解除。至此自效验已全部去除。
但是我们点习题集的话,会出现如下错误。
如图16:
这个不属于自效验,我们下一步再讨论.
3.关于浮点错误。
定位错误点:
[C] 纯文本查看 复制代码
0042DB20 . 8B85 00FEFFFF mov eax,dword ptr ss:[ebp-0x200]
0042DB26 . 83EC 08 sub esp,0x8
0042DB29 . DD1C24 fstp qword ptr ss:[esp]
0042DB2C . 50 push eax
0042DB2D . 8D8D 3CFCFFFF lea ecx,dword ptr ss:[ebp-0x3C4]
0042DB33 . 68 2CC24A00 push ESIExamP.004AC22C ; ID_%d_Score_%.1f_Answer
0042DB38 . 51 push ecx
0042DB39 . E8 0286FDFF call ESIExamP.00406140
0042DB3E . 8B46 F4 mov eax,dword ptr ds:[esi-0xC]
0042DB41 . 83C4 14 add esp,0x14
具体原因:
代码调用了浮点数,而程序在启动时因为缺省没有调用初始化浮点数的函数。
解决办法:
程序启动阶段___tmainCRTStartup函数中调用了__cinit函数,在这个函数的第一个判断是校验浮点运算初始化函数指针所处的section是否为可写,
如果可写的话就跳过浮点运算初始化函数,因此缺省情况下会直接显示出错信息并退出,如果该区段不可写,代码会调用浮点运算初始化函数,缺省的指向出错函数的指针会被替换成正常处理函数,因此可以正常运算。但是004AC22C处于区段MPRESS1中
如图17:
但是如果我们将MPRESS1区段改为不可写,程序则运行不起来。
如图18:
那么怎么办呢?既然修改区段不成功,那么我们就让他强行初始化。用IDA 定位代码处:
__cinit函数相关代码如下:
[C] 纯文本查看 复制代码
.MPRESS1:00475555 __cinit proc near ; CODE XREF: ___tmainCRTStartup+E1p
.MPRESS1:00475555
.MPRESS1:00475555 var_4 = dword ptr -4
.MPRESS1:00475555 arg_0 = dword ptr 8
.MPRESS1:00475555
.MPRESS1:00475555 mov edi, edi
.MPRESS1:00475557 push ebp
.MPRESS1:00475558 mov ebp, esp
.MPRESS1:0047555A cmp off_4A11A8, 0
.MPRESS1:00475561 jz short loc_47557C
.MPRESS1:00475563 push offset off_4A11A8
.MPRESS1:00475568 call __IsNonwritableInCurrentImage
.MPRESS1:0047556D pop ecx
.MPRESS1:0047556E test eax, eax
.MPRESS1:00475570 jz short loc_47557C
.MPRESS1:00475572 push [ebp+arg_0]
.MPRESS1:00475575 call off_4A11A8
.MPRESS1:0047557B pop ecx
.MPRESS1:0047557C
.MPRESS1:0047557C loc_47557C: ; CODE XREF: __cinit+Cj
.MPRESS1:0047557C ; __cinit+1Bj
.MPRESS1:0047557C call __initp_misc_cfltcvt_tab
.MPRESS1:00475581 push offset dword_49B80C
.MPRESS1:00475586 push offset dword_49B7F0
.MPRESS1:0047558B call __initterm_e
.MPRESS1:00475590 pop ecx
.MPRESS1:00475591 pop ecx
.MPRESS1:00475592 test eax, eax
.MPRESS1:00475594 jnz short loc_4755D8
.MPRESS1:00475596 push offset sub_47C41B ; void (__cdecl *)()
.MPRESS1:0047559B call _atexit
.MPRESS1:004755A0 mov eax, offset dword_49B754
.MPRESS1:004755A5 mov [esp+4+var_4], offset dword_49B7EC
.MPRESS1:004755AC call __initterm
.MPRESS1:004755B1 cmp dword_4CC6F0, 0
.MPRESS1:004755B8 pop ecx
.MPRESS1:004755B9 jz short loc_4755D6
.MPRESS1:004755BB push offset dword_4CC6F0
.MPRESS1:004755C0 call __IsNonwritableInCurrentImage
.MPRESS1:004755C5 pop ecx
.MPRESS1:004755C6 test eax, eax
.MPRESS1:004755C8 jz short loc_4755D6
.MPRESS1:004755CA push 0
.MPRESS1:004755CC push 2
.MPRESS1:004755CE push 0
.MPRESS1:004755D0 call dword_4CC6F0
.MPRESS1:004755D6
.MPRESS1:004755D6 loc_4755D6: ; CODE XREF: __cinit+64j
.MPRESS1:004755D6 ; __cinit+73j
.MPRESS1:004755D6 xor eax, eax
.MPRESS1:004755D8
.MPRESS1:004755D8 loc_4755D8: ; CODE XREF: __cinit+3Fj
.MPRESS1:004755D8 pop ebp
.MPRESS1:004755D9 retn
.MPRESS1:004755D9 __cinit endp
.MPRESS1:004755D9
__IsNonwritableInCurrentImage判断地址是否可写,,不能写则调用__fpmath进行初始化。
我们让它强制初始化,修改如下:
[C] 纯文本查看 复制代码
00475570 |. /74 0A je short ESIExamP.0047557C 改为nop
保存,运行。程序正常运行.
如图19:
未注册的只能有少量试题,接下来我们终于可以来解决限制了,不容易啊。
好吧,容小菜休息一下..................
4.限制解除。
未注册的版本,只有少量试题.
如图20:
注意有字符串提示:"未购买试题点击购买“,右键搜索字符串(有两处),右键跟随
如图21:
[C] 纯文本查看 复制代码
0043032E > \83BB 5C010000>cmp dword ptr ds:[ebx+0x15C],0x0
可见标志位保存在[ebx+0x15C]中,修改方法有两种。
1.搜索cmp dword ptr ds:[ebx+0x15C],0x0 然后修改其跳转.
2.找到[ebx+0x15C]赋值的地方,让他赋值正确。
如果找不到[ebx+0x15C]赋值的地方,可以用第一种方法。
找到的话当然是第二种更简单喽,这下面是我找到的赋值处.
[C] 纯文本查看 复制代码
第一组:
004220C6 > \89BB 5C010000 mov dword ptr ds:[ebx+0x15C],edi
004220CE > \89BB 5C010000 mov dword ptr ds:[ebx+0x15C],edi
第二组:
0042FFF8 > \89BB 5C010000 mov dword ptr ds:[ebx+0x15C],edi
00430016 > \89BB 5C010000 mov dword ptr ds:[ebx+0x15C],edi
修改如下:
[C] 纯文本查看 复制代码
第一组:
00421B28 /0F84 98050000 je ESIExamP.004220C6
004220C6 47 inc edi
004220C7 90 nop
004220C8 90 nop
004220C9 90 nop
004220CA 90 nop
004220CB 90 nop
004220CC 90 nop
004220CD 90 nop
第二组:
0042FA57 /E9 9C050000 jmp ESIExamP.0042FFF8
0042FA5C |90 nop
0042FFF8 47 inc edi
0042FFF9 90 nop
0042FFFA 90 nop
0042FFFB 90 nop
0042FFFC 90 nop
0042FFFD 90 nop
0042FFFE 90 nop
0042FFFF 90 nop
00430000 90 nop
00430001 90 nop
00430002 90 nop
00430003 90 nop
00430004 90 nop
00430005 90 nop
00430006 90 nop
00430007 90 nop
00430008 90 nop
00430009 90 nop
0043000A 90 nop
0043000B 90 nop
0043000C 90 nop
0043000D 90 nop
0043000E 90 nop
0043000F 90 nop
00430010 90 nop
00430011 90 nop
00430012 90 nop
00430013 90 nop
00430014 90 nop
00430015 90 nop
OK,我们保存,运行,限制解除。
如图22:
至此功能上已完全爆破,无任何限制。
但是程序启动时还是会提示注册,现在我们来移除掉注册NAG
5.移除注册NAG
bp CreateDialogDia
会中断两次,第一次是程序主界面,第二次才是注册NAP,堆栈回溯,我们找到00438341处
如图23
[C] 纯文本查看 复制代码
00438341 . /75 2A jnz short ESIExamP.0043836D 改为jmp
大功告成。
后记:这篇文章断断续续写了好久,中间因为各种事耽搁了,还好最后还是把它完成了,凡事还是要坚持,希望这篇文章对大家有所帮助。
PS:求加分啦
因为附件上传的大小限制,只好分卷了.
=================================================================
传送门:
破解 实战-第一战:http://www.52pojie.cn/thread-197281-1-1.html
破解实战-第二战:http://www.52pojie.cn/thread-197598-1-1.html
破解实战-第三站:http://www.52pojie.cn/thread-197957-1-1.html
破解实战-第四站:http://www.52pojie.cn/thread-198203-1-1.html
破解实战-第五战:http://www.52pojie.cn/thread-198365-1-1.html
破解实战-第六战:http://www.52pojie.cn/thread-198930-1-1.html
破解实战-第七战:http://www.52pojie.cn/thread-199459-1-1.html
破解实战-第八战:http://www.52pojie.cn/thread-199834-1-1.html
破解实战-第九战:http://www.52pojie.cn/thread-200655-1-1.html
破解实战-第十战:http://www.52pojie.cn/thread-200798-1-1.html
免费评分
查看全部评分