欧美性爱

91 萝莉 [转帖]白盒AES算法详解(二)


发布日期:2024-10-26 13:32    点击次数:83


91 萝莉 [转帖]白盒AES算法详解(二)

上篇著述咱们分析了AES的具体达成91 萝莉,况兼从表面旨趣以及数理标的一步步进行了DFA膺惩的达成,接下来这篇著述咱们从实践动身,探索针对白盒算法怎么快速侦破。

一、 器用选拔

工欲善其事,必先利其器,通过上篇著述固然咱们可以逐渐去达成DFA膺惩,但真果然践时,效率实在低下,总结一下咱们的办法:

差分故障分析,传入正确密文和一系列故障密文,就径直复返第十轮的轮密钥以致是主密钥 基于AES的轮密钥收复主密钥

基于以上需求,推选两个开源神气:Stark 与 phoenixAES,stark用于基于轮密钥赢得主密钥,营救DES、AES、SM4等算法,具体旨趣可自行查阅源码。phoenixAES概况凭证传入的正确密文和一系列故障密文,复返第十轮的轮密钥以致是主密钥,况兼营救加密与解密。

phoenixAES 可以通过pip径直安设,tracefile中,第一瞥传正确密文,后头传入故障密文。

phoenixAES很好用,有以下优点:

具备精致的输出日记,比如上头的情况中只提供了两组故障密文,无法还原出完整的轮密钥,那么它会打印出已还原的部分,未还原的部分用星号示意。

会检测输入的故障密文是否合规,可用就用,不可用就舍弃此密文。 要是造作密文为四字节,且是四种模式之一,那么咱们知谈这是一个正确时机的故障,器用会输出 good candidate。 要是时机晚,造作密文少于四字节,器用会教导 too few impact。 时机早,造作密文卓越四字节,会教导 too much impact。

它营救加密息争密,本文只讲了加密,解密其实技能上也近似。crack_file函数的第三个参数传False即代表解密。在解密情况中,首行放正确明文,后头是故障明文。

二、 达成故障&拿获故障密文

咱们学习了DFA的旨趣,以偏激达成器用phoenixAES。那么问题来了,咱们用什么器用达成故障,以及拿获故障密文。

2-1 源码

要是咱们径直赢得到了源码,那天然是最佳的,在门径中修改一个字节以及打印结果可以说毫无压力。固然施行场景中不太可能赢得到源码,然而把白盒门径按扩充流抠出来,用某种高等谈话复写,比如C/Python,那和源码没两样。

有的一又友可能会困惑,既然都抠出代码了,为什么还要还原Key,径直跑不也挺好?在有白盒门径源码的情况下,并接续顶需要还原出Key,咱们可以用这个场景来进修对DFA的掌捏进度。

2-2 IDA

使用IDA动态调试互助IDAPython剧本,可以很好的完成需求,但许各类本都会检测和抵拒IDA动态调试,因此不是一个额外好的决议。本系列著述不会张开参议这个决议。

丝袜写真 2-3 Frida

Frida 可以很恣意的达成屡次扩充办法函数、修改 state 一个字节,打印输出等武艺,是最佳的办法之一。

2-4 Unidbg

Unidbg 和 Frida 一样,都口舌常好的决议,亦然系列著述先容的要点。

三、 使用源码进行DFA膺惩

接下来咱们参议有源码情况下,对白盒化AES的DFA膺惩奈何达成。

示例一

如下代码从变量定名上可以看出,像是IDA F5的伪代码,被作家抠出来用Python复写出来的:

在上一篇文中咱们提到,在对门径AES达成作念DFA时,需要找到合适的位置修改 state 中一个字节,贴一下之前的代码:

那么在白盒化的AES达成中,可以找到对应的第九轮,对应的阿谁时机,对应的state吗?这即是DFA 应用于白盒之上的三个进犯问题。

仔细不雅察swap函数,它其实即是ShiftRows武艺,而除此之外的其余武艺,找不到思绪,即其余三个武艺被整合后以查表形态达奏效力。

