实例

#include <iostream>
#include <Windows.h>

int main()
{
	PROCESS_INFORMATION pi = {};
	STARTUPINFOEXA si = {};
	SIZE_T attributeSize = 0;

	InitializeProcThreadAttributeList(NULL, 1, 0, &attributeSize);
	PPROC_THREAD_ATTRIBUTE_LIST attributes = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, attributeSize);
	InitializeProcThreadAttributeList(attributes, 1, 0, &attributeSize);

	DWORD64 policy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;
	UpdateProcThreadAttribute(attributes, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &policy, sizeof(DWORD64), NULL, NULL);
	si.lpAttributeList = attributes;

	// 创建notepad子进程
	CreateProcessA(NULL, (LPSTR)"notepad", NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si.StartupInfo, &pi);
	HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, attributes);

	return 0;
}

使用这个创建的notepad进程是无法被不带微软签名的注入

禁止Dll注入Hook保护程序_Windows

可以看到多了一个Signatures restricted (Microsoft only)属性

使用ProcessHacker工具注入DLL

禁止Dll注入Hook保护程序_#include_02

注入一个没有微软签名的DLL就会报错

禁止Dll注入Hook保护程序_Windows_03

但是这样只能保护子进程,如果要保护当前进程只需要三条命令

#include <iostream>
#include <Windows.h>

int main()
{
	PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY sp = {};
	sp.MicrosoftSignedOnly = 1;
	SetProcessMitigationPolicy(ProcessSignaturePolicy, &sp, sizeof(sp));
	system("pause");
	return 0;
}

禁止Dll注入Hook保护程序_#include_04

注入Dll报错

禁止Dll注入Hook保护程序_#include_05

检测

可以使用powershell来检测当前有那些应用程序开启了这个策略

get-process | select -exp processname -Unique | % { Get-ProcessMitigation -ErrorAction SilentlyContinue -RunningProcesses $_ | select processname, Id, @{l="Block non-MS Binaries"; e={$_.BinarySignature|select -exp MicrosoftSignedOnly} } }

禁止Dll注入Hook保护程序_#include_06

ON就是开启了ACG策略,OFF就是关闭了ACG策略

弊端

ACG不会阻止远程进程直接分配内存、编写和执行shellcode

所以使用VirtualAllocExWriteProcessMemory这两个函数,通过远程线程注入的方式可以对进程进行分配内存、编写和执行shellcode 的操作

可以写一个分配内存的Demo来测试

#include <iostream>
#include <Windows.h>
#include <processthreadsapi.h>

int main()
{
	STARTUPINFOEX si;
	DWORD oldProtection;
	
	PROCESS_MITIGATION_DYNAMIC_CODE_POLICY policy;
	ZeroMemory(&policy, sizeof(policy));
	policy.ProhibitDynamicCode = 1;

	void* mem = VirtualAlloc(0, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (mem == NULL) {
		printf("[!] Error allocating RWX memory\n");
	}
	else {
		printf("[*] RWX memory allocated: %p\n", mem);
	}

	printf("[*] Now running SetProcessMitigationPolicy to apply PROCESS_MITIGATION_DYNAMIC_CODE_POLICY\n");
	
	// Set our mitigation policy
	if (SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &policy, sizeof(policy)) == false) {
		printf("[!] SetProcessMitigationPolicy failed\n");
		return 0;
	}

	// Attempt to allocate RWX protected memory (this will fail)
	mem = VirtualAlloc(0, 1024, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (mem == NULL) {
		printf("[!] Error allocating RWX memory\n");
	}
	else {
		printf("[*] RWX memory allocated: %p\n", mem);
	}

	void* ntAllocateVirtualMemory = GetProcAddress(LoadLibraryA("ntdll.dll"), "NtAllocateVirtualMemory");

	// Let's also try a VirtualProtect to see if we can update an existing page to RWX
	if (!VirtualProtect(ntAllocateVirtualMemory, 4096, PAGE_EXECUTE_READWRITE, &oldProtection)) {
		printf("[!] Error updating NtAllocateVirtualMemory [%p] memory to RWX\n", ntAllocateVirtualMemory);
	}
	else {
		printf("[*] NtAllocateVirtualMemory [%p] memory updated to RWX\n", ntAllocateVirtualMemory);
	}
}

NtAllocateVirtualMemoryR0函数也是无法分配内存的