yara-rule-authoring

yara-rule-authoring

熱門

引導撰寫用於惡意軟體識別的高品質 YARA-X 偵測規則。適用於撰寫、審查或最佳化 YARA 規則。涵蓋命名規範、字串選擇、效能最佳化、從舊版 YARA 遷移,以及降低誤報率。觸發條件:YARA、YARA-X、malware detection、threat hunting、IOC、signature、crx module、dex module。

6336星標
545分支
更新於 2026/7/30
SKILL.md
唯讀
名稱
yara-rule-authoring
描述

引導撰寫用於惡意軟體識別的高品質 YARA-X 偵測規則。適用於撰寫、審查或最佳化 YARA 規則。涵蓋命名規範、字串選擇、效能最佳化、從舊版 YARA 遷移,以及降低誤報率。觸發條件:YARA、YARA-X、malware detection、threat hunting、IOC、signature、crx module、dex module。

YARA-X 規則撰寫指南

撰寫能精準擷取惡意軟體、又不會讓誤報淹沒你的偵測規則。

本 Skill 專為 YARA-X 設計。YARA-X 是以 Rust 開發的舊版 YARA 繼任者,為 VirusTotal 生產系統提供支援,也是官方推薦的實作版本。若已有現成規則,請參閱 從舊版 YARA 遷移

核心原則

  1. 字串必須能產生良好的 Atom — YARA 會擷取 4 個位元組的子序列以進行快速比對。包含重複位元組、常見序列或少於 4 個位元組的字串,會迫使過多檔案進入耗時的位元組碼驗證流程。

  2. 鎖定特定家族,而非模糊分類 —「偵測勒索軟體」這類規則等於什麼都抓又什麼都抓不到;「偵測 LockBit 3.0 組態擷取常式」才能精準命中目標。

  3. 部署前務必對正常檔案進行測試 — 一條會觸發 Windows 系統檔案告警的規則毫無價值。部署前請透過 VirusTotal 的正常檔案語料庫(goodware corpus)或自訂的乾淨檔案集驗證。

  4. 先執行低代價檢查以觸發捷徑運算 — 在執行高成本的字串搜尋或模組呼叫前,先放上 filesize < 10MB and uint16(0) == 0x5A4D 這類快捷條件。

  5. Metadata 即檔案說明 — 未來的你(以及你的團隊)需要知道這條規則抓到了什麼、原因為何,以及樣本來源。

適用場景

  • 撰寫用於惡意軟體偵測的新 YARA-X 規則
  • 審查現有規則的品質或效能問題
  • 最佳化執行速度過慢的規則集
  • 將 IOC 或威脅情資轉化為偵測特徵碼
  • 除錯與修正誤報(False Positive)問題
  • 準備將規則部署至生產環境
  • 將舊版 YARA 規則遷移至 YARA-X
  • 分析 Chrome 擴充功能(crx 模組)
  • 分析 Android 應用程式(dex 模組)

不適用場景

  • 需要反組譯的靜態分析 → 使用 Ghidra/IDA 相關 Skill
  • 動態惡意軟體分析 → 使用沙盒分析相關 Skill
  • 網路層級偵測 → 使用 Suricata/Snort 相關 Skill
  • 使用 Volatility 進行記憶體鑑識 → 使用記憶體鑑識相關 Skill
  • 純 Hash 偵測 → 直接使用 Hash 清單即可

YARA-X 概觀

YARA-X 是以 Rust 開發的舊版 YARA 繼任者:常規表示式比對速度快 5-10 倍、更友善的錯誤訊息、內建格式化工具、更嚴謹的驗證機制、全新模組(crx、dex),且具備 99% 的規則相容性。

安裝: brew install yara-x (macOS) 或 cargo install yara-x

核心命令: yr scanyr checkyr fmtyr dump

跨平台考量

YARA 適用於任何檔案類型。請依據目標對象調整模式:

平台 Magic Bytes 不佳的字串 理想的字串
Windows PE uint16(0) == 0x5A4D API 名稱、Windows 路徑 Mutex 名稱、PDB 路徑
macOS Mach-O uint32(0) == 0xFEEDFACE (32-bit), 0xFEEDFACF (64-bit), 0xCAFEBABE (universal) 常見的 Obj-C 方法 鍵盤記錄器字串、常駐(persistence)路徑
JavaScript/Node (無須設定) require, fetch, axios 混淆器特徵碼、eval+decode 鏈
npm/pip packages (無須設定) postinstall, dependencies 可疑的套件名稱、資料外洩 (exfil) URL
Office 文件 uint32(0) == 0x504B0304 VBA 關鍵字 巨集自動執行、編碼過後的 Payload
VS Code 擴充功能 (無須設定) vscode.workspace 罕見的 activationEvents、隱藏檔案存取行為
Chrome 擴充功能 使用 crx 模組 常見 Chrome API 權限濫用、manifest 異常
Android Apps 使用 dex 模組 標準 DEX 結構 混淆後的類別(class)、可疑權限

macOS 惡意軟體偵測

目前尚無專用的 Mach-O 模組,請結合 Magic Bytes 檢查與字串模式:

