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