侧信道攻击,从喊666到入门之——错误注入攻击白盒

2019 年 10 月 10 日 小米安全中心

0x00 前言


上文中,我们介绍了有关Unicorn的使用,为了避免只造轮子不开车的现象出现,我们就用Unicorn来亲手攻击一个AES白盒。

我选取了CHES 2016竞赛中的AES白盒,这个白盒非常白甚至给了源码,代码和程序可以在"https://github.com/SideChannelMarvels/Deadpool/tree/master/wbs_aes_ches2016" [1]中找到。文章中还包含里Writeup,但是其中使用的工具很老了,还是python2的代码,并且使用的执行引擎是PIN,如果是ARM的安卓APP里的白盒就没办法了。

0x001 啊呜,数学

所有计算均在——有限域GF(2^8)

在进行白盒破解之前,我们看一下错误注入的原理是什么。

对于AES128来说,错误注入的目标在第九轮的MixColumns计算之前,第九轮的MixColumns计算之前的数据假设是这个样子的:

假设我们的错误正好命中了第一个字节,则数据流变成了:

之后,数据流会依次进入:

  • MixColumns

  • AddRoundKey K9

  • SubBytes

  • ShiftRows

  • AddRoundKey K10

中间的过程就不写了,有兴趣的通过可以自己推一下,如果熟悉AES的计算过程,不难推算。"https://blog.quarkslab.com/differential-fault-analysis-on-white-box-aes-implementations.html"[2]该文有详细的推导过程。

最后,AddRoundKey *K*10 结束之后输出,应该是这个样子的:

如果成功错误注入的话,会变成这个样子(其中的+号表示异或):

以第一个字节为例,我们设

之后把OO’进行Xor计算:


得到:

设:

原式变为:

把剩下3个字节补齐,得到:

四个Y的取值都是0-255,遍历四个Y,就可以得到Z的一个取值范围 。得到Z的值范围了之后,可以对应一组Y。(再说一次,乘法和加法都在GF(2^8)上)。

之后通过关系公式:

推导出一组K10(0,7,10,13)密钥的值。

这只是错误出现在第一个Byte的情况,通过多组错误输出,可以唯一的推导所有的K10,之后通过密钥扩展算法,推导出AES的密钥。

这个地方有点绕,我们举个例子:

假设O13 ^O'13 = 0x55,我们尝试求一下:

sbox=(
    0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
    0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
    0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
    0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
    0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
    0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
    0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
    0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
    0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
    0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
    0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
    0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
    0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
    0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
    0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
    0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16)

a=[]
for y3 in range(256):
    #假设O13 ^ O'13 = 0x55
    a.append(sbox.index(0x55 ^ sbox[i]) ^ y3)
print(a)

计算得到了256个数,但是由于其中有的数是重复的,所以可以缩小Z的取值范围。拿到了Z之后,就可以推导出对应的Y,由于O是已知的,所以可以推出密钥或者缩小密钥的范围。

那么2Z3Z怎么计算?

这里的2,3与Z的关系是有限域中的乘法,所以计算求Z的时候,并不是简单的除一下就行了,而是域中的计算。需要涉及到生成多项式0x11B求逆元的计算。(推荐一本书,密码编码学与网络安全—原理与实践-第六版,写的很好。)

0x002 实践操作


我没有像"https://bbs.pediy.com/thread-254042.htm"[3]一样用fridaidapython去做,这样不太灵活。我使用了unicorn引擎,一般来说,白盒AES算法都会被封装在一个或者连续的几个函数中,这样对于Unicorn 是十分方便的。

我的目标没有选择上文中的wbDES,它太老了,而且DES的使用越来越少,我也没有使用参看文献中的基于OLLVM的实现,因为OLLVM混淆之后的AES也不是严格意义上的白盒,我选用了CHES 2016 CTF上的一道题。

首先对程序使用GDB进行分析,发现程序的main函数主要是获取输入和输出,加密过程chow_aes3_encrypt_wb函数中,在chow_aes3_encrypt_wb下断点。

(注:我没有使用github中提供的Shared object文件,而是使用源码,在makefile中添加了-no-pie参数,重新编译了一个executable文件)

之后在函数的执行结束的位置下断点。

