Welcome My Friend

Crack007

Crack007-aLoNg3x.2

关于题目

  • 此题和上题很相似,但是具体内部实现是不一样的,而且本题的目标是写出注册机。同样的这个程序是用Delphi写的,无壳,程序隐藏两个按钮才达到破解,首先输入用户名和序列号,点击register,如果正确,register按钮隐藏,会出现一个again按钮,两个按钮全部隐藏既破解成功,另外有个about按钮,点击会弹出四个form,只是一些说明和提醒,还有一个cancella按钮,用于将序列号清零,当你输入的序列号不为纯数字的时候会跳出提醒,当输入序列号为0时也会弹出提示框。下面为程序初始状态:

Crack013

Crack013

Crack013

Crack013

解题思路

借助DelphiDecompiler找到各个事件入口地址,用OllyDBG动态调试程序,在事件入口打断点,然后单步分析指令,分析逻辑关系,找出主要算法,写出注册机。

题解过程

  • 用DelphiDecompiler打开exe文件查看各个按钮事件的入口地址并在下地址下断,事件后就为入口地址:

Crack013Crack013Crack013Crack013

  • 单步调试,查看算法,先查看register事件,输入用户名:qwer12,序列号:123456:

Crack013

由于之前在register事件入口下断,所以程序会停在register事件入口,这时单步F8向下调试,

Crack013

到这里可以看到,这个je跳过了提示框以及下面三个call,说明输入符合要求。继续F8运行,

Crack013

到上面一步,这个跳转跳过了隐藏register按钮和显示again的关键call,按下esc往上一步看,test里面al的值决定这个跳转,再往上看,test上一条指令,call aLoNg3x_.00442FF2,很有可能这个call里面就有关键的算法,单步F7进去查看算法,

Crack013

F8单步到这一步的时候,可以看到一个关键的跳转,JNZ跳过了一句赋值语句,让bl为1的赋值语句,然后继续F8,当跳出函数,回到上图test语句的时候,这时al为0

Crack013

将上一步的JNZ指令nop掉,让bl直接为1,可以看到,al的值也为1,并且register按钮隐藏,again按钮显示出来,再点击一下again按钮就破解成功了,如下图:

Crack013

Crack013

Crack013Crack013

通过上面分析可以判断,上面图中,JNZ上一步的cmp为关键判断,这条指令比较的是寄存器EBX和ECX里面的值,再往上分析,去寻找EBX和ECX的算法。重新运行一下程序,然后单步进入关键call,从建立栈帧开始单步往下分析,下图所示,通过call取出用户名长度存在EAX中,然后通过cmp判断输入用户名是否合法,这里的限制条件是用户名必须大于4位。

Crack013

继续往下调试,可以看到有两个循环

Crack013

这里执行的算法是:

内层循环中,开始取输入的用户名的第一个字符和最后一个字符相乘,然后再与edi相乘,结果存在edx,最后将ebx与edx相加后结果存在ebx,比如上面例子中,输入用户名为qwer12,那么第一次就是字符q的asc码与字符2的asc码相乘,然后与edi里面的值相乘,最后加上ebx里面的值结果存在ebx。

因为esi第一次赋值为1,在内存循环中不变,所以在一次外层循环中,edx始终保持不变,对于外层循环来说,外层循环一次,等于输入用户名的一个字符依次乘用户名的所有字符,并乘edi,求和之后保存在ebx。

这里执行的时候上面有指令将ebx置0,那么变量只剩下edi了,程序调试中,edi始终为0,这就导致最后结果一直为零,关键判断不相等,跳过将bl置1的指令。所以需要寻找到edi的赋值指令,往上会看到

Crack013

这条指令将eax的值给了edi,而前面的语句没有提及eax,所以要回到call外面去找,重新点击register,程序断下之后寻找eax赋值指令

Crack013

