码迷,mamicode.com
首页 > 其他好文 > 详细

逆向工程实战--Afkayas.1

时间:2016-04-06 23:36:47      阅读:431      评论:0      收藏:0      [点我收藏+]

标签:

0x00 序言

去年玩了几个月的渗透测试,当初觉得很高端的样子,现在看来不过都是些小把戏,于是开始折腾逆向工程。学习过程中参考的是《逆向工程核心原理》这本书,讲的很详细,按照上面的步骤破解了几个crackme,然后自己在网上找了一些程序来玩,第一次独立成功破解Afkayas.1,有点兴奋,于是将破解过程记录下来,算是一个开启逆向工程大门的里程碑吧。

0x01 准备

玩逆向工程需要至少一个调试工具,这里我推荐OllyDbg。还需要一些小程序,可以利用已有的 CrackMe 小程序。

0x02 初次运行

拿到程序后,首先运行,看看有什么特征:
技术分享

这个是典型的字符串序列破解程序,根据name的值推出serial。
我们尝试输入:
技术分享

一个很明显的特征就是点击 OK 按钮后,程序会弹框,而且会显示特征字符串。

0x03 开始调试

我们打开 OllyDbg,加载程序后大致是这样:
技术分享

1、查询特征字符串
根据上面的弹框可以推测,如果serial输入正确,则会提示成功的信息;上面我们获得了失败时的字符串,按如下步骤在代码段中查找:

首先右键代码区,”Search for” => “All referenced text strings”
技术分享

在新的对话框中找到失败的提示字符串:
技术分享

双击其中一个,回到代码区,可以看到注释中出现了失败和成功时的字符串:
技术分享

2、条件判断
我们发现成功和失败时的字符串相隔不远,可以初步断定程序会在这之前进行判断,如果输入的serial正确则成功,否则失败;接着我们向上看,发现调用字符串比较函数的入口点:
技术分享

3、参数传递
我们知道调用一个函数时需要给它传递适当的参数。汇编调用函数之前会先把参数入栈,然后用 call 指令调用函数。我们发现在字符串比较函数之前有一句 PUSH EAX 指令,可以推测这里的 EAX 就是字符串的首地址。

4、找出真正的 serial
我们在字符串比较函数这条指令前设置断点(按 F2),然后执行(按 F9)。注意中间会弹出程序主界面,我们需要输入然后点击 OK 按钮:
技术分享

这时程序停在了我们设置断点的地方,查看栈区(右下角),可以发现栈顶处就是真正的 serial 的地址,注释已经标明了 serial:
技术分享

接着我们打开原程序,输入 name 和 serial:
技术分享

发现已经成功破解。下面我们进一步查找真正的原因。

0x04 破解加密方式

以上我们已经成功破解了 serial,但是并不知道如何从 name 得到 serial,下面我们将详细讲述。

1、函数的起点
每个函数都有起始点,在 IA32 架构下,函数都有自己的栈帧,所以首先会创建自己的帧:

PUSH EBP        ;保存调用者的帧指针
MOV EBP, ESP    ;创建自己的帧
SUB ESP, 0C     ;分配局部存储空间

我们单击 OK 按钮时会调用函数来读取 name,加密 name 得到 serial,比较 serial等操作,所以我们首先要找到该函数的起点:
从刚才的字符串比较函数处往上找可以看到:
技术分享

2、获取 name
我们应该明白的一点是,单击按钮后,程序首先会获得 name 字符串,从而生成 serial,所以我们下面需要找到 name 字符串的位置:
单步执行(按 F8),到程序调用 strlen 之前,我们在栈顶发现了输入的 name:
技术分享

3、发现可疑目标
得到name后,紧接着就是得到 serial,往下看,我们发现了一些可疑的函数,都加上断点(按 F2):
技术分享

4、锁定目标
我们直接执行(按 F9),发现三个可疑函数并没有什么特别的,当执行到之前的字符串比较函数处时突然冒出正确的 serial,往上看发现了 serial 中的 “AKA-“:
技术分享

这部分就是直接拼接上去的,所以可以断定 serial 的其余部分就在那几个可疑函数产生的,于是我们继续运行,重新输入 name,运行到最后一个可疑函数处,按 F7 进入函数:
技术分享

按 F8 单步执行指令,到下面会跳转:
技术分享

跳转之后:
技术分享

这里把跳转点加上断点,然后继续 F8 单步执行:
执行到第二个 call 指令时寄存器中出现了 serial:
技术分享

这条指令的前一条指令是:

LEA ECX,[EBP-1C]

可以推测是跳转后的第一个 call 指令调用的函数计算出的 serial,于是我们 F7 进去看看:
反复的 F7 我们发现有一个循环:
技术分享

这段指令很有趣,它把 ECX 中的值存入 EAX,然后不断的用 EAX 除 10(十六进制 0xA),得到的商放在 EAX 中,余数移到 EDI 指向的内存缓冲区中;实际上就是把 ECX 转化成十进制字符串。

我们发现 serial 来源于 ECX,记录下其值(000D6504),我们往前找 ECX。

5、逆向分析
F9 运行到底,重新输入 name,继续运行到断点处(第三个可疑函数),发现 EDI 已经修改为 000D6504,于是我们跟踪 EDI:
技术分享

仔细观察附近的指令,发现有很多针对 EDI 的,于是我们重新回到三个可疑函数的第一个下面开始单步执行:
技术分享

结果是非常令人兴奋的: EDI = strlen(name) * 0x17CFB;
算出来是 000D64D3,和 000D6504 差了 0x31,继续 F8 单步:
技术分享

看见了吗,第二个可疑函数返回了 0x31,于是我们只需要搞清楚这个 0x31 到底是怎么回事就行了,继续跟踪第二个可疑函数:
F7 进入后,F8 单步,命中目标:
技术分享

调用系统函数之后,出现了MOVZX AX,BYTE PTR [EBP-2],此时 AX 变成 0x31,右键寄存器区查看 name 在内存中的区域:
技术分享
技术分享

发现 0x31 就是 name 第一个字符 ‘1’ 的ASCII码。

6、最后的判定
经过以上分析,我们可以推测出由 name 到 serial 的算法:

serial = ‘AKA-‘ + 逆序itoa(strlen(name) * 0x17CFB + name[0]);

0x05 程序验证

根据上述步骤,我们破解了其加密方式,下面我们用 C语言程序验证:

#include <stdio.h>
#include <string.h>
#define BUFSIZ 1024

int main()
{
    char name[BUFSIZ];
    char serial[BUFSIZ];
    int num, i = 0;

    printf("Input your name: ");
    scanf("%s", name);
    printf("Serial: AKA-");

    num = strlen(name) * 0x17cfb + name[0];
    while (num > 0) {
        serial[i++] = num % 10 + ‘0‘;
        num /= 10;
    }

    while (i--)
        putchar(serial[i]);
    putchar(‘\n‘);

    return 0;
}

程序很简单,首先获取 name, 然后根据上面的分析得到中间数 num,接着把 num 转化成字符串,最后逆序输出该字符串。

1、C语言程序运行结果
技术分享

2、Afkayas.1运行结果
技术分享

我们可以发现,其实该程序的中间数只与字符串的长度和第一个字符有关.

0x06 总结

第一次写这么长的博文,第一次做逆向分析,第一次破解一个小程序。

逆向工程实战--Afkayas.1

标签:

原文地址:http://blog.csdn.net/qq_20480611/article/details/51077329

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!