CrackMe007:if和else都要执行?

本文详细记录了对CrackMe007程序的逆向分析过程,从现象观察到注册机编写。通过分析Delphi语言编写的程序,发现注册按钮的隐藏关键在于逻辑A和逻辑B。爆破时需进入逻辑B,而编写注册机则需确保逻辑A执行以获取g_KEY。逆向过程中,重点解析了函数C的密码和用户名处理逻辑,以及逻辑A中g_KEY的计算方法。最终,通过这些分析实现了注册机的编写,并验证了其正确性。
摘要由CSDN通过智能技术生成

下面是网上的160个CrackMe的部分逆向笔记,包括逆向思路、注册机实现和逆向中常用的知识整理

注意:逆向前一定要先操作一下软件,熟悉软件的运行现象;逆向一定要自己操作一遍,看是很难看会的(高手除外)

这个程序和CrackMe006是同一个作者,可以理解成是CrackMe006的升级版,难点是if {A} else {B} 流程中{A}{B}都要执行一次,后面会说明为什么都要执行

在这里插入图片描述

1.现象

对比会发现这个程序只需要使注册按钮隐藏即可(实际上隐藏完注册按钮还会有其他按钮显示出来,这个在开始逆向时不用关心)

在这里插入图片描述

2.程序基本信息

CrackMe006一样的方法,发现程序使用Delphi语言编写,无壳