除此之外,咱们没法依赖门径达成中轮运算里武艺的先后律例来推断白盒达成,因为在密码白盒化过程中,这些武艺的律例可能被冲突重组。

但不要慌,咱们对三个问题逐一参议,当先是“轮"的认识。咱们发现,swap函数调用了十次,前九次是较复杂的查表运算:

终末一轮是较为约略的查表:

对照一下门径AES达成——终末一轮少了最为复杂的列浑浊武艺。

两相对比后意志到,咱们碰到的这个AES白盒达成,它和门径AES之间像是有一种玄妙的研究和对应。即门径的十轮和白盒化的十轮是否认对应的,这就达成了”轮“上的对应。

接下来商酌修改的时机,在前文咱们考据过,倒数两次列浑浊之间都是等价且安妥的时机。在门径AES达成中,因为第十轮不存在列浑浊武艺,是以”倒数两次列浑浊之间“就指的是第八轮以选取九轮运算中两次列浑浊之间的时机。进而咱们可以说,”第九轮运算肇始处“这个时机点一定是合适的,因为它处于通盘这个词时机的中间部分。

回到样本这个白盒加密,咱们说它和门径AES之间像是有一种玄妙的研究和对应,那么,在它的第九轮肇始处作念故障注入,是否会是一个好的时机呢?咱们先这样假设。

轮和时机都找到了,接下来找 state 。

咱们发现,inp变量疑似 state。奈何作念出的这个判断?前文咱们说过,数据以state的样式策画、中间存储和传输,也可以反过来说,进展策画、中间存储和传输功能的阿谁变量即是 state。

res 运算的结果终末赋值给inp,inp参与下一轮运算,并给与下一轮的结果月盈则食,咱们测度 inp 即是state。而且从样式上看,inp在门径中是十六字节样式,这也和 state 所需一致。

底下尝试注入故障,并凭证密文结果来考据咱们的测度是否正确。当先记载泛泛运行的结果:

e2cea35825826c8c5d3e7d6cea9d98f1,在第九轮肇始处修改inp的一个字节。

运行结果:44cea35825826c0c5d3e556cea3798f1

两相对比

咱们发现第一、第八、第十一、第十四字节和正确密文不同,完整适应DFA告捷注入的特征。

接下来变化注入故障的位置以及故障值,inpList[index] = x,修改index以及x。蓄积故障密文,放入phoenixAES。别忘了,第一瞥是正确密文,之后是故障密文。

奏凯运行出结果

要是读者仍未统共出结果,就多塞几个故障密文。

终末用 stark 求出主密钥 61316C5F7434623133355F525F6F5235

咱们在我方的Aes-128Encrypt中考据一番:

可以发现结果统共正确。

示例二

这是 网上冲浪 时在博主著述里看到的一个例子。在这个白盒达成中,雷同存在数个大表,咱们将其放在头文献里。而且从函数名可知,这是一个白盒解密函数。解密和加密在处理上有渺小不同,借这个例子好好参议一下。

依葫芦画瓢,当先寻找“轮”:

咱们发现主函数里面有一个大的轮回,但单纯静态看,看不太出有几轮,我添加了计数器,打印输出一下。

运行后果如下:

可以发现,在通盘这个词解密过程中,存在十轮运算。这和上个例子近似,让咱们看到了但愿。需要隆重,有一些更好的白盒达成中,找不到较着的“轮”,或者并非9/10次轮回,那就难熬了。

找到轮之后91 萝莉,咱们将时机校服在第九轮开头处,接下来找 state 。我以为变量 s 相比像存放state的变量,或者说,它像一个结构体,其中一部分是 state。

这是咱们的输入密文:8D 63 D7 56 DB 55 CD 06 56 70 B9 74 E6 24 B5 86,它被放在了s中。

除此之外,s在门径中多数参与运算。相比适应 state 策画、中间存储和传输的功能需求。要是咱们判断造作,那也问题不大,大不了再行猜嘛。

咱们并不会像例一那样,修改s指向的前十六个字节块,因为咱们不雅察到,输入密文被放到了内存中第1-4、9-12、17-20、25-28这四块偏移里。

