概念:

在密码学中,RC4(Rivest Cipher 4)是一种流加密算法,密钥长度可变,它加解密使用相同的密钥,因此也属于对称加密算法,RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。
补充说明:序列密码(流密码):
流密码也属于对称密码,但与分组加密算法不同的是,流密码不对明文数据进行分组,而是用密钥生成与明文一样长短的密码流对明文进行加密,加解密使用相同的密钥。也就是说,RC4不是对明文进行分组处理,而是字节流的方式依次加密明文中的每一个字节,解密的时候也是依次对密文中的每一个字节进行解密

C语言实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdio.h>

#include <stdint.h>



void rc4_init(uint8_t*s,uint8_t*key,uint32_t len)

{

    int i;

    int j=0;

    char k[256];

    uint8_t tmp;



    for(i=0;i<256;i++)

    {

        s[i]=i;

        k[i]=key[i%len];//sbox初始化

    }

    for (i=0;i<256;i++)

    {

        j=(j+s[i]+k[i])%256;

        tmp=s[i];

        s[i]=s[j];

        s[j]=tmp;//密钥流:根据密钥打乱sbox

    }

}



void rc4_crypt(uint8_t*s,uint8_t*buf,uint32_t len)//prga开始加密密文

{

    int i=0,j=0,t=0;

    uint32_t k=0;

    uint8_t tmp;



    for (k=0;k<len;k++)

    {

        i=(i+1)%256;

        j=(j+s[i])%256;



        tmp=s[i];

        s[i]=s[j];

        s[j]=tmp;//打乱sbox



        t=(s[i]+s[j])%256;

        buf[k]^=s[t];//遍历待输入数组(明文)的每一个字节,之后从sbox里选出字节与之异或



    }

}

// int main() {

//     uint8_t s[256];

//     uint8_t key[] = "testkey";

//     rc4_init(s, key, 7);

//     // 打印前几个s的值验证一下

//     for(int i = 0; i < 10; i++) {

//         printf("%02x ", s[i]);

//     }

//     printf("\n");

//     return 0;

// }

python实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def KSA(key):

    key_length = len(key)

        # 初始化S盒

    S = list(range(256))

    j = 0

    for i in range(256):

        j = (j + S[i] + key[i % key_length]) % 256

        S[i], S[j] = S[j], S[i]

    return S



def PRGA(S):

    i = 0

    j = 0

    while True:

        i = (i + 1) % 256

        j = (j + S[i]) % 256

        S[i], S[j] = S[j], S[i]

        K = S[(S[i] + S[j]) % 256]

        yield K



def RC4(key, data):

    S = KSA(key)

    keystream = PRGA(S)

    res = []

    for c in data:

        res.append(c ^ next(keystream))

    return bytes(res)



key = b'密钥'

encrypted_data = b'数据' # 注意是 bytes 类型的



decrypted_data = RC4(key, encrypted_data)

print(decrypted_data)

识别特征:

该算法在初始化s盒的时候有一个循环次数为256次的for循环
之后根据密钥打乱s盒
最后遍历输入明文的每个字节,从s盒中取一个字节与之异或,完成加密
RC4的加密操作和解密操作一致,因此有时候在动调可以直接下断点在rc4加密之后实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
int __fastcall main(int argc, const char **argv, const char **envp)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

n10 = 0LL;
v14[0] = 0x79656B74736574LL;
v4 = 0;
n256_1 = 0;
n256 = 256LL;
do
{
n256_2 = n256_1;
*(&v14[34] + n256_1) = n256_1;
n256_3 = n256_1;
v9 = n256_1 / 7;
++n256_1;
*(&v14[2] + n256_2) = *(v14 + n256_3 - 7 * v9);
}
while ( n256_1 < 256 );

v10 = 0LL;
do
{
v11 = *(&v14[34] + v10);
v4 = (v11 + *(&v14[2] + v10) + v4) % 256;
v12 = &v14[34] + v4;
*(&v14[34] + v10++) = *v12;
*v12 = v11;
--n256;
}
while ( n256 );

do
{
sub_140001010("%02x ");
++n10;
}
while ( n10 < 10 );

sub_140001010("\n");
return 0;
}

这里是ida里呈现的伪代码
像在学这种对称密码时,我们可以直接用c实现一下,其次托ida里分析它的反汇编以及伪代码,以此来寻找他们的特征

python解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.Cipher import ARC4

key=b''#这里输入密钥

cipher=bytes.fromhex("")#这里输入密文的十六进制

rc4=ARC4.new(key)

plain=rc4.decrypt(cipher)



print(plain)

由于CTF比赛里rc4经常出变种
因而大多用不到库函数,所以就要自己写rc4,因此建议各位去学习如何写rc4变种的解密(就从加密中学习就行)