针对这个程序,寻找注册函数有2种方法:

  • 1.字符串方式:这个程序密码不输入或者输入全是数字,会有对话框弹出错误原因,根据对话框里面的字符串在OD中很容定位到注册函数

  • 2.用工具Darkde4分析程序,可以直接定位到注册函数(优先推荐这种方式,更通用

下图是用Darkde4分析的结果的部分截图,主要是找到按钮关联的事件和RVA

在这里插入图片描述

可以看到程序实际上有4个按钮,按钮和响应事件的对应关系已经标识出来

建议:分析注册按钮前有2点建议,这2点建议也适用于逆向其他程序

  • 建议1:充分利用IDA

    如果使用OD作为主力软件分析程序:分析前用IDA加载程序,然后保存MAP文件,OD再加载MAP文件进行分析会提高效率

  • 建议2:先爆破程序,再分析注册机

    逆向程序时,要重点关注跳转语句,可以修改相应标志位或者nop掉相关代码,更改程序走向,即想办法先爆破出程序,然后才涉及到分析注册机的事(没有爆破就瞎分析,非常有可能陷入作者故意设计的冗余代码中无法自拔)

3.注册按钮分析

按钮分析

注册按钮响应函数的整体框架如下(IDA分析结果,变量被适当修改了)

在这里插入图片描述

详细点介绍:

  • 逻辑A:密码不是纯数字才会进入这个逻辑,这个逻辑里最重要的是全局变量g_KEY

  • 逻辑B:密码纯数字才会进入这个逻辑,真正生成有用密码的逻辑

  • 函数C:关键函数,函数的参数是g_KEY、用户名,密码;即真正的密码是由用户输入的用户名和错误的序列号共同决定的

    函数C的返回结果期望是非零

笔记中,最开始提到的CrackMe007升级的地方是if {A} else {B} 流程中{A}{B}都要执行一次,这里指的就是逻辑A和逻辑B都要执行

  • 爆破:一定要进逻辑B

    第一次分析程序时,目的是为了爆破程序,通常都会忽略掉逻辑A,会发现逻辑B中的函数C才是注册按钮不显示的关键逻辑;

  • 注册机:一定要进逻辑A

    当想要写出注册机时,才会发现函数C的参数g_KEY一直是零,导致函数C结果一直是零;回溯函数调用会发现逻辑A一定要进入给g_KEY进行赋值,函数C才有可能计算出正确的密码

注意:如果单纯是为了爆破程序,后面就不需要看了,因为已经找了关键函数(函数C),直接nop关键代码就可以

逆向整个程序思路

为了逆向整个程序,经上面的分析,要先用非数字密码计算一次g_KEY,然后再用纯数字密码计算一次真正的密码才可以

下面是OD的分析截图,直观看可能没有IDA的显示效果友好,但这个因人而异,毕竟只是一个工具而已

在这里插入图片描述

4.注册机

第一次逆向这个程序写注册机,应该是先分析函数C,然后是逻辑A的流程,下面简单分析

注意:如果可以的话,最好用IDA调试一下,这样分析的效率会提高

key 1.函数C

下面是函数C的处理逻辑的主要框架

在这里插入图片描述

简单说明,分成用户名和密码处理这2个部分:

用户名处理

  • 外层A:从左到右,每次取用户名的一个字符,记为X
  • 内层B:从右向左,每次取用户名的一个字符,记为Y,累加和sum = g_KEY * X * Y

因此,用户名处理后的总结果有如下公式:res = (g_KEY * X * Y)% 666666

密码和比较逻辑

  • 密码处理:临时密码 = 密码 % 80 + 密码 / 89 + 1

  • 运算C:要求用户名计算结果res与临时密码相等

    //最终要求如下:
    res == pwd_num % 80 + pwd_num /89 + 1
    //如果知道res,就可以反推出pwd_num,即通过用户名得到正确的密码
    //求模运算有类似的公式:a % b = a -(a / b)* b,逆向本程序不用这个公式,直接枚举就可以
    

通过用户名计算公式res = (g_KEY * X * Y)% 666666会发现g_KEY一定不能为零,g_KEY是函数参数,由外层传入,因此要分析外层的处理逻辑
在这里插入图片描述

外层循环只要保证密码是非数字即可,因此分析一下逻辑A的处理流程,看看是怎么得到g_KEY的?

key 2.逻辑A

逻辑A中给g_KEY赋值的主要逻辑如下:

在这里插入图片描述

函数参数是用户输入密码password,先进行了一个for循环,然后对结果进行了取余数运算

因此,当密码长度符合要求时,g_KEY有类似下面的处理逻辑

int res = 0x37B;
int g_KEY = 0;
for (int i = 1; i <= strlen(password) - 1; i++) {
    res += password[i-1] * (password[i] % 0x11 + 1);
}
g_KEY = abs(res % 0x7148);

真正的密码是由用户输入的用户名和错误的序列号共同决定的

key 3.注册机

根据上面的分析,写出如下简单的注册机

#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
	char pwd[100] = {0};
	char user_name[100] = {0};
	printf("请输入用户名(长度>5):");
	scanf_s("%s", user_name, 100);
	printf("请输入密码(必须是非纯数字,且长度>6):");
	scanf_s("%s", pwd, 100);

	//计算g_KEY
	int res = 0x37B;
	int g_KEY = 0;
	for (int i = 1; i <= strlen(pwd) - 1; i++) {
		res += pwd[i - 1] * (pwd[i] % 0x11 + 1);
	}
	g_KEY = abs(res % 0x7148);

	//用户名,密码,g_KEY共同起作用,计算最终密码
	int sum = 0;
    for (int i = 1; i <= strlen(user_name); i++) {
		for (int j = strlen(user_name); j >= 1; j--) {
			sum += g_KEY * user_name[j - 1] * user_name[i - 1];
		}
	}
	res = (int)abs(sum) % 666666;
	
	//反向计算密码(枚举)
    int key = INT_MIN;
	for (key = INT_MIN; key <= INT_MAX; key++) {
		if (res == key % 80 + key / 89 + 1)
			break;
	}
	printf("用户名:%s, 对应的密码是%d\n", user_name, key);
	system("pause");
    return 0;
}

5.验证结果

在这里插入图片描述

验证整体流程有点繁琐,因此,简单整理如下:

  • 图1:任意用户名 + 非纯数字的密码,更新全局变量g_KEY;示例:test123/abcdefg,会有一个错误弹窗,不用管
  • 图2:用户名 + 注册机生成的密码(会用到上一步骤的g_KEY);示例:test123/23632399,注册按钮消失,出现了一个again按钮
  • 图3:将图1和图2的输入再输入一遍,again按钮也消失了,逆向成功

此时细心会发现图3中again按钮还没有逆向呢???怎么就逆向成功了

下面是again按钮的反编译代码,跟注册函数的逻辑是一样的,因此注册函数逆向成功,再输入一遍参数,again按钮也会被逆向成功

在这里插入图片描述

CrackMe007逆向操作很容易找到关键点,但是要描述清楚写成笔记却浪费了一些时间

6.参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值