免杀专题
12、Windows策略防止挂钩
1. 课程目标
学习如何利用Windows安全策略来防止安全软件挂钩我们的进程,保护代码执行不被监控。
1.1 学习目标
- 了解Windows提供的进程保护机制
- 掌握ACG、CIG等策略的使用
- 学会配置进程缓解策略
- 理解各策略的优缺点
2. 名词解释
| 名词 | 英文全称 | 解释 |
|---|---|---|
| ACG | Arbitrary Code Guard | 任意代码防护,阻止动态生成可执行代码 |
| CIG | Code Integrity Guard | 代码完整性保护,只允许签名代码执行 |
| CFG | Control Flow Guard | 控制流防护,防止ROP/JOP攻击 |
| ASLR | Address Space Layout Randomization | 地址空间随机化 |
| DEP | Data Execution Prevention | 数据执行保护 |
| BlockNonMicrosoftBinaries | - | 阻止非微软签名的DLL加载 |
| Mitigation Policy | - | 进程缓解策略 |
3. 进程缓解策略概述
3.1 可用的缓解策略
| 策略 | 作用 | 对抗Hook |
|---|---|---|
| PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES | 阻止非MS签名DLL | 阻止安全软件DLL注入 |
| PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE | 禁止动态代码 | 需要特殊处理 |
| PROCESS_CREATION_MITIGATION_POLICY_CONTROL_FLOW_GUARD | 控制流保护 | 防止Hook跳转 |
| PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_REMOTE | 禁止远程镜像 | 阻止网络加载 |
| PROCESS_CREATION_MITIGATION_POLICY_IMAGE_LOAD_NO_LOW_LABEL | 禁止低完整性镜像 | 阻止低权限加载 |
4. 核心实现代码
4.1 创建受保护的子进程
#include <windows.h>
#include <stdio.h>
// 创建带有缓解策略的子进程
BOOL CreateProtectedProcess(LPCWSTR szPath) {
printf("[*] 创建受保护进程: %ws\n", szPath);
// 1. 初始化属性列表
SIZE_T attrSize = 0;
InitializeProcThreadAttributeList(NULL, 1, 0, &attrSize);
LPPROC_THREAD_ATTRIBUTE_LIST pAttrList =
(LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attrSize);
if (!InitializeProcThreadAttributeList(pAttrList, 1, 0, &attrSize)) {
printf("[-] InitializeProcThreadAttributeList失败: %d\n", GetLastError());
return FALSE;
}
// 2. 设置缓解策略
// 阻止非微软签名的DLL加载
DWORD64 policy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;
if (!UpdateProcThreadAttribute(
pAttrList,
0,
PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,
&policy,
sizeof(policy),
NULL,
NULL)) {
printf("[-] UpdateProcThreadAttribute失败: %d\n", GetLastError());
DeleteProcThreadAttributeList(pAttrList);
HeapFree(GetProcessHeap(), 0, pAttrList);
return FALSE;
}
printf("[+] 策略: BLOCK_NON_MICROSOFT_BINARIES\n");
// 3. 创建进程
STARTUPINFOEXW si = { 0 };
si.StartupInfo.cb = sizeof(si);
si.lpAttributeList = pAttrList;
PROCESS_INFORMATION pi = { 0 };
if (!CreateProcessW(
szPath,
NULL,
NULL,
NULL,
FALSE,
EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
NULL,
NULL,
&si.StartupInfo,
&pi)) {
printf("[-] CreateProcess失败: %d\n", GetLastError());
DeleteProcThreadAttributeList(pAttrList);
HeapFree(GetProcessHeap(), 0, pAttrList);
return FALSE;
}
printf("[+] 进程创建成功! PID: %d\n", pi.dwProcessId);
// 清理
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
DeleteProcThreadAttributeList(pAttrList);
HeapFree(GetProcessHeap(), 0, pAttrList);
return TRUE;
}
4.2 设置当前进程的缓解策略
#include <windows.h>
#include <processthreadsapi.h>
#include <stdio.h>
// 动态设置当前进程的策略
BOOL SetCurrentProcessPolicy() {
// 获取SetProcessMitigationPolicy函数
typedef BOOL(WINAPI* pSetProcessMitigationPolicy)(
PROCESS_MITIGATION_POLICY MitigationPolicy,
PVOID lpBuffer,
SIZE_T dwLength
);
HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
pSetProcessMitigationPolicy SetProcessMitigationPolicy =
(pSetProcessMitigationPolicy)GetProcAddress(hKernel32, "SetProcessMitigationPolicy");
if (!SetProcessMitigationPolicy) {
printf("[-] 系统不支持SetProcessMitigationPolicy\n");
return FALSE;
}
// 设置动态代码策略
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dcPolicy = { 0 };
dcPolicy.ProhibitDynamicCode = 1;
dcPolicy.AllowThreadOptOut = 1; // 允许线程选择退出
if (!SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &dcPolicy, sizeof(dcPolicy))) {
printf("[-] 设置动态代码策略失败: %d\n", GetLastError());
} else {
printf("[+] 动态代码策略已启用\n");
}
// 设置二进制签名策略
PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY sigPolicy = { 0 };
sigPolicy.MicrosoftSignedOnly = 1;
if (!SetProcessMitigationPolicy(ProcessSignaturePolicy, &sigPolicy, sizeof(sigPolicy))) {
printf("[-] 设置签名策略失败: %d\n", GetLastError());
} else {
printf("[+] 仅允许微软签名DLL\n");
}
return TRUE;
}
4.3 完整的策略保护示例
#include <windows.h>
#include <stdio.h>
#define PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON (0x00000001ui64 << 44)
#define PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON (0x00000001ui64 << 36)
BOOL CreateFullyProtectedProcess(LPCWSTR szPath) {
SIZE_T attrSize = 0;
InitializeProcThreadAttributeList(NULL, 2, 0, &attrSize);
LPPROC_THREAD_ATTRIBUTE_LIST pAttrList =
(LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attrSize);
InitializeProcThreadAttributeList(pAttrList, 2, 0, &attrSize);
// 组合多个缓解策略
DWORD64 policy = 0;
policy |= PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;
// 注意:PROHIBIT_DYNAMIC_CODE会阻止VirtualAlloc(MEM_EXECUTE)和VirtualProtect(PAGE_EXECUTE_*)
// policy |= PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON;
UpdateProcThreadAttribute(pAttrList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,
&policy, sizeof(policy), NULL, NULL);
STARTUPINFOEXW si = { sizeof(si) };
si.lpAttributeList = pAttrList;
PROCESS_INFORMATION pi = { 0 };
BOOL result = CreateProcessW(szPath, NULL, NULL, NULL, FALSE,
EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
NULL, NULL, &si.StartupInfo, &pi);
if (result) {
printf("[+] 受保护进程已创建, PID: %d\n", pi.dwProcessId);
printf("[+] 安全软件将无法注入DLL到此进程\n");
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
DeleteProcThreadAttributeList(pAttrList);
HeapFree(GetProcessHeap(), 0, pAttrList);
return result;
}
int main() {
printf("========================================\n");
printf(" Windows策略防止挂钩演示\n");
printf("========================================\n\n");
CreateFullyProtectedProcess(L"C:\\Windows\\System32\\notepad.exe");
return 0;
}
5. 各策略详细说明
5.1 BLOCK_NON_MICROSOFT_BINARIES
作用: 阻止非微软签名的DLL加载到进程
效果:
- 安全软件的Hook DLL无法注入
- 第三方DLL无法加载
- 仅限微软签名的DLL可用
注意: 这会阻止很多正常DLL,可能导致应用功能受限
5.2 PROHIBIT_DYNAMIC_CODE
作用: 禁止动态生成可执行代码
影响:
- VirtualAlloc不能使用PAGE_EXECUTE_*
- VirtualProtect不能将内存改为可执行
- JIT编译器无法工作
绕过: 使用AllowThreadOptOut允许特定线程动态代码
6. 注意事项
- 策略不可逆: 一旦设置,无法在进程运行时取消
- 兼容性问题: 某些应用依赖动态代码或第三方DLL
- 调试困难: 受保护进程可能难以调试
- 权限要求: 某些策略需要管理员权限
7. 课后作业
7.1、作业1:基础实现(必做)
- 创建一个使用BLOCK_NON_MICROSOFT_BINARIES策略的进程
- 验证该进程无法被常规DLL注入
7.2、作业2:策略测试(进阶)
- 测试不同策略组合的效果
- 观察哪些策略会影响ShellCode执行
8. 下一课预告
下一课我们将学习Windows策略防止ShellCode执行的技术。