吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 63318|回复: 131
收起左侧

[原创] VB程序的破解思路总结、编译方式vs破解工具 比较

    [复制链接]
dsong 发表于 2015-2-10 17:12
本帖最后由 dsong 于 2015-2-10 17:41 编辑

WARNING: 此文章非常长,如果你感兴趣但是没耐心看完,可以做个标记然后按浏览器的关闭按钮,等到下次有兴趣了再看。这里我尽量多和详细地解释了VB程序的破解(其实也可看到反破解)的相关东西,把一个简单的VB计时器程序研究透了,对于VB破解应有较大帮助,如果觉得无用的不要喷,谢谢!可能包含错误认识,如有错误欢迎指出。
VB程序也是一个非常有趣的东西,你去看VB的主程序,是用Microsoft Visual C++ 5.0编写的,也就是说,其实里面调用的各种命令和控件,都是一段VC++的代码。还有VB运行时必须的“库”(虚拟机):msvbvm50, msvbvm60, 都是Microsoft Visual C++ DLL,所以非常明显的,只要研究透了VB的这个VM虚拟机DLL,完全可以反编译出P-code的程序的源码。著名的程序就有比如VB Decompiler,它对于P-code的效果大家可以在下面的分析中看得出来,当然它对于编译成Native Code的程序效果也不错,只不过名称什么的都不太清楚。所以说,VB的P-code程序(其实Native Code程序也差不了多少,只不过虚拟机里的代码一部分都插入了程序里而已)和Flash的SWF还是有异曲同工之妙的:都可以反编译(可能可以得到源码),原因都在于它们用了比较“通用”的虚拟机。vb的就是vbvmXX.dll,flash的就是Flash Player XX。

为了更好地研究VB程序的破解,我特意使用了一个小程序来做演示。
另外,由于正向和逆向是有联系的,所以我这里写正向的时候可以类推到逆向,写逆向的时候可以类推到正向。
这个程序是某个同学给我的,听说我学破解,就想让我来看看他的程序编译到底是编译成P-code好还是编译成native code好,如果编译成native code又要不要优化一下呢?
我打算顺便骗到源码,但是居然不给我!不过他倒是送我一对注册名和注册码。拿到程序一看关于窗口还写着“演示版”,不就是传说中的Demo吗!算了,不管这些细节了。
我拿到的程序有以下几个:Timer_nc_speed.exe(256KB)[Native-Code并进行代码速度优化]、Timer_p-code.exe(80KB)[P-code程序]、Timer_nc_length.exe(240KB)[Native-Code并进行代码长度优化]、Timer_nc_none.exe(240KB)[Native-code无优化]。可以看到,P-code程序非常小,但是它运行必须要VB的VM DLL。
首先来看看这个程序是如何进行授权及验证的:
打开后主窗口:
上面有一个注册按钮正好遮掉计时器的“分”的十位(也就是说你计时不能超过10分钟,否则你自己都不知道过了多久),然后会过随机的时间跳出“请尽快注册”的窗口,输入了注册码之后会提示“注册码已存储,请立即重启程序,如果正确下次将不再有限制。”看来是纯重启验证类型的。不过貌似还有个突破点,就是按“倒”按钮(即倒计时)会提示“未注册版本不支持倒计时,是否立即注册?y/n”。也许可以从这个对话框入手哦!
另外,这个软件还有个版本更新历史(我去,都更新到构造23了),里面有一句话引起我的注意:
更改 VB 内部 MSGBOX 成为 user32.dll 的 API 里的 "MessageBoxA".
额,这么说,所有对话框在入口点前的API表(后面会提到)里下断点都是无效的了。

现在,拿出几个神器(网上有提到的): SMARTCHECK,WKTVBDebugger,VB Decompiler。当然OD也用来看看效果。
首先是P-code程序载入OD:入口点的特征就是push XXXXXXXX,Call XXXXXXXX。入口点上方是各种VB虚拟机DLL里面的API,下面就是各种OD识别不出的东西。(不是汇编代码当然识别不出啦)
然后是Native-code程序载入OD:其实做各种优化的都差不多,首先入口点特征与P-code的差不多,上方也是一张表(不过好像更大?),下方也有一段数据,但是再往下拉会发现:
 00408C60   > \55            push ebp
 00408C61   .  8BEC          mov ebp,esp
 00408C63   .  83EC 18       sub esp,18
 00408C66   .  68 26314000   push <jmp.&MSVBVM60.__vbaExceptHandler> ;  SE 句柄安装
 00408C6B   .  64:A1 0000000>mov eax,dword ptr fs:[0]
 00408C71   .  50            push eax
 00408C72   .  64:8925 00000>mov dword ptr fs:[0],esp
 00408C79   .  B8 D0010000   mov eax,1D0
 00408C7E   .  E8 9DA4FFFF   call <jmp.&MSVBVM60.__vbaChkstk>
 00408C83   .  53            push ebx
 00408C84   .  56            push esi
 00408C85   .  57            push edi
 00408C86   .  8965 E8       mov dword ptr ss:[ebp-18],esp
 00408C89   .  C745 EC B8114>mov dword ptr ss:[ebp-14],Timer_nc.0040>
 00408C90   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00408C93   .  83E0 01       and eax,1
 00408C96   .  8945 F0       mov dword ptr ss:[ebp-10],eax
 00408C99   .  8B4D 08       mov ecx,dword ptr ss:[ebp+8]
 00408C9C   .  83E1 FE       and ecx,FFFFFFFE
这不是我们熟悉的汇编代码了嘛呵呵。
所以说,到目前为止,P-code的防破解作用远远大于Native-code的。
<破解思路1>在API上面下断点跟踪......
这个对于P-code程序是完全无效的了,但是对于Native Code的可以一试。
首先,以他的水平来说,比较注册码肯定是明码比较,但是我没那么无聊去做内存注册机,来爆破试试看。
打开Timer_nc_XXX.exe,在入口点前面的大表这里下断:
004032E2   $- FF25 B0104000 jmp dword ptr ds:[<&MSVBVM60.__vbaStrCmp>]           ;  MSVBVM60.__vbaStrCmp
运行程序,第一次断下先放行,结果窗口就出来了,说明第一次断下就已经到了关键.
重载程序,断下后F8,来到这里:
 734793DA >  FF7424 08       push dword ptr ss:[esp+8]
 734793DE    FF7424 08       push dword ptr ss:[esp+8]
 734793E2    6A 00           push 0
 734793E4    E8 44E6FFFF     call MSVBVM60.__vbaStrComp
 734793E9    C2 0800         retn 8
 
再按Alt+F9来到这里:
00414BAE   .  50            push eax
 00414BAF   .  68 78734000   push Timer_nc.00407378
 00414BB4   .  E8 29E7FEFF   call <jmp.&MSVBVM60.__vbaStrCmp>
 00414BB9   .  F7D8          neg eax                                              ;  here
 00414BBB   .  1BC0          sbb eax,eax
 00414BBD   .  F7D8          neg eax
 00414BBF   .  F7D8          neg eax
 