Magic bytes:

// Mach-O 32-bit
uint32(0) == 0xFEEDFACE
// Mach-O 64-bit
uint32(0) == 0xFEEDFACF
// 通用二進位檔 (Fat Binary)
uint32(0) == 0xCAFEBABE or uint32(0) == 0xBEBAFECA

macOS 惡意軟體的良好指標:

  • 鍵盤記錄器跡象:CGEventTapCreatekCGEventKeyDown
  • SSH Tunnel 字串:ssh -Dtunnelsocks
  • 常駐路徑:~/Library/LaunchAgents/Library/LaunchDaemons
  • 憑證竊取:security find-generic-passwordkeychain

來自 Airbnb BinaryAlert 的範例模式:

rule SUSP_Mac_ProtonRAT
{
    strings:
        // Library indicators
        $lib1 = "SRWebSocket" ascii
        $lib2 = "SocketRocket" ascii

        // Behavioral indicators
        $behav1 = "SSH tunnel not launched" ascii
        $behav2 = "Keylogger" ascii

    condition:
        (uint32(0) == 0xFEEDFACF or uint32(0) == 0xCAFEBABE) and
        any of ($lib*) and any of ($behav*)
}

JavaScript 偵測決策樹

撰寫 JavaScript 規則?
├─ npm 套件?
│  ├─ 檢查 package.json 模式
│  ├─ 尋找 postinstall/preinstall Hook
│  └─ 鎖定資料外洩 (exfil) 模式:fetch + 環境變數存取 + 憑證路徑
├─ 瀏覽器擴充功能?
│  ├─ Chrome:使用 crx 模組
│  └─ 其他:鎖定 manifest 模式、背景腳本行為
├─ 獨立 JS 檔案?
│  ├─ 尋找混淆標記:eval+atob、fromCharCode 鏈
│  ├─ 鎖定獨特的函式/變數名稱(通常在縮減後依然保留)
│  └─ 檢查是否有打包/編碼過後的 Payload
└─ 經過縮減(Minified)/ webpack 打包檔?
   ├─ 鎖定打包後仍保留的獨特字串(URL、Magic Value)
   └─ 避開函式名稱(會被混淆/重命名)

JavaScript 特有的良好字串:

  • 以太坊函式選擇器 (Ethereum function selectors):{ 70 a0 82 31 } (transfer)
  • 零寬字元(隱寫術):{ E2 80 8B E2 80 8C }
  • 混淆器特徵碼:_0xvar _0x
  • 特定的 C2 模式:網域名稱、webhook URL

JavaScript 特有的不佳字串:

  • requirefetchaxios — 太過常見
  • Buffercrypto — 到處都有合法的用途
  • 單純的 process.env — 需要搭配特定的環境變數名稱

必備工具箱

工具 用途
yarGen 擷取候選字串:yarGen.py -m samples/ --excludegood → 透過 yr check 驗證
FLOSS 擷取混淆字串/堆疊字串:floss sample.exe(當 yarGen 無效時使用)
yr CLI 驗證:yr check;掃描:yr scan -s;檢視:yr dump -m pe
signature-base 參考高品質規則範例
YARA-CI 在部署前使用正常檔案語料庫進行測試

掌握這五個工具即可,不要被複雜的工具清單分心。

應拒絕的合理化藉口

當你發現自己出現以下想法時,請立刻停下來重新評估。

合理化藉口 專家回應
「這個通用的字串已經夠獨特了」 先對正常檔案進行測試,你的直覺通常是錯的。
「這是 yarGen 產生的字串」 yarGen 只是建議,你必須親自驗證。請手動檢查每一個字串。
「在我的 10 個樣本上測試過都沒問題」 10 個樣本不等於生產環境。請使用 VirusTotal 的正常檔案庫測試。
「寫一條規則抓出所有變種」 這會引發誤報風暴。請針對特定家族編寫。
「等遇到誤報再改精細一點」 預先撰寫嚴謹的規則。誤報會破壞使用者信任。
「這個 Hex 模式很獨特」 在單一樣本中獨特 ≠ 在整個惡意軟體生態系中獨特。
「效能不重要」 一條過慢的規則會拖慢整個規則集。請最佳化 Atom。
「PEiD 規則依然有用」 已經過時了。32 位元的加殼工具現在已不具參考價值。
「我以後再補更多條件」 部署弱規則 = 已經造成傷害。
「這只是用來做 Hunting 的」 Hunting 規則終將成為偵測規則,應保持相同的品質標準。
「這個 API 名稱代表它有惡意」 合法軟體也會使用相同的 API,需要結合行為上下文判斷。
「對這些常見字串用 any of 就好」 常見字串搭配 any = 誤報災難。只有在字串本身即具獨特性時才用 any of
「這個常規表示式已經夠精準了」 /fetch.*token/ 會命中所有認證程式碼,必須加上資料外洩目的地條件。
「這個 JavaScript 看起來很乾淨」 攻擊者會在合法程式碼中植入注入碼。請檢查是否有 eval+decode 鏈。
「為了彈性我用 .* 好了」 無界限的常規表示式 = 效能災難 + 記憶體爆炸。請改用 .{0,30}
「我到處都加上 --relaxed-re-syntax」 這只會掩蓋真正的 Bug。請修復常規表示式本身,而不是藏起問題。