debug稽查第九轮肇始处 s 的情况:

int 在内存里是小端序,是以注入故障,将0xa273eb53 修改成 0xa273eb52,修改了最低的一字节。

运行稽查结果,解密时和加密同理,会有四个字节发生更变,但所更变的四个字节和加密过程中不同,不必死记硬背,径直把正确输出输出和故障输出放入 phoenixAES,crack_file的第三个参数传入False,代表这是一个解密过程。

运行

可以发现,日记相配了了的告诉咱们,这是一个及格的故障明文,适应解密场景。而且下一样还说,它属于”group 0“,即四种模式中的第一种。

为什么 phoenixAES 能作念到?因为在它里面保存了对应关系

这给咱们带来了两点启发

要是记不住加密以及解密到底有哪几种故障模式,以致记不住到底影响了几个字节,那就把正确输入和故障输入塞给phoenixAES,让它来判断,但一定要凭证加解密模式传入正确的第三个参数给crack_file API。 要是没法判断一个门径是白盒化加密照旧白盒化解密,可以通过故障输出属于加密照旧解密的故障模式来判断。

接下来屡次修改state,记载输出的故障明文

记载的结果喂给phoenixAES

运行

在DFA作用于解密函数时,径直求得运行轮密钥K_0,按照AES密钥编排章程即是密钥自身。

可以作念一下考据,咱们写的Aes-128Encrypt没处联贯密过程,但咱们可以倒着测试,考据输出的明文+求出的Key 加密后是否等于输入,结果统共适应。

示例三

第三个例子是老版块的sgmain里的一个白盒AES,来具体看一下,主函数如下:

这个例子比前边两个难度大一些,前边的例子里,门径给与十六字节的输入,输出十六字节,即统共适应AES自身的界说。然而要是输入并非16字节呢?比如32字节或者45字节。咱们需要追思一下分组和填充的关系学问。

一种加密算法或哈希算法,潜在的、待处理的明文长度是自便且近乎无尽的。有限的门径逻辑如那边理无尽长的数据?这时常离不开轮回。要是按照某个单元长度折柳红”数块“后轮回处理,这即是分组加密,所谓的某个单元长度即是分组长度。每个数据块被处理后的密文块拼接在一皆,即是完整密文,要是只保留终末一个密文块,那就近似哈希算法。

分组势必存在两个问题

待处理的明文并不总能被有时分红多组 不同组之间是否联系联

假设分组大小为8字节,输入如下

分组后

可以发现,第二个块不完整。因此咱们需要填充——把明文填充成可以被完整分割的多个块,因为只接管固定长度的输入。填充的决议好多,每个东谈主都能假想我方的填充决议,但有一个硬性条目——解密时,得能区分哪部分是原文,哪部分是填充。底下盘货一些填充决议

当先是补零决议

在终末一个颓残块后补0到适应分组长度,这即是补零填充,解密时删掉末尾的零就行。

但要是明文如下呢?

补零填充后即是

那解密时,怎么区分补上去的零和原文末尾本就有的零呢?除非约法三章,条目输入不以字节0结果,不然就只能换个填充决议。

来看咱们的新决议——补零+长度决议,假设末尾应该填充4个零字节,那么新决议就只填充3个,终末一字节存储所填充的总长度,此处即是4。

这个新决议真可以,即使输入以零结果也不影响咱们区分填充和原文各自的部分。但还有一个隐患,要是明文有时可以被完整分红数个组呢?这种情况下如那边理?

当先咱们得问,能不补吗?能不补天然不补,大师都知谈,决议越约略,缝隙越少。底下举个例子,看不补行不可。

明文A

明文B

明文A有时两个分组长度,咱们选拔不补;明文B终末一个块空泛两字节,补完即

晦气了,咱们根柢没办法区分这两组明文,这较着是不可接管的。因此即使输入有时得志分组长度,也必须作念填充。新章程如下:当明文有时可以被分红多个完整的组时,就认定为空泛”一组“,明文A在这种政策下被补成