这里已经是程序的代码段了,可以更改代码了,继续跟踪看看。
00414BC1   .  66:8985 68FEF>mov word ptr ss:[ebp-198],ax
 00414BC8   .  8D4D D8       lea ecx,dword ptr ss:[ebp-28]
 00414BCB   .  E8 60E7FEFF   call <jmp.&MSVBVM60.__vbaFreeStr>
 00414BD0   .  8D4D B4       lea ecx,dword ptr ss:[ebp-4C]
 00414BD3   .  E8 B6E6FEFF   call <jmp.&MSVBVM60.__vbaFreeVar>
 00414BD8   .  0FBF85 68FEFF>movsx eax,word ptr ss:[ebp-198]
 00414BDF   .  85C0          test eax,eax
 00414BE1   .  0F84 E60B0000 je Timer_nc.004157CD     ;这里跳了
 00414BE7   .  C745 FC 1F000>mov dword ptr ss:[ebp-4],1F
 00414BEE   .  66:8365 DC 00 and word ptr ss:[ebp-24],0
 00414BF3   .  C745 FC 20000>mov dword ptr ss:[ebp-4],20
 00414BFA   .  68 7C744000   push Timer_nc.0040747C                                 ;  UNICODE "Timer_Regcode.inf"
 00414BFF   .  6A 01         push 1
 00414C01   .  6A FF         push -1
 
可以看到,00414BE1这里跳转跳了,但是应该是不要跳的,因为下面的代码才开始读取注册码. 于是NOP。
 00414C03   .  6A 01         push 1
 00414C05   .  E8 78E6FEFF   call <jmp.&MSVBVM60.__vbaFileOpen>
 00414C0A   >  C745 FC 21000>mov dword ptr ss:[ebp-4],21
 00414C11   .  6A 01         push 1
 00414C13   .  E8 64E6FEFF   call <jmp.&MSVBVM60.#571>
 00414C18   .  0FBFC0        movsx eax,ax
 00414C1B   .  85C0          test eax,eax
 00414C1D   .  0F85 8E000000 jnz Timer_nc.00414CB1
 00414C23   .  C745 FC 22000>mov dword ptr ss:[ebp-4],22
 
但是接下来问题也随之出现,就是说这个文件不存在,却要被打开(00414C05处),会出现异常的,所以这句代码也得NOP。不过这个程序令我惊讶的是,居然自带了异常处理程序!现在不能观摩,否则异常不断产生会导致程序卡死,先要把所有异常都处理好,不过那时候也不能再观摩了.
所以还要NOP:
 00414C05   .  E8 78E6FEFF   call <jmp.&MSVBVM60.__vbaFileOpen>
 00414C13   .  E8 64E6FEFF   call <jmp.&MSVBVM60.#571>
 
另外,为了不浪费程序的感情不断读取文件,我们把00414C1D的jnz改为jmp跳过读取阶段. 然后就到了这里:
00414CB1   > \C745 FC 2B000>mov dword ptr ss:[ebp-4],2B
 00414CB8   .  6A 01         push 1
 00414CBA   .  E8 ABE5FEFF   call <jmp.&MSVBVM60.__vbaFileClose>
 00414CBF   .  C745 FC 2C000>mov dword ptr ss:[ebp-4],2C
 00414CC6   .  C785 ECFEFFFF>mov dword ptr ss:[ebp-114],Timer_nc.004>
 00414CD0   .  C785 E4FEFFFF>mov dword ptr ss:[ebp-11C],8008
 00414CDA   .  C785 DCFEFFFF>mov dword ptr ss:[ebp-124],Timer_nc.004>
 00414CE4   .  C785 D4FEFFFF>mov dword ptr ss:[ebp-12C],8008
 00414CEE   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00414CF1   .  05 A4000000   add eax,0A4
 00414CF6   .  50            push eax
 00414CF7   .  8D85 E4FEFFFF lea eax,dword ptr ss:[ebp-11C]
 00414CFD   .  50            push eax
 00414CFE   .  8D45 B4       lea eax,dword ptr ss:[ebp-4C]
 00414D01   .  50            push eax
 00414D02   .  E8 57E5FEFF   call <jmp.&MSVBVM60.__vbaVarCmpNe>
 00414D07   .  50            push eax
 00414D08   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00414D0B   .  05 B4000000   add eax,0B4
 00414D10   .  50            push eax
 00414D11   .  8D85 D4FEFFFF lea eax,dword ptr ss:[ebp-12C]
 00414D17   .  50            push eax
 00414D18   .  8D45 A4       lea eax,dword ptr ss:[ebp-5C]
 00414D1B   .  50            push eax
 00414D1C   .  E8 3DE5FEFF   call <jmp.&MSVBVM60.__vbaVarCmpNe>
 00414D21   .  50            push eax
 00414D22   .  8D45 94       lea eax,dword ptr ss:[ebp-6C]
 00414D25   .  50            push eax
 00414D26   .  E8 39E5FEFF   call <jmp.&MSVBVM60.__vbaVarOr>
 00414D2B   .  50            push eax
 00414D2C   .  E8 6FE5FEFF   call <jmp.&MSVBVM60.__vbaBoolVarNull>
 00414D31   .  0FBFC0        movsx eax,ax
 00414D34   .  85C0          test eax,eax
 00414D36   .  0F84 6D090000 je Timer_nc.004156A9
 
一样的,需要NOP的:
00414CBA   .  E8 ABE5FEFF   call <jmp.&MSVBVM60.__vbaFileClose>
而在00414D36这里,如果跳转就是未注册了. 所以NOP.
继续:
 00414D3C   .  C745 FC 2D000>mov dword ptr ss:[ebp-4],2D
 00414D43   .  C785 ECFEFFFF>mov dword ptr ss:[ebp-114],Timer_nc.004>
 00414D4D   .  C785 E4FEFFFF>mov dword ptr ss:[ebp-11C],8
 00414D57   .  8D95 E4FEFFFF lea edx,dword ptr ss:[ebp-11C]
 00414D5D   .  8B4D 08       mov ecx,dword ptr ss:[ebp+8]
 00414D60   .  83C1 64       add ecx,64
 00414D63   .  E8 08E5FEFF   call <jmp.&MSVBVM60.__vbaVarCopy>
 00414D68   .  C745 FC 2E000>mov dword ptr ss:[ebp-4],2E
 00414D6F   .  C785 ECFEFFFF>mov dword ptr ss:[ebp-114],Timer_nc.004>
 00414D79   .  C785 E4FEFFFF>mov dword ptr ss:[ebp-11C],8
 00414D83   .  8D95 E4FEFFFF lea edx,dword ptr ss:[ebp-11C]
 00414D89   .  8B4D 08       mov ecx,dword ptr ss:[ebp+8]
 00414D8C   .  83C1 74       add ecx,74
 00414D8F   .  E8 DCE4FEFF   call <jmp.&MSVBVM60.__vbaVarCopy>
 00414D94   .  C745 FC 2F000>mov dword ptr ss:[ebp-4],2F
 00414D9B   .  C785 ECFEFFFF>mov dword ptr ss:[ebp-114],Timer_nc.004>
 00414DA5   .  C785 E4FEFFFF>mov dword ptr ss:[ebp-11C],8008
 00414DAF   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00414DB2   .  05 A4000000   add eax,0A4
 00414DB7   .  50            push eax
 00414DB8   .  8D85 E4FEFFFF lea eax,dword ptr ss:[ebp-11C]
 00414DBE   .  50            push eax
 00414DBF   .  E8 0CE5FEFF   call <jmp.&MSVBVM60.__vbaVarTstEq>
 00414DC4   .  0FBFC0        movsx eax,ax
 00414DC7   .  85C0          test eax,eax
 00414DC9   .  74 05         je short Timer_nc.00414DD0
 00414DCB   .  E9 4A160000   jmp Timer_nc.0041641A
 
