使用C++防止非法软件结束自己的任务和注入、篡改内存等对自己的程序恶意操作
使用C++防止非法软件结束自己的任务和注入、篡改内存等对自己的程序恶意操作
本文探讨在 Windows 环境下,如何通过用户态缓解策略与内核态对象回调,构建针对恶意程序注入与非法终止的纵深防御体系。所有测试均在关闭第三方安全软件的纯净虚拟机中进行,仅针对未知恶意行为进行防御研究。
1. 防御架构设计
单一防护极易被高权限恶意程序绕过。本方案采用三层纵深防御:
- 用户态缓解:利用 Windows 原生 Mitigation 策略,阻断常规 Shellcode 与 DLL 注入。
- 内核态拦截:通过 WDK 注册
ObRegisterCallbacks,在句柄创建阶段剥离关键访问权限。 - 运行时校验:后台线程对关键内存区域进行周期性哈希校验,防范底层直接内存篡改。
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 纯净虚拟机中测试:
- 常规结束:任务管理器点击“结束任务”,提示“拒绝访问”。
- 命令行强杀:以管理员身份运行
taskkill /f /pid <目标PID>,返回“错误: 无法终止 PID 为 XXX 的进程。原因: 拒绝访问。” - DLL 注入测试:使用常规注入工具尝试加载测试 DLL,
LoadLibrary在目标进程中失败,注入工具报错。
6. 局限性与总结
本方案显著提升了进程被非法操控的门槛,符合现代 EDR 的轻量级防护思路。但需明确:若攻击者已获取 Ring 0 级别权限且具备编写定制 Rootkit 的能力,可通过直接修改内核对象或 PatchGuard 绕过此类常规回调。因此,该方案定位为“提高自动化恶意软件与普通高级威胁的攻击成本”,而非绝对的“防破解/防杀”银弹。
合规声明:本文代码仅供学术研究与防御未知恶意软件参考,严禁用于对抗合法安全软件或从事非法活动。
这是辰空昭影的博客,转载请注明出处

浙公网安备 33010602011771号