这就贬责了上头拖迂缓拉的问题,终末的决议——补零+补长度+有时适应分组长度时补一个分组 ,这是一个完善的好决议!只能惜咱们生的太晚,前东谈主也曾料想了这个决议,并将它定名为ANSI X9.23。

现行的,最通用世俗的填充门径是PKCS7,它比ANSI X9.23更优雅那么一些(填充0给东谈主一种很暗昧的嗅觉)。

假设明文为

距离完整8字节分组少了4个字节,那么填充4个字节,且每个字节均为4。

假设明文为

那么填充 8个字节,每个字节均为 8

不论是PKCS7照旧ANSI X9.23,只须分组长度不卓越0xFF,都是可行的好决议,一朝分组长度卓越0xFF,咱们就没办法用一个字节示意长度了。除此之外,要是PKCS7的分组长度固定为8字节时,这个决议也叫PKCS5,因为AES分组长度固定为16字节,是以没法遵循PKCS5。换言之,要是对AES采选PKCS5, 那么AES也不会遵循,本色上采选PKCS7。

上头咱们处理了“待处理的明文并不总能被有时分红多组”,接下来商酌“不同组之间是否联系联”这个问题。

这是个由分组滋生出来的进犯问题,叫作念责任模式。当先,咱们的朴素想法是,不同块之间分别加密,结果约略拼接在一皆。

这种朴素的决议叫ECB,它有很大的优点,多数明文分组可以并走运算,并行加密。但它存在致命劣势,由于明文块相互之间颓败,是以调换的明文块会被加密成调换的密文块。那么,假设密文中有两个内容块数据一致,就可以反推对应明文内容也一致,这在某些情况下足以实施伪造和诓骗。

除此之外,业界心爱展示ECB加密后的图片,这会了了阐扬它的症结。图片文献中,左近区块的内容通常一致,密文也一致,这使得图片概述了了可见,如下是经典的企鹅加密图。

固然有劣势,但使用ECB的情况照旧不少,因为好多建树东谈主员并不防备安全。除了它之外,使用最多的模式是CBC。在这个模式中,每个明文块在运算前,先与前一个分组的输出结果作念异或运算。因此,调换的分组内容不会带来调换输出,除非两者的前一个分组也调换。咱们发现CBC中存在一个问题,终末一个输入块和前一个输出块异或,第二个输入块和第一个输出块异或,那么,第一个输入块和谁异或呢?为了处理这个问题,使用者需要传入一个和分组等长的字节串,供其异或,学名叫运行化向量,缩写IV。

通盘这个词情况如下图所示,“圈加”象征在密码学图示中出现频率很高,一般指异或运算。

除此之外还存在数种责任模式,有各式各样的优点,安全性以致比CBC更好,但在SO中出现频率远不如ECB和CBC,这里不去提了。

复习完分组和填充的关系学问,咱们回到例三。分组模式和填充会给DFA膺惩带来什么影响,这是咱们最暖热的内容。当先,DFA膺惩时,咱们不雅察十六字节在故障注入后的密文变化,要是门径存在多个分组的输入,那多个分组的输出会影响咱们蓄积和考据故障输出。因此咱们十分但愿门径的输入只须一个分组。因此咱们要适度输入,在1-15个字节之间,这样填充后只会进行一个分组的加密或解密运算。(输入十六个字节时,会被填充一整组,终末导致两组加密。)

再商酌CBC模式中的IV对咱们的影响。DFA不关注输入,暖热的是正确输出和故障输出。在加密过程中,IV会影响考据DFA求出的密钥是否正确。在解密过程中,需要找到故障输出而非IV异或后的输出。听起来有些绕,但简而言之,为了减少IV的过问,我提议在CBC模式中,将IV全填充为0后再作念DFA。需要隆重,这是指的不是字符串0,而是字节0。

如下所示,咱们将IV改周详0数组,输入改成十五字节,因为样本采选PKCS7_padding,可以料想,明文末尾会填充01。不坦然的可以自行debug。