00414DC9这个跳转不跳的话就会产生1个异常,并且计时器的显示不正确,虽然可以正确及时,而且调整窗口是否全屏也会出错,不过现在可以顺便观摩一下异常处理窗口了:
 异常处理程序
   10:48:02:异常发生.已拦截.无需进一步操作. 错误编号:0, 错误描述:, 引起错误在:“计时器”窗口.
   10:48:31:异常发生.已拦截.无需进一步操作. 错误编号:380, 错误描述:无效属性值, 引起错误在:“计时器”窗口.
   10:48:31:异常发生.已拦截.无需进一步操作. 错误编号:380, 错误描述:无效属性值, 引起错误在:“计时器”窗口.
   10:48:31:异常发生.已拦截.无需进一步操作. 错误编号:380, 错误描述:无效属性值, 引起错误在:“计时器”窗口.
   10:48:31:异常发生.已拦截.无需进一步操作. 错误编号:380, 错误描述:无效属性值, 引起错误在:“计时器”窗口.
  程序已经成功处理了异常,这个窗口关闭后也可正常运行,但是一个或多个命令执行失败.
  你可以将本窗口截屏或复制叙述并配以适当文字叙述(比如是在什么情况下引起异常,因为错误对象有时不准确),然后联系作者,会尽快处理问题. 谢谢!
                                                    关闭                                                     复制全部    复制选中    清
感觉好高级的。呵呵。扯远了,重载程序,这里需要把00414DC9跳转改成jmp.
继续看:
 00414DD0   > \C745 FC 32000>mov dword ptr ss:[ebp-4],32
 00414DD7   .  C785 ECFEFFFF>mov dword ptr ss:[ebp-114],1
 00414DE1   .  C785 E4FEFFFF>mov dword ptr ss:[ebp-11C],2
 00414DEB   .  C785 DCFEFFFF>mov dword ptr ss:[ebp-124],1
 00414DF5   .  C785 D4FEFFFF>mov dword ptr ss:[ebp-12C],2
 00414DFF   .  8D85 E4FEFFFF lea eax,dword ptr ss:[ebp-11C]
 00414E05   .  50            push eax
 00414E06   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00414E09   .  05 A4000000   add eax,0A4
 00414E0E   .  50            push eax
 00414E0F   .  8D45 B4       lea eax,dword ptr ss:[ebp-4C]
 00414E12   .  50            push eax
 00414E13   .  E8 3AE4FEFF   call <jmp.&MSVBVM60.__vbaLenVar>
 00414E18   .  50            push eax
 00414E19   .  8D85 D4FEFFFF lea eax,dword ptr ss:[ebp-12C]
 00414E1F   .  50            push eax
 00414E20   .  8D85 30FEFFFF lea eax,dword ptr ss:[ebp-1D0]
 00414E26   .  50            push eax
 00414E27   .  8D85 40FEFFFF lea eax,dword ptr ss:[ebp-1C0]
 00414E2D   .  50            push eax
 00414E2E   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00414E31   .  05 08010000   add eax,108
 00414E36   .  50            push eax
 00414E37   .  E8 1CE4FEFF   call <jmp.&MSVBVM60.__vbaVarForInit>
 00414E3C   .  8985 F8FDFFFF mov dword ptr ss:[ebp-208],eax
 00414E42   .  E9 0B020000   jmp Timer_nc.00415052
 ......
 00415052   > \83BD F8FDFFFF>cmp dword ptr ss:[ebp-208],0
 00415059   .^ 0F85 E8FDFFFF jnz Timer_nc.00414E47
 
00415059此处也得NOP。
经过了3段类似代码以后,终于来到关键跳(前面跳转必须全部改对才能执行到这里哦):
00415316   .  E8 FBDEFEFF   call <jmp.&MSVBVM60.__vbaVarCmpGe>
 0041531B   .  50            push eax
 0041531C   .  8D45 84       lea eax,dword ptr ss:[ebp-7C]
 0041531F   .  50            push eax
 00415320   .  E8 75DFFEFF   call <jmp.&MSVBVM60.__vbaVarAnd>
 00415325   .  50            push eax
 00415326   .  E8 75DFFEFF   call <jmp.&MSVBVM60.__vbaBoolVarNull>
 0041532B   .  0FBFC0        movsx eax,ax
 0041532E   .  85C0          test eax,eax
 00415330   .  0F84 4F020000 je Timer_nc.00415585       ;***
 
00415330直接NOp了,这下后面的代码就是设置成已注册的了!
 00415336   .  C745 FC 3D000>mov dword ptr ss:[ebp-4],3D
 0041533D   .  8B45 08       mov eax,dword ptr ss:[ebp+8]
 00415340   .  8B00          mov eax,dword ptr ds:[eax]
 00415342   .  FF75 08       push dword ptr ss:[ebp+8]
 00415345   .  FF90 24030000 call dword ptr ds:[eax+324]
 0041534B   .  50            push eax
 0041534C   .  8D45 CC       lea eax,dword ptr ss:[ebp-34]
 0041534F   .  50            push eax
 00415350   .  E8 23E0FEFF   call <jmp.&MSVBVM60.__vbaObjSet>
 00415355   .  8985 68FEFFFF mov dword ptr ss:[ebp-198],eax
 0041535B   .  6A 00         push 0
 0041535D   .  8B85 68FEFFFF mov eax,dword ptr ss:[ebp-198]
 00415363   .  8B00          mov eax,dword ptr ds:[eax]
 00415365   .  FFB5 68FEFFFF push dword ptr ss:[ebp-198]
 0041536B   .  FF90 94000000 call dword ptr ds:[eax+94]
 00415371   .  DBE2          fclex
 
很好,并且没有了注册按钮,而且程序开启还会显示已注册!(虽然注册名和注册码都是空的。)
先保存到文件,再来看看关于窗口,反正看了也不会怎么样吧。(因为某些原因,需要把学号和学校代号抹掉,呵呵)
关于
          计时器 中文版 版本1.7 构建23
           此软件由****开发.
    Copyright (c) 2015 ****. 保留所有权利.
            你正在使用演示版(未注册)
                本软件尚未注册!
 
  注册名:未注册
  注册码:为了支持软件开发,请及时注册软件! (暂
  未对软件试用进行时间限制)
 
                      关闭
一连3个未注册提示,额,有一种不祥的预感,不过至少现在没有注册提示框. 并且设置窗口大小、是否置顶都没出现任何问题。
于是,我再手贱地按了一下“倒”按钮(即倒计时)。结果:
12345678901234567890
 123456789
      
            
    关于 返回
额,果然有暗桩。我一开始以为本来功能就没有的,结果我用他给我的注册码一试,发现还是有倒计时功能而且完整的。所以再次拖入OD调试。
不过这个反破解有点坑,虽然不是最坑,但是想退出程序还真难!按“返回”按钮没有任何用处,按了开始计时按钮提示"00:00已用完."(这是正常的,因为我还没有设置过多长时间的倒计时),于是又一次手贱按了“设”按钮(设置),结果倒计时窗体不见了,只有一个设置窗口。再次手贱设置完了倒计时时间,还勾选了"允许超时",最后一次手贱就按了“关”按钮(关闭设置窗口),结果程序一个窗口都不见了......好窘。打开任务管理器,发现还在运行啊:
taskmgr.exe                  Admin...  00     5,476 K
 Timer_nc_none.exe            Admin...  00     5,640 K       ;***
 NOTEPAD.EXE                  Admin...  00       832 K
