0%

re-rc4及其变种

re-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
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
// re_rc4.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

/*
S 状态向量
K 密钥
len 密钥长度
*/
void rc4_init(unsigned char* S, unsigned char* K, unsigned long len)
{
char T[256] = { 0 }; //临时向量T
unsigned char tmp = 0;
for(int i=0; i<256; i++)
{
S[i] = i;
T[i] = K[i%len];
}
int j = 0;
for(int i=0; i<256; i++)
{
j = (j + S[i] + T[i]) % 256;
int middle = S[i];
S[i] = S[j];
S[j] = middle;
}
}

void rc4_crypt(unsigned char* S, unsigned char* Data, unsigned long len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for(; k<len; k++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
t = (S[i] + S[j]) % 256;
Data[k] ^= S[t];
}
}
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 }; // S-box
char key[256] = { "justfortest" };
char pData[512] = "这是一个用来加密的数据Data";
unsigned long len = strlen(pData);
int i;

printf("pData=%s\n", pData);
printf("key=%s,length=%d\n\n", key, strlen(key));
rc4_init(s, (unsigned char*)key, strlen(key)); // 已经完成了初始化
printf("完成对S[i]的初始化,如下:\n\n");
for (i = 0; i < 256; i++)
{
printf("%02X", s[i]);
if (i && (i + 1) % 16 == 0)putchar('\n');
}
printf("\n\n");
for (i = 0; i < 256; i++) // 用s2[i]暂时保留经过初始化的s[i],很重要的!!!
{
s2[i] = s[i];
}
printf("已经初始化,现在加密:\n\n");
rc4_crypt(s, (unsigned char*)pData, len); // 加密
printf("pData=%s\n\n", pData);
printf("已经加密,现在解密:\n\n");
rc4_crypt(s2, (unsigned char*)pData, len); // 解密
printf("pData=%s\n\n", pData);
getchar();
return 0;
}

而这里,所以我们只需要截取

pData加密过后数据,key,2个变量我们就可以解密了

利用py2的Crypto库

1
2
3
4
5
6
7
8
#coding=utf-8
from Crypto.Cipher import *
data = "7C553E5F0EB4CCB977BF6BD960E0B968FB11CED2154B0EB5F73E51EE514D5A9C01A0C53AD038"
data= data.decode("hex")
key = "SimpleCryptography"
cipher = ARC4.new(key) #加载密钥
m = cipher.decrypt(data) #用该密钥解密
print(m)

或者py3

1
2
3
4
5
6
7
8
from Crypto.Cipher import ARC4
import binascii
import struct

#rc4 = ARC4.new(struct.pack("<Q", 0x6a757374666f7274657374))
rc4 = ARC4.new(b"SimpleCryptography")
data = binascii.unhexlify("7C553E5F0EB4CCB977BF6BD960E0B968FB11CED2154B0EB5F73E51EE514D5A9C01A0C53AD038")
print(rc4.decrypt(data))

为了应对变种,这里给出一份python2的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
# -*- coding: utf-8 -*-
import random, base64

def rc4_crypt(data, key):
"""RC4 algorithm"""
x = 0
box = range(256)
for i in range(256):
x = (x + box[i] + ord(key[i % len(key)])) % 256
temp = box[i]
box[i] = box[x]
box[x] = temp
x = y = 0
out = []
for char in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
temp = box[x]
box[x] = box[y]
box[y] = temp
out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))

return ''.join(out)

if __name__ == '__main__':
data="c9deea9964ca63e5b389a6ac6358a582fc4befb11334".decode("hex")
key = "Please input the flag:\n"
print(rc4_crypt(data,key))

python3

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
# coding: utf-8

# import base64
import binascii


def rc4_crypt(PlainBytes:bytes, KeyBytes:bytes) -> str:
'''[summary]
rc4 crypt
Arguments:
PlainBytes {[bytes]} -- [plain bytes]
KeyBytes {[bytes]} -- [key bytes]

Returns:
[string] -- [hex string]
'''

keystreamList = []
cipherList = []

keyLen = len(KeyBytes)
plainLen = len(PlainBytes)
S = list(range(256))

j = 0
for i in range(256):
j = (j + S[i] + KeyBytes[i % keyLen]) % 256
temp = S[i]
S[i] = S[j]
S[j] = S[i]
#S[i], S[j] = S[j], S[i]

i = 0
j = 0
for m in range(plainLen):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
cipherList.append(k ^ PlainBytes[m])

result_hexstr = ''.join(['%02x' % i for i in cipherList])
return result_hexstr.upper()


if __name__ == "__main__":
data = '43C8B53E236C4756B8FF24E5AA08A549'
key = '3C381919191918181818181817111111'
rc4_result = 'BC9CD0200AB174B467956B4CAE2178BE'
print(f'data:{data}\nkey:{key}\nrc4_original:{rc4_result}')
print("rc4 result:", rc4_crypt(binascii.a2b_hex(data), binascii.a2b_hex(key.upper())))

这样对着代码稍作改动就可以解密

变种rc4–写错的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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// re_rc4.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

/*
S 状态向量
K 密钥
len 密钥长度
*/
void rc4_init(unsigned char* S, unsigned char* K, unsigned long len)
{
char T[256] = { 0 }; //临时向量T
unsigned char tmp = 0;
for(int i=0; i<256; i++)
{
S[i] = i;
T[i] = K[i%len];
}
int j = 0;
for(int i=0; i<256; i++)
{
j = (j + S[i] + T[i]) % 256;
int middle = S[i];
S[i] = S[j];
S[j] = middle;
}
}

