【深入理解AES】山西省首届大学生信息安全技能大赛–价值200分的逆向

作者: skywilling 分类: PE逆向,逆向 发布时间: 2017-06-23 16:54

转自http://www.52pojie.cn/thread-618809-1-1.html

0x00前言
一直以来都在研究Android的逆向,最近才开始研究PE逆向。这是第一次发关于PE逆向的帖子,所以有什么不妥或错误之处,还请坛友纠正。5月份,山西省举办了首届大学生信息安全技能大赛–个人赛(借助i春秋平台),本人有幸得到了本次大赛中唯一的一道逆向题目(价值200分,属于中级题目)。本文以该题目作为研究对象(题目会在文章末尾的附件给出),下面正式开始题目的初探。。。
0x01初探
当得到这个题目之后,我们需要先了解该题目类型,下面是我得到的题目属性截图:

显然这是一个windows平台上面的题目,接下来我们看一下这个CrackMe的运行效果

这里是在cmd中运行的,这里要说一下的是,如果直接双击运行的话,在输入答案之后,程序就会直接退出,看不见“回答错误!!!”这个信息,所以我们需要在cmd中运行,才能看到输入答案后的结果。
明白了运行的效果,我们接下来看一下,这个CrackMe有没有加壳,以及使用了哪些加密算法(看了官方的writeup之后,才知道PEID可以查出来)

通过PEID查壳,我们可以看出,该CM没有加壳。而且借助PEID的插件,我们也可以看出来该CM使用了MD5和Rijndael(AES)加密算法。
0x02分析加密流程
分析完了CM加壳和加密情况之后,我们正式开始CM的调试之旅。

通过动态静态分析,我们在这里看到了MD5加密的特征数。

F5我们进一步分析,发现该CM对前8字节进行MD5加密(不太熟悉MD5的话可以去补习一下)。

继续分析,这里是对MD5加密后的密文进行比较,大概的流程如下:

这可以看作是一个解方程组的过程,最后解出的结果是:
a=0x4d2ea664

b=0xd50fa3b6

c=0x3f67863b

d=0x9560e59b

那么MD5密文就是64a62e4db6a30fd53b86673f9be56095

因为MD5加密是不可逆的,也就是说MD5加密是没有解密算法的,这里就需要我们借助在线的MD5解密平台了。


通过在线解密,我们看到明文是ichunqiu,接下来,我们继续分析。


继续分析,我们发现这里对剩下的字符串长度进行了比较,可以看出来,如果剩下字符串长度不等于0x10就退出,所以这里的字符串长度一定是0x10。


在这里对剩下字符串判断,是否是大写字母,到这里我们可以得到“字符串是16字节的大写字母字符串”这个结论。


往下分析,我们看到,在这里以FROMYWWAY作为密钥,对16字节的字符串进行了维吉尼亚加密。


最后到了这里就是AES加密了,这里就不再具体看汇编代码了,值得一提的是,这里用的AES加密模式CBC模式。

因为使用的是AES-CBC加密,所以需要一个IV,在这里,我们看到IV就是ichunqiu的MD5密文。


在这里是比较AES加密后的结果,比较数据是:



到这里加密流程就分行完了,接下来详细对加密进行分析。
0x03加密详解
通过对加密流程的分析,我们可以得到加密流程如下:

在这里我们主要要找的明文是全是大写字母的16字节字符串,所以我们需要详细分析一下AES加密流程。

[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
void func6(unsigned char*mi,unsigned char*key,unsigned char*md5) {
        int i;
        //轮密钥加
        for (i = 0; i < 0x10; i++) {
                mi ^= key;
        }
        for (i = 1; i < 10;i++) {
                func4(mi,key,i);
                func5(mi); //列混淆
        }
        func4(mi,key,10);
        for (i = 0; i < 0x10; i++) {
                mi ^= md5;
        }
}

 

[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
void func4(unsigned char*mi,unsigned char*key,int k) {
        int i, j;
        unsigned char a, b;
        unsigned char *c,*d;
        //向下列移位
        /*
        state’[j] = state[(4+i-j)%4][j]
        */
        a = mi[9];
        b = mi[0xD];
        mi[0xD] = a;
        a = mi[5];
        mi[9] = a;
        a = mi[1];
        mi[5] = a;
        a = mi[0xA];
        mi[1] = b;
        b = mi[2];
        mi[2] = a;
        a = mi[0xE];
        mi[0xA] = b;
        b = mi[6];
        mi[6] = a;
        a = mi[7];
        mi[0xE] = b;
        b = mi[3];
        mi[3] = a;
        a = mi[0xB];
        mi[7] = a;
        a = mi[0xF];
        mi[0xB] = a;
        mi[0xF] = b;
        //字节替换
        d = mi;
        for (i = 0; i < 4;i++) {
                c = d;
                for (j = 0; j < 4;j++) {
                        a = *c;
                        c += 4;
                        a=table3[a];
                        *(c - 4) = a;
                }
                d++;
        }
        //轮密钥加
        for (i = 0; i < 0x10; i++) {
                mi ^= *(key-0x10*k+i);
        }
}


这就是我分析出来的AES加密流程代码,大致分为以下几个流程:
1.密钥扩展
2.10轮加密变换
3.矩阵行列互换

通过对标准AES的加密流程的分析,我们来分析一下,CM用的AES加密流程是什么样的?
根据我编写的加密代码,AES的加密流程是:
1.轮密钥加
2.(向下列移位,字节替代,列混淆)9轮加密
3.向下列移位,字节替代
4.异或MD5
通过比较,我们发现这里的AES加密过程事实上是一个标准的AES解密过程

但是如果我们足够细心,还可以发现一处不同之处,明明在标准的AES加密解密过程中,进行的是行移位,但是在CM中却是列移位。按我的理解是,因为在最后进行了矩阵的行列互换导致的吧,这一点我依然持保留意见。
详细分析了加密流程,写出解密代码就简单多了。加解密代码我都会在附件中给出。
0x04结语

最后以成功的效果图作为结尾。
附件: http://pan.baidu.com/s/1mi3beeG 密码: 6
xjf

发表评论

电子邮件地址不会被公开。 必填项已用*标注