对于逆向破解而言,一般分为三个层次: 第一层次:能爆破。新人们只要能找到关键跳,改一下跳转命令就可以了。 第二层次:追真码。需要逆向者要读懂代码,能够发现真码出现的位置。 第三层次:逆算法。需要逆向者要读懂算法,真正了解验证的机制。 当然,对于新人们而言,当下主要的目标就是能爆破。 只要能快速的找到核心代码的位置,找到关键CALL和关键跳就是胜利! 当你有了一定的爆破能力,就不会再满足只停留在第一层次了。 你也想向一些“高手”看齐,可以找到真码,可以弄个注册机。 呵呵,把你的注册机发给朋友,是不是更有成就感? 今天,我就和大家一起来共同提升一下层次,弄个注册机玩玩。 本节课,我们用的是吾爱论坛上的一个CM,软件我放到附件里。 感谢CM作者的付出。 见下图: ![]() 下面我们就一起玩玩吧,“LET's GO”! 我们先用DIE64查一下,见下图: ![]() 这个软件加了UPX的壳,很简单,大家用UPX专门的脱壳工具就搞定了。 然后我们先把软件拖进OD,运行看看情况。 见下图: ![]() 当我们输入用户名和密码后,会出现一个错误信息框。 呵呵,我们有点兴奋了。 我们可以考虑几种办法进行下断: 1、搜字符串 2、对MessageBoxA下断。 3、F12暂停法 4、对GetWindowTestA或者GetDlgItemTextA下断。 这个软件比较简单,很容易就定位到关键位置。 所以,大家不要怕不是易语言的程序, 无论什么语言编写的,通用的方法是搜字符串、F12暂停法、API断点。 尤其是API断点,99%是可行的,前提你必须熟悉API函数。 关键代码的位置,见下图: ![]() 今天,我们要换个花样玩。 我们不直接爆破, 你这次要从上面的代码一句一句的跟下来。 可能你会比较为难,因为要读懂每一句代码是不容易的。 别着急,我们有办法。 我们的办法就是“挑着看”。 挑什么样的代码来看呢? 呵呵,我们就来个“三大注意”。 第一,要注意每一个CALL的返回值。 我们都知道,CALL的返回值主要是放在EAX里, 所以,你F8单步路过CALL以后,你就看一下寄存器EAX的值,然后在CALL后面备注一下“返回值==***”。 比如下图: ![]() 在经过红色、绿色箭头指的CALL后,在寄存器EAX里会依次出现你输入的用户名、假码的长度。 说明一下:GetDlgItemTextA函数是取出输入框里的文本并转换为整数,读取到的值放在BUFFER后面的地址里, 你在数据窗口就可以看到你输入的用户名和假码。 第二,要注意用户名做参数和假码做参数的CALL。 如果是用户名做参数的CALL,一般是这样: PUSH 用户名 CALL ****** 如果是假码做参数,一般是这样: PUSH 假码 CALL ****** 我们为什么要注意这样的CALL呢? 你想想看,软件一般的验证机制是不是这样? 程序会根据你输入的用户名计算出一个真码,然后用这个真码和你输入的假码进行比较。 如果相等就走上成功之路,如果不相等就步入失败。 我们也可以换成数学公式表达。 假定:y代表真码,x代表输入的用户名,z代表假码。 程序首先执行y=f(x);f就是算法函数,x是参数。 然后K(y,z)=0(或者1),K是验证函数。 在我们OD里这个f和K就是某一个CALL。 在汇编语言里,函数的参数主要是通过PUSH命令入栈。 所以当你看到 PUSH 用户名 CALL ****** 这个CALL很可疑,所以要特别关注这样类型CALL的返回值。 可能是取用户名的长度,也可能就是计算出真码或者与真码有关的字符串。 比如: ![]() 红色箭头指的004012F6就是PUSH 用户名,所以下面的CALL要关注。 这个CALL是系统的API函数,是计算出用户名的长度。 再比如: ![]() 0040132F push 0x403138 这句就是假码做参数,下面的CALL就非常关键。 你CALL完后,看EAX的值,会发现是把假码转换为十六进制。 下面的40133A cmp eax,esi 就是把转换为十六进制的假码和ESI的值进行比较。 如果相等,就弹出正确的弹窗。 可见,ESI的值转换为十进制后就是真码。 第三、要注意假码和一个可疑的字符串一起做参数的CALL。 这种类型在汇编里就是这样: PUSH 假码 PUSH 可疑字符串 CALL **** 也就是我们上文说的K(y,z)=0(或者1),K是验证函数。 大概率来说,这个CALL就是对真假码进行验证的CALL。 如果是易语言程序,你会发现这个CALL里面就是我们用文本比较通杀命令(test edx,3)定位的CALL。 这次的CM不是易语言编写的,也没有使用专门的CALL来验证。 只是通过40133A cmp eax,esi 这句代码直接进行比较了。 很多软件会使用专门的CALL来进行验证。 特别提醒: 有些软件进行伪装,不直接用PUSH 假码 和PUSH 可疑字符串,而采取PUSH 加密(假码)和 PUSH 可疑字符串 作为参数。 比如是这样的:K(加密(y),加密(z))= 0(或者1) 所以,你要在前面备注好哪个可疑字符串是用户名运算得来的,只要是这个可疑字符串做参数就要值得警惕。 以上,我们主要和大家一起来学习了如何简单快捷地分析代码。 因为我们新人朋友们还没有能力去分析具体的算法,所以只要按照以上“三大注意”去备注和分析代码就可以了。 至少,你分析完后,就知道软件的主要验证流程以及真码出现的位置了。 好了,我们别停,继续。 我们今天的任务是做一个简单的注册机。 我们刚才已经知道了一个重要的事实: 如果我们在40133C下一个断点,当软件断下的时候,ESI里存放的就是真码的十六进制。 好,已经够用了。 我们可以使用一个软件来完成我们的注册机的制作。 软件在吾爱破解的“爱盘”里。 见下图: ![]() 软件打开后,见下图: ![]() 你点红色箭头指的“其他”,选择里面的“内存注册机”,然后按下图进行设置: ![]() 这里要说明的是: 中断地址就是我们要下断点的地址40133C, 40133C的硬编码是75 15,所以第一字节填75,总共有两个字节,指令长度填2。 我们知道ESI里存放的是十六进制的真码,所以我们选择寄存器方式ESI,十进制转换,就可以得到真码了。 呵呵,会了吗? 生成后,你把注册机存放在CM的目录里,我们看看生成后的效果。 ![]() 注册码出来了。我们试一下: ![]() 呵呵,破解成功,我们有了自己的小白注册机。 学会了吗? 从今天开始,你也可以制作自己的注册机了。 给自己一个点赞吧! 如果您觉得我发的内容确实对您有所帮助,请麻烦您支持一个热心值,进行精神鼓励,也是我继续写下去的动力! |