使用C++防止非法软件结束自己的任务和注入、篡改内存等对自己的程序恶意操作

使用C++防止非法软件结束自己的任务和注入、篡改内存等对自己的程序恶意操作

本文探讨在 Windows 环境下,如何通过用户态缓解策略与内核态对象回调,构建针对恶意程序注入与非法终止的纵深防御体系。所有测试均在关闭第三方安全软件的纯净虚拟机中进行,仅针对未知恶意行为进行防御研究。

1. 防御架构设计

单一防护极易被高权限恶意程序绕过。本方案采用三层纵深防御:

  1. 用户态缓解:利用 Windows 原生 Mitigation 策略,阻断常规 Shellcode 与 DLL 注入。
  2. 内核态拦截:通过 WDK 注册 ObRegisterCallbacks,在句柄创建阶段剥离关键访问权限。
  3. 运行时校验:后台线程对关键内存区域进行周期性哈希校验,防范底层直接内存篡改。

2. 用户态缓解策略实现

放弃易触发误报的 API Hook,直接调用系统级缓解策略。此部分代码需在进程初始化最早期执行。

#include <windows.h>
#include <processthreadsapi.h>

void initMit() {
    PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dcp = {0};
    dcp.ProhibitDynamicCode = 1;
    SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &dcp, sizeof(dcp));

    PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY bsp = {0};
    bsp.MicrosoftSignedOnly = 1;
    SetProcessMitigationPolicy(ProcessSignaturePolicy, &bsp, sizeof(bsp));
    
    PROCESS_MITIGATION_CHILD_PROCESS_POLICY cpp = {0};
    cpp.DisallowChildProcessCreation = 1;
    SetProcessMitigationPolicy(ProcessChildProcessPolicy, &cpp, sizeof(cpp));
}

效果CreateRemoteThread 注入非微软签名 DLL 或执行动态生成的 Shellcode 将被系统直接拒绝(返回 ERROR_ACCESS_DENIED)。

3. 内核态句柄权限剥离 (WDK)

即使攻击者获取 Administrator 权限,只要驱动已注册回调,其通过 OpenProcess 获取句柄时,系统会强制修改其请求的访问掩码。

#include <ntifs.h>

HANDLE tPid;
PVOID rH;

OB_PREOP_CALLBACK_STATUS preCb(PVOID reg, POB_PRE_OPERATION_INFORMATION info) {
    if (info->ObjectType != *PsProcessType) return OB_PREOP_SUCCESS;
    
    PEPROCESS ep = (PEPROCESS)info->Object;
    if (PsGetProcessId(ep) == tPid) {
        ACCESS_MASK* pDes = &info->Parameters->CreateHandleInformation.DesiredAccess;
        *pDes &= ~(PROCESS_TERMINATE | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD);
        
        ACCESS_MASK* pDup = &info->Parameters->DuplicateHandleInformation.DesiredAccess;
        *pDup &= ~(PROCESS_TERMINATE | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD);
    }
    return OB_PREOP_SUCCESS;
}

NTSTATUS regCb(ULONG pid) {
    tPid = (HANDLE)pid;
    OB_OPERATION_REGISTRATION opR = {
        PsProcessType, 
        OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE, 
        preCb, NULL
    };
    OB_CALLBACK_REGISTRATION cbR = {
        OB_FLT_REGISTRATION_VERSION, 1, RtlConvertLongToLuid(0x8848), NULL, &opR
    };
    return ObRegisterCallbacks(&cbR, &rH);
}

VOID unregCb() {
    if (rH) ObUnRegisterCallbacks(rH);
}

效果:任务管理器、taskkill /f 或恶意注入工具尝试打开目标进程时,获取的句柄将缺失终止和内存操作权限,后续操作均返回 0xC0000022 (STATUS_ACCESS_DENIED)。

4. 内存完整性自校验

作为最后一道防线,防范攻击者通过内核漏洞(如 MmCopyVirtualMemory)绕过句柄限制直接篡改内存。

#include <windows.h>
#include <wincrypt.h>

DWORD WINAPI memGuard(LPVOID pBase) {
    HCRYPTPROV hProv;
    HCRYPTHASH hHash;
    BYTE hash[32];
    DWORD hLen = sizeof(hash);
    
    if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) return 1;
    
    while (true) {
        if (CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
            CryptHashData(hHash, (BYTE*)pBase, 4096, 0);
            CryptGetHashParam(hHash, HP_HASHVAL, hash, &hLen, 0);
            CryptDestroyHash(hHash);
            
            // 此处需与预存的正确 Hash 值比对
            // if (!isValid(hash)) { SecureExit(); }
        }
        Sleep(500);
    }
    CryptReleaseContext(hProv, 0);
    return 0;
}

5. 测试验证

在 Windows 11 22H2 纯净虚拟机中测试:

  1. 常规结束:任务管理器点击“结束任务”,提示“拒绝访问”。
  2. 命令行强杀:以管理员身份运行 taskkill /f /pid <目标PID>,返回“错误: 无法终止 PID 为 XXX 的进程。原因: 拒绝访问。”
  3. DLL 注入测试:使用常规注入工具尝试加载测试 DLL,LoadLibrary 在目标进程中失败,注入工具报错。

6. 局限性与总结

本方案显著提升了进程被非法操控的门槛,符合现代 EDR 的轻量级防护思路。但需明确:若攻击者已获取 Ring 0 级别权限且具备编写定制 Rootkit 的能力,可通过直接修改内核对象或 PatchGuard 绕过此类常规回调。因此,该方案定位为“提高自动化恶意软件与普通高级威胁的攻击成本”,而非绝对的“防破解/防杀”银弹。

合规声明:本文代码仅供学术研究与防御未知恶意软件参考,严禁用于对抗合法安全软件或从事非法活动。

posted @ 2026-06-08 17:28  辰空昭影MC_Chenzhao  阅读(67)  评论(0)    收藏  举报