Analyse von Malware-Familienbeziehungen mit Malpedia
Übersicht
Malpedia ist eine kollaborative Plattform, die vom Fraunhofer FKIE betrieben wird und Malware-Familien mit ihren Aliasen, YARA-Regeln, Bedrohungsakteuren und Referenzberichten katalogisiert. Mit über 2.600 dokumentierten Malware-Familien dient sie als maßgebliche Ressource, um Malware-Linien nachzuvollziehen, Variantenentwicklungen zu verfolgen und Malware mit bestimmten Bedrohungsgruppen zu verknüpfen. Diese Fähigkeit umfasst das Abfragen der Malpedia-API, das Kartieren von Beziehungen zwischen Malware-Familien, das Extrahieren von YARA-Regeln zur Erkennung und das Aufbauen von Bedrohungsinformationen über Malware-Ökosysteme, die von Angreifern genutzt werden.
Wann zu verwenden
- Bei der Untersuchung von Sicherheitsvorfällen, die die Analyse von Malware-Familienbeziehungen mit Malpedia erfordern.
- Beim Erstellen von Erkennungsregeln oder Bedrohungsjagd-Abfragen für diese Domäne.
- Wenn SOC-Analysten strukturierte Verfahren für diese Analyseart benötigen.
- Bei der Validierung der Abdeckung von Sicherheitsüberwachung für verwandte Angriffstechniken.
Voraussetzungen
- Python 3.9+ mit den Bibliotheken
requests,yara-python,stix2. - Malpedia-API-Schlüssel (Registrierung unter https://malpedia.caad.fkie.fraunhofer.de/).
- Verständnis der Malware-Klassifikation und Benennungskonventionen.
- Vertrautheit mit der YARA-Regel-Syntax für die Erkennung.
- Zugriff auf Malware-Beispiele zur Validierung (optional).
Schlüsselkonzepte
Malpedia-Datenmodell
Malpedia organisiert Malware in Familien (z. B. „win.cobalt_strike“), die jeweils enthalten: Aliase (vendor-spezifische Namen wie „Beacon“, „CobaltStrike“), YARA-Regeln (von der Community und Herstellern beigetragen), Akteurszuordnungen (Bedrohungsgruppen, die die Familie nutzen), Referenzberichte (CTI-Berichte, die die Familie dokumentieren) und Beispiel-Hashes (repräsentative Samples für jede Variante).
Benennung von Malware-Familien
Malpedia verwendet das Format platform.family_name (z. B. win.emotet, elf.mirai, apk.flubot). Zu den Plattformen gehören win (Windows), elf (Linux), apk (Android), osx (macOS) und py (Python). Diese standardisierte Benennung löst das Problem der „vielen Namen“, bei dem verschiedene Hersteller derselben Malware unterschiedliche Namen zuweisen.
Familienbeziehungen
Malware-Familien haben Beziehungen, die Folgendes umfassen: Eltern-Kind (Wiederverwendung von Code, Forks), Lader-Payload (Emotet lädt TrickBot, TrickBot lädt Ryuk), gemeinsame Autorenschaft (derselbe Bedrohungsakteur entwickelt mehrere Werkzeuge) und gemeinsame Infrastruktur (gemeinsame C2-Frameworks).
Arbeitsablauf
Schritt 1: Abfrage der Malpedia-API nach Malware-Familien
import requests
import json
from collections import defaultdict
class MalpediaClient:
BASE_URL = "https://malpedia.caad.fkie.fraunhofer.de/api"
def __init__(self, api_key):
self.headers = {"Authorization": f"apitoken {api_key}"}
def get_family_list(self):
"""Ruft die Liste aller Malware-Familien ab."""
resp = requests.get(f"{self.BASE_URL}/list/families",
headers=self.headers, timeout=30)
if resp.status_code == 200:
families = resp.json()
print(f"[+] Malpedia: {len(families)} Malware-Familien")
return families
return {}
def get_family_info(self, family_name):
"""Ruft detaillierte Informationen zu einer Malware-Familie ab."""
resp = requests.get(f"{self.BASE_URL}/get/family/{family_name}",
headers=self.headers, timeout=30)
if resp.status_code == 200:
info = resp.json()
print(f"[+] Familie: {family_name}")
print(f" Aliase: {info.get('alt_names', [])}")
print(f" Akteure: {[a.get('value', '') for a in info.get('attribution', [])]}")
print(f" URLs: {len(info.get('urls', []))} Referenzen")
return info
print(f"[-] Familie nicht gefunden: {family_name}")
return None
def get_family_yara(self, family_name):
"""Ruft YARA-Regeln für eine Malware-Familie ab."""
resp = requests.get(f"{self.BASE_URL}/get/yara/{family_name}",
headers=self.headers, timeout=30)
if resp.status_code == 200:
rules = resp.json()
rule_count = sum(len(v) for v in rules.values()) if isinstance(rules, dict) else 0
print(f"[+] YARA-Regeln für {family_name}: {rule_count} Regeln")
return rules
return {}
def get_actor_families(self, actor_name):
"""Ruft Malware-Familien ab, die mit einem Bedrohungsakteur verbunden sind."""
resp = requests.get(f"{self.BASE_URL}/get/actor/{actor_name}",
headers=self.headers, timeout=30)
if resp.status_code == 200:
data = resp.json()
families = data.get("families", {})
print(f"[+] {actor_name}: {len(families)} Malware-Familien")
return data
return {}
def search_families(self, keyword):
"""Durchsucht Familien nach einem Stichwort."""
all_families = self.get_family_list()
matches = {
name: info for name, info in all_families.items()
if keyword.lower() in name.lower()
or keyword.lower() in str(info.get("alt_names", [])).lower()
}
print(f"[+] Suche '{keyword}': {len(matches)} Treffer")
return matches
client = MalpediaClient("IHR_MALPEDIA_API_SCHLUESSEL")
families = client.get_family_list()
emotet_info = client.get_family_info("win.emotet")
Schritt 2: Kartieren von Beziehungen zwischen Malware-Familien
class MalwareFamilyMapper:
def __init__(self, malpedia_client):
self.client = malpedia_client
self.relationship_graph = defaultdict(list)
def map_actor_ecosystem(self, actor_name):
"""Kartiert das Malware-Ökosystem, das von einem Bedrohungsakteur genutzt wird."""
actor_data = self.client.get_actor_families(actor_name)
families = actor_data.get("families", {})
ecosystem = {
"actor": actor_name,
"families": [],
"family_count": len(families),
}
for family_name in families:
info = self.client.get_family_info(family_name)
if info:
ecosystem["families"].append({
"name": family_name,
"aliases": info.get("alt_names", []),
"description": info.get("description", "")[:200],
"shared_actors": [
a.get("value", "")
for a in info.get("attribution", [])
],
"reference_count": len(info.get("urls", [])),
})
print(f"\n=== Malware-Ökosystem von {actor_name} ===")
for fam in ecosystem["families"]:
shared = [a for a in fam["shared_actors"] if a != actor_name]
print(f" {fam['name']}")
print(f" Aliase: {fam['aliases'][:5]}")
if shared:
print(f" Auch verwendet von: {shared}")
return ecosystem
def find_shared_tooling(self, actor_names):
"""Findet Malware-Familien, die von mehreren Bedrohungsakteuren gemeinsam genutzt werden."""
actor_families = {}
for actor in actor_names:
data = self.client.get_actor_families(actor)
actor_families[actor] = set(data.get("families", {}).keys())
# Überschneidungen finden
shared = {}
for i, actor1 in enumerate(actor_names):
for actor2 in actor_names[i+1:]:
common = actor_families[actor1] & actor_families[actor2]
if common:
shared[f"{actor1} <-> {actor2}"] = sorted(common)
print(f"\n=== Analyse gemeinsam genutzter Werkzeuge ===")
for pair, families in shared.items():
print(f" {pair}: {len(families)} gemeinsam genutzte Familien")
for f in families[:5]:
print(f" - {f}")
return shared
def build_loader_payload_chain(self, family_name):
"""Erstellt die Lader-Payload-Lieferkette für eine Familie."""
info = self.client.get_family_info(family_name)
if not info:
return {}
chain = {
"family": family_name,
"description": info.get("description", ""),
"known_loaders": [],
"known_payloads": [],
}
# Bekannte Lieferketten
known_chains = {
"win.emotet": {"loaders": ["email/macro"], "payloads": ["win.trickbot", "win.qakbot", "win.cobalt_strike"]},
"win.trickbot": {"loaders": ["win.emotet"], "payloads": ["win.ryuk", "win.conti", "win.cobalt_strike"]},
"win.qakbot": {"loaders": ["email/macro", "win.emotet"], "payloads": ["win.cobalt_strike", "win.blackbasta"]},
"win.cobalt_strike": {"loaders": ["win.emotet", "win.trickbot", "win.qakbot"], "payloads": ["ransomware"]},
}
if family_name in known_chains:
chain["known_loaders"] = known_chains[family_name]["loaders"]
chain["known_payloads"] = known_chains[family_name]["payloads"]
return chain
mapper = MalwareFamilyMapper(client)
ecosystem = mapper.map_actor_ecosystem("Wizard Spider")
shared = mapper.find_shared_tooling(["Wizard Spider", "FIN7", "Lazarus Group"])
chain = mapper.build_loader_payload_chain("win.emotet")
Schritt 3: Extrahieren und Kompilieren von YARA-Regeln
def compile_yara_ruleset(client, family_names, output_file="malware_yara_rules.yar"):
"""Kompiliert YARA-Regeln für mehrere Malware-Familien."""
all_rules = []
for family in family_names:
yara_data = client.get_family_yara(family)
if isinstance(yara_data, dict):
for source, rules in yara_data.items():
if isinstance(rules, list):
for rule in rules:
all_rules.append(f"// Quelle: {source} - Familie: {family}\n{rule}")
elif isinstance(rules, str):
all_rules.append(f"// Quelle: {source} - Familie: {family}\n{rules}")
with open(output_file, "w") as f:
f.write(f"// Malpedia YARA-Regeln - {len(all_rules)} Regeln\n")
f.write(f"// Familien: {', '.join(family_names)}\n\n")
for rule in all_rules:
f.write(rule + "\n\n")
print(f"[+] {len(all_rules)} YARA-Regeln nach {output_file} kompiliert")
return all_rules
compile_yara_ruleset(client, ["win.emotet", "win.trickbot", "win.cobalt_strike"])
Validierungskriterien
- Malpedia-API erfolgreich für Malware-Familien abgefragt.
- Familieninformationen mit Aliasen, Akteuren und Referenzen abgerufen.
- Akteur-Familien-Beziehungen korrekt kartiert.
- Gemeinsam genutzte Werkzeuge zwischen Akteuren identifiziert.
- YARA-Regeln extrahiert und für die Erkennung kompiliert.
- Lader-Payload-Ketten für die Bedrohungsanalyse dokumentiert.