算法还原之RC4
一 简介
一次一密
对称加密算法:使用最广泛的流密码就是RC4
优点:密钥随机产生,只使用一次;无条件安全、加解密位加法运算效率高
缺点:要求密钥至少与明文一样长,密钥共享困难
流密码(序列密码)
- 流密码基本思想:
密钥流发生器f产生zi=f(k,σ \sigmaσi),即种子密钥k产生密钥流z=z0z1z2…
加密y=y0y1y2…=Ez0(x0)Ez1(x1)Ez2(x2)…
- 有内部记忆原件的为流密码,否则分组密码
- 内部记忆原件状态σ \sigmaσi独立于明文的称同步流密码,否则自同步流密码
- 同步流密码加密器=滚动密钥生成器+加密变换器
- 二元加法流密码,加密变换yi=zi⨁ \bigoplus⨁xi
- 一次一密是加法流密码原型,若zi=ki,则加法流密码就退化成一次一密
- 密钥流序列性质:极大的周期、良好的统计特性、抗线性分析、抗统计分析
- 一次一密的密钥长度和明文一样长,流密码不是,需要种子密钥通过密钥生成器产生密钥流
二 RC4算法原理
介绍
首先,RC4算法所依赖的最根本原理是:对明文使用同一个密钥异或两次最后仍是得到原文。即生成密钥之后,由密钥与明文异或后生成密文(加密过程),由同一密钥与密文异或后得到明文(解密过程)。
在介绍RC4算法原理之前,先看看算法中的几个关键变量:
1、密钥流:RC4算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是500字节,那么密钥流也是500字节。当然,加密生成的密文也是500字节,因为密文第i字节=明文第i字节^密钥流第i字节;
2、状态向量S:长度为256,S[0],S[1]…..S[255]。每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换;
3、临时向量T:长度也为256,每个单元也是一个字节。如果密钥的长度是256字节,就直接把密钥的值赋给T,否则,轮转地将密钥的每个字节赋给T;
4、密钥K:长度为1-256字节,注意密钥的长度keylen与明文长度、密钥流的长度没有必然关系,通常密钥的长度趣味16字节(128比特)。
实现步骤
下面是对RC4算法具体实现的简单介绍:
1、先初始化状态向量S(256个字节,用来作为密钥流生成的种子1)
按照升序,给每个字节赋值0,1,2,3,4,5,6…..,254,255
2、初始密钥(由用户输入),长度任意。如果输入长度小于256个字节,则进行轮转,直到填满。例如输入密钥的是“1,2,3,4,5”, 那么填入的是1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5……..
由上述轮转过程得到256个字节的向量T(用来作为密钥流生成的种子2)。
3、开始对状态向量S进行置换操作(用来打乱初始种子1),按照下列规则进行:
从第零个字节开始,执行256次,保证每个字节都得到处理
4、最后是秘钥流的生成与加密。
上面四个步骤简单总结一下:
- 第一步:生成了初始状态向量S
- 第二步:输入初始密钥,生成临时向量T
- 第三步:对状态向量S进行置换操作,打乱初始种子,生成S’
- 第四步:使用明文和S‘生成最终加密的密钥流
- 第五步:使用密钥流对明文进行异或,实现最终加密。
代码实现
具体实现代码如下:RC4加解密算法
解密按照前面写的,异或两次就是原文,所以只要把密钥流重新拿过来异或一次就能得到原文了
下面是调用python简单实现的上述所说:
def gen_S(): |
三 实现标准RC4算法
|
四 RC4算法汇编分析
上图中的代码是没有进行变量抽取之前的,可以看到函数名都还是可以看到的。
可以在代码中加上如下代码,进行变量抽取:
set (CMAKE_CXX_FLAGS "$(CMAKE_CXX_FLAGS" -fvisibility=hidden) |
整个汇编代码基本和C的区别不大,这块就不细看了。。。。
RC4算法的特征有:
- 首先根据原理我们可以看到会初始化一个256字节的数组
- 其次会将一个key也填充到数组中
- 函数的话大概率都是两个参数,一个是key 一个是keylen
具体分析,可以见逆向分析中的密码学—RC4_rc4逆向-CSDN博客
五 总结
RC4算法本身实现并不复杂,只要熟悉其加密/解密流程,逆向分析过程中一般都能很好的进行识别。
分析其它标准加密算法基本也是同样的流程,对于自定义的一些加密算法就需要耐心的跟踪分析了。
另外对于标准加密算法,也可以借助PEID的“Krypto ANALyzer”插件,或者IDA的“FindCrypt2”插件进行识别,使用这些插件能够更好地提高工作效率。
一般不怎么会在渗透过程中遇到RC4算法的,主要不方便,还要求一次一密。。。