一、准备
工具:OllyDbg
软件:Acid burn.exe
二、破解
1.运行程序,查看程序功能
打开程序后会先发现弹出了一个对话框
点击确定后出现如下界面:
左边要求输入是用户名和序列号,而右边仅仅要求输入序列号
随便输入看看错误信息,如下:
2.用OD打开程序
先从较为简单的序列号入手,在反汇编窗口右键选择中文引擎搜索一栏中的智能搜索,找到之前的错误信息“Try Again!!”,发现有三个,依次点进去查看。
定位到第一个try again,发现在错误信息之上便是成功的信息。再之上有个跳转的指令jnz,很明显它控制最后信息的显示,将这个指令用nop填充即可实现显示成功信息。
然后可以想到在这之上应该会有个函数接收用户输入的序列号和正确的序列号比较,于是我们再往上找,找到过程的起点设置断点。
按F9运行程序,点击确定后,点击右侧按钮,然后点击check it.程序运行到到断点处停下。按F8单步运行。前面几行代码建立栈帧并将eax置零。之后将Hello与Dude字符串中间加个空格然后拼接成Hello Dude。
此时栈中的情况如下:
接着运行到下图位置:
这两行代码将局部变量3、4分别传给edx和eax,然后调用了一个过程。到栈窗口中查看发现这两个局部变量分别为我们输入的和Hello Dude,这为两个参数,调用函数之后便紧跟跳转语句,再之后便是成功信息和正确信息。可以猜测Hello Dude为正确的序列号。经过验证可以发现正确。
接着分析第二个try again.定位到其位置。
往上找,找到过程的起点设置断点,并将程序运行到断点。
之后按F8单步运行,之后的代码是一系列计算,先不管它,往下找,直到出现分支。
发现是与4比较,之上的函数调用前将输入的name传入,返回的eax为0x19,恰好为字符串的长度,说明这是在判断长度是否大于等于4.
那么第三个try again对应的应该是name/serial,猜想大致是利用输入的用户名计算序列号然后和输入的序列号对比,判断是否正确。
同理,只要将上面的跳转语句用nop填充便可实现破解。
三、serial计算的简单分析
在之前发现的判断字符串长度是否大于等于4的后方设置断点,单步运行。
之后这一段代码将输入的用户名(我输入的是12345)的第一位取出,乘以一个常量0x29,然后再与自己本身相加(相当于乘以2),得到0FB2,存放在0x431750处。之后是将CW、-、CRACKED放入栈。
接着运行,会发现在这一步出现了4018这个数。4018是0FB2的十进制写法,说明这是十六进制转十进制。
接着往下看,可以发现最后产生了如下结果:
然后CW-4018-CRACKED被用来与输入的序列号比较,说明其为正确的序列号。
那么生成序列号的方法也清楚了,就是将Name的第一位乘以0x29然后乘以2,转化为十进制与CW、CRACJED、-拼接得到。
总结
这是我第一个crackme的练习,所以写的有点啰嗦。主要目的是记录并且复习一下学习的过程。