逆向工程实战--Acid burn

0x00 序言

这是第二次破解 crackme 小程序,感觉明显比第一次熟练,破解过程很顺利,几乎是分分钟就可以找到正确的 serial,但是我们的目标是破解计算过程,下面将详细介绍。

0x01 初次运行

刚开始拿到 crackme 先运行程序,看看有哪些明显的特征,或者有哪些任务需要完成:
逆向工程实战--Acid burn_第1张图片
双击程序后弹框,显然第一个任务就是把这个框框弄掉,我们继续运行:

这个小程序比上次的要复杂,有两个 serial ,我们先看看左边的:


不出意外,猜错了,有明显的弹框和失败字符串作为特征,我们接着看右边的:
逆向工程实战--Acid burn_第2张图片

不出意外,再次失败,依然是弹框。

0x02 开始调试

1、明确目标
通过上面的运行分析,我们需要干掉第一个弹框,以及后续的两个 serial 。同时我们发现三者的共同特征为弹框,所以首先拦截弹框函数:
右键代码区选择 “serach for” => “All intermodules calls”:
逆向工程实战--Acid burn_第3张图片

在新窗口中输入 messageboxa,右键,选择”Set breakpoint on every call to MessageBoxA”:

这样我们就给所有调用弹框函数的地方下了断点,接着回到代码区运行程序。

2、调用者
按 F9 执行到弹框函数处,我们发现此时的栈顶就是第一次弹框时的字符串的地址,于是我们需要找到那个调用弹框函数的函数,叫做调用者。这里我们往上看,找到当前这个函数的入口并下断点:

然后我们 Ctrl + F2 重新载入程序,F9 执行到刚才下断点的入口:
这里写图片描述
此时栈顶就是调用者执行call指令时保存的返回点,我们在代码区中查找这个地址(42F79C),注意单击代码区,按 Ctrl + G 进行查找:
逆向工程实战--Acid burn_第4张图片

看见了吗,就是这个函数,只有几句代码,下面我们就来消灭它。

3、去掉弹框
调用了函数才会弹框,我们的想法就是让它不调用函数,那么直接让函数返回是最简单的方式,于是我们把函数入口处的第一条指令改成RETN 即可:
单击指令,按一下空格键可以修改:
逆向工程实战--Acid burn_第5张图片

此时我们可以把修改保存到文件中:
右键指令,选择 “Copy to executable” => “selection”:

逆向工程实战--Acid burn_第6张图片

在新窗口中右键选择 “Save file”:
逆向工程实战--Acid burn_第7张图片

然后保存:
逆向工程实战--Acid burn_第8张图片

运行新的程序发现第一次的弹框成功消失。

4、破解右侧serial
接下来我们转到右边的 serial,输入任意字符串,然后点击按钮:
我们发现程序停在了弹框函数的入口:
逆向工程实战--Acid burn_第9张图片

此时栈顶的值就应该是上级函数的返回地址:
逆向工程实战--Acid burn_第10张图片

我们继续在代码区搜索此地址(42F509):
逆向工程实战--Acid burn_第11张图片

发现了吗,有判断条件,可以看出是字符串比较函数,我们设置断点,F9 运行到底后重新点击按钮:
逆向工程实战--Acid burn_第12张图片

程序停在了断点处,看看栈区,发现给函数的参数中的字符串:

破解起来确实很轻松,字符串是固定的:Hello Dude!
逆向工程实战--Acid burn_第13张图片

5、破解左侧 serial
我们继续运行,转到左侧,输入任意字符串后点击按钮:
根据刚才的方式找到调用者返回地址:42FB37
这里写图片描述

查找代码区:

发现字符串比较函数并下断点,此时查看栈区:

再往上看代码区:
逆向工程实战--Acid burn_第14张图片

我们可以推测出 serial 是 “CW-” + 某个数 + “CRACKED”,中间的数是我们需要找的目标。

6、真实的目标
我们给 serial 生成函数的入口下一个断点,然后重新点击按钮运行到断点处 F8 单步走:

中间发现两段代码:

EAX = name[0] * 7 + name[1] * 0x10;
EAX = name[3] * 0xB + name[2] * 0xE

继续向下运行,发现另外一段代码:

函数入口的下面有一句不起眼的代码:

两个结合起来就是:

EAX = name[0] * 0x29 * 2;

后面我们发现调用字符串输出函数之前 EAX 的值被置为那个内存单元的值:

继续往下调试结果就很明显了,第三段代码才是我们要的。

0x03 双重检测

1、简单粗暴的 C语言
代码如下:

#include <stdio.h>

int main()
{
    char name[1024];

    printf("Input your name: ");
    scanf("%s", name);
    printf("Serial: CW-%d-CRACKED\n", name[0] * 0x29 * 2);
    return 0;
}

运行结果:

2、原程序检验

0x04 总结

这个小程序左边的 serial 和 name 的第一个字符有关,并且字符串长度不能小于4.

你可能感兴趣的:(破解,逆向工程)