RC4加密算法及逆向方法初探
看来可以写一个系列了
之前的两篇
算法分析
基本介绍
RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。 —-wiki https://zh.wikipedia.org/zh-hans/RC4
加密(解密)原理
RC4由伪随机数生成器和异或运算组成。RC4的密钥长度可变,范围是[1,255]。RC4一个字节一个字节地加解密。给定一个密钥,伪随机数生成器接受密钥并产生一个S盒。S盒用来加密数据,而且在加密过程中S盒会变化。
由于异或运算的对合性,RC4加密解密使用同一套算法。
C代码表示
先来看内部的几个基本变量
S-Box 也就是所谓的S盒,是一个256长度的char型数组,每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换。
密钥K char key[256] 密钥的长度keylen与明文长度、密钥流的长度没有必然关系
临时向量k 长度也为256,每个单元也是一个字节。如果密钥的长度是256字节,就直接把密钥的值赋给k,否则,轮转地将密钥的每个字节赋给k
1. 初始化
包含三个参数
参数1是一个256长度的char型数组,定义为: unsigned char sBox[256];
参数2是密钥,其内容可以随便定义:char key[256];
参数3是密钥的长度,Len = strlen(key);
初始化长度为256的S盒。第一个for循环将0到255的互不重复的元素装入S盒。第二个for循环根据密钥打乱S盒。
i确保S-box的每个元素都得到处理,j保证S-box的搅乱是随机的。
void rc4_init(unsigned char *s,unsigned char *key, unsigned long Len) |
2. 加解密
包含三个参数
参数1是上边rc4_init函数中,被搅乱的S-box;
参数2是需要加密的数据data;
参数3是data的长度.
每收到一个字节,就进行while循环。通过一定的算法定位S盒中的一个元素,并与输入字节异或,得到k。循环中还改变了S盒。如果输入的是明文,输出的就是密文;如果输入的是密文,输出的就是明文。
void rc4_crypt(unsigned char *s,unsigned char *Data,unsigned long Len) |
3. 主函数
int main() |
逆向分析
拿今年九月安恒杯 NewDriver这道来看
栈平衡一下,然后f5
限制输入33位
base64加密
rc4加密
base64改了密码表,但结构很清晰,具体识别方法看我上一篇
rc4共有两个函数 sub_E41000,sub_E410E0
下面来具体分析这两个函数,具体解释都放在图里了,看图即可。
sub_E41000 初始化
函数头如下,三个值sub_E41000(&v6, &v10, strlen(&v10));
对应上面源码void rc4_init(unsigned char *s,unsigned char *key, unsigned long Len)
伪代码
反汇编
将0到255的互不重复的元素装入S盒
打乱S盒
sub_E410E0 加密
sub_E410E0(&v6, v3, strlen(v3));
对应上面源码void rc4_crypt(unsigned char *s,unsigned char *Data,unsigned long Len)
伪代码
int __usercall sub_E410E0@<eax>(int result@<eax>, int a2, unsigned int a3) |
伪代码看的就很清晰了,IDA分析时将数组按指针形式显示
反汇编
0FFFFFF00h取负就是256
魔改RC4
其实RC4魔改还是比较难的,稍有改变,整个算法就完全不同了。因此,大多数赛题将rc4与其他算法进行组合来加密flag
常见变化位置
- 密钥经过上一步的其他加密后传入
- s盒内部数据固定
- rc4加密后数据进行重加密
总结
个人感觉rc4重点理解算法即可,并且对内部多次限制256次循环,mod256,以及对数据strlen的读取的特点注意即可
参考网址:
https://zh.wikipedia.org/zh-hans/RC4
https://zh.wikipedia.org/wiki/S%E7%9B%92
https://ctf-wiki.github.io/ctf-wiki/crypto/streamcipher/special/rc4/