CrackMe001:关键字符串思路

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

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

1.现象

在这里插入图片描述
运行软件,发现有2个地方需要破解,一个是序列号/用户名,另一个是单独的序列号

在这里插入图片描述

2.序列号逆向

step 1.错误提示

OD启动程序,F9,随机输入一个序列号,验证,出现错误对话框

在这里插入图片描述

step 2.关键字符串

根据错误提示的字符串Try Again!!,在OD里搜索一下,看看能不能发现线索?

找到了一个可疑的字符串,在字符串的地址处设置断点

在这里插入图片描述

重新输入一下序列号,验证,断点命中,说明线索有效(注意:这个过程有时要找很多次才能找到,要有耐心

step 3.关键跳转

命中断点(0x42F4F8)后,简单分析一下命中前的部分代码,发现了正确提示和可疑的**关键跳转(0x42F4D5)**指令

在这里插入图片描述

说明:详细分析可以看到,错误提示中的call调用的0x0042A170应该是类似于MessageBox的对话框函数

爆破:直接将关键跳转指令改成nop,再次运行一下验证序列号流程(随便输入一个序列号),发现弹出正确提示框;如果不想继续查看,直接保存就可以得到序列号破解程序

在这里插入图片描述

step 4.正确的序列号

程序在关键跳转(0x42F4D5)前面一定会有判断逻辑来验证序列号,通常都是离关键跳转很近的函数调用

OD重新加载程序,在关键跳转上面的第一个函数调用(0x42F4D0)处设置断点,F9,执行;断点命中后,查看函数的可能参数

  • eax里保存的是我随机输入的系列号123
  • edx里保存的是一个陌生的字符串Hello Dude!,这个字符串大概率就是正确的序列号

在这里插入图片描述

step 5.验证结果

经验证Hello Dude!就是正确的序列号
在这里插入图片描述

这是一个很简单的Crack思路,主要是利用错误提示框中的信息找到破解点,这也是最常用的套路

缺点:后续软件增加反调试或者不弹出错误对话框,这个思路就失效了

3.序列号/用户名逆向

逆向软件前,最好熟悉一组字符串的ASCII码,这样会增加逆向的效率,下面是我常用的用户名和密码的ASCII码

注意:后续所有笔记基本使用的都是下面的用户名和序列号

字符串对用的ASCII(十六进制)
test12374 65 73 74 31 32 33
45634 35 36

step 1.错误提示

输入一组序列号和用户名,点击验证发现出现错误对话框

提示:用上面的字符串思路直接可以爆破这个程序;为了分析出注册机,因此不采用爆破的方式

在这里插入图片描述

step 2.关键跳转

通过错误字符串Sorry,The serial is incorect!,用上面的方法可以直接定位到关键跳转(0x42FB03

在关键跳转上面最近的函数调用(即call指令)处(0x42FAFE)设置断点,重新运行程序,输入错误的用户名和序列号(test123/456),断点命中后分析如下:

  • 序列号:没有变化
  • 用户名:输入test123,结果应该是CW-9512-CRACKED,想要写注册机就要找到用户名处理逻辑

在这里插入图片描述


扩展:IDA查看Graph图

IDA加载程序,通过错误字符串Sorry,The serial is incorect!找到对应处理函数,转换成graph视图,可以看到CRACKED应该是一个固定字符串,猜测最终结果后半部分应该是拼接CRACKED字符串

在这里插入图片描述

提示:逆向小程序使用OD或者x64dbg就能应付,但是逆向大一点的程序最好结合IDA进行分析,尤其IDA产生的辅助MAP文件很有用,后面的CrackMe004会有介绍


step 3.分析用户名处理逻辑

直接在上面关键跳转的函数起始处设置断点,重新运行程序;输入用户名和密码,分析处理逻辑,实际上包括2个部分:

  • 1.用户名长度大于等于4

下面是用户名处理逻辑的前半部分,处理用户名的前4个字符是结构类似的代码

提示:这部分对用户名的处理结果后面没有使用(分析了个寂寞),后续的CrackMe笔记中会看到,结合IDA分析可以很快识别出关键处理逻辑

在这里插入图片描述


扩展:使用repne scas byte ptr es:[edi]计算字符串长度

上面截图地址0042FA52中调用的函数是计算字符串长度的函数,要熟悉这个函数的反汇编形式,逆向中经常看到;反汇编代码对应如下:

; 计算字符串长度
00406930  /$  89FA          mov     edx, edi
00406932  |.  89C7          mov     edi, eax                        ;  edi存放字符串
00406934  |.  B9 FFFFFFFF   mov     ecx, -1                         ;  mov ecx,0xFFFFFFFF
00406939  |.  30C0          xor     al, al                          ;  al存放字符x;al=0,将遍历整个字符串
0040693B  |.  F2:AE         repne   scas byte ptr es:[edi]          ;  以字节为单位遍历字符串,每循环一次ecx-1,遇到字符x则停止
0040693D  |.  B8 FEFFFFFF   mov     eax, -2                         ;  mov eax,0xFFFFFFFE
00406942  |.  29C8          sub     eax, ecx                        ;  eax里面存储的就是字符串长度
00406944  |.  89D7          mov     edi, edx
00406946  \.  C3            retn

C++代码验证上面反汇编代码:

#include "StdAfx.h"
#include <stdio.h>
#include <string.h> 
int main() {
    char str[] = "1234567";
    int str_len = 0;
    int record_ecx = 0;
    _asm
    {
        mov     edx, edi					//使用edi前临时保存起来
		lea     edi, str					//edi存放字符串
        mov     ecx, 0xFFFFFFFF
        xor     al, al						//al存放字符x;al=0,将遍历整个字符串
        repne   scas byte ptr es:[edi]		//以字节为单位遍历字符串,每循环一次ecx-1,遇到字符x则停止
        mov     eax, 0xFFFFFFFE
        sub     eax, ecx
        mov		record_ecx, ecx
        mov		str_len, eax
		mov     edi, edx
    }
    printf("record_ecx=%d, str_len=%d, strlen()=%d", record_ecx, str_len, strlen(str));
    return 0;
}

运行程序可以看到上面汇编代码和strlen计算的结果一致:在这里插入图片描述


  • 2.用户名处理

输入test123,经过计算结果是CW-9512-CRACKED,这个对应关系要时刻牢记;下面是分析的整体截图,详细计算:

首先,用户名test,取第一个字符t,乘以0x29,再乘以2最终结果=0x74 * 0x29 * 2 = 0x2528 = 9215

其次,将9215转换成字符串与CWCRACKED进行拼接,得到有效序列号CW-9512-CRACKED,即序列号是根据用户名动态生成的

在这里插入图片描述

至此,用户名处理逻辑分析完,注册机实现就很容易了

step 4.注册机

注意:没有考虑复杂的输入,仅仅是为了验证算法分析的是否正确用,后续笔记的注册机也都是这个目的

#include "StdAfx.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
    char user_name[100] = {0};					//用户名
    printf("请输入用户名(长度>=4):");
    scanf_s("%s", user_name, 100);
    
	//根据用户名(第一位)生成序列号
    int user_serial = user_name[0] * 0x29 * 2;  //乘以0x29再乘以2
    
	//拼接
    char serial[200] = {0};
	char serial1[] = "CW";						
    char serial2[] = "CRACKED";
    sprintf(serial, "%s-%d-%s", serial1, user_serial, serial2);
    printf("用户名:%s, 对应的序列号:%s\n", user_name, serial);
    system("pause");
    return 0;
}

运行结果:
在这里插入图片描述

验证注册机通用性,简单的注册机符合要求

在这里插入图片描述

简单总结:这个逆向案例其实很简单,主要是想将利用关键字符串破解的思路写一个笔记

4.参考

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值