共计 959 个字符,预计需要花费 3 分钟才能阅读完成。
Crackme017 的逆向分析
1. 程序观察
还有一个 Readme,大概意思是说希望我们找到正确的序列号,还说正确的序列号不会出现内存中。
2. 简单查壳
使用 VB5 编写的,没有壳。
3. 程序分析
使用 OD 载入程序,搜索字符串,点击跟进代码
可以看到不远处就有一个比较语句,下断点,运行程序,程序断在了断点处
修改 ZF 标志位,继续运行程序,程序提示成功
可以看出,刚才的比较处是程序的关键。
再次运行到断点处,查看函数的参数
可以看到,程序有两个参数。一个参数是 0,还有一个参数是 FFFF。
继续观察代码,发现上面有一个赋值的代码
正是这行代码,将参数 2 的值变为了 FFFF。
我们大胆猜测,FFFF 是正确的标志。
将参数 1 的值也修改为 FFFF,程序提示正确。
来到代码头部,下断点,点击 check 按钮,程序就断了下来
向下调试代码,发现程序居然出现了一个新的提示
再查看上面的代码,程序先使用了循环浪费时间,然后使用循环结束的时间减去循环开始的时间,如果时间过大,就判断程序正在被调试,就会弹窗提示
然后程序进行长度检测,如果长度小于 5,就会直接提示错误
接下来程序会根据序列号的长度建立一个循环,循环的次数为序列号的长度
在循环中,程序依次比较每个字符是否和后一个字符是否相同
如果字符和后一个字符不相同,就进入下次循环;如果相同,就会在内存 0012F558 处加 1
然后在后面和序列号长度减去 1 作比较,如果相同,则跳转到错误提示处
也就说序列号不可以全部为同一个值,比如说都是 1。
接下来,又是一个循环
程序求得序列号的长度,然后转化为字符串
然后得到序列号最左边的字符,最后也转化为字符串
最后调用函数,将两个数相乘,也就是将 序列号的长度和序列号第一个字符的 ASCII 值相乘
接下里,程序依次将序列号相加
循环结束,程序将相加的结果和相乘的结果进行比较。如果相等,则返回 FFFF;不想等在返回 0。
在最后再和 FFFF 进行比较,相同说明正确。
4. 注册机
程序对序列号的要求有以下几点:
- 不能少于 5 位
- 不能全部相同
- 序列号首位和长度的乘积要等于序列号各位相加的和
本来是想写注册机的,但是我发现了一个有趣的规律,所以就不用写注册机了
当序列号是五位数的时候。序列号首位随便填一个值,然后在 ASCII 码表上找到该值相邻的上面 2 个值和下面 2 个值,就是一个可以使用的序列号。
相关文件在我的 Github