在关键call上一条,将地址0x445830的值赋给eax了,但是这时这地址里的值为零,这时要寻找给这个地址赋值的指令,往上可以看到一条,mov dword ptr [0x445830],
eax,但是这条指令被上面判断序列号是否合法的跳转语句跳过了,再往上找不到操作这个地址的指令了,可以判断,在mov dword ptr [0x445830], eax指令上一条call指令,很有可能包含eax的算法,分析这个call,可以找出eax的值。输入一个不合要求的序列号,带字母即可,单步进入这个call,进行分析。

Crack013

Crack013Crack013

上图输入不是数字的序列号,顺利进入到赋值语句之前的关键call里面,图中有一条指令cmp eax,0x5,这条指令要求输入序列号必须大于五位,所以这里的cmp置Z标志位为1,跳转指令跳过了关键算法,重新输入序列号,重新进入,分析主要算法。

Crack013

这里算法只有一个for循环,刚开始将序列号长度取出存在eax,并将其赋给ebx,作为控制条件,然后取出序列号的第二个字符除以0x11的余数存在edx,然后再加一,取出序列号第一个字符与edx相乘,这算一次循环,下次操作第三个字符和第二个字符,循环五次,最后的结果加上0x37B。接着分析下面算法:

Crack013

计算的结果存在eax中,然后结果除以0x7148,结果存在eax,余数存在edx,然后将结果转存在ebx,最后又将ebx的值返还给eax,计算的结果暂称为因子,因子的计算解决了对图十二分析时所遇到的问题,但这里要输入不合法字符串才能计算。接下来继续分析图十分析之后的算法:

Crack013

首先将计算的结果存在eax,,然后对0xA2C2A进行取余,结果存在ebx,然后用输入的序列号除0x59,商保存在ecx,输入的序列号再对0x50取余,结果加上之前的ecx,最终结果再加一,然后和ebx值相比较,如果相等,则jnz不会跳转,bl的值会等于1,这时候,再回到这个call之外,将不会再将隐藏register按钮和显示again按钮的指令跳过,会执行,也就破解成功一半,again按钮的计算方法和register按钮就算方法一样,所以只要执行一遍对register按钮的操作,again按钮也将隐藏。

Crack013

  • 编写注册机

上面细致分析了算法,接下来就是根据算法编写注册机,下图为注册机界面:

Crack013

在计算注册码的时候会生成多个,所以可以随机选择。

特别说明:(1).在计算的时候,如果用户名字符串输入过长,或者长度小于6,都是属于不合法的用户名。输入过长的话,计算的时候,因为寄存器为32位,所以结果很可能溢出造成错误。经过测试,如果输入用户名为6个纯字母,结果溢出,所以用户名最好以数字和字母配合,而长度大于6位,很大几率造成溢出,如果选取asc码值比较小的符号当中用户名的话,情况会好一些。(这些可能是程序本身造成的限制)

(2).验证注册码是否正确的步骤应该是,随机填写用户名和注册码(这个注册码一定为不合法的注册码,也就是不要全为数字,这样edi的值才不为0),点击register键,出现提示框点掉,然后用注册机生成注册码,将生成的注册码重新填入程序,点击register,这时候register会消失,然后重新做一遍上述操作,again也会被隐藏,破解成功。

下图为随机验证:

Crack013Crack013Crack013Crack013Crack013Crack013

破解之后会出现Cracked by casa63.

另外补上注册不成功的截图:

Crack013

补充-OllyDBG破壳

用OD加载进去之后,先F8单步运行一下,然后看见右边ESP字体是红色的,右键ESP在数据窗口跟随,这时候右键左下方的地址后面的十六进制码,选择long,然后address,然后选择esp那里作为断点(硬件访问->word),(然后这种方法不可行)

另一种方法:使用UPXEasyGUI去壳,scan文件夹,option一下是加壳还是脱壳,然后点击开始,再用pied查壳发现没壳了

-------------本文结束-------------

文章作者: Summary
文章链接: http://noblestaspiration.net/2018/04/13/Crack007/
版权声明:博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议,转载请注明出处!

想要分我一杯羹吗