• #免杀系列之利用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
    ");
    	}
    	else {
    		printf("[*] RWX memory allocated: %p
    ", mem);
    	}
    
    	printf("[*] Now running SetProcessMitigationPolicy to apply PROCESS_MITIGATION_DYNAMIC_CODE_POLICY
    ");
    	
    	// Set our mitigation policy
    	if (SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &policy, sizeof(policy)) == false) {
    		printf("[!] SetProcessMitigationPolicy failed
    ");
    		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
    ");
    	}
    	else {
    		printf("[*] RWX memory allocated: %p
    ", 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
    ", ntAllocateVirtualMemory);
    	}
    	else {
    		printf("[*] NtAllocateVirtualMemory [%p] memory updated to RWX
    ", ntAllocateVirtualMemory);
    	}
    }
    view raw
    
    

    编译并执行这段代码,我们将看到如下内容:

    我们可以看到在 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

    使我有洛阳二倾田,安能配六国相印
  • 相关阅读:
    asp.net与javascript问题
    动态加载用户控件
    ASP.NET中实现模版的动态加载
    一个简单的购物车
    给图片加上水印效果
    用存储过程自定义分页
    上传图片及显示图片
    sql server图片的保存和读取
    Legato Single Server SertupFor RMAN
    确定裸设备上控制文件的大小
  • 原文地址:https://www.cnblogs.com/H4ck3R-XiX/p/15391205.html
Copyright © 2020-2023  润新知