算了,先结束了进程,再载入OD调试看看:
按了一下“倒”按钮,发现真的又一次读取了注册码:
00427562   .  F7D8          neg eax
 00427564   .  1BC0          sbb eax,eax
 00427566   .  F7D8          neg eax
 00427568   .  F7D8          neg eax
 0042756A   .  66:8985 68FEF>mov word ptr ss:[ebp-198],ax
 00427571   .  8D4D D8       lea ecx,dword ptr ss:[ebp-28]
 00427574   .  E8 B7BDFDFF   call <jmp.&MSVBVM60.__vbaFreeStr>
 00427579   .  8D4D B4       lea ecx,dword ptr ss:[ebp-4C]
 0042757C   .  E8 0DBDFDFF   call <jmp.&MSVBVM60.__vbaFreeVar>
 00427581   .  0FBF85 68FEFF>movsx eax,word ptr ss:[ebp-198]
 00427588   .  85C0          test eax,eax
 0042758A   .  0F84 0F0D0000 je Timer_nc.0042829F
 00427590   .  C745 FC 07000>mov dword ptr ss:[ebp-4],7
 00427597   .  66:8365 DC 00 and word ptr ss:[ebp-24],0
 0042759C   .  C745 FC 08000>mov dword ptr ss:[ebp-4],8
 004275A3   .  68 7C744000   push Timer_nc.0040747C                  ;  UNICODE "Timer_Regcode.inf"
于是我们也有思路了,只要搜索push 0040747C即可,把所有相关的都改掉. (改的东西都基本一模一样的,因为是单独的再次读取和验证,所以不可能改一处就完美,得一个一个改.......蛋疼啊。)<--此处反破解思路
总共有6处。都改完了以后......终于是完美的了。哈哈。

<破解思路2>使用动态调试程序SMARTCHECK快速定位
SMARTCHECK是NUMEGA公司推出的一款调试VB程序的程序。我找到的最新版是6.20(Build1286) RC2的,1999年发布的......老古董了。网上有几篇文章的,貌似很好用,其实限制也有,不信打开一个P-code程序试试看:
SmartCheck汉化版
  Timer_p-code.exe 被编到p代码
   SmartCheck 是不能的提供调试工程信息为编了的p代码。
  从 SmartCheck 得到,保证与这些 Visual Basic 编译器背景造这
  个工程:
     - 编到本机代码
     - 没有优化
     - 创造符号调试信息
         继续打开程序( )               不打开程序( )
     不显示出这条消息( )
悲剧的是,貌似同学给我的这几个程序都不符合要求:
Timer_nc_none.exe - 程序结果
   类型                              Qty.     合计 (字节)    类型            
                                                                                                                          No details)
                                                                              No events
 
              Results               Events
 
 No source file
于是,我联系同学,让他再给我发个符合要求的......终于来了,Timer_nc_none_dbg.exe就是这个了。(从这里可以看出,SMARTCHECK是为编程程序员设计的,不是为逆向而生......)
试试看......
what??还是没有结果,那这个程序就扔掉了吧。没用啊。
不过,幸好,我在扔掉前想到会不会是因为我用的是绿色版的原因,于是我费尽千辛万苦找到6.20 RC2 Retail安装包,安装以后发现要输序列号,不管,先用,结果发现程序没有正确的序列号就不能调试其他程序,显示试用期已过,于是爆破SCShell.dll,可以正常使用了。
结果再测试......发现其实之前的非P-code文件也是可以正常调试的,甚至被优化的也可正常调试,而且P-code程序也可以调试,而且也有有用的东西,只不过一些语句不太明确而已......真是白忙活了,绿色版害死人啊.
好吧,打开程序,调试,由于Timer事件不断产生,所以我们就点击一次注册按钮,再点击一次“倒”按钮,发现真的好清楚:
    Timer_nc_none.exe - 程序结果
   类型                              Qty.     合计 (字节)    类型            
                                                                                                                          No details)
                                                                              No events
              Results               Events
 No source file
                  Thread 0 [thread id:2360 (0x938)]
              Event reporting started: 2015-02-10 12:37:35
                  Form1 (Form) created
                  Form1_Load
                       OnError
                       Form1.hWnd
                       GetSystemMenu returns HMENU:6D058F
                       RemoveMenu returns BOOL:1
                       Form1.hWnd
                       GetSystemMenu returns HMENU:6D058F
                       RemoveMenu returns BOOL:1
                       Form1.hWnd
                       GetSystemMenu returns HMENU:6D058F
                       RemoveMenu returns BOOL:1
                       Form1.hWnd
                       SetWindowPos returns BOOL:1
                       sfd.Text <-- "1" (String)
                       Timer1.Interval <-- 1000 (Long)
                       Form1.Caption <-- "计时器" (String)
                       Label1.Caption <-- "00:00" (String)
                       Command1.Caption <-- "退出" (String)
                       comd2.Caption <-- "√" (String)
                       Command3.Caption <-- "X" (String)
                       Command4.Caption <-- "‖" (String)
                       Command7.Caption <-- "大" (String)
                       Command8.Caption <-- "关于" (String)
                       Command9.Caption <-- "常" (String)
                       Text1.Visible <-- False (Boolean)
                       Text2.Visible <-- False (Boolean)
                       Timer1.Enabled <-- False (Boolean)
                       comd2.Enabled <-- True (Boolean)
                       Command3.Enabled <-- False (Boolean)
                       Command4.Enabled <-- False (Boolean)
                       sfd.Visible <-- False (Boolean)
                       Timer2.Enabled <-- False (Boolean)
看了老半天,没发现这些语句如何修改,于是只能做追码工具了......
我们先输入注册名注册码:(此程序貌似支持中文注册名啊......)
用户名:dsong@吾爱破解论坛 WwW.52PoJie.Cn
 注册码:01234567890ABCDEFabcdef
额,然后同一目录下生成了明码的注册码存储......
然后是长长的检验和计算过程:
                      Dir                          //获取目录
                       Open                         //打开
                       EOF                         //是否到最后一行
                       LineInputNum                         //输入
                       EOF                         //是否到最后一行
                       LineInputNum                         //输入
                       EOF                         //....
                       Close                         //关闭
                       Len returns LONG:1243848
                       Mid
                       OnError
                       Asc returns Integer:100
                       Hex
                       Resume
                       Visual Basic Runtime Error 20: 无错误恢复
                       Handling Visual Basic Runtime Error 20
                       Resuming from Visual Basic Runtime Error
                       Resume
                       String ("&H64") --> Long (100)
                       Hex
                       Mid
                       OnError
                       Asc returns Integer:115
                       Hex
                       Resume
                       Visual Basic Runtime Error 20: 无错误恢复
                       Handling Visual Basic Runtime Error 20
                       Resuming from Visual Basic Runtime Error
                       Resume
                       String ("&H73") --> Long (115)
                       Hex
                       Mid
                       OnError
                       Asc returns Integer:111
                       HexResume
                       Visual Basic Runtime Error 20: 无错误恢复
 .......
                       Hex
                       String ("&HA0") --> Long (160)
                       String ("&HA0") --> Long (160)
                       Hex
                       String ("&H56") --> Long (86)
                       String ("&H56") --> Long (86)
                       Chr
                       Resume
                       Visual Basic Runtime Error 20: 无错误恢复
                       Handling Visual Basic Runtime Error 20
                       Resuming from Visual Basic Runtime Error
                       Resume
                       Mid
                       OnError
                       String ("&HBE") --> Long (190)
                       String ("&HBE") --> Long (190)
                       String ("&HBE") --> Long (190)
                       Hex
                       String ("&H74") --> Long (116)
                       String ("&H74") --> Long (116)
                       Chr
                       Resume
                       Visual Basic Runtime Error 20: 无错误恢复
                       Handling Visual Basic Runtime Error 20
                       Resuming from Visual Basic Runtime Error
                       Resume
                       Mid
                       OnError
                       String ("&H0A") --> Long (10)
                       String ("&H0A") --> Long (10)
                       Hex
                       String ("&H3A") --> Long (58)
                       String ("&H3A") --> Long (58)
                       String ("&H3A") --> Long (58)
                       Chr
 ......
                       Mid
                       OnError
                       Mid
                       OnError
                       Mid
                       OnError
                       Mid
                       OnError
                       Mid
                       OnError
                       Mid
                       OnError
                       Mid
                       OnError
                       Mid
                       OnError
                       Trim               //注册码明码出现
                       Len returns LONG:1243832               //注册码明码出现
                       Timer2.Interval <-- 1000 (Long)               //定时弹出提醒注册窗口,看到这里要往前找
                       Timer2.Enabled <-- True (Boolean)
                       Form1.Height
                       Label1.FontSize
                       Form1.Height
                       Label1.Height
                       Form1.Width
                       Label1.Width
                       Text1.Text <-- "dsong@吾爱破解论坛 WwW.52PoJie.Cn" (String)               //注册名
                       Text2.Text <-- "01234567890ABCDEFabcdef" (String)        //注册码(假)
                       csy.Visible <-- False (Boolean)
                       csy.Text <-- "0" (String)
                       Resume
                       Visual Basic Runtime Error 20: 无错误恢复
                       Handling Visual Basic Runtime Error 20
                       Resuming from Visual Basic Runtime Error
                       Resume
