逆向常见加密算法

逆向常见加密算法

0x10 RC4

简绍

在密码学中,RC4(Rivest Cipher 4)是一种流加密算法,密钥长度可变,它加解密使用相同的密钥)因此也属于对称加密算法,RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。

补充说明:序列密码(流密码):

流密码也属于对称密码,但与分组加密算法不同的是,流密码不对明文数据进行分组,而是用密钥生成与明文一样长短的密码流对明文进行加密,加解密使用相同的密钥。也就是说,RC4不是对明文进行分组处理,而是字节流的方式依次加密明文中的每一个字节,解密的时候也是依次对密文中的每一个字节进行解密。

解密逻辑

S盒初始化

1
2
3
4
5
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]

生产密钥流

1
2
3
4
5
6
7
i = j = 0
key_stream = []
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
key_stream.append(S[(S[i] + S[j]) % 256])

加密

1
2
3
for i in range(len(plain)) :
plain[i] ^= key_stream[i]

完整脚本示例

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
def init_sbox(key: bytes):
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + key[i % len(key)]) % 256
s[i], s[j] = s[j], s[i]
return s

def rc4_encrypt(key: bytes, plaintext: bytes) -> bytes:
s = init_sbox(key)
i = j = 0
ciphertext = bytearray()
for char in plaintext:
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) % 256]
ciphertext.append(char ^ k)
return bytes(ciphertext)

# 示例用法
if __name__ == "__main__":
key = b"secretkey"
plaintext = b"Hello, RC4 Encryption!"

# 加密
encrypted = rc4_encrypt(key, plaintext)
print("Ciphertext (Hex):", encrypted.hex())

0x02 TEA系列加密

简绍

TEA是Tiny Encryption Algorithm的缩写,以加密解密速度快,实现简单著称。
TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,推荐的迭代轮数是64轮,最少32轮。
为解决TEA算法密钥表攻击的问题,TEA算法先后经历了几次改进,tea->xtea->xxtea
TEA系列算法中均使用了一个DELTA常数,但DELTA的值对算法并无什么影响,只是为了避免不良的取值,推荐DELTA的值取为黄金分割数与232的乘积,取整后的十六进制值为0x9e3779B9,用于保证每一轮加密都不相同。但有时该常数会以减法的形式出现,-0x61C88647=0x9E3779B9,因此出现了0x61c88647时也应当注意。

TEA

加密逻辑

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
#include <stdio.h>
#include <stdint.h>
typedef uint32_t u32;
const u32 delta = 0x9e3779b9; //魔数
const int rounds = 32; //加密轮数

void encrypt(uint32_t * v , uint32_t * k) {
u32 v0 = v[0], v1 = v[1];
u32 k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
u32 sum = 0;

// TEA

for (int i = 0; i < rounds; i ++) { //加密流程
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}

v[0] = v0;
v[1] = v1;
}

void decrypt(uint32_t * v , uint32_t * k) {
u32 v0 = v[0], v1 = v[1];
u32 k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
u32 sum = 32 * delta;

// Tea
for(int i = 0; i < rounds; i ++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}

v[0] = v0;
v[1] = v1;
}

void encrypt_multiple_blocks(unsigned char * text , unsigned char * key) {
uint32_t *v = (uint32_t *)text;
uint32_t *k = (uint32_t*)key;
for (int i = 0; i < 8; i += 2) //一组只能加密八个字节
{
encrypt(v + i, k);
printf("加密后的数据:%u %u\n", v[i], v[i+1]);
}

for (int i = 0; i < 32; i++) {
printf("0x%x ,", text[i]);
}
}

void decrypt_multiple_blocks(unsigned char * text , unsigned char * key) {
uint32_t *v = (uint32_t *)text;
uint32_t *k = (uint32_t*)key;
for (int i = 0; i < 8; i += 2) //8组
{
decrypt(v + i, k);
printf("解密后的数据:%u %u\n", v[i], v[i+1]);
}

for (int i = 0; i < 32; i++) {
printf("%c", text[i]);
}
}


