Process Mitigation Policy


发布于 2021-10-23


在Windows平台开发应用软件时,自己的程序被三方程序注入 dll 或者注入 shellcode,干扰了自己程序的正常运行,是件非常头痛的事。更令人难过的是,国内的木马病毒、流氓软件太多了,整个环境都很糟糕。阻止外部任意代码的执行,变成了很重要的安全问题。

Chromium 浏览器通过 chromium_elf.dll 模块来阻止三方 dll 注入到浏览器,具体可以参考我之前写的一篇文章Chrome Early Loading Framework

此外 Chromium将拒绝第三方软件注入

微软的Edge浏览器开发团队曾经写过一篇文章 Mitigating arbitrary native code execution in Microsoft Edge ,来介绍Edge应用的一些win10最新的安全防护技术。(此时的Edge还是非Chromium内核)。

Process Mitigation Policy

win8 之后,windows有个Process Mitigation Policy,用来防护进程被攻击。它一般有三种设置方法:

  1. 被保护进程自己调用SetProcessMitigationPolicy api 来设置 Process Mitigation Policy
  2. 用管理员权限来运行配置工具Set-ProcessMitigation,它会为某个进程名的进程设置 Process Mitigation Policy。其结果其实存在于注册中的HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options里面
  3. 创建被保护子进程时设置 Process Mitigation Policy

以设置 Code Integrity Guard (CIG) 为例,三种设置方式如下。

通过Set-ProcessMitigation设置:

Set-ProcessMitigation -name WindowsProject3.exe -enable BlockNonMicrosoftSigned

通过SetProcessMitigationPolicy api设置:

  PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY bsp = {};
  bsp.MicrosoftSignedOnly = 1;
  SetProcessMitigationPolicy(ProcessSignaturePolicy, &bsp, sizeof(bsp));

创建被保护子进程时设置:

  STARTUPINFOEXA si;
  PROCESS_INFORMATION pi;
  SIZE_T size = 0;

  ZeroMemory(&si, sizeof(si));
  si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
  si.StartupInfo.dwFlags = EXTENDED_STARTUPINFO_PRESENT;

  InitializeProcThreadAttributeList(NULL, 1, 0, &size);

  si.lpAttributeList =
      (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, size);

  InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);

  DWORD64 policy =
      PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;

  UpdateProcThreadAttribute(si.lpAttributeList, 0,
                            PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &policy,
                            sizeof(policy), NULL, NULL);

  BOOL ret =
      CreateProcessA(NULL, (LPSTR) "C:\\Windows\\System32\\notepad.exe", NULL,
                     NULL, true, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL,
                     reinterpret_cast<LPSTARTUPINFOA>(&si), &pi);

进程设置 Process Mitigation Policy 成功之后,可以通过api GetProcessMitigationPolicy来查询,也可以通过 Process Hacker 这个工具查看进程的 Properties -> General -> Mitigation policies -> Details,如下图所示:

Microsoft Signed Only

Code Integrity Guard (CIG)

CIG 策略是根据证书来限制进程可以加载的可执行文件。

PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY里面选项:

  • MicrosoftSignedOnly,值为1表示阻止加载没有微软签名的模块
  • StoreSignedOnly,值为1表示阻止加载没有微软应用商店签名的模块
  • MitigationOptIn,值为1表示阻止加载没有微软、微软应用商店、Windows Hardware Quality签名的模块

如果设置了MicrosoftSignedOnly,那么非微软签名的 dll 无法注入到进程里了。可以起到一定的防护作用。

Arbitrary Code Guard (ACG)

ACG 策略是防止进程生成动态代码或者修改已经存在的可执行文件。存在的代码页不可写,没有签名的代码页不能被创建。 也就是说不能通过调用ProtectVirtualMemoryVirtualAlloc来操作例如PAGE_EXECUTE_READWRITE这样的内存。内存不能同时拥有写入权限(W)和执行权限(X)。

同样的 ACG 也可以用于阻止三方模块的 dll 注入到进程中。

因为 ACG 限制了动态生成代码指令,因此它与浏览器渲染进程中的 JavaScript 引擎的 JIT 编译优化是相冲突的。因此 Edge 浏览器把 Chakra 的 JIT 放到一个独立进程里,再把 JIT 编译生成的代码映射到渲染进程里。

其他

Process Mitigation Policy 里面的策略非常多,比如CFG、ASLR等等,具体可以参考 SetProcessMitigationPolicy

Chromium 浏览器的Sandbox 有些对进程的限制也是用到了 Process Mitigation Policy。

不足

Process Mitigation Policy 的设置方式对于恶意程序来说,也可以绕过的。

通过SetProcessMitigationPolicy设置,如果在调用之前,防护是不生效的。

通过Set-ProcessMitigation工具设置,配置写在注册表里。恶意程序找到位置也可以删除掉。

通过创建被保护子进程时设置,假如恶意程序自己启动被保护进程,也是没有办法防护。

另外看起来 ACG 防护策略似乎可以阻止远程代码代码注入 shellcode,但实际不行。可能是因为远程代码代码注入 shellcode 里面对 VirtualAlloc 的调用都在 shellcode 进程里,不在被防护的进程里。

参考