在注册码明码出现的时候,看旁边的细节窗口:
string (variant)
      String  .bstrVal = 001559A4
               = "h1141X:if:2Vt:y78OTEiMr34VyX11HaF"
这就是我们的注册码了。使用这个注册码注册一下,然后看看关于窗口:
关于
          计时器 中文版 版本1.7 构建23
           此软件由****开发.
    Copyright (c) 2015 ****. 保留所有权利.
            你正在使用演示版(已注册)
                本软件已授权给:
 
  注册名:dsong@吾爱破解论坛 WwW.52PoJie.Cn
  注册码:h1141X:if:2Vt:y78OTEiMr34VyX11HaF
 
                      关闭
不过只看关于窗口是不够的,因为它这个程序只要检测到输入过注册码,就会显示已注册,所以我们再来按“倒”按钮:<--反破解思路
倒计时 已注册
 00:00   
            
    关于 返回
发现一切正常(这就好啦哈哈).
(其实如果软件设计成注册码分段验证的会更好,这样的话追码是不可能了,算法分析也会有阻碍.)
---拓展:算法分析
它这个算法也不难,不过是单向的,如果反过来就会检验错误。呵呵。所以只能是明码比较。算法贴出来,让他自己去改代码去。
由于SMARTCHECK代码太长,我这里来说一下它的大致算法。
首先把你的用户名逐位转换成HEX,然后把第一个HEX+4(第一个Hex指用户名第一位的HEX值,后面类推),第二个HEX+8,第三个HEX+C,第四个HEX+10,以此类推,然后取最小为0的hex即48(0x30),最大为z(区分大小写)的hex即122(0x7A),如果过小就+48(0x30),过大就-74(0x4A),然后最后组合起来就是注册码. 既然它程序使用VB写,那么我们也可以用VB来写写看。最后成品放在附件上了。
<3>使用静态反编译工具VB Decompiler快速找到爆破点并更清晰地分析算法
VB Decompiler 是神器了。用它作用非常的大,可以快速找到Native-Code编译的程序爆破点,而不像SMARTCHECK那样不能用来爆破程序。
并且,它不像SMARTCHECK一样渴望是Native Code的程序,它对于P-code的支持反而大于Native Code。看来真是分析了VB虚拟机的运作的成品啊!
应该说,它可以直接把程序算法给爆出来,如下:
  loc_412296:   If CBool((global_164 <> vbNullString) Or (global_180 <> vbNullString)) Then
   loc_4122A3:     global_100 = vbNullString
   loc_4122B1:     global_116 = vbNullString
   loc_4122C5:     If (global_164 = vbNullString) Then
   loc_4122CA:       Exit Sub
   loc_4122CB:     End If
   loc_4122E2:     For var_108 = 1 To Len(global_164): global_264 = var_108 'Variant
   loc_41231B:       global_244 = ZFto16(CStr(Mid(global_164, CLng(global_264), 1)))
   loc_41235B:       global_244 = CStr((CVar(CLng("&H" & global_244)) + (global_264 * 4)))
   loc_41238E:       global_100 = global_100 & Hex(global_244)
   loc_4123A1:     Next var_108 'Variant
   loc_4123BD:     global_212 = Trim(global_100)
   loc_4123DB:     For var_12C = 1 To Len(global_212): global_264 = var_12C 'Variant
   loc_412421:       var_10C = ZFto16ZF(CStr(Mid(global_212, CLng(((2 * global_264) - 1)), 2)))
   loc_412433:       global_116 = global_116 & CVar(var_10C)
   loc_41244D:     Next var_12C 'Variant
   loc_412469:     global_228 = Trim(global_116)
   loc_41249C:     If CBool((global_180 = global_228) And (Len(global_228) >= 10)) Then
   loc_4124AD:       Me.Command5.Visible = False
   loc_4124BF:       global_296 = 0
   loc_4124D4:       Me.Timer3.Interval = &H7D0
   loc_4124EA:       Me.Timer3.Enabled = True
   loc_412500:       Me.Command6.Enabled = True
   loc_412512:       global_312 = 1
   loc_412519:     Else
   loc_41252C:       Me.Timer2.Interval = &H3E8
   loc_412542:       Me.Timer2.Enabled = True
   loc_412554:       global_312 = 0
   loc_412558:     End If
   loc_41255D:   Else
   loc_412570:     Me.Timer2.Interval = &H3E8
   loc_412586:     Me.Timer2.Enabled = True
   loc_412598:     global_312 = 0
   loc_41259C:   End If
   loc_4125A1: Else
   loc_4125B4:   Me.Timer2.Interval = &H3E8
   loc_4125CA:   Me.Timer2.Enabled = True
   loc_4125DC:   global_312 = 0
   loc_4125E0: End If