void rc4_crypt(unsigned char* S, unsigned char* Data, unsigned long len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for(; k<len; k++)
{
i = (i + 1) % 256;
j = (j + S[i]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
t = (S[i] + S[j]) % 256;
Data[k] ^= S[t];
}
}
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 }; // S-box
char key[256] = { "justfortest" };
char pData[512] = "这是一个用来加密的数据Data";
unsigned long len = strlen(pData);
int i;
rc4_init(s, (unsigned char*)key, strlen(key)); // 已经完成了初始化
for (i = 0; i < 256; i++) // 用s2[i]暂时保留经过初始化的s[i],很重要的!!!
{
s2[i] = s[i];
}
rc4_crypt(s, (unsigned char*)pData, len); // 加密
rc4_crypt(s2, (unsigned char*)pData, len); // 解密
return 0;
}

解密算法

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
# coding: utf-8

# import base64
import binascii


def rc4_crypt(PlainBytes:bytes, KeyBytes:bytes) -> str:
'''[summary]
rc4 crypt
Arguments:
PlainBytes {[bytes]} -- [plain bytes]
KeyBytes {[bytes]} -- [key bytes]

Returns:
[string] -- [hex string]
'''

keystreamList = []
cipherList = []

keyLen = len(KeyBytes)
plainLen = len(PlainBytes)
S = list(range(256))

j = 0
for i in range(256):
j = (j + S[i] + KeyBytes[i % keyLen]) % 256
temp = S[i]
S[i] = S[j]
S[j] = S[i]
#S[i], S[j] = S[j], S[i]

i = 0
j = 0
for m in range(plainLen):
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
cipherList.append(k ^ PlainBytes[m])

result_hexstr = ''.join(['%02x' % i for i in cipherList])
return result_hexstr.upper()


if __name__ == "__main__":
data = '43C8B53E236C4756B8FF24E5AA08A549'
key = '3C381919191918181818181817111111'
rc4_result = 'BC9CD0200AB174B467956B4CAE2178BE'
print('data:',data , 'key', key, 'rc4_result:',rc4_result)
print("rc4 result:", rc4_crypt(binascii.a2b_hex(data), binascii.a2b_hex(key.upper())))

变种rc4–带偏移的rc4

rc4_init这里还是很明显的

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
bool __fastcall sub_401760(__int64 a1, __int64 a2, __int64 a3, _DWORD *a4, int a5)
{
bool result; // al
int v6; // ST04_4
signed __int64 v7; // [rsp+8h] [rbp-18h]
int v8; // [rsp+14h] [rbp-Ch]
int v9; // [rsp+18h] [rbp-8h]
signed int i; // [rsp+1Ch] [rbp-4h]
signed int j; // [rsp+1Ch] [rbp-4h]

*a4 = 0;
a4[1] = 0;
v7 = (a4 + 2);
for ( i = 0; i <= 255; ++i )
*(v7 + 4LL * i) = i;
v8 = 0;
result = 0;
LOBYTE(v9) = 0;
for ( j = 0; j <= 255; ++j )
{
v6 = *(4LL * j + v7);
v9 = (v9 + v6 + *(v8 + a3));
*(v7 + 4LL * j) = *(4LL * v9 + v7);
*(v7 + 4LL * v9) = v6;
result = ++v8 >= a5;
if ( v8 >= a5 )
v8 = 0;
}
return result;
}

这里做了点变化

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
_DWORD *__fastcall sub_40188D(__int64 a1, __int64 a2, __int64 a3, _DWORD *a4, int a5)
{
int v5; // ST04_4
int v6; // ST00_4
_DWORD *result; // rax
signed __int64 v8; // [rsp+8h] [rbp-18h]
int v9; // [rsp+14h] [rbp-Ch]
int v10; // [rsp+18h] [rbp-8h]
int i; // [rsp+1Ch] [rbp-4h]

v10 = *a4;
v9 = a4[1];
v8 = (a4 + 2);
for ( i = 0; i < a5; ++i )
{
v10 = (v10 + 1);
v5 = *(4LL * v10 + v8);
v9 = (v9 + v5);
v6 = *(4LL * v9 + v8);
*(v8 + 4LL * v10) = v6;
*(v8 + 4LL * v9) = v5;
*(i + a3) ^= *(4LL * (v5 + v6 + 24) + v8); //重点 24
}
*a4 = v10;
result = a4;
a4[1] = v9;
return result;
}

这里加了偏移,24

变种的解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding: utf-8 -*-
import random, base64

def rc4_crypt(data, key):
"""RC4 algorithm"""
x = 0
box = range(256)
for i in range(256):
x = (x + box[i] + ord(key[i % len(key)])) % 256
box[i], box[x] = box[x], box[i]
x = y = 0
out = []
for char in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
out.append(chr(ord(char) ^ box[(box[x] + box[y]+24) % 256]))

return ''.join(out)

if __name__ == '__main__':
data="c9deea9964ca63e5b389a6ac6358a582fc4befb11334".decode("hex")
key = "Please input the flag:\n"
print(rc4_crypt(data,key))

本文作者:NoOne
本文地址https://noonegroup.xyz/posts/95c19a10/
版权声明:转载请注明出处!