unsigned char keys[] = "WelcomeToNewStar";
unsigned char plain[] = {0x66, 0x6c, 0x61, 0x67, 0x7b, 0x54, 0x68, 0x65, 0x72, 0x65, 0x5f, 0x52, 0x5f, 0x54, 0x45, 0x41, 0x5f, 0x58, 0x54, 0x45, 0x41, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x58, 0x58, 0x54, 0x45, 0x41, 0x7d};
unsigned char cipher[] = {0x78 ,0x20 ,0xf7 ,0xb3 ,0xc5 ,0x42 ,0xce ,0xda ,0x85 ,0x59 ,0x21 ,0x1a ,0x26 ,0x56 ,0x5a ,0x59 ,0x29 ,0x2 ,0xd ,0xed ,0x7 ,0xa8 ,0xb9 ,0xee ,0x36 ,0x59 ,0x11 ,0x87 ,0xfd ,0x5c ,0x23 ,0x24};
int main()
{
unsigned char a;
encrypt_multiple_blocks(plain, keys);
decrypt_multiple_blocks(cipher , keys);
return 0;
}

特征识别

  • 标准DELTA常熟(魔数)
  • 密钥为16字节(4个DWORD)
  • 加密轮数为16/32/64轮
  • 加密结构中存在左4右5位移和很多异或
  • 加密结构中存在轮加/减相同常熟的语句

xTEA

加密逻辑

区别于TEA加密的只有轮加密过程,魔数都也一样

1
2
3
4
5
6
7
8
9
10
11
12
//encrypt过程
for (int i = 0; i < rounds; i ++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]);
}
//decrypt过程
for (int i = 0; i < rounds; i ++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
}

特征识别

  • 同TEA加密
  • 加密结构中存在右移11位并3的运算

xxTEA

加密逻辑

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
#include<stdio.h>
#include<stdint.h>
typedef uint32_t u32;
#define DELTA 0x9e3779b9 //魔数
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))

void xxtea(u32* v , int n , u32* key){
u32 y, z, sum;
unsigned p, rounds, e;

if(n > 1) { //正数加密 复数解密
rounds = 6 + 52 / n; //特征识别
sum = 0;
z = v[n - 1];
do{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p ++ ){
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}

else if(n < -1) {
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p --){
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}

unsigned char keys[] = "WelcomeToNewStar";
unsigned char plain[] = {0x66, 0x6c, 0x61, 0x67, 0x7b, 0x54, 0x68, 0x65, 0x72, 0x65, 0x5f, 0x52, 0x5f, 0x54, 0x45, 0x41, 0x5f, 0x58, 0x54, 0x45, 0x41, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x58, 0x58, 0x54, 0x45, 0x41, 0x7d};
unsigned char cipher[] = {0xc3 ,0x43 ,0x20 ,0xf3 ,0xcc ,0x78 ,0x3 ,0xc8 ,0x65 ,0x46 ,0x9b ,0x7 ,0xae ,0xcb ,0x78 ,0x23 ,0xe7 ,0x4f ,0xe0 ,0xe4 ,0x6a ,0x80 ,0xbe ,0xcc ,0x21 ,0xbc ,0x2f ,0xa9 ,0x1d ,0xff ,0xc1 ,0x64};

int main(){

// 加密 plain
xxtea((u32 *)plain, sizeof(plain) / 4, (u32 *)keys);
printf("Encrypted plain: ");
for (int i = 0; i < sizeof(plain); i++) {
printf("0x%02x, ", plain[i]);
}
printf("\n");

// 解密 cipher
xxtea((u32 *)cipher, -(sizeof(cipher) / 4), (u32 *)keys);
printf("Decrypted cipher: ");
for (int i = 0; i < sizeof(cipher); i++) {
printf("%c", cipher[i]);
}
printf("\n");

}