恩,挺变态的吧,再试试看Native-code的:
  loc_00414BC1: var_198 = (Dir("Timer_Regcode.inf", 7) = vbNullString)
   loc_00414BE1: If var_198 = 0 Then GoTo loc_004157CD
   loc_00414C05: Open "Timer_Regcode.inf" For Input As #1 Len = -1
   loc_00414C0A: 
   loc_00414C1D: If EOF(1) <> 0 Then GoTo loc_00414CB1
   loc_00414C35: Line Input #1, Me
   loc_00414C47: If var_24 <> 0 Then GoTo loc_00414C67
   loc_00414C62: ecx = Me
   loc_00414C67: 'Referenced from: 00414C47
   loc_00414C73: If var_24 <> 1 Then GoTo loc_00414C93
   loc_00414C8E: ecx = Me
   loc_00414C93: 'Referenced from: 00414C73
   loc_00414C9E: var_24 = var_24 + 0001h
   loc_00414CA8: var_24 = var_24
   loc_00414CAC: GoTo loc_00414C0A
   loc_00414CB1: 'Referenced from: 00414C1D
   loc_00414CBA: Close #1
   loc_00414CC6: var_114 = vbNullString
   loc_00414CDA: var_124 = vbNullString
   loc_00414D02: var_ret_1 = (Me <> vbNullString)
   loc_00414D1C: var_ret_2 = (Me <> vbNullString)
   loc_00414D26: call Or(var_6C, var_ret_2, var_ret_1, var_34, var_6C, Me, var_34, var_6C, Me, var_34, var_6C, Me, var_34, var_6C, Me)
   loc_00414D36: If CBool(Or(var_6C, var_ret_2, var_ret_1, var_34, var_6C, Me, var_34, var_6C, Me, var_34, var_6C, Me, var_34, var_6C, Me)) = 0 Then GoTo loc_004156A9
   loc_00414D43: var_114 = vbNullString
   loc_00414D63: ecx = vbNullString
   loc_00414D6F: var_114 = vbNullString
   loc_00414D8F: ecx = vbNullString
   loc_00414D9B: var_114 = vbNullString
   loc_00414DC9: If (Me = vbNullString) = 0 Then GoTo loc_00414DD0
   loc_00414DCB: GoTo loc_0041641A
   loc_00414DD0: 'Referenced from: 00414DC9
   loc_00414E37: For Me = 1 To Len(Me) Step 1
   loc_00414E42: GoTo loc_00415052
   loc_00414E47: 
   loc_00414EA4: var_eax = Timer.1788
   loc_00414EAA: var_198 = Timer.1788
   loc_00414EEC: ecx = var_2C
   loc_00414F3A: var_ret_4 = CLng("&H" & eax+000000F4h)
   loc_00414F3F: var_124 = var_ret_4
   loc_00414F98: var_2C = var_ret_4 + Me * 4
   loc_00414FA8: ecx = var_2C
   loc_00415012: ecx = Me & Hex(Me)
   loc_00415047: Next Me
   loc_0041504C: var_208 = Next Me
   loc_00415052: 'Referenced from: 00414E42
   loc_00415059: If var_208 <> 0 Then GoTo loc_00414E47
   loc_00415082: ecx = Trim(Me)
   loc_004150F6: For Me = 1 To Len(Me) Step 1
   loc_00415101: GoTo loc_00415284
   loc_00415106: 
   loc_004151AD: var_eax = Timer.1792
   loc_004151B3: var_198 = Timer.1792
   loc_004151EC: var_210 = var_2C
   loc_004151FC: var_84 = var_210
   loc_0041522E: ecx = Me & var_210
   loc_00415279: Next Me
   loc_0041527E: var_20C = Next Me
   loc_00415284: 'Referenced from: 00415101
   loc_0041528B: If var_20C <> 0 Then GoTo loc_00415106
   loc_004152B4: ecx = Trim(Me)
   loc_00415320: var_ret_B = (Me = Me) And (Len(Me) >= 10)
   loc_00415330: If CBool(var_ret_B) = 0 Then GoTo loc_00415585
   loc_0041536B: Command5.Visible = False
   loc_00415373: var_19C = eax
   loc_004153DB: ecx = False
   loc_00415418: Timer3.Interval = CInt(2000)
   loc_0041541D: var_19C = eax
   loc_00415490: Timer3.Enabled = True
   loc_00415495: var_19C = eax
   loc_00415508: Command6.Enabled = True
   loc_00415510: var_19C = eax
   loc_0041557B: ecx = CInt(1)
   loc_00415580: GoTo loc_004156A4
   loc_00415585: 'Referenced from: 00415330
   loc_004155BD: Timer2.Interval = CInt(1000)
   loc_004155C2: var_19C = eax
   loc_00415635: Timer2.Enabled = True
   loc_0041563A: var_19C = eax
   loc_0041569F: ecx = False
   loc_004156A4: 'Referenced from: 00415580
   loc_004156A4: GoTo loc_004157C8
   loc_004156A9: 'Referenced from: 00414D36
   loc_004156E1: Timer2.Interval = CInt(1000)
   loc_004156E6: var_19C = eax
   loc_00415759: Timer2.Enabled = True
   loc_0041575E: var_19C = eax
   loc_004157C3: ecx = False
   loc_004157C8: 'Referenced from: 004156A4
   loc_004157C8: GoTo loc_004158EC
   loc_004157CD: 'Referenced from: 00414BE1
   loc_00415805: Timer2.Interval = CInt(1000)
   loc_0041580A: var_19C = eax
   loc_0041587D: Timer2.Enabled = True
   loc_00415882: var_19C = eax
   loc_004158E7: ecx = False
恩,代码明显差很多,但是对于调试的帮助还是有挺多的,比如上面可以得出415330的跳转应该不跳,然后到OD里面前前后后看看即可爆破了,不需要再费尽心思猜API来入手了。
这里我也不多说明,但是很明显的,编译成P-code的程序在遇到VB Decompiler的时候马上就跪了,之前的硬壳直接被看穿。
<破解思路3>利用动态调试器WKTVBDebugger来动态调试与修改P-code的VB程序
之前的VB Decompiler对于P-code的程序支持很好,但是并没有很明显的线索去修改VB程序。这时使用WKTVBDebugger就可以按照它里面的帮助文件进行修改跳转等东西了。
注意事项:
1. 此程序只能用于动态调试VB的P-code程序,对于Native-Code程序没有任何用处。
2. XP下使用时为了不出错,要把要调试的程序放在WKTVBDebugger同一目录下。(XP以前的系统应该没有这个问题,以后的没测试)
还有,帮助文件也很重要,里面有P-code和opcode的对应,对于修改爆破程序是有必要稍微了解一些的,否则代码你看不懂的话怎么破解呢。
我们先来看帮助文件,我这里直接打开会显示“已取消到该网页的导航”,对于这种问题解决办法:
右键属性,在下部看到一个“安全”,按旁边的“解除锁定”即可。最后记得要按确定.
安全:       此文件来自其他计算机,可能
             被阻止以帮助保护该计算机。   解除锁定( )
然后就正常了。点击目录中“操作码与助记符列表”,然后点击"标准设置",就是长长的一列对照表了。因为P-code与Intel的汇编代码完全不一样,所以得像初学OD那样先掌握一些P-code的含义。
目光聚焦到了这里:
1Eh Branch 3 
 1Ch BranchF 3 
 5Ch BranchFVar 3 
 1Dh BranchT 3 
这里可以知道,1c就代表jnz,1d就代表je,1e就代表jmp。(至少我当时是这么稚嫩地认为的。)然后我就到处找,汇编中的NOP在P-code里面该怎么表示呢?我在里面看这张表,找了三遍都没找到相关指令。然后无意中看到了这篇文章:http://blog.sina.com.cn/s/blog_5000f4c901013iiy.html
里面有提到:
...... 所以解密插入一段代码是基本功,但在p-code里这样做比INTEL难。   看了下面的说明,你就会明白p-code语言插入语句为什么困难,如果你懂INTEL汇编,这事并不太难,加句NOP(90)很easy,但p-code不一样,他的语句大部分都与堆栈有关,比如:p-code里面转向语句一共有三个,
Branch (1E) ---- 无条件跳转
 BranchT(1D) ---- 栈顶数据为真则跳转
 BranchF(1F) ---- 栈顶数据为假则跳转
 第一次接触p-code的人会想当然的认为,解密时可以把条件跳转,换成无条件跳转,比如BranchT(1D)换成Branch(1E)但这是错误的,我想这也是解密者犯的第一个错误,因为BranchTbranchF都有一个退栈动作,而Branch与堆栈无关,所以只能用BranchT与branchF互换,下面给出一段我想像的程序,看看他们与通常的机器语言有什么不同,假设一个过程,被调入的基址为00004000,我不知道怎么用p-code中标准术语描述,就称之为一个过程吧。在解密时,你不要想插入所谓空指令,因为栈会乱,改动程序要当心。 ......
