CrackMe033:OD和IDA分析结果不同?

下面是网上的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,这个a2edi寄存器,即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

  • 对字符串处理

    序列号字符串转成数字形式,然后与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.参考

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值