$npx -y skills add killvxk/cybersecurity-skills-zh --skill analyzing-malware-family-relationships-with-malpedia使用 Malpedia 平台和 API 研究恶意软件家族关系、追踪变体演化、将家族关联到威胁行为者,并整合 YARA 规则用于跨恶意软件谱系的检测。
| 1 | # 使用 Malpedia 分析恶意软件家族关系 |
| 2 | |
| 3 | ## 概述 |
| 4 | |
| 5 | Malpedia 是由弗劳恩霍夫 FKIE 维护的协作平台,收录了恶意软件家族的别名、YARA 规则、威胁行为者关联和参考报告。收录超过 2,600 个恶意软件家族,是了解恶意软件谱系、追踪变体演化以及将恶意软件关联到特定威胁组织的权威资源。本技能涵盖查询 Malpedia API、映射恶意软件家族关系、提取 YARA 规则用于检测,以及构建对手所用恶意软件生态系统的情报。 |
| 6 | |
| 7 | ## 前置条件 |
| 8 | |
| 9 | - Python 3.9+,安装 `requests`、`yara-python`、`stix2` 库 |
| 10 | - Malpedia API 密钥(在 https://malpedia.caad.fkie.fraunhofer.de/ 注册) |
| 11 | - 了解恶意软件分类和命名规范 |
| 12 | - 熟悉用于检测的 YARA 规则语法 |
| 13 | - 访问恶意软件样本进行验证(可选) |
| 14 | |
| 15 | ## 核心概念 |
| 16 | |
| 17 | ### Malpedia 数据模型 |
| 18 | |
| 19 | Malpedia 将恶意软件组织为家族(如"win.cobalt_strike"),每个家族包含:别名(厂商特定名称,如"Beacon"、"CobaltStrike")、YARA 规则(社区和厂商贡献)、行为者关联(使用该家族的威胁组织)、参考报告(记录该家族的 CTI 报告)和样本哈希(每个变体的代表性样本)。 |
| 20 | |
| 21 | ### 恶意软件家族命名 |
| 22 | |
| 23 | Malpedia 使用 `平台.家族名称` 格式(如 `win.emotet`、`elf.mirai`、`apk.flubot`)。平台包括 win(Windows)、elf(Linux)、apk(Android)、osx(macOS)和 py(Python)。这种标准化命名解决了不同厂商对同一恶意软件使用不同名称的"多名问题"。 |
| 24 | |
| 25 | ### 家族关系 |
| 26 | |
| 27 | 恶意软件家族之间存在以下关系:父子关系(代码复用、分叉)、加载器-载荷关系(Emotet 加载 TrickBot 加载 Ryuk)、共同作者关系(同一威胁行为者开发多种工具)以及基础设施共享(共同 C2 框架)。 |
| 28 | |
| 29 | ## 实践步骤 |
| 30 | |
| 31 | ### 步骤 1:查询 Malpedia API 获取恶意软件家族 |
| 32 | |
| 33 | ```python |
| 34 | import requests |
| 35 | import json |
| 36 | from collections import defaultdict |
| 37 | |
| 38 | class MalpediaClient: |
| 39 | BASE_URL = "https://malpedia.caad.fkie.fraunhofer.de/api" |
| 40 | |
| 41 | def __init__(self, api_key): |
| 42 | self.headers = {"Authorization": f"apitoken {api_key}"} |
| 43 | |
| 44 | def get_family_list(self): |
| 45 | """获取所有恶意软件家族列表。""" |
| 46 | resp = requests.get(f"{self.BASE_URL}/list/families", |
| 47 | headers=self.headers, timeout=30) |
| 48 | if resp.status_code == 200: |
| 49 | families = resp.json() |
| 50 | print(f"[+] Malpedia: {len(families)} malware families") |
| 51 | return families |
| 52 | return {} |
| 53 | |
| 54 | def get_family_info(self, family_name): |
| 55 | """获取恶意软件家族的详细信息。""" |
| 56 | resp = requests.get(f"{self.BASE_URL}/get/family/{family_name}", |
| 57 | headers=self.headers, timeout=30) |
| 58 | if resp.status_code == 200: |
| 59 | info = resp.json() |
| 60 | print(f"[+] Family: {family_name}") |
| 61 | print(f" Aliases: {info.get('alt_names', [])}") |
| 62 | print(f" Actors: {[a.get('value', '') for a in info.get('attribution', [])]}") |
| 63 | print(f" URLs: {len(info.get('urls', []))} references") |
| 64 | return info |
| 65 | print(f"[-] Family not found: {family_name}") |
| 66 | return None |
| 67 | |
| 68 | def get_family_yara(self, family_name): |
| 69 | """获取恶意软件家族的 YARA 规则。""" |
| 70 | resp = requests.get(f"{self.BASE_URL}/get/yara/{family_name}", |
| 71 | headers=self.headers, timeout=30) |
| 72 | if resp.status_code == 200: |
| 73 | rules = resp.json() |
| 74 | rule_count = sum(len(v) for v in rules.values()) if isinstance(rules, dict) else 0 |
| 75 | print(f"[+] YARA rules for {family_name}: {rule_count} rules") |
| 76 | return rules |
| 77 | return {} |
| 78 | |
| 79 | def get_actor_families(self, actor_name): |
| 80 | """获取与威胁行为者关联的恶意软件家族。""" |
| 81 | resp = requests.get(f"{self.BASE_URL}/get/actor/{actor_name}", |
| 82 | headers=self.headers, timeout=30) |
| 83 | if resp.status_code == 200: |
| 84 | data = resp.json() |
| 85 | families = data.get("families", {}) |
| 86 | print(f"[+] {actor_name}: {len(families)} malware families") |
| 87 | return data |
| 88 | return {} |
| 89 | |
| 90 | def search_families(self, keyword): |
| 91 | """按关键词搜索家族。""" |
| 92 | all_families = self.get_family_list() |
| 93 | matches = { |
| 94 | name: info for name, info in all_families.items() |
| 95 | if keyword.lower() in name.lower() |
| 96 | or keyword.lower() in str(info.get("alt_names", [])).lower() |
| 97 | } |
| 98 | print(f"[+] Search '{keyword}': {len(matches)} matches") |
| 99 | return matches |
| 100 | |
| 101 | client = MalpediaClient("YOUR_MALPEDIA_API_KEY") |
| 102 | families = client.get_family_list() |
| 103 | emotet_info = client.get_family_info("win.emotet") |
| 104 | ``` |
| 105 | |
| 106 | ### 步骤 2:映射恶意软件家族关系 |
| 107 | |
| 108 | ```python |
| 109 | class MalwareFamilyMapper: |
| 110 | def __init__(self, malpedia_client): |
| 111 | self.client = malpedia_client |
| 112 | self.relationship_graph = defaultdict(list) |
| 113 | |
| 114 | def map_actor_ecosystem(self, actor_name): |
| 115 | """映射威胁行为者使用的恶意软件生态系统。""" |
| 116 | actor_data = self.client.get_actor_families(actor_name) |
| 117 | families = actor_data.get("families", {}) |
| 118 | |
| 119 | ecosystem = { |
| 120 | "actor": actor_name, |
| 121 | "families": [], |
| 122 | "family_count": len(families), |
| 123 | } |
| 124 | |
| 125 | for family_name in families: |
| 126 | info = self.client.get_family_info(family_name) |
| 127 | if info: |
| 128 | ecosystem["families"].append({ |
| 129 | "name": family_name, |
| 130 | "aliases": info.get("alt_names", []), |
| 131 | "description": info.get("description", "")[:200], |
| 132 | "shared_actors": [ |