決策樹

這個字串夠好嗎?

這個字串夠好嗎?
├─ 少於 4 個位元組?
│  └─ 否 — 尋找更長的字串
├─ 包含重複位元組 (0000, 9090)?
│  └─ 否 — 加上前後上下文
├─ 是 API 名稱 (VirtualAlloc, CreateRemoteThread)?
│  └─ 否 — 改用呼叫點 (call site) 的 Hex 模式
├─ 出現在 Windows 系統檔案中?
│  └─ 否 — 太過通用,尋找獨特特徵
├─ 是常見路徑 (C:\Windows\, cmd.exe)?
│  └─ 否 — 尋找惡意軟體專屬路徑
├─ 對此惡意軟體家族是獨一無二的嗎?
│  └─ 是 — 使用它
└─ 也出現在其他惡意軟體中?
   └─ 也許 — 與家族專屬標記組合使用

何時使用 "all of" 與 "any of"

應該要求匹配所有字串還是允許任意字串?
├─ 字串個別對惡意軟體具備獨特性?
│  └─ any of them(單一字串即具備可疑性)
├─ 字串本身常見,但組合起來很可疑?
│  └─ all of them(需要完整模式匹配)
├─ 字串具備不同的置信度等級?
│  └─ 分組:all of ($core_*) and any of ($variant_*)
└─ 出現大量誤報?
   └─ 嚴格化:將 any 改為 all,並增加所需的必要字串

來自生產環境的教訓: 規則中使用 any of ($network_*) 且字串包含 "fetch"、"axios"、"http" 時,幾乎會命中所有的 Web 應用程式。將規則修改為同時需要憑證路徑 AND 網路呼叫 AND 資料外洩目的地後,誤報完全消除。

何時該放棄目前的規則撰寫方向

在以下情況請果斷停下並轉向:

  • yarGen 只回傳 API 名稱與通用路徑 → 參閱 當字串失效時,轉向結構分析

  • 找不到 3 個獨特字串 → 很可能已加殼。請針對解殼後的版本撰寫,或轉為偵測加殼器本身。

  • 規則命中正常檔案(Goodware) → 字串不夠獨特。1-2 個命中 = 調查並加嚴;3-5 個命中 = 尋找其他指標;6 個以上命中 = 重頭開始。

  • 即使最佳化後效能依然極差 → 架構問題。拆分為多個聚焦的規則,或加入嚴格的前置過濾條件。

  • 描述很難寫 → 規則定義太模糊。如果你無法清楚說明它抓到了什麼,代表它抓到了太多不相關的東西。

誤報(False Positive)除錯流程

誤報調查流程:
│
├─ 1. 命中了哪一個字串?
│     執行:yr scan -s rule.yar false_positive.exe
│
├─ 2. 它是否屬於合法的 Library?
│     └─ 加上:not $fp_vendor_string 排除條件
│
├─ 3. 是否為常見的開發模式?
│     └─ 尋找更具體的指標,替換該字串
│
├─ 4. 是否為多個通用字串組合在一起被匹配?
│     └─ 加嚴條件為必須匹配全部 + 加上獨特標記
│
└─ 5. 惡意軟體是否使用了常見技術?
      └─ 鎖定惡意軟體專屬的實作細節,而非技術本身

Hex vs 文字 vs 常規表示式

應該使用哪種字串類型?
│
├─ 精確的 ASCII/Unicode 文字?
│  └─ TEXT: $s = "MutexName" ascii wide
│
├─ 特定的位元組序列?
│  └─ HEX: $h = { 4D 5A 90 00 }
│
├─ 帶有變化的位元組序列?
│  └─ 帶萬用字元的 HEX: { 4D 5A ?? ?? 50 45 }
│
├─ 具備結構的模式(URL、路徑)?
│  └─ 有界限的常規表示式:/https:\/\/[a-z]{5,20}\.onion/
│
└─ 未知編碼(XOR、base64)?
   └─ 帶修飾符的 TEXT: $s = "config" xor(0x00-0xFF)

樣本是否已加殼?(優先檢查)

在撰寫任何基於字串的規則之前:

樣本是否已加殼?
├─ 熵值 (Entropy) > 7.0?
│  └─ 很可能已加殼 — 先尋找未加殼的層級
├─ 很少或幾乎沒有可讀字串?
│  └─ 很可能已加殼 — 改用熵值、PE 結構或加殼器特徵碼
├─ 偵測到 UPX/MPRESS/自訂加殼器?
│  └─ 鎖定解殼後的 Payload,或者直接偵測加殼器本身
└─ 有可讀的字串可用?
   └─ 繼續進行基於字串的偵測

專家指引: 切勿針對加殼層撰寫規則。加殼方式會變,但 Payload 不會變。

當字串失效時,轉向結構分析

如果 yarGen 只回傳 API 名稱與通用路徑:

St