发现程序使用RSIRDI进行传参,RSI保存的指针是输出缓冲区,RDI保存的指针是函数输出数据的位置。

之后开始栈空间的构建,具体构建的方法和调试请参考上一篇文章。

有错误注入攻击,一定需要能量分析攻击,在针对芯片的攻击中,SPA和DPA可以提供攻击位置信息,针对白盒的攻击也差不多,白盒的实现是针对查找表实现的,所以我们首先需要打印出来所有内存读的位置,这也是为了后续的攻击做准备。在hook中添加筛选条件:

if access == UC_MEM_READ and size == 1 and address<0xb0000000:

其中,size==1表示每次读取的大小是一个字节,因为AES是以字节为单位进行计算的;address<0xb0000000是为了排除程序在操作栈中数据时的误触发。

(左边数值是地址值的十进制表示,实际是从0x61a800(6400000)到0x6acfc0(7000000))这个图可以看出,查找表随着时间是从高地址向低地址分布的。

接下来,我们开始hook并错误注入,我们需要注入的是第九轮,也就是说,在时间上是比较靠后的位置,在这个过程中,我们需要不停的改变注入的位置,通过分析错误输出,来了解是否注入对了地方,如果正好输出了四个错误,并且位置符合,就是注入对了地方;如果错误的位置过多,表示注入的靠前了,如果错误的位置只有一个,说明注入的位置靠后了。

我们拿到了符合条件的错误输出值:

628caf41f9a2f7a51c57b9e23e137365
628cf341f961f7a5c157b9e23e137366
628c2f41f91ff7a5b557b9e23e13730e
628c1541f9caf7a56e57b9e23e1373b8
628c6e41f9b0f7a5d857b9e23e137323
628c1b41f961f7a5c457b9e23e1373aa
628c3d41f93ff7a57857b9e23e13730e
628c1e41f902f7a5bb57b9e23e13732b
628c8c41f9e4f7a5a757b9e23e137319
628ca341f948f7a56057b9e23e1373a2
628cc241f950f7a50f57b9e23e137319
628cbc41f9aef7a58157b9e23e13735a
628c4e41f9a1f7a50057b9e23e1373e3
628ccf41f914f7a57f57b9e23e137317
628cbc41f9aef7a58157b9e23e13735a
628caf4af9a286a51cf9b9e2d7137365
628cafd9f9a22aa51c3bb9e205137365
628cafd9f9a22aa51c3bb9e205137365
628cafd9f9a22aa51c3bb9e205137365
628caf85f9a27aa51cb4b9e2d4137365
628cafc2f9a245a51ce9b9e2f4137365
628cafd9f9a22aa51c3bb9e205137365
f88caf41f9a2f7441c5782e23ef47365
6c8caf41f9a2f7c71c57c6e23e297365
a68caf41f9a2f7781c57e6e23eb97365
828caf41f9a2f7391c5739e23ef27365
d48caf41f9a2f7931c57f7e23e8b7365    
3d8caf41f9a2f7061c5736e23ee87365
6236af4122a2f7a51c57b9b83e138f65
62faaf41bba2f7a51c57b9483e133365
6236af4122a2f7a51c57b9b83e138f65    
6296af41b6a2f7a51c57b9f93e138a65
6272af41b3a2f7a51c57b9493e13bb65
62f4af41ada2f7a51c57b9ef3e13bd65
6272af41b3a2f7a51c57b9493e13bb65
62c5af4167a2f7a51c57b93e3e133f65

拿到足够多的错误输出后,我使用了工具https://github.com/SideChannelMarvels/JeanGrey/tree/master/phoenixAES[4]进行上述的数学计算推导过程

得到第10轮密钥之后,使用工具aes_keyschedule推算出AES-128密钥。

0x003 参考


[1]https://github.com/SideChannelMarvels/Deadpool/tree/master/wbs_aes_ches2016

[2]https://blog.quarkslab.com/differential-fault-analysis-on-white-box-aes-implementations.html

[3]https://bbs.pediy.com/thread-254042.htm

[4]https://github.com/SideChannelMarvels/JeanGrey/tree/master/phoenixAES




登录查看更多
0

相关内容

白盒测试(也称为透明盒测试,玻璃盒测试,透明盒测试和结构测试)是一种软件测试方法,用于测试应用程序的内部结构或功能,而不是其功能(即黑盒测试)。在白盒测试中,系统的内部视角以及编程技能被用来设计测试用例。测试人员选择输入以遍历代码的路径并确定预期的输出。这类似于测试电路中的节点,在线测试(ICT)。白盒测试可以应用于软件测试过程的单元,集成和系统级别。尽管传统的测试人员倾向于将白盒测试视为在单元级别进行的,但如今它已越来越频繁地用于集成和系统测试。它可以测试单元内的路径,集成期间单元之间的路径以及系统级测试期间子系统之间的路径。
专知会员服务
42+阅读 · 2020年7月7日
[ICML-Google]先宽后窄:对深度薄网络的有效训练
专知会员服务
34+阅读 · 2020年7月5日
斯坦福2020硬课《分布式算法与优化》
专知会员服务
118+阅读 · 2020年5月6日
【中科院自动化所】视觉对抗样本生成技术概述
专知会员服务
35+阅读 · 2020年4月15日
【ICLR2020-哥伦比亚大学】多关系图神经网络CompGCN
专知会员服务
49+阅读 · 2020年4月2日
干货书《数据科学数学系基础》2020最新版,266页pdf
专知会员服务
319+阅读 · 2020年3月23日
【综述】基于图的对抗式攻击和防御,附22页论文下载
专知会员服务
68+阅读 · 2020年3月5日
模型压缩究竟在做什么?我们真的需要模型压缩么?
专知会员服务
27+阅读 · 2020年1月16日
专知会员服务
36+阅读 · 2019年12月13日
GAN 为什么需要如此多的噪声?
AI科技评论
14+阅读 · 2020年3月17日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
16+阅读 · 2019年5月13日
卷积神经网络四种卷积类型
炼数成金订阅号
18+阅读 · 2019年4月16日
差分隐私保护:从入门到脱坑
FreeBuf
17+阅读 · 2018年9月10日
干货 | 对抗样本的基本原理
AI科技评论
7+阅读 · 2018年6月9日
对抗样本引发的系列讨论
机器学习研究会
5+阅读 · 2018年3月22日
理解神经网络的激活函数
论智
7+阅读 · 2018年1月8日
蒙特卡罗方法入门
算法与数学之美
7+阅读 · 2017年9月26日
Deflecting Adversarial Attacks
Arxiv
8+阅读 · 2020年2月18日
Area Attention
Arxiv
5+阅读 · 2019年2月5日
Adversarial Metric Attack for Person Re-identification
VIP会员
相关VIP内容
专知会员服务
42+阅读 · 2020年7月7日
[ICML-Google]先宽后窄:对深度薄网络的有效训练
专知会员服务
34+阅读 · 2020年7月5日
斯坦福2020硬课《分布式算法与优化》
专知会员服务
118+阅读 · 2020年5月6日
【中科院自动化所】视觉对抗样本生成技术概述
专知会员服务
35+阅读 · 2020年4月15日
【ICLR2020-哥伦比亚大学】多关系图神经网络CompGCN
专知会员服务
49+阅读 · 2020年4月2日
干货书《数据科学数学系基础》2020最新版,266页pdf
专知会员服务
319+阅读 · 2020年3月23日
【综述】基于图的对抗式攻击和防御,附22页论文下载
专知会员服务
68+阅读 · 2020年3月5日
模型压缩究竟在做什么?我们真的需要模型压缩么?
专知会员服务
27+阅读 · 2020年1月16日
专知会员服务
36+阅读 · 2019年12月13日
相关资讯
GAN 为什么需要如此多的噪声?
AI科技评论
14+阅读 · 2020年3月17日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
16+阅读 · 2019年5月13日
卷积神经网络四种卷积类型
炼数成金订阅号
18+阅读 · 2019年4月16日
差分隐私保护:从入门到脱坑
FreeBuf
17+阅读 · 2018年9月10日
干货 | 对抗样本的基本原理
AI科技评论
7+阅读 · 2018年6月9日
对抗样本引发的系列讨论
机器学习研究会
5+阅读 · 2018年3月22日
理解神经网络的激活函数
论智
7+阅读 · 2018年1月8日
蒙特卡罗方法入门
算法与数学之美
7+阅读 · 2017年9月26日
Top
微信扫码咨询专知VIP会员