| name | performing-malware-ioc-extraction |
| description | 恶意软件 IOC(失陷指标)提取是指通过分析恶意软件,识别可操作的失陷指标,包括文件哈希、网络指标(C2 域名、IP 地址、URL)、注册表修改、互斥体名称、嵌入字符串和行为产物。 |
| domain | cybersecurity |
| subdomain | threat-intelligence |
| tags | ["threat-intelligence","cti","ioc","mitre-attack","stix","malware-analysis","yara","reverse-engineering"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
执行恶意软件 IOC 提取
概述
恶意软件 IOC(失陷指标,Indicator of Compromise)提取是指通过分析恶意软件,识别可操作的失陷指标,包括文件哈希、网络指标(C2 域名、IP 地址、URL)、注册表修改、互斥体名称、嵌入字符串和行为产物。本技能涵盖:使用 PE 解析和字符串提取进行静态分析、通过沙箱引爆进行动态分析、使用 YARA 等工具进行自动化 IOC 提取,以及将结果格式化为 STIX 2.1 指标以供共享。
前置条件
- Python 3.9+,安装
pefile、yara-python、oletools、stix2 库
- 访问恶意软件分析沙箱(Cuckoo、CAPE、Any.Run、Joe Sandbox)
- VirusTotal API 密钥(用于富化分析)
- 隔离分析环境(虚拟机或容器)
- 了解 PE 文件格式和常见加壳技术
- 熟悉 YARA 规则语法
核心概念
静态分析 IOC
- 文件哈希:样本及任何释放文件的 MD5、SHA-1、SHA-256
- 导入哈希(imphash):导入函数表的哈希值,可对恶意软件家族进行分类
- Rich Header 哈希:PE Rich Header 哈希,用于编译器指纹识别
- 字符串:嵌入的 URL、IP 地址、域名、注册表路径、互斥体名称
- PE 元数据:编译时间戳、节名称、资源、数字签名
- 嵌入产物:PDB 路径、版本信息、证书详情
动态分析 IOC
- 网络活动:DNS 查询、HTTP 请求、TCP/UDP 连接、SSL 证书
- 文件系统:创建/修改/删除的文件和目录
- 注册表:创建/修改的注册表键和值
- 进程:生成的进程、注入的进程、服务创建
- 行为:API 调用、互斥体创建、计划任务、持久化机制
YARA 规则
YARA 是一种用于识别和分类恶意软件的模式匹配工具。规则由字符串(文本、十六进制、正则表达式)和定义匹配逻辑的条件组成。规则可以检测恶意软件家族、加壳程序、漏洞利用工具包和特定活动工具。
实践步骤
步骤 1:静态分析——PE 解析和哈希生成
import pefile
import hashlib
import os
def analyze_pe(filepath):
"""通过静态分析从 PE 文件中提取 IOC。"""
iocs = {"hashes": {}, "pe_info": {}, "strings": [], "imports": []}
with open(filepath, "rb") as f:
data = f.read()
iocs["hashes"]["md5"] = hashlib.md5(data).hexdigest()
iocs["hashes"]["sha1"] = hashlib.sha1(data).hexdigest()
iocs["hashes"]["sha256"] = hashlib.sha256(data).hexdigest()
iocs["hashes"]["file_size"] = len(data)
try:
pe = pefile.PE(filepath)
iocs["hashes"]["imphash"] = pe.get_imphash()
iocs["pe_info"]["compilation_time"] = str(pe.FILE_HEADER.TimeDateStamp)
iocs["pe_info"]["machine_type"] = hex(pe.FILE_HEADER.Machine)
iocs["pe_info"]["subsystem"] = pe.OPTIONAL_HEADER.Subsystem
iocs["pe_info"]["sections"] = []
for section in pe.sections:
iocs["pe_info"]["sections"].append({
"name": section.Name.decode("utf-8", errors=).strip(),
: section.Misc_VirtualSize,
: section.SizeOfRawData,
: section.get_entropy(),
: section.get_hash_md5(),
})
(pe, ):
entry pe.DIRECTORY_ENTRY_IMPORT:
dll_name = entry.dll.decode(, errors=)
functions = [
imp.name.decode(, errors=)
imp entry.imports
imp.name
]
iocs[].append({: dll_name, : functions})
iocs[][] = pe.is_dll()
iocs[][] = pe.is_driver()
iocs[][] = pe.is_exe()
(pe, ):
entry pe.FileInfo:
st entry:
item st.entries.items():
key = item[].decode(, errors=)
val = item[].decode(, errors=)
iocs[][] = val
pe.close()
pefile.PEFormatError e:
iocs[][] = (e)
iocs
步骤 2:字符串提取和 IOC 模式匹配
import re
def extract_ioc_strings(filepath):
"""从二进制文件中提取与 IOC 相关的字符串。"""
patterns = {
"ipv4": re.compile(
r"\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}"
r"(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b"
),
"domain": re.compile(
r"\b(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+"
r"(?:com|net|org|io|ru|cn|tk|xyz|top|info|biz|cc|ws|pw)\b"
),
"url": re.compile(
r"https?://[^\s\"'<>]{5,200}"
),
"email": re.compile(
r"\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b"
),
"registry": re.compile(
r"(?:HKEY_[A-Z_]+|HKLM|HKCU|HKU|HKCR|HKCC)"
r"\\[\\a-zA-Z0-9_ .{}-]+"
),
"filepath_windows": re.compile(
r"[A-Z]:\\(?:[^\\/:*?\"<>|\r\n]+\\)*[^\\/:*?\"<>|\r\n]+"
),
"mutex": re.compile(
r"(?:Global\\|Local\\)[a-zA-Z0-9_\-{}.]{4,}"
),
"useragent": re.compile(
r"Mozilla/[45]\.0[^\"']{10,200}"
),
"bitcoin": re.compile(
r"\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b"
),
"pdb_path": re.compile(
r"[A-Z]:\\[^\"]{5,200}\.pdb"
),
}
with open(filepath, ) f:
data = f.read()
ascii_strings = re.findall(, data)
unicode_strings = re.findall(
, data
)
all_strings = [s.decode(, errors=) s ascii_strings]
all_strings += [
s.decode(, errors=) s unicode_strings
]
extracted = {category: () category patterns}
string all_strings:
category, pattern patterns.items():
matches = pattern.findall(string)
matches:
extracted[category].add()
{k: (v) k, v extracted.items() v}
步骤 3:YARA 规则扫描
import yara
def scan_with_yara(filepath, rules_path):
"""使用 YARA 规则扫描文件进行恶意软件分类。"""
rules = yara.compile(filepath=rules_path)
matches = rules.match(filepath)
results = []
for match in matches:
result = {
"rule": match.rule,
"namespace": match.namespace,
"tags": match.tags,
"meta": match.meta,
"strings": [],
}
for offset, identifier, data in match.strings:
result["strings"].append({
"offset": hex(offset),
"identifier": identifier,
"data": data.hex() if len(data) < 100 else data[:100].hex() + "...",
})
results.append(result)
return results
SAMPLE_YARA_RULE = """
rule Suspicious_Network_Indicators {
meta:
description = "检测可疑的网络相关字符串"
author = "CTI Analyst"
severity = "medium"
strings:
$ua1 = "Mozilla/5.0" ascii
$cmd1 = "cmd.exe /c" ascii nocase
$ps1 = "powershell" ascii nocase
$wget = "wget" ascii nocase
$curl = "curl" ascii nocase
$b64 = "base64" ascii nocase
$reg1 = "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" ascii nocase
condition:
uint16(0) == 0x5A4D and
(2 of ($ua1, $cmd1, $ps1, $wget, $curl, $b64)) or $reg1
}
rule Packed_Binary {
meta:
description = "检测可能加壳的二进制文件"
author = "CTI Analyst"
condition:
uint16(0) == 0x5A4D and
for any section in pe.sections : (
section.entropy >= 7.0
)
}
"""
步骤 4:生成 STIX 2.1 指标
from stix2 import (
Bundle, Indicator, Malware, Relationship,
File as STIXFile, DomainName, IPv4Address,
ObservedData,
)
from datetime import datetime
def create_stix_bundle(pe_iocs, string_iocs, yara_results, sample_name):
"""从提取的 IOC 创建 STIX 2.1 包。"""
objects = []
malware = Malware(
name=sample_name,
is_family=False,
malware_types=["unknown"],
description=f"已分析的恶意软件样本: {pe_iocs['hashes']['sha256']}",
allow_custom=True,
)
objects.append(malware)
sha256 = pe_iocs["hashes"]["sha256"]
hash_indicator = Indicator(
name=f"恶意软件哈希: {sha256[:16]}...",
pattern=f"[file:hashes.'SHA-256' = '{sha256}']",
pattern_type="stix",
valid_from=datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"),
indicator_types=["malicious-activity"],
allow_custom=True,
)
objects.append(hash_indicator)
objects.append(Relationship(
relationship_type="indicates",
source_ref=hash_indicator.id,
target_ref=malware.id,
))
for ip in string_iocs.get("ipv4", []):
if not ip.startswith(("10.", "172.", "192.168.", "127.")):
ip_indicator = Indicator(
name=,
pattern=,
pattern_type=,
valid_from=datetime.now().strftime(),
indicator_types=[],
allow_custom=,
)
objects.append(ip_indicator)
objects.append(Relationship(
relationship_type=,
source_ref=ip_indicator.,
target_ref=malware.,
))
domain string_iocs.get(, []):
domain_indicator = Indicator(
name=,
pattern=,
pattern_type=,
valid_from=datetime.now().strftime(),
indicator_types=[],
allow_custom=,
)
objects.append(domain_indicator)
objects.append(Relationship(
relationship_type=,
source_ref=domain_indicator.,
target_ref=malware.,
))
bundle = Bundle(objects=objects, allow_custom=)
bundle
验证标准
- PE 文件成功解析,包含哈希、导入表和节分析
- 字符串提取识别出网络 IOC(IP、域名、URL)
- YARA 规则匹配已知恶意软件特征
- STIX 2.1 包含有效的 Indicator 和 Malware 对象
- 私有 IP 范围和良性字符串已从 IOC 输出中过滤
- IOC 可用于封锁和检测规则创建
参考资料