【病毒分析】NotPetya 勒索病毒Salsa20算法实现的缺陷分析

http://p5.qhimg.com/t01b645c930c6e166b5.jpg

作者:Shi Lei && pwd && K-one@360CERT

 

0x00 背景

 

2017年6月份,NotPetya勒索病毒试图通过The Shadow Brokers泄露出的“永恒之蓝”等漏洞再次攻击全球网络系统。目前,关于NotPetya的算法解密工作目前并没有明确的解密进展。

360CERT团队在对NotPetya病毒所自定义实现的Salsa20算法分析过程中,发现存在两处变化。其中一处明显降低了标准Salsa20算法的加密强度,在一定条件下可以对加密数据进行解密。

 

0x01 Salsa20的简单介绍

 

Salsa20的原理是产生一种伪随机的字节流。 这种字节流在很长(约2的70次方)范围内和真正的随机字节流无法区分。 这样做到了和一次一密密码本(OTP,One Time Pad)加密等价的效果。

伪随机数流的产生其实就是将64字节(512比特)的输入送入核心函数,然后得到512比特的输出的过程。 每次输入的字节包含密钥、初始向量和计数器。 这样,要产生长度是N字节的伪随机数流,只需要调用核心函数若干次,直到获取了足够长度(不少于N)的输出即可。

64字节的输入如下:

 http://p5.qhimg.com/t01dd44897d929fe920.png

本文所讨论的差异就是上面64字节产生的不同,核心函数都是相同的。

 

0x02 差异一:常量不同

 

原算法的常量:

 http://p7.qhimg.com/t015733656f16d1bace.png

样本的常量:

 http://p5.qhimg.com/t011b857692d3cb9229.png

结论】对算法的强度没有影响

 

0x03 差异二:小端化函数不同

 

原算法s20_littleendian函数:

 https://p3.ssl.qhimg.com/t01f731edaef8858862.png

样本s20_littleendian函数:

 https://p2.ssl.qhimg.com/t0121c569cf7a186fdc.png

差异】样本中原本是想模拟原算法的操作,但因为要在MBR中运行,采用了WORD为单位的运算,shl ax 10h时就会把ax清零。这样导致的后果就是64字节的输入的高位WORD会被填充为0,相当于将原函数改为:

 

https://p1.ssl.qhimg.com/t01a516c2de1c3faf96.png

效果】原先的64字节输入:

0xdeadbeef 0xdeadbeef……0xdeadbeef(一共16个0xdeadbeef)

经过s20_littleendian函数后:

0x0000beef 0x0000beef ……0x0000beef(一共16个0x0000beef)

影响】进入核心函数后:

 https://p2.ssl.qhimg.com/t011e70695f41118279.png

虽然输入的随机序列有一半为零,但是经过1轮异或移位的操作,随机序列已经不含零了。并且该算法要进行10轮这样的操作,所以得到的序列随机化程度还是很高。

进入核心函数前:

 https://p1.ssl.qhimg.com/t010e8ed508778a653c.png

经过一轮异或移位操作后:

 https://p4.ssl.qhimg.com/t01933ea952390f1ea1.png

结论】 64字节的输入经过小端化函数后会导致高位2个字节清零。这样的话,爆破该输入的规模就从2的256次方降为了2的128次方,约为10的38次方,所以直接爆破出密钥的可能性几乎没有。

 

0x04“修改版”Salsa20算法的缺陷攻击

 

NotPetya勒索病毒的修改版Salsa20算法造成的差异会导致每隔64K块出现重复的核心函数输入项,这将极大影响这种加密算法的安全性。对此,算法攻击者只要已知连续4MB明文,就能解密全部密文。另外若已知若干离散明文块,则可解密部分密文,也可能解密全部密文(已知部分分布合适的情况)。

相关证明如下:

 https://p3.ssl.qhimg.com/t01bb6cf548997e996e.png

0x05 与Petya中修改Salsa进行对比

 

Petya中修改的Salsa分析链接:

http://www.freebuf.com/vuls/101714.html

(1)秘钥空间不同

Petya中为了方便用户输入,字符必须从数字和大小写字母中选取,定义了54种有效字符:

 https://p4.ssl.qhimg.com/t01490f877e2ab3b281.png

来作为8位的原始秘钥,同时用低位为b与字符“z”对应ASCII(122)之和,高位为b*2来扩展成16字节的秘钥。其实只有8个秘钥需要破解,所以秘钥空间为:54^8。

NotPetya中,一共是32个字节,但是由于清零了一半,所以一共是16个字节需要破解,秘钥空间为2^128。

(2)输出数据不同

Petya中采用了2字节的WORD作为数据基本长度,在输出结果中字段从2字节扩展为4个字节,其高位WORD会被填充为0,在接下来的异或操作中,就会暴露出明文的特征。

NotPetya中在核心函数中保持着4个字节的基本长度,所以输出结果的高位不会被填充为零。可以正常加密。

综上两点区别,Petya可以被暴力破解,而NotPetya很难被暴力破解,Petya的具体破解代码:

https://github.com/leo-stone/hack-petya

这里的破解算法引用了第三方库,

https://github.com/handcraftsman/GeneticGo

https://github.com/willf/bitset

 

0x06 其他破解的可能性

 

(1)截断差分攻击

这种攻击是针对较少轮次的Salsa20,参考资料认为能攻击到8轮的Salsa20,样本进行了20轮,所以这种攻击实现的可能性小。

(2)滑动攻击

 https://p5.ssl.qhimg.com/t01b4d62442419be105.png

这使得破解Salsa20在理论上存在可能,参考文献里也给了具体的算法来计算。

 

0x07 参考文档

[1] www.freebuf.com/vuls/101714.html

[2]穆昭薇. 流密码算法Salsa20的安全性研究[D].西安电子科技大学,2011.

(完)