6

[原创][KCTF2021]第十题 一统江湖 WriteUp ---- 龙猫变换 黑盒解法

 3 years ago
source link: https://bbs.pediy.com/thread-267902.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[KCTF2021]第十题 一统江湖 WriteUp

龙猫变换 黑盒解法

一,    分析篇

a)      程序整体流程很简单,如图:

752_NQ9GYF9PMZYV88A.jpg

大致流程就是,key做一个变换(Aes256Encrypt,随手写的名字,其实不是),跟name比较一下,相等则成功。

Name需要扩展到16字节:

752_6EVVKT3DUFK27FK.jpg

Key由16进制字符串转成字节码

Aes256Encrypt,跟https://github.com/kokke/tiny-AES-c/blob/master/aes.c,里面的Cipher结构一模一样。

752_VQWVCKNUNTNG83Z.jpg

752_KD95HPRAHDAMPNE.jpg

只是AddRoundKey不一样而已,AddRoundKey做了一点点事情,见下图

752_TN32BA6Q4AESFXP.jpg

b)      一个让IDA死掉的函数

752_KTRDQZ4SMYQ75AD.jpg

里面有大约2.5M的汇编代码。至于是啥,完全不知道。

c)      所以结论:完全不想逆401610这个函数。

二,    猜想篇

还好,401610里面没有anti,写个程序调用一下(这里为了方便,直接调用上面的AddRoundKey函数(因为进出都是16字节)

我们输入 00000000000000000000000000000000

发现输出了6DE448F7A5202570F7283A8BF98BCC63

然后输入了00000000000000000000000000000001

发现输出了EFD30F8DCF306277DEDA00D2E7F06DC4

然后输入了80000000000000000000000000000000

发现输出了CDF38AF72C4C18072CD8D383C7599A74

然后输入了80000000000000000000000000000001

发现输出了4FC4CD8D465C5F00052AE9DAD9223BD3

然后发现 6DE448F7A5202570F7283A8BF98BCC63 xor EFD30F8DCF306277DEDA00D2E7F06DC4 xor CDF38AF72C4C18072CD8D383C7599A74 = 4FC4CD8D465C5F00052AE9DAD9223BD3

看上去就是一个巧合!!

逆不了题目,我们靠猜来弥补:

首先我们假设作者的这个函数是可逆的(一定可逆),而且没有多解!!!(有多解可以看到女装照)

所以,我们假设作者这个AddRoundKey里面设置了128个向量表和一个基础0号向量base(6DE448F7A5202570F7283A8BF98BCC63),按照输入的bit位是否为1,决定了是否异或向量表中的这一项。换句话说,就是128个向量的叠加(有限域2的世界里面,加法就是异或运算)。

即 Y = A*x + B。A是128向量矩阵,B是base向量,x是输入,Y是输出。

然后调用exe里面的AddRoundKey把这128个向量(输出结果要异或一下base向量)给抓出来(不列举了):

然而很快就被打脸了!!

按照上面的猜想 “00000000000000000000000000000001” 与 “00000000000000000000000000000002” 输出叠加后应该是“00000000000000000000000000000003”的输出,结果却等于了“00000000000000000000000000000004”的输出,恰好等于我们的2号向量(1 <<2)

752_NYJKFH8RJUN5QZB.jpg

不仅这一组,我们发现,还有很多组都是这样的。写个程序,跑一下我们的iv表,得出例外(3个向量异或值为全0),这样一共有42组(下图):也就是说,我们的向量表,实际上不能生成叠加后的任意值,不是线性无关的128个向量。一共42组,每组3个,覆盖了126bit。

752_NMTQ6YFJ45AJXS2.jpg

每个bit,只出现了一次,没有重叠!没有重叠!没有重叠!重要的事情说三遍,如果重叠了,直接就放弃了!

基于我们大概率看不到女装照,所以应该想办法把向量弄成线性无关的。

我们继续靠猜想来弥补:

观察0,1,2这组,其实是 1,2,4bit位的向量值

按我们上面的猜想理论,1和2应该是叠加成3的输出,结果却出现了4,如果3和4的输入,在叠加向量前被交换了呢?那结果不就符合实验数据了吗?1,2,4bit,可以组成8个数,除了0以外,还有7个数字。调用exe的函数,穷举一下:

752_Z6NB2TYCYWT85KH.jpg

不难发现,3和4交换后,用1,2,4向量就可以生成其他所有输出,然后细节处还发现了,6和7 也被交换了!!这7个向量中,找出任意3个线性不相关的向量,就可以生成出其他4个,为了简便运算,我们直接固定1,2,强行交换3和4,这样,7个都能生成出来了,然后再判断一下,5,6,7是否被交换过(只可能交换一次)。

这样,我们抓出线性不相关的128个向量表,以及交换表(3和4强制交换):

752_59CMKTBPTCW63EP.jpg

三,    解题篇

核心猜想:作者设计的算法,可逆!无多解!

总结一下思路:

函数的输入128bit,输出128bit,由于可逆,无多解,我们可以函数的一个完全等价体是:有一张超级大的映射表,对于每一个输入,都有唯一的输出,映射表的有2^128行,这个完全不可能存下来,所以,我们在这个表里面,找出128+1个线性无关的向量(那一个是全0的输出,我们称为base,设为B),列出一个128bit矩阵的表达式:

Y = A*x + B

752_DRH4MEERHNVMWS6.jpg

其中,B是常量,Y是输出,x是输入,A是128个向量的矩阵

逆向运算,就是在已知Y的情况下,求x。这样可以展开成128元一次方程组。方程组中,每个数都是2进制的。

由于依次对128bit设置为1,看输出,发现有42组的3bit生成的向量和为0,说明2^128的向量表有些项被交换过了。

所以,这个AddRoundKey过程,可以用这样的算法来描述:

752_7NSD7CDG8BMSJNZ.jpg

那么逆运算就是:

752_7AVV6BB8P23EGZN.jpg

四,    代码篇

首先把Aes256框架抄过来:

https://github.com/kokke/tiny-AES-c/blob/master/aes.c

然后F5掉几个函数

752_FANSNAEUBM5YSC2.jpg

由于exe带重定位,因此我们直接调用401610函数

752_5U9JQ6NAP2443XZ.jpg

然后,抓出128 + 1个向量

752_ZJVMEEWAWTS4C5C.jpg

处理交换表,并修复向量表

752_FFD8T4V54EAWGKG.jpg

然后打印出来,作为预加载部分代码:

752_H8EEKFHQT7CQU9Q.jpg

以后就调用preload就行了,就是上面超长的函数

752_4D28DZVSEUU6F2A.jpg

写出逆向的AddRoundKey:

752_9H5N9HJGR9UV3UM.jpg

然后Aes框架抄一下:换成我们改好的InvAddRoundKey

752_J96SVQP4MWT32NH.jpg

最后kg,结束

752_PS9WSS84Q6A59UM.jpg

代码,在vs2017中编译通过。

大龙猫(作者)

看场雪(看雪密码学版主)

还有几位科锐的学生

[看雪官方培训] Unicorn Trace还原Ollvm算法!《安卓高级研修班》2021年6月班火热招生!!

最后于 5天前 被kanxue编辑 ,原因:

上传的附件:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK