共计 3029 个字符,预计需要花费 8 分钟才能阅读完成。
作者:逆向驿站微信公众号:逆向驿站知乎:逆向驿站
crackme007, 是 006 的升级版,程序开发者给出的难度是 3 星,可能是迷惑有点多?个人觉得条线还是比较清晰,难度也不大,依然适合新手
准备
【环境和工具】
win7/xp 虚拟机环境
CrackMe007(aLoNg3x.2.exe)
ollydbg
Dededark
【学习层次】
逆向分析程序验证流程逻辑
解密算法,写注册机
积累 Delphi 程序逆向特点经验
实战图文
最终效果展示
程序验证流程逻辑图
动态分析
1. 程序观察 crackme006 的升级版,最终目标是一致的,均是要求给下方的蓝色 logo 无遮盖的显示出来,也就是说要给这个区域的控件全部隐藏,程序界面如下图
同时可见开发 crackme 的和学习 crackme 的目标和标准是一致的,path 的方式是不被认可的,即不可爆破,crackme 若是个美貌女子,则应征服其心,切不可霸王硬上弓。
2. 控件 ID,事件函数信息依然老规矩,既然是 delphi 的程序,我们就先用 dededark 给控件信息和事件函数信息搜集出来
3. 控件 ID 常量搜索法,打开入手点程序开始只有一个 Register 按钮,对应上图,其控件 ID 是 2CC, 那么我们依然就从 2CC 常量出发查找→所有常量→2CC(Register 按钮控件 ID),结果如下跟入第一个,根据之前的对 dephi 程序逆向的经验,应该可以一眼看出,这里的反汇编代码,功能是:dl 的值 0 是隐藏,1 是显示,如下图可以看出,若是程序如期执行到这里,则隐藏 Register 按钮,并显示 Again 按钮,那么我们在这个代码的函数块入口处下断点,来动态分析这个函数块的逻辑流程,如下图可以看到,这个函数实际就是点击 Register 按钮的事件函数,首先会对 code 进行验证,若是纯数字则跳到下方,否则弹框报错,并给 [0x445830] 赋值,看似多此一举,实则是必须过程,原因后面会提到,如果输入的是纯数字,则执行以下流程,如图在这里我们看到了算法函数,算法函数需要三个参数(用户名、code、[0x445830]的值),算法函数若是合规,则隐藏 Register 按钮,显示 Again 按钮。那么我们就 F7 跟入算法函数去研究算法
4. 分析算法在分析算法前,需要对 [0x445830] 这个全局变量值做一个说明
初始值是 0
经过动态分析(请自行动手)得出,对它赋值的触发条件是,需要 code 输入至少 6 个英文字母,然后点击 Regsiter 按钮
输入 AAAAAA,它会被赋值固定值 0x1686
既然是这种输入输出都可控的全局变量值,我们就不去纠结其算法什么的了,当然如果你想去研究分析,那也是值得提倡得
然而为什么非得多此一举得对他赋值呢?因为后面得核心算法中,它的值将作为一个乘数,若是 0 的话,那么算法的最终结果无论如何都会是 0,0 是无法完成算法合规的,简单的说,若是这个值是 0,则不可能完成注册,所以要对他进行这种看似多此一举的隐藏赋值。是不是类似开启隐藏奶牛关,呵呵!
后面得所有分析中我们都按照,code 输入 AAAAAA 后 [0x445830] 被赋值 0x1686 为准
我们来分析算法,如图可见核心算法是
首先要求用户名要大于 4 个字符,为了防止溢出,我写的注册机就硬性规定为 5 个字符
根据输入的用户名,经过两次嵌套循环,和 [0x445830] 的值,即我们控制其值为 0x1686,共同计算出一个值,暂时记为 nTemp
nTemp = nTemp % 0xA2C2A
第二次输入的注册码要求是纯数字,纯数字作为 10 进制的数字型值,记为 nCode
则公式是 nCode/0x59+nCode%0x50+1 = nTemp
这种不是摘要 hash 的,是直接可以逆推计算出注册码,根据以上分析,写出逆推注册码的源码,如下
//code 输入 AAAAAA 给 [0x445830] 赋的值
int nKey = 0x1686;
char szRes[1024] = {0};
char szName[32] = {0};
int nCode = 0;
int nTemp = 0;
GetDlgItemText(IDC_EDIT1,szName,31);
if (strlen(szName)!=5)
{
MessageBox(“ 请输入 5 字符长度的字符串 ”,” 逆向驿站提示您 ”);
}
else
{
// 根据 name 字符串计算
for (int i =1;i<=5;i++)
{
for (int j =5;j>=1;j–)
{
nTemp = nTemp + (int)szName[i-1] * (int)szName[j-1] * nKey;
}
}
}
// 取模
nTemp = nTemp%0xA2C2A ;
// 反推 code
nCode = (0x50 – ((nTemp -1)*0x59 % 0x50))+(nTemp-1) * 0x59 ;
sprintf(szRes,”1. 把注册机的五字符长度用户名输入 nome 处 \r\n\r\n”);
sprintf(szRes+strlen(szRes),”2. 请在 code 处输入 AAAAAA, 然后点击 Register 按钮, 弹框确认关闭即可 \r\n\r\n”);
sprintf(szRes+strlen(szRes),”3. 请在 code 处输入 %d, 然后点击 Register 按钮 \r\n\r\n”, nCode);
sprintf(szRes+strlen(szRes),”4.Register 按钮消失,again 按钮出现 \r\n\r\n”);
sprintf(szRes+strlen(szRes),”5. 请再次在 code 处输入 AAAAAA, 然后点击 again 按钮, 弹框确认关闭即可 \r\n\r\n”);
sprintf(szRes+strlen(szRes),”6. 请再次在 code 处输入 %d, 然后点击 again 按钮, 按钮消失, 注册成功 \r\n\r\n”, nCode);
SetDlgItemText(IDC_EDIT2,szRes);
crackme 注册机的完整源码均在网盘
5. 分析 Again 按钮事件函数我们现在已经成功的隐藏了 Register 按钮,但是又出来了一个 Again 按钮,有了如上的过程作为经验,我们 ” 依葫芦画瓢 ”, 对 Again 按钮进行分析,结果发现,其实验证流程完全是重复了一遍 Regsiter 按钮,Again 按钮点击事件逆向代码如下
可以看到,给 [0x445830] 赋值的隐藏算法和最后的合规核心算法,均自动显示出来了中文标签,这就是习惯做标签的好处,之所以会显示出来,那证明跟上方的 Regsiter 部分的两个算法均调用的相同的算法函数,参数相同,算法相同,那么结果一定相同了。所以 Again 按钮消失的方法是跟 Register 一模一样的,只是他消失后,不再显示其他按钮而已,至此注册成功,Crackme007 的标题也温顺的变成了 Crackme by “your name” 了。
是不是有如开头所说的征服美女的快感?去网盘中下载,试试吧
文章中涉及软件、课件、源码等均在网盘,为避免网盘链接失效,公众号中回复:网盘
欢迎关注微信公众号:逆向驿站
相关文章
● CrackMe-006 精解
● CrackMe-005 精解(下)
● CrackMe-005 精解(上)
● CrackMe-004 精解
● CrackMe-003 精解
● CrackMe-002 精解
● CrackMe-001 精解
标签:逆向 | 破解 | 反汇编 |olldbg| 渗透测试 | 病毒分析 | 网络安全 | 区块链本期标签:dededark|delphi 反汇编 |crackme|crackme7|crackme07