玄 - 利用blockdlls和ACG保護惡意進程


blockdlls

Cobalt Strike 3.14版本以后添加了blockdlls功能,它將創建一個子進程並限定該子進程只能加載帶有Microsoft簽名的DLL。

這個功能可以阻止第三方安全軟件向子進程注入DLL,也就無法對子進程進行hook,最終起到保護子進程的效果。

XPN在博客中分享了實現同樣功能的c代碼

#include <Windows.h>

int main()
{
	STARTUPINFOEXA si;
	PROCESS_INFORMATION pi;
	SIZE_T size = 0;
	BOOL ret;

	// 請求一個 STARTUPINFOEXA 結構體
	ZeroMemory(&si, sizeof(si));
	si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
	si.StartupInfo.dwFlags = EXTENDED_STARTUPINFO_PRESENT;

	//獲取要分配的 PROC_THREAD_ATTRIBUTE_LIST 大小
	InitializeProcThreadAttributeList(NULL, 1, 0, &size);

	//為 PROC_THREAD_ATTRIBUTE_LIST 分配內存
	si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
		GetProcessHeap(),
		0,
		size
	);

	// 初始化我們的列表 
	InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size);

	// 啟用阻止未經Microsoft簽名的DLL功能
	DWORD64 policy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;

	// Assign our attribute
	UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &policy, sizeof(policy), NULL, NULL);

	// 創建進程
	ret = CreateProcessA(
		NULL,
		(LPSTR)"C:\\Windows\\System32\\cmd.exe",
		NULL,
		NULL,
		true,
		EXTENDED_STARTUPINFO_PRESENT,
		NULL,
		NULL,
		reinterpret_cast<LPSTARTUPINFOA>(&si),
		&pi
	);
}

通過STARTUPINFOEX結構體指定了要創建子進程的安全策略(開啟PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON),這個安全策略起到了阻止加載非Microsoft簽名dll的作用。

生成子進程后,使用ProcessHacker能夠看到開啟blockdlls功能的提示,如下圖:

開啟blockdlls功能后,嘗試對這個進程進行dll注入,注入的代碼可參考三好學生
注入時報錯,提示如圖:

接下來,需要了解此功能相關細節。在微軟官方文檔中,找到了相關API GetProcessMitigationPolicy(),可讀取進程的安全策略。

而簽名策略對應的結構體為PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY,資料顯示該API支持的最低系統為Win8,這里猜測API GetProcessMitigationPolicy()同blockdlls支持的操作系統版本應該相同。

經過測試,發現Cobalt Strike中blockdlls支持的系統最低為Win8。

分析blockdlls在CS中的實現

如果我們搜索CS beacon二進制文件,我們會看到對UpdateProctThreadAttribute的引用:

0x20007的屬性參數實際上定義為PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,並且0x10000000000的值解析為PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON。所以Cobalt Strike在這里所做的是使用CreateProcess API調用以及包含一個緩解策略的結構體STARTUPINFOEX,而該策略正是用於阻止非微軟簽名DLL的加載。

任意代碼保護

ACG是Windows系統的另一個安全策略,用於阻止外部代碼分配和/或修改內存,這里不多贅述

要了解此緩解策略的實際效果,我們創建一個小程序並嘗試使用 SetMitigationPolicy 添加開啟 ACG :

#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);
	}
}

編譯並執行這段代碼,我們將看到如下內容:

我們可以看到在 SetProcessMitigationPolicy 失敗后嘗試分配 RWX 的內存頁,以及使用諸如 VirtualProtect 之類的調用來分配或修改內存保護,結果都是失敗的。

那為什么要提這個呢? 因為我們確實看到了由微軟簽名的 EDR 注入DLL的例子,@Sektor7Net 展示了 Crowdstrike Falcon 可以不受 PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON 的影響

但許多EDR產品常見的操作是將他們的DLL注入到其想監測的進程中,圍繞特定的API函數實現用戶態hook技術(參考文章)。由於hook技術通常需要修改現有的可執行內存頁以添加hook,因此EDR通常需要調用VirtualProtect來更新內存保護。如果我們在惡意軟件設計上啟用ProcessDynamicCodePolicy可能有助於保護其免受EDR hook監測的影響,就可能會強制阻止一個帶微軟簽名的DLL加載。

總結

現在,我們要將這些策略進行整合,在生成惡意進程時,可以用PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON以及SetMitigationPolicyAPI調用進行保護。當然,還有其他方法可以對進程進行保護,例如通過簡單的CreateProcessA生成任意進程。
這里,我僅根據以上展開的思路編寫了新款免殺馬(開源是不可能開源的,只提供思路大家自行創作),通殺國內外一流殺軟,命名“冢虎”,在座的各位師傅有誰贊同,有誰反對?

參考:
https://blog.cobaltstrike.com/2019/05/02/cobalt-strike-3-14-post-ex-omakase-shimasu/
https://www.ired.team/offensive-security/defense-evasion/acg-arbitrary-code-guard-processdynamiccodepolicy#enabling-acg
https://blog.xpnsec.com/protecting-your-malware/
https://www.4hou.com/posts/0Xov


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM