Communitygithub.com

分析使用UPX加殼的惡意軟體

識別並解開 UPX 加殼的惡意軟體樣本,包含修改過 UPX 魔術位元組或標頭以阻擋自動解壓縮的執行檔,以恢復原始可執行檔進行靜態分析。當樣本顯示高熵、極少匯入,或匯入表中僅有 LoadLibrary/GetProcAddress 時使用,或當準備將加殼二進位檔送入 Ghidra 或 IDA 進行反組譯時使用。

分析使用UPX加殼的惡意軟體 是什麼?

這個技能提供一套完整的工作流程,用於分析使用 UPX 加殼的惡意軟體,包括處理被惡意軟體作者刻意修改以避免自動解壓縮的樣本。它會引導使用者通過五個主要步驟:使用 Detect It Easy 等工具識別加殼器,嘗試標準 UPX 解壓縮,修復修改過的 UPX 標頭(包含 Python 腳本),在 x64dbg 中進行手動脫殼,以及驗證解壓縮後二進位檔的完整性。該技能支援在 Linux 環境中使用 UPX、Detect It Easy、Python 的 `pefile` 函式庫和 x64dbg 等工具。其文件包含常見場景的詳細說明,例如處理被修改的 UPX 魔術位元組(`UPX!` 被改為其他值),並對雙重加殼和忽略重疊資料等陷阱提出警告。最終產出一個標準化的解壓縮分析報告,協助分析人員記錄結果。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/analyzing-packed-malware-with-upx-unpacker

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

分析使用 UPX 加殼的惡意軟體

使用時機

  • 靜態分析顯示高熵區段且匯入函式極少,表示二進位檔已加殼
  • PEiD、Detect It Easy 或 PEStudio 識別出 UPX 或其他已知加殼器
  • 匯入表中僅包含 LoadLibrary 和 GetProcAddress(加殼二進位檔典型的執行時期匯入解析)
  • 需要還原原始二進位檔,以便在 Ghidra 或 IDA 中進行正確的反組譯與反編譯
  • 自動 UPX 解壓縮失敗,因為惡意軟體作者修改了 UPX 魔術位元組或標頭

請勿使用於自訂加殼器、基於虛擬機的保護程式(Themida、VMProtect),或透過除錯進行動態脫殼更合適的樣本。