这一来,我才明白,原来P-code的vb程序不能像Intel程序一样,随便把je,jnz改成jmp,也没有NOP指令给你用了,必须要另辟途径。
好了,到这里准备工作也做得差不多了,把程序载入WKTVBDebugger。看一下关于窗口,发现是2001年的作品,说明最近十几年除了VB Decompiler在不断更新以外,其他的VB工具基本都停留在了10几年以前,这跟微软的保密策略肯定有着非常大的关系(未公开关于P-code的详细信息,不信你去百度或Google搜索,没有什么特别有价值的信息)。对于P-code研究最大的成果也就这么几个。扯远了,来看看程序。界面如下:
WKTVBDebugger v1.3 / 汉化:小生我怕怕[LCG]
   -Code 代码源:  Locs. Addr: 0012FA94h                      Proc. Range:   411F14h-  412838h                       堆栈:
  00411F14: 00 LargeBos
  00411F16: 00 LargeBos                                                            0012F8B4: 00 00 00 00 00 00 00 00
                                                                                   0012F8AC: 80 FF 12 00 00 00 00 00                       ESP
  00411F18: 4B OnErrorGoto 004126ECh                                               0012F8A4: 38 28 41 00 6B 3B 0E 66
  00411F1B: 00 LargeBos                                                            0012F89C: EC FA 12 00 B4 F8 12 00                                Byte
  00411F1D: 04 FLdRfVar 0012FA64h                                                  0012F894: 98 DF 15 00 15 1F 41 00
  00411F20: 05 ImpAdLdRf                                                           0012F88C: EC FA 12 00 02 02 00 00                      
                                                                                   0012F884: 00 00 00 00 00 00 00 00
  00411F23: 24 NewIfNullPr Form1 004040FC                                                                                                           Word
                                                                                   0012F87C: 00 00 00 00 00 00 00 00
  00411F26: 0D VCallHresult get__ipropHWNDFORM                                     0012F874: 8C F8 12 00 44 FF 00 10
  00411F2B: F5 LitI4: -> 0h 0                                                      0012F86C: C4 FA 12 00 6C F8 12 00                                Dword
  00411F30: 6C ILdRf 00000000h                                                     0012F864: 0A 00 00 00 44 F8 12 00
                                                                                   0012F85C: F8 FF FF FF B4 F8 12 00
  00411F33: 5E ImpAdCallI4 user32!GetSystemMenu                                    0012F854: 10 00 00 00 58 4D 05 10
  00411F38: 71 FStR4                                                               0012F84C: 00 00 00 00 12 00 12 00                        
  00411F3B: 3C SetLastSystemError                                                  0012F844: FF 00 00 FF 7A 9F 80 7C                                EBP
  00411F3C: F5 LitI4: -> 1000h 4096                                                0012F83C: 9A 9A 83 7C 80 9F 80 7C
  00411F41: F5 LitI4: -> FFFFF060h -4000                                                                                                             ESP
  00411F46: 6C ILdRf 00000000h
  00411F49: 0A ImpAdCallFPR4 user32!RemoveMenu
  00411F4E: 3C SetLastSystemError                                                                                                                    Enable
  00411F4F: 00 LargeBos
 
                                                                                                                                                                                                                                                                                  EBP
                                                                                                                                                                                       上一页                                         下一页 >
                                                                                                                                                                                                           内存转存 (Ctrl+M)
                                                                                                                                                                                                              加载模块符号
                                                                                                                                                                                                         字符串参考. (Ctrl+S)
 
  Op: 00 02                                                                 文件偏移:      00011F14                        编辑                              跟踪命令:                                                        断点
 
  Form1!00411F14
                                                                                                                                                                                       单步跟踪 (F8)                                                API (Ctrl+B)
 堆栈转存是启用的,相对到 ESP<-EBP.
                                                                                                                                                                                     执行到返回 (F12)                                         操作码(Ctrl+O)
                                                                                                                                                                                   跟踪当前指令 (F10)                                     执行断点 (Ctrl+E)
                                                                                                                                                                                            运行 (F5)                                             跟踪X行代码 (F6)
   反汇编信息保存           保存信息                  选项                    管理窗口 (Ctrl+F)                     管理杂项
                                           清除日志                  帮助                    深层信息 (Ctrl+I)                      高级信息
     命令 >
比较有用的适合刚接触的就是“管理窗口 (Ctrl+F)”,使用这个,可以轻松地对程序载入、按钮按下等下断点。我们打开它,选择Form1(加载时默认的主窗口,如果不是可以一个一个慢慢试)。然后它会给你地址:
对象属性
  Form1
 地址: 004040FCh
  Picture
  Label
  TextBox
  Frame
  Command
  CheckBox
  Option
  ComboBox
  ListBox
  HScrollBar
  VScrollBar
  Timer
  Printer
  Screen
  Clipboard
  DriveListBox
  DirListBox
  FileListBox
  Menu
  Shape
  Line
  Image
  PropiertyPage
  UserControl
  Unknow Controls
