算法详解

RC4是一种流加密算法,其工作原理可以分为两个主要部分:密钥调度算法KSA和伪随机生成算法PRGA

  1. KSA密钥调度算法:

    初始化一个256字节的数组S,S[i] = i。

    根据密钥对S进行混排。通过循环交换S数组中的元素,确保密钥影响S的内容。

  2. PRGA伪随机生成算法:

    使用KSA生成的S数组,通过循环更新和交换元素生成伪随机字节。

    生成的字节与明文进行异或运算,得到密文。

RC4的加密和解密过程相同,因为它是基于与伪随机流的异或运算。

实战识别

在逆向分析实战中判断RC4算法的可从其会初始化一个256字节的数组将一个key填充到数组中以及加密函数大概率有两个参数,一个是key 一个是keylen

代码实现

下面是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
#include <stdio.h>
#include <stdlib.h>

void swap(unsigned char* a, unsigned char* b) // 交换两个字节
{
unsigned char temp = *a;
*a = *b;
*b = temp;
}

void RC4_enc(unsigned char* plaintext, int length, const char* key) // RC4加密函数
{
int i, j;
unsigned char* S;
unsigned char k[256];
int keylen = 0;

while (key[keylen] != '\0')
{
keylen++;
}// 计算密钥长度

for (i = 0; i < 256; i++)
{
k[i] = key[i % keylen];
} // 初始化密钥数组k

S = (unsigned char*)malloc(256 * sizeof(unsigned char));
for (i = 0; i < 256; i++) {
S[i] = i;
}// 初始化S盒

j = 0;
for (i = 0; i < 256; i++) {
j = (j + S[i] + k[i]) % 256;
swap(&S[i], &S[j]);
}// 打乱S盒

i = 0;
j = 0;
for (int n = 0; n < length; n++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
swap(&S[i], &S[j]);
int t = (S[i] + S[j]) % 256;
plaintext[n] ^= S[t];
}// 进行加密

free(S);
}

int main() {
unsigned char plaintext[] =
{
0x11,0x45,0x14
};//此处为密文
const char key[] = "Key"; //此处为秘钥
RC4_enc(plaintext, sizeof(plaintext), key);

for (int i = 0; i < sizeof(plaintext); i++)
printf("%02X ", plaintext[i]);
printf("\n"); // 输出加密后的密文

return 0;
}

由于RC4加密具有自反性,所以解密过程与加密过程相同,只需要将密文作为明文,秘钥作为密钥即可

例题

[XYCTF2025]WARMUP

搜索VBS相关知识可得:

修改后运行得到以下内容:

一眼RC4

[FSCTF 2023]EZRC4

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)
{
unsigned __int8 data[27]; // [rsp+20h] [rbp-40h] BYREF
unsigned __int8 key[17]; // [rsp+40h] [rbp-20h] BYREF
unsigned int key_len; // [rsp+5Ch] [rbp-4h]

_main();
strcpy((char *)key, "wanyuanshenwande");
key_len = 16;
puts("what is this?");
data[0] = 0xEB;
data[1] = 13;
data[2] = 97;
data[3] = 41;
data[4] = -65;
data[5] = -101;
data[6] = 5;
data[7] = 34;
data[8] = -13;
data[9] = 50;
data[10] = 40;
data[11] = -105;
data[12] = -29;
data[13] = -122;
data[14] = 77;
data[15] = 45;
data[16] = 90;
data[17] = 42;
data[18] = -93;
data[19] = 85;
data[20] = -86;
data[21] = -43;
data[22] = -76;
data[23] = 108;
data[24] = -117;
data[25] = 81;
data[26] = -79;
rc4_crypt(data, 0x1Bu, key, 0x10u);
putchar(10);
return 0;
//flag{I_L0VE_gensh1n_Imp4ct}
}

贴脸告诉密文和秘钥,标准的RC4

[HZNUCTF 2023 final]signin

UPX头修正+动调+RC4

学习了UPX头的知识后用010Editor将三处要修改的地方改为UPX

动调得到密文

由反汇编代码直接可以看到秘钥为justfortest

用RC4解密脚本解密