前置作業

  • 已安裝 UPX(Ultimate Packer for eXecutables)(apt install upx-ucl 或從 https://upx.github.io/ 下載)
  • 用於識別加殼器的 Detect It Easy (DIE)
  • Python 3.8+ 及 pefile 函式庫,用於手動修復標頭
  • 用於自動化工具失敗時手動脫殼的 x64dbg 或 x32dbg
  • 用於檢查與修復 PE 標頭的 PE-bear 或 CFF Explorer
  • 隔離的分析虛擬機,不具網路連線能力

工作流程

步驟 1:識別加殼器

判斷樣本是否已加殼並識別加殼器:

# 使用 Detect It Easy 檢查
diec suspect.exe

# 使用 UPX 檢查(僅測試不解壓)
upx -t suspect.exe

# 基於 Python 的熵值與加殼器檢測
python3 << 'PYEOF'
import pefile
import math

pe = pefile.PE("suspect.exe")

print("區段分析:")
for section in pe.sections:
    name = section.Name.decode().rstrip('\x00')
    entropy = section.get_entropy()
    raw = section.SizeOfRawData
    virtual = section.Misc_VirtualSize
    print(f"  {name:8s} 熵值:{entropy:.2f}  原始:{raw:>8}  虛擬:{virtual:>8}")

# 檢查 UPX 區段名稱
section_names = [s.Name.decode().rstrip('\x00') for s in pe.sections]
if 'UPX0' in section_names or 'UPX1' in section_names:
    print("\n[!] 偵測到 UPX 區段名稱")
elif '.upx' in [s.lower() for s in section_names]:
    print("\n[!] 偵測到 UPX 變體區段名稱")

# 檢查匯入數量(加殼二進位檔通常非常少)
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
    total_imports = sum(len(e.imports) for e in pe.DIRECTORY_ENTRY_IMPORT)
    print(f"\n匯入總數:{total_imports}")
    if total_imports < 10:
        print("[!] 匯入極少 - 可能已加殼")
else:
    print("\n[!] 無匯入目錄 - 高度加殼")
PYEOF

步驟 2:嘗試標準 UPX 解壓縮

嘗試內建的 UPX 解壓縮功能:

# 標準 UPX 解壓縮
upx -d suspect.exe -o unpacked.exe

# 如果 UPX 失敗並顯示 "not packed by UPX" 錯誤,表示標頭可能已被修改
# 輸出詳細資訊以進行除錯
upx -d suspect.exe -o unpacked.exe -v 2>&1

# 驗證解壓縮後的檔案
file unpacked.exe
diec unpacked.exe

步驟 3:修復修改過的 UPX 標頭

如果標準解壓縮失敗,修復被竄改的魔術位元組:

# 修復修改過的 UPX 標頭
import struct

with open("suspect.exe", "rb") as f:
    data = bytearray(f.read())

# UPX 魔術位元組:"UPX!" (0x55505821)
# 惡意軟體作者常修改這些位元組以防止自動解壓縮

# 搜尋修改過的 UPX 簽名
upx_magic = b"UPX!"
modified_patterns = [b"UPX0", b"UPX\x00", b"\x00PX!", b"UPx!"]

# 尋找並還原區段名稱
pe_offset = struct.unpack_from("<I", data, 0x3C)[0]
num_sections = struct.unpack_from("<H", data, pe_offset + 6)[0]
section_table_offset = pe_offset + 0x18 + struct.unpack_from("<H", data, pe_offset + 0x14)[0]

print(f"PE 偏移量:0x{pe_offset:X}")
print(f"區段數量:{num_sections}")
print(f"區段表偏移量:0x{section_table_offset:X}")

for i in range(num_sections):
    offset = section_table_offset + (i * 40)
    name = data[offset:offset+8]
    print(f"區段 {i}:{name}")

# 還原二進位檔中的 UPX 魔術位元組
# 搜尋 UPX 標頭簽名位置(通常位於已壓縮資料的尾部)
for i in range(len(data) - 4):
    if data[i:i+3] == b"UPX" and data[i+3] != ord("!"):
        print(f"在偏移量 0x{i:X} 處找到修改過的 UPX 魔術位元組:{data[i:i+4]}")
        data[i:i+4] = b"UPX!"
        print(f"已還原為:UPX!")

# 如果區段名稱也被修改,一併還原
for i in range(num_sections):
    offset = section_table_offset + (i * 40)
    name = data[offset:offset+8].rstrip(b'\x00')
    if name in [b"UPX0", b"UPX1", b"UPX2"]:
        continue  # 已正確
    # 檢查常見的修改
    if name.startswith(b"UP") or name.startswith(b"ux"):
        original = f"UPX{i}".encode().ljust(8, b'\x00')
        data[offset:offset+8] = original
        print(f"已在偏移量 0x{offset:X} 處將區段名稱還原為 {original}")

with open("suspect_fixed.exe", "wb") as f:
    f.write(data)

print("\n已寫入修復後的檔案。重新嘗試:upx -d suspect_fixed.exe -o unpacked.exe")

步驟 4:使用除錯器手動脫殼

當自動脫殼完全失敗時,使用動態脫殼:

使用 x64dbg 手動 UPX 脫殼:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. 在 x64dbg 中載入加殼樣本
2. 執行到進入點(系統中斷點後按 F9)
3. UPX 脫殼 Stub 模式:
   a. PUSHAD(儲存所有暫存器)
   b. 解壓縮迴圈(處理已壓縮的區段)
   c. 解析匯入(LoadLibrary/GetProcAddress 呼叫)
   d. POPAD(還原暫存器)
   e. JMP 到 OEP(原始進入點)
4. 在 PUSHAD 之後設定 ESP 的硬體中斷點:
   - PUSHAD 之後,在暫存器中對 ESP 按右鍵 -> 在傾印中跟隨
   - 在 [ESP] 位址上設定存取型硬體中斷點
   - 執行 (F9) - 會在跳到 OEP 之前於 POPAD 處中斷
5. 向前逐步執行 (F7/F8) 直到抵達跳至 OEP 的 JMP 指令
6. 在 OEP 處:使用 Scylla 外掛傾印並修復匯入:
   - 外掛 -> Scylla -> OEP = 目前 EIP
   - 點擊 "IAT Autosearch" -> "Get Imports"
   - 點擊 "Dump" 儲存脫殼後的二進位檔
   - 點擊 "Fix Dump" 修復匯入表

步驟 5:驗證脫殼後的二進位檔

驗證脫殼後的樣本是否有效且完整:

# 驗證脫殼後的 PE 是否有效
python3 << 'PYEOF'
import pefile

pe = pefile.PE("unpacked.exe")

# 檢查區段是否正常
print("脫殼後區段分析:")
for section in pe.sections:
    name = section.Name.decode().rstrip('\x00')
    entropy = section.get_entropy()
    print(f"  {name:8s} 熵值:{entropy:.2f}")

# 驗證匯入是否已解析
print(f"\n匯入數量:")
if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
        dll = entry.dll.decode()
        count = len(entry.imports)
        print(f"  {dll}: {count} 個函式")
    total = sum(len(e.imports) for e in pe.DIRECTORY_ENTRY_IMPORT)
    print(f"  總計:{total} 個匯入")

# 比較檔案大小
import os
packed_size = os.path.getsize("suspect.exe")
unpacked_size = os.path.getsize("unpacked.exe")
print(f"\n加殼前:   {packed_size:>10} 位元組")
print(f"脫殼後: {unpacked_size:>10} 位元組")
print(f"比例:    {unpacked_size/packed_size:.1f}x")
PYEOF

關鍵概念

術語定義
加殼壓縮或加密可執行程式碼以減少檔案大小並阻礙靜態分析;二進位檔包含一個在執行時還原程式碼的脫殼 Stub
UPXUltimate Packer for eXecutables;開放原始碼的可執行檔加殼器,因其免費且有效而常被惡意軟體作者濫用
原始進入點 (OEP)加殼前惡意軟體程式碼的真正起始位址;脫殼 Stub 解壓縮程式碼後會跳轉到 OEP
匯入重建在使用 Scylla 或 ImpRec 等工具將脫殼後的行程從記憶體傾印出來後,重建匯入位址表的過程
PUSHAD/POPADx86 指令,用於儲存/還原所有通用暫存器;UPX 使用此模式在脫殼期間保留暫存器狀態
區段熵值PE 區段資料的隨機性度量;加殼區段的熵值 > 7.0,而一般程式碼區段平均為 5.0-6.5
魔術位元組檔案中用於識別其格式的簽名位元組;UPX 使用 "UPX!",惡意軟體作者會修改此值以防止自動解壓縮

工具與系統

  • UPX:開放原始碼的可執行檔加殼器,對於正確加殼的檔案具有內建的解壓縮功能
  • Detect It Easy (DIE):加殼器、編譯器和連結器偵測工具,可識別 PE、ELF 和 Mach-O 檔案上的保護
  • x64dbg/x32dbg:開放原始碼的 Windows 除錯器,用於透過動態執行和基於中斷點的 OEP 尋找來進行手動脫殼
  • Scylla:與 x64dbg 整合的匯入重建工具,用於在記憶體傾印後重建 IAT
  • PE-bear:PE 檔案檢視器與編輯器,用於在脫殼後檢查和修復 PE 標頭

常見情境

情境:脫殼具有修改過 UPX 標頭的惡意軟體

背景:一個惡意軟體樣本透過區段名稱 (UPX0, UPX1) 被識別為 UPX 加殼,但 upx -d 失敗並顯示 "CantUnpackException: header corrupted"。惡意軟體作者修改了 UPX 魔術位元組以防止自動解壓縮。

方法:

  1. 在十六進位編輯器中開啟二進位檔,搜尋 UPX 標頭區域(通常位於已壓縮資料的尾部)
  2. 識別被修改的魔術位元組(例如 "UPX!" 被改為 "UPX\x00" 或完全歸零)
  3. 使用 Python 修復腳本恢復 "UPX!" 魔術位元組並修正區段名稱
  4. 在修復後的二進位檔上重新嘗試 upx -d
  5. 如果修復失敗,改用手動脫殼搭配 x64dbg(PUSHAD -> 在 ESP 設硬體中斷點 -> POPAD -> JMP OEP)
  6. 驗證脫殼後的二進位檔是否具有正確的匯入和合理的熵值
  7. 匯入 Ghidra 或 IDA 進行完整的靜態分析

注意陷阱:

  • 假設 UPX 是唯一的加殼器;二進位檔可能經過雙重加殼(UPX + 自訂層)
  • 修改原始的加殼樣本,而不是在副本上操作
  • 在人工記憶體傾印後未重建匯入(沒有 IAT 修正的傾印二進位檔會崩潰)
  • 忘記檢查附加在 UPX 加殼 PE 區段之後的重疊資料

輸出格式

脫殼分析報告
===========================
樣本:           suspect.exe
SHA-256:          e3b0c44298fc1c149afbf4c8996fb924...
加殼器:           UPX 3.96(標頭已修改)

加殼二進位檔
區段:         UPX0 (熵值:0.00) UPX1 (熵值:7.89) .rsrc (熵值:3.45)
匯入:          2 (kernel32.dll:LoadLibraryA, GetProcAddress)
檔案大小:        98,304 位元組

脫殼方法
方法:           標頭修復 + UPX -d
標頭修正:       在偏移量 0x1F000 處還原 UPX! 魔術位元組
指令:          upx -d suspect_fixed.exe -o unpacked.exe
結果:           成功

脫殼二進位檔
區段:         .text (熵值:6.21) .rdata (熵值:4.56) .data (熵值:3.12) .rsrc (熵值:3.45)
匯入:          147 (kernel32, user32, advapi32, wininet, ws2_32)
檔案大小:        245,760 位元組(2.5 倍膨脹)
OEP:              0x00401000

驗證
PE 有效:         是
匯入已解析:     是(跨 8 個 DLL,共 147 個函式)
可執行:          是(在沙箱中執行不會崩潰)

後續步驟
- 將 unpacked.exe 匯入 Ghidra 進行完整反組譯
- 對脫殼後的二進位檔執行 YARA 規則
- 將脫殼後的二進位檔提交至 VirusTotal 以獲得更好的偵測率

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

相關技能