下面是网上的160个CrackMe的部分逆向笔记,包括逆向思路、注册机实现和逆向中常用的知识整理
注意:逆向前一定要先操作一下软件,熟悉软件的运行现象;逆向一定要自己操作一遍,看是很难看会的(高手除外)
1.基本信息
CrackMe033和CrackMe034都是《使用OllyDbg从零开始Cracking》第九章的案例
2个程序都是汇编写的,没有壳
题外话:开始入门时看的就是《使用OllyDbg从零开始Cracking》,这个文档很适合入门,当时还对着操作了一遍,但是这次逆向居然不记得以前学过了,重复操作浪费时间了,因此有2点后续一定要注意
1.一定要自己逆向出来,即使参考别人的也要自己操作一遍
2.逆向思路写出来
逆向可能半个小时,写笔记有可能花3倍甚至更多时间;看似浪费时间,但是写笔记实际上思路的整理过程,也方便后续自己复习
说了些废话,看CrackMe033的程序吧,随机输入注册码,注册,程序会弹出错误提示框(关闭错误提示框还会再弹一次)
下面都是常规操作:
一看到错误提示框,就喜欢迫不及待的搜索一下字符,呵呵;根据提示框错误字符串,找到2个错误字符串被引用的位置
查看汇编代码,发现上面的2个字符串被2个MessageBox引用,正好对应上程序会弹出2个错误对话框
程序基本信息就这么多,剩下的就是分析一下2个错误对话框的调用函数,干就完了
2.第1个错误对话框
先分析第一个错误提示框所在函数,起始地址是0x40137E
,IDA中的反编译分析如下
为了不调用错误提示框函数,一定要在第11行
处返回;正确注册流程要经历如下:
-
1.对用户名每个字符初步处理
要求
:不能小于'A'
,超过'Z'
,要减小32(如果是字符相当于变成大写)提示
:最简单的用户名直接全是字母就一定不会有错,下面是用户名经初步处理的结果示例截图[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HsrVE7aU-1653875572246)(…/…/图片/image-2022041214640.png)]
-
2.所有字符的ASCII值相加,结果与
0x5678
异或注意
:本程序的很多函数调用约定不是平时常用的stdcall
等形式,因此函数结果不一定保存在eax
中举例
:sub_4013C2
函数作用是参数指定的字符串中所有字符的ASCII相加,结果存入edi
sub_4013C2
:累加结果全部存入V1
,即存入edi
中sub_40137E
:调用完sub_4013C2
函数,紧接着操作a2
,这个a2
是edi
寄存器,即sub_4013C2
函数的计算结果
至此,分析完第一个对话框所在函数,其实就是对用户名一顿操作
3.第2个错误对话框
IDA反编译地址0x401362
,发现实际上在WndProc
函数中;下面是结合调试后得到的最终分析结果
解析如下:
-
位置1:第1个错误对话框所在函数,已经分析过了,主要处理用用户名
-
位置2:用户名处理逻辑,下面是分析结果
作用
:序列号字符串转成数字形式,然后与0x1234
进行异或细节
:反编译窗口居然看不到与0x1234
进行异或,导致验证自己猜想时浪费了一点时间,但是反汇编窗口可以看到
Hex-Rays插件介绍
参考:《ID Pro权威指南》23.1 Hex-Rays 章节,自己进行了修改
Hex-Rays是一个反编译器插件,能够生成
类似C语言的伪代码
由于编译过程中会丢失一些信息,因此反编译很难百分百还原C语言格式,会看到更多的goto语句
不建议过于依赖 Hex-Rays,与对应的汇编代码相比,C 源代码确实更具可读性,也更加简明,但反编译并不完美(上面出现问题就是一个例子)
- 建议:对照基础汇编代码来验证你通过阅读 Hex-Rays 伪代码得出的任何结论
- 注意:虽然 Hex-Rays 可用于处理用 C++代码编译的二进制文件,但它只能生成 C 代码,并且生成的代码缺乏任何特定于 C++代码的特性
扩展:llvm在github上非常流行,简单理解就是一个开源的编译器,clang和mlir就是基于llvm的,支持基本100%的反编译,反汇编,如果有时间可以研究一下里面自己感兴趣的地方
- 位置3:用户名和序列号的处理结果进行比较,都相等就认为注册成功
4.验证猜想
上面分析汇总
-
对用户名处理
- 1.不能小于
'A'
,超过'Z'
,要减小32(如果是字符相当于变成大写) - 2.所有字符的ASCII值相加,结果与
0x5678
异或
示例:用户名
testaaa
,初步计算变成TESTAAA
,所有字符的ASCII值相加变成0x203
,再异或上0x5678
得到0x547B
- 1.不能小于
-
对字符串处理
序列号字符串转成数字形式,然后与
0x1234
进行异或示例:直接用用户名反推需要的序列号序列号,
0x547B^0x1234=0x464F=17999
下面是验证结果,说明分析是正确的
5.注册机
提示:验证时发现,用户名长度超多10的部分在内存中直接被截断了,估计是获取控件函数干的,不研究了
输入用户名:CrackMethisistest
,内存情况中用户名情况如下:
修复一下用户名长度,得到的简单注册码如下:
#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char name[100] = {0};
int res = 0;
printf("请输入用户名(字符要的ASCII码>='A'): ");
scanf_s("%s", name, 100);
//用户名处理
int len = strlen(name) >= 10 ? 10 : strlen(name);
for (int i = 0; i < len; i++) {
if (name[i] > 0x5A)
name[i] -= 0x20;
res += name[i];
}
res ^= 0x5678;
//反推序列号
res ^= 0x1234;
printf("计算的序列号: %d\n", res);
system("pause");
return 0;
}
验证结果:
6.参考
- 1.常用软件可以在这里下载:爱盘 - 最新的在线破解工具包 (52pojie.cn)
- 2.【反汇编练习】160个CrackME索引目录1~160建议收藏备用
- 3.160个Crackme_鬼手56的博客-CSDN博客
- 4.《使用OllyDbg从零开始Cracking》系列的文章也不错