底下追思到泛泛的DFA经过。

当先是寻找“轮”:

这份代码抠的很漂亮,咱们发现主体是九轮运算,前边两个例子都是十轮运算,这里却少了一轮。不枢纽,咱们照旧试着在第九轮开头时作念故障注入,要是后果分歧,就推前到第八轮。归正可以凭证结果来判断时机早了照旧晚了,大不了多试几次。

代码的定名很了了,咱们不必刻意找state在哪。

当先记载正确输出

73cc1e47c49d6675de5a14273c3b046c

底下开头注入故障:

65cc1e47c49d662bde5a40273cdf046c

这个结果既老练又让东谈主得意,这不即是加密过程中故障注入告捷所呈现的四种模式中的第一种嘛。

底下无间,故障注入记载如下

将正确密文和八个故障密文丢入phoenixAES

运行

放入stark

即密钥 445352704242354C364731654E303657。

使用Aes-128Encrypt 考据,明文别忘了是30313233343536373839616263646501

结果统和谐致。

四、使用Unidbg进行DFA 膺惩

源码进行 DFA 膺惩的阶段终结,接下来,咱们约略参议使用Unidbg处理DFA。

案例的代码如下,Unidbg中有另一个办法可以匡助”找时机“。我先卖个关子,大师先往下看。

当先和前文一样,Call wbaes_encrypt_ecb。

运行结果:

可以发现策画结果统和谐致。

接下来咱们要作图,读者可能会困惑,作念什么图?事实上,因为白盒加密的主要达成形态是查表法,是以加密主体即是多数的内存访谒。那么记载函数对内存的访谒以及发起访谒的地址(PC指针),绘画成折线图,就可以较好的反应加密经过。

使用Unidbg的ReadHook:

章程如下:监控通盘这个词SO地址范围内的内存读取操作,记载其发起地址,我减去了SO基地址,只打印偏移,这样呈现后果更好。

traceAESRead 函数放于如下位置:

运行结果如图:

将这几千札记载拷贝出来,保存在trace.txt 中,在Python中作念可视化,这十分约略。需要安设matplotlib以及numpy库。

运行青年景折线图,将其放大是如下后果

X轴的计数单元是次数,示意现时是第几次内存访谒,如图,在门径的运行过程中,发生了1400余次对SO内存的读操作。Y轴是发起访谒的偏移地址。需要隆重,X与Y轴的数值示意为十进制。图上可得,Y主要在80000-100000之间,咱们修改Y轴范围,增强呈现后果。

运行后

似乎还可以收缩到85000-90000之间,再次收缩Y的范围

这样看着欢喜多了,咱们对它进行分析。

当先,可以相比较着的看到,存在十个叠加的模式,这代表了十轮运算。这少许是有效的,可用于区分AES-128/192/256,分别对应10/12/14 轮。

除此之外,咱们发现每轮运算的起初是一个较低的地址,具体在86000近邻傍边,转成十六进制即是0x14FF0近邻。

在IDA 中稽查该处,咱们发现恰是上一篇中所分析的wbShiftRows中。这即是我说的”Unidbg中的另一个好办法“,这成绩于Unidbg中赢得扩充流相配容易。

接下来就再次来到故障膺惩的部分,通盘这个词代码近似于Frida Hook代码的复刻。

将正确密文与运行出的故障密文放入phoenixAES以及stark,可以得到和前文调换的结果。

五、总结

在这篇著述中,咱们主要处理了用什么器用达成故障,以及拿获故障密文,并分别用源码以及 Unidbg 的形态进行了DFA 膺惩演练。然而也只学了很少对于白盒、对于分析白盒密钥的学问,当你真确需要逆向一个白盒加密时,无法处理的概率广泛于能处理的概率,在白盒里面会进行多维度的防患。接下来咱们将尝试涵养白盒 aes具体的达成想路,一步步看一下怎么将逻辑操作退换成查表操作,以及怎么应酬 DFA 等膺惩步履,本想两篇著述涵养终结91 萝莉,奈何篇幅过于长...