Malware Analysis
Einstieg in statische Malware-Analyse
Ein strukturierter Workflow für den ersten Blick auf unbekannte Binaries — von Triaging über Disassembly bis zur IOC-Extraktion.
Bevor du eine unbekannte Probe in die Sandbox wirfst, lohnt sich ein disziplinierter statischer Überblick. Statische Analyse beantwortet nicht alles — aber sie liefert dir in wenigen Minuten Risikoeinschätzung, Verdachtsmomente und eine gezielte Hypothesenliste für die dynamische Phase.
Dieser Artikel beschreibt einen praxisnahen Workflow, den ich für Windows-PE-Samples nutze. Die Befehle sind copy-paste-fähig; Pfade und Dateinamen passe ich an ein fiktives Sample sample.exe an.
Vorbereitung: Lab & Hygiene
Arbeite niemals mit Malware auf deinem Host-System. Minimum-Setup:
| Komponente | Empfehlung |
|---|---|
| VM | Isolierte Analyse-VM (Win10/11), keine Shared Folders |
| Snapshot | Snapshot vor jeder Analyse — Rollback nach Session |
| Netzwerk | VM-Netzwerk disabled oder auf Host-Only/FakeNet |
| Tools | Remnux, FLARE-VM oder eigene Windows-Analyse-VM |
| Hashing | SHA256 vor dem Öffnen dokumentieren |
Arbeitsverzeichnis anlegen
mkdir -p ~/malware-lab/samples/2026-07-14-sample
cd ~/malware-lab/samples/2026-07-14-sample
Sample sicher übertragen
Sample per USB, geschütztem Share oder scp in die VM kopieren. Direkt hashen:
# Linux / Remnux
sha256sum sample.exe | tee sample.exe.sha256
# Windows PowerShell
Get-FileHash -Algorithm SHA256 .\sample.exe | Format-List
Beispielausgabe (fiktiv):
SHA256: 3f8a1b2c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678
Hash in deine Analyse-Notizen übernehmen — später für IOCs, YARA und Austausch mit der Community.
Optional: VirusTotal-Check (nur Hash!)
curl -s --request GET \
--url "https://www.virustotal.com/api/v3/files/<SHA256_HIER_EINFÜGEN>" \
--header "x-apikey: <DEIN_VT_API_KEY>"
Hinweis: Upload nur, wenn du die Policy deines Labs/Arbeitgebers kennst. Für sensible Samples reicht oft der Hash-Lookup.
Phase 1: Triaging
Ziel: Was ist das für eine Datei? Ist sie gepackt? Enthält sie verdächtige Strings oder Imports?
1.1 Dateityp & Basisinformationen
file sample.exe
Typische Ausgabe:
sample.exe: PE32 executable (GUI) Intel 80386, for MS Windows
exiftool sample.exe
Achte auf: OriginalFileName, InternalName, CompanyName, CompileTimestamp — oft spoofed, aber dokumentationswürdig.
1.2 Entropie — Packer-Verdacht
Hohe Entropie (> 7.0) in einzelnen Sections deutet auf Packing/Verschlüsselung hin.
# mit binwalk
binwalk -E sample.exe
# alternativ: ent (falls installiert)
ent sample.exe
Interpretation:
| Entropie (Section) | Einschätzung |
|---|---|
| < 6.5 | eher ungepackt / normale Code-Section |
| 6.5 – 7.2 | grenzwertig — genauer hinschauen |
| > 7.2 | starker Verdacht auf Packer/Verschlüsselung |
1.3 Detect It Easy (DIE) — Packer/Compiler
# Windows (DIE CLI, Pfad anpassen)
"C:\Tools\die\diec.exe" -d sample.exe
Beispielausgabe:
PE32
Operation system: Windows(95)[I386]
Protector: UPX(3.96)[NRV,brute]
Language: C/C++
→ Sofort notieren: UPX → später upx -d testen (nur in isolierter VM).
1.4 PE-Struktur mit peframe
peframe sample.exe | head -60
Relevante Felder:
Magic— PE-ValidierungEntry Point— StartadresseSections— Namen wie.upx0,.upx1sind Packer-IndikatorenImports— erste API-Hypothesen
1.5 Strings extrahieren
strings -n 8 sample.exe | tee strings.txt
strings -el sample.exe | tee strings_unicode.txt # UTF-16LE (Windows)
Verdächtige Muster suchen:
grep -iE '(http|https|ftp)://' strings.txt
grep -iE '(\.exe|\.dll|\.bat|cmd\.exe|powershell)' strings.txt
grep -iE '(HKEY_|Software\\Microsoft\\Windows\\CurrentVersion\\Run)' strings.txt
grep -iE '(VirtualAlloc|WriteProcessMemory|CreateRemoteThread)' strings.txt
Beispiel-Treffer (fiktiv):
http://malicious-c2.example.com/gate.php
cmd.exe /c whoami
Software\Microsoft\Windows\CurrentVersion\Run
→ C2-URL, Command Execution, Registry-Persistence — drei Hypothesen für Phase 3.
1.6 Imports clustern (fcli / pedump)
# fcli (FLARE) — Import-Übersicht
fcli sample.exe imports
# oder mit Python pefile
python3 << 'EOF'
import pefile
pe = pefile.PE("sample.exe")
for entry in pe.DIRECTORY_ENTRY_IMPORT:
print(f"\n[DLL] {entry.dll.decode()}")
for imp in entry.imports:
if imp.name:
print(f" - {imp.name.decode()}")
EOF
Verdächtige API-Cluster:
| API-Gruppe | APIs | Verdacht |
|---|---|---|
| Injection | VirtualAllocEx, WriteProcessMemory, CreateRemoteThread |
Prozess-Injektion |
| Persistence | RegSetValueEx, RegCreateKeyEx |
Registry-Persistence |
| Netzwerk | InternetOpenUrl, HttpSendRequest, WSAStartup |
C2 / Exfiltration |
| Anti-Analysis | IsDebuggerPresent, CheckRemoteDebuggerPresent |
Evasion |
| Droppers | URLDownloadToFile, CreateProcess |
Download & Execute |
Phase 2: Disassembly
Ziel: Entry Point verstehen, Kontrollfluss skizzieren, Obfuscation erkennen — nicht sofort alles deobfuscaten.
2.1 Ghidra — Projekt anlegen
# Ghidra Headless (Batch-Import)
analyzeHeadless /opt/ghidra/projects MalwareProj \
-import sample.exe \
-overwrite \
-scriptPath /opt/ghidra/scripts
Oder interaktiv: Ghidra öffnen → New Project → Import sample.exe → Analyze (Standard-Optionen reichen für den Start).
2.2 Entry Point lokalisieren
In Ghidra:
- Window → Symbol Tree → Functions
entryoderEntryPointsuchen- Aufrufkette der ersten 10–20 Funktionen notieren
Was du dokumentierst:
entry()
└── FUN_00401000() ; vermutlich CRT-Init
└── FUN_00401230() ; Hauptlogik / Packer-Stub
└── FUN_00401800() ; Entpack-Routine?
2.3 Obfuscation erkennen
Typische Muster in der Disassembly:
; Junk-Code / opaque predicates
CMP EAX, 2
JNZ loc_dead_code ; wird nie genommen
...
loc_dead_code:
XOR EBX, EBX ; Müll
; API-Hashing statt direkter Imports
PUSH 0x91AFCA54 ; Hash von kernel32.dll
CALL resolve_api_by_hash
Regel: Erst Struktur verstehen, dann gezielt deobfuscaten — nicht blind durch den ganzen Binary klicken.
2.4 Verdächtige Funktionen benennen
In Ghidra Funktionen sinnvoll umbenennen — spart Stunden:
| Original | Umbenennen zu | Grund |
|---|---|---|
FUN_00401800 |
unpack_stub |
Entropie + Schleife über Sections |
FUN_00402100 |
resolve_apis |
PEB-Walk / GetProcAddress-Muster |
FUN_00402500 |
persist_registry |
RegSetValueEx-Aufrufe |
2.5 Optional: UPX entpacken
Nur wenn DIE UPX meldet und du in einer isolierten VM bist:
upx -d sample.exe -o sample_unpacked.exe
Danach Triaging wiederholen — Strings und Imports sind oft erst jetzt sichtbar:
strings -n 8 sample_unpacked.exe | grep -iE 'http'
peframe sample_unpacked.exe | head -30
Phase 3: Verhaltenshypothesen
Aus Phase 1 und 2 formulierst du testbare Fragen für die dynamische Analyse:
Hypothesen-Tabelle (Beispiel)
| # | Hypothese | Statischer Beleg | Dynamischer Test |
|---|---|---|---|
| H1 | Sample persistiert via Run-Key | String CurrentVersion\Run + RegSetValueEx |
Procmon: Registry-Writes |
| H2 | C2-Kommunikation über HTTP | String http://malicious-c2.example.com |
Wireshark / FakeNet |
| H3 | Prozess-Injektion | Imports WriteProcessMemory, CreateRemoteThread |
API-Monitor / x64dbg |
| H4 | Anti-VM / Anti-Debug | IsDebuggerPresent, Registry-Checks |
Sandbox mit/ohne Artefakte |
Mini-Checkliste vor der Sandbox
[ ] SHA256 dokumentiert
[ ] Packer identifiziert (ja/nein, welcher)
[ ] Verdächtige Strings extrahiert
[ ] Import-Cluster notiert
[ ] Entry-Point-Call-Chain skizziert
[ ] Hypothesen-Tabelle erstellt
[ ] VM-Snapshot erstellt
[ ] Netzwerk isoliert oder FakeNet bereit
Phase 4: IOCs extrahieren & Übergabe
Statische Findings werden zu Indicators of Compromise — die Grundlage für Detection und Threat Hunting.
4.1 IOC-Sammlung (Beispiel)
# iocs/sample_2026-07-14.yml
hashes:
sha256: "3f8a1b2c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678"
file:
filename: "sample.exe"
size_bytes: 245760
network:
domains:
- "malicious-c2.example.com"
urls:
- "http://malicious-c2.example.com/gate.php"
host:
registry_keys:
- "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\WindowsUpdate"
mutex:
- "Global\\MalwareMutex_0x4141" # falls in Strings gefunden
imports_flagged:
- "WriteProcessMemory"
- "CreateRemoteThread"
- "RegSetValueExA"
4.2 Einfache YARA-Regel (String-basiert)
rule AetherSec_Sample_C2_String {
meta:
author = "AetherSec"
description = "Detects sample with hardcoded C2 URL"
date = "2026-07-14"
hash = "3f8a1b2c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678"
strings:
$c2 = "malicious-c2.example.com" ascii wide
$run = "CurrentVersion\\Run" ascii wide
condition:
uint16(0) == 0x5A4D and
filesize < 5MB and
$c2 and $run
}
Testen:
yara -s aethersec_sample.yar sample.exe
4.3 Übergabe an dynamische Analyse
Was du der Sandbox mitgibst:
- Hypothesen-Tabelle (Phase 3)
- IOC-YAML (Phase 4)
- Entpacktes Binary (falls vorhanden:
sample_unpacked.exe) - Ghidra-Projekt-Export (optional: Function-Namen als Referenz)
Dynamische Tools je nach Hypothese:
| Hypothese | Tool | Was du beobachtest |
|---|---|---|
| Persistence | Procmon | RegSetValue auf Run-Keys |
| C2 | Wireshark / FakeNet | HTTP-Requests, DNS |
| Injection | API Monitor | WriteProcessMemory + CreateRemoteThread |
| Evasion | x64dbg / ScyllaHide | Debugger-Checks, Timing |
Komplett-Workflow auf einen Blick
# === VORBEREITUNG ===
mkdir -p ~/malware-lab/samples/$(date +%Y-%m-%d)-sample && cd $_
sha256sum sample.exe | tee sample.exe.sha256
# === TRIAGING ===
file sample.exe
binwalk -E sample.exe
diec sample.exe # oder peframe
strings -n 8 sample.exe | tee strings.txt
strings -el sample.exe | tee strings_u.txt
grep -iE '(http|HKEY_|VirtualAlloc|cmd\.exe)' strings.txt
# === DISASSEMBLY ===
# Ghidra: Import → Analyze → Entry Point → Call-Chain dokumentieren
# === OPTIONAL: UNPACK ===
upx -d sample.exe -o sample_unpacked.exe # nur bei UPX, nur in VM!
# === IOCs ===
yara -s aethersec_sample.yar sample.exe
Häufige Fehler (und wie du sie vermeidest)
Zu früh dynamisch analysieren.
→ Erst statisch triagen. Du sparst Sandbox-Zeit und vermeidest, dass ein Evasion-Mechanismus deine Session verdirbt.
Alles auf einmal deobfuscaten.
→ Struktur vor Details. Entry Point → Hauptfunktionen → dann gezielt tiefer.
Keine Dokumentation.
→ Jeder Befehl, jede Ausgabe, jeder Hash in Notizen. Dein zukünftiges Ich (und dein Team) wird es dir danken.
Netzwerk an in der VM.
→ Isolation first. C2-Callbacks auf echte Infrastruktur sind vermeidbar.
Sample ohne Snapshot öffnen.
→ Ein Klick auf die falsche Datei — VM weg. Snapshot ist Pflicht.
Tooling-Referenz
| Phase | Tool | Zweck |
|---|---|---|
| Hashing | sha256sum, Get-FileHash |
Integrität & IOC |
| Triaging | file, binwalk, die, peframe |
Typ, Entropie, Packer |
| Strings | strings, grep |
C2, Pfade, Mutex, Registry |
| Imports | fcli, pefile |
API-Verhalten ableiten |
| Disassembly | Ghidra, IDA, Binary Ninja | Kontrollfluss, Deobfuscation |
| Unpacking | upx -d, manuell in Debugger |
Entpackte Analyse |
| Detection | YARA | Regelbasierte Erkennung |
| Dynamisch | Procmon, Wireshark, x64dbg | Hypothesen testen |
Fazit
Statische Malware-Analyse ist kein Ersatz für dynamisches Verhalten — aber der effizienteste Startpunkt. Ein disziplinierter 30–60-Minuten-Block vor der Sandbox liefert dir:
- Risikoeinschätzung (Packer? Injection? C2?)
- Konkrete Hypothesen für dynamische Tests
- IOCs und YARA-Grundlagen für Detection
Wer hier sauber dokumentiert, analysiert schneller und trifft in der dynamischen Phase bessere Entscheidungen.
Feedback, Sample-Hinweise oder Korrekturen gerne über GitHub oder X.