可以说,非常齐全,但是它只能根据控件来进行下断。而我们根据之前的分析,它在Form_Load的时候就检测了注册码。(如果没有重启验证,那么可以在按钮上下断点。)所以我们不得不再想另外的办法。<--反破解思路,做成纯重启验证也有它的好处。
再次打开VB Decompiler,发现Form_Load事件是在412838,于是打开WKTVBDebugger,下断412838,结果发现断不下!再仔细看看,发现这其实并不是代码的地址,而是窗体地址。所以在VB Decompiler反编译结果的窗口中选中第一句的地址411F26,再下断。
测试成功!这时候就可以取消断点,把VB Decompiler拖到注册验证段,开始是4121F0,再下断。
这里的跳转应该是不跳的,现在这里跳了,所以必须改掉。
这里为了验证BranchF/BranchT不能改成Branch,我们先改了试试看。
点击编辑,把目前的1c改成1e,然后运行。发现也没什么问题啊,请问那篇文章的真实性?我不得而知,望大牛来解释一下。
好,重新来一次。到这里以后看看代码:
004121D2: 3A LitVarStr 'Timer_Regcode.inf'
 004121D7: 4E FStVarCopyObj 0012FA3Ch
 004121DA: 04 FLdRfVar 0012FA3Ch
 004121DD: 0B ImpAdCallI2 rtcDir on address 660D4F71h
 004121E2: 23 FStStrNoPop
 004121E5: 1B LitStr: ''
 004121E8: 3D NeStr
 004121EA: 2F FFree1Str
 004121ED: 35 FFree1Var
 004121F0: 1C BranchF 004125A1 (Jump ?       ;在这
 004121F3: 00 LargeBos
 004121F5: F4 LitI2_Byte: -> 0h 0
 004121F7: 70 FStI2 0012FA36
 004121FA: 00 LargeBos
 004121FC: 1B LitStr: 'Timer_Regcode.inf'
 004121FF: F4 LitI2_Byte: -> 1h 1
 00412201: F4 LitI2_Byte: -> FFh 255
 00412203: FE Lead3/OpenFile
 00412207: 00 LargeBos
004121F0的opcode为:1c 8d 06 先改成1c 00 00可以看到:
004121F0: 1C BranchF 00411F14 (Jump ?
而我们的目标为BranchF 00412296(那里开始注册码的校验,由于这里没有NOP指令,只能先跳过读取阶段),而412296-411F14=382,所以我们就可以改为:1c 82 03 。值得注意的是,这里又和Intel的汇编指令不同,汇编指令的跳转是以当前地址为参照,而这里P-code是以起始代码为参照的。这样一改,反而还挺好的,没有注册码就跳过读取阶段,有就不跳过,这样的话可以随意改写注册文件了。
然后就到了验证注册码的第一个环节:
00412296: 1C BranchF 0041255D (Jump ?             ;在这
 00412299: 00 LargeBos
 0041229B: 3A LitVarStr ''
 004122A0: 08 FLdPr
 004122A3: FD Lead2/MemStVarCopy
 004122A7: 00 LargeBos
 004122A9: 3A LitVarStr ''
 004122AE: 08 FLdPr
 004122B1: FD Lead2/MemStVarCopy
 004122B5: 00 LargeBos
 004122B7: 08 FLdPr
 004122BA: 06 MemLdRfVar
 004122BD: 3A LitVarStr ''
 004122C2: 5D HardType
 004122C3: 33 EqVarBool
 004122C5: 1C BranchF 004122CB ?
 004122C8: 00 LargeBos
 004122CA: 13 ExitProcHresult
 004122CB: 00 LargeBos
依葫芦画瓢,后面的跳转也可这样改,比如00412296这里要跳到412299即下一行,于是412299-411F14=385,于是改成1c 85 03即可。后面的修改也都是差不多的,参照VB Decompiler里面的指令修改起来会很准确很清楚。(不知道如果我使用WKTVBDebugger像OD一样熟练还会不会要VB Decompiler)
Native Code和P-code程序的比较和各种破解VB程序的工具的比较就到这里告一个段落了,如果你能看完整篇文章,那我承认你对于它是极度感兴趣了,呵呵。
最后做个总结: VB的Native Code程序爆破起来比较简单(主要是OD用熟练了),分析算法的话用VB Decompiler就要多花点心思。而P-code的程序追码和分析算法都非常简单,而爆破就要多花一些时间了(主要是WKTVBDebugger不太熟悉)。
顺便加个对话:
我: 各有利弊,.......(上面总结的话)......,你自己看着办吧。
 小A: 哦,那我就用Native Code吧,反正反编译出来的源码就不那么直接清楚了。
 我: 不过你那个程序算法太简单了一点,加个重壳吧。
 小A: 不,加了重壳以后计时的延迟就太大了。
 我: 我已经写出你那个软件的注册机了。
 小A: 啊?......算了,我换一种编程语言写吧。
 我: ......
P.S.: 经过我的百般祈求,我的那个小A同学仍然不同意我把他的程序公开。对不起了,大家还是用自己的程序试炼一下吧。恩不过他没说我不能把注册机放出来......呵呵,我相信他不会打我的。

制作总结性的东西总是很累,这个笔记就当大家的参考吧,以后遇到VB程序脱了壳后破解起来应该会挺方便了吧。希望大家支持一下哦!写这篇文章差点写到浏览器卡死...... 下一篇帖子估计要等到一年半以后了。(初二下和初三应该没时间再来研究逆向这种耗费时间的东西了。)

一些提到的软件的链接:(解压密码全部为dsong@52PoJie.Cn)
1. Numega SmartCheck:
链接: http://pan.baidu.com/s/1qWzAlqc 密码: 2oh1

2. DotFix VB Decompiler:
链接: http://pan.baidu.com/s/1i3L3jvR 密码: bf8v

3. WKTVBDebugger:
链接: http://pan.baidu.com/s/1bnF9KV9 密码: ikce

4. Timer's Keygen:
链接: http://pan.baidu.com/s/1ntolbKl 密码: ilal

免费评分

参与人数 47吾爱币 +8 热心值 +46 收起 理由
wei5383079 + 1 + 1 热心回复!
XiroNeko + 1 + 1 谢谢@Thanks!
海洲光电 + 2 童鞋毕业没有?找工作联系我
Rude + 1 + 1 已答复!
汪锴锴 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
liushuaijie123 + 1 + 1 我很赞同!
海天一色001 + 1 + 1 谢谢@Thanks!
kitefall + 1 我很赞同!
qwerttqqaz + 1 已答复!
hanna518 + 1 谢谢@Thanks!
wq999999 + 1 谢谢@Thanks!
daohang + 1 谢谢@Thanks!
speedboy + 1 谢谢@Thanks!
Mrxn + 1 不错不错 看完了
zeu0d + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
vigers + 1 我很赞同!
125733578 + 1 热心回复!
li1314li + 1 我很赞同!
aricyoung + 1 谢谢@Thanks!
chenhuanlin + 1 我很赞同!
盈盈一水间cc + 1 谢谢@Thanks!
linzi + 1 值得学习啊
寻梦的人 + 1 收藏了慢慢看
Mister_小牛 + 1 热心回复!
myqqq + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
tlld1234 + 1 先留住
tmsdy + 1 我很赞同!
Jacve + 1 楼主好厉害啊,看得我眼花缭乱
1185004936 + 1 谢谢@Thanks!
小生我怕怕 + 1 好文章啊,一定得拜读下
大风车 + 1 我很赞同!
杜锋2015 + 1 谢谢@Thanks!
17452214 + 1 热心回复!
wanttobeno + 1 我很赞同!
影子幽 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
逍遥枷锁 + 1 谢谢@Thanks!
红绡枫叶 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩.
逆袭撸破 + 1 我这里有个VB的牛软件,搞了半个月没有头绪.
zeromaggot + 1 谢谢@Thanks!
晴非得雨 + 1 还在读初二的孩纸,真厉害!
Passerby + 1 牛人,膜拜中
双菜鱼 + 1 谢谢大牛,又涨知识了··好犀利
蚯蚓翔龙 + 1 谢谢@Thanks!
凌云9 + 1 谢谢@Thanks!
XhyEax + 1 我很赞同!
kian + 1 热心回复!
bigharvest + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zeromaggot 发表于 2015-2-10 20:14
果然非常长,还是收藏了慢慢看吧
chornam 发表于 2015-2-10 18:44
期待有大神和楼主交流讨论,也好我从中学习一二。
头像被屏蔽
wanxia 发表于 2015-2-10 18:42
卿少~爱装逼 发表于 2015-2-10 18:15 来自手机
什么也看不到。。。。。
Hmily 发表于 2015-2-10 17:18
dsong最近几篇文章科普性技术性极高,感谢分享,加精鼓励,已经获得3篇精华贴,自动获得大牛认证勋章!

点评

十分感谢鼓励和关注!  发表于 2015-2-10 17:28
Avenshy 发表于 2015-2-10 17:22
感谢大神 刚刚全部看完了才回复的
蚯蚓翔龙 发表于 2015-2-10 17:23
{:1_903:}学习了,多谢。。虽然有点长
29565633 发表于 2015-2-10 17:26
高手的文章,一定要好好看看,很长知识的.
小楠 发表于 2015-2-10 17:27
其实我很想看完,但是太长了。真的太长了,这让我正在学习c++的人觉得,我的c++的人生才刚刚开始!
qwe86453242 发表于 2015-2-10 17:40
现在还不太懂  先收藏吧
XhyEax 发表于 2015-2-10 17:43
写得好!给楼主一个赞,不过太长没看完,先收藏了
凌云9 发表于 2015-2-10 17:45
前来膜拜大神的
双菜鱼 发表于 2015-2-10 18:02
谢谢大牛,虽然不懂编程,但依旧涨了好多知识{:1_931:}真心膜拜
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-27 07:08

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表