3. 哈希计算与威胁情报匹配
任务目标
本案例针对一个待分析的恶意代码样本文件,完成以下闭环:计算其 MD5、SHA-1、SHA-256 哈希值,并基于哈希值在 VirusTotal 等威胁情报平台进行查询,获取该样本的威胁标签与家族信息,从而建立“样本文件 → 哈希指纹 → 情报标签”的快速判定链路。
环境与依赖
- Python 3.8+,无需第三方库即可完成哈希计算(使用标准库
hashlib)。 - 查询 VirusTotal 需要
requests库(pip install requests),以及一个有效的 VirusTotal (免费注册即可获取,社区版限额 4 次/分钟)。
关键完整代码
以下代码实现两个核心功能:(1) 对指定文件计算三种哈希;(2) 调用 VirusTotal API 查询文件报告并提取威胁标签与家族信息。代码采用最小可运行实现,文件路径与 通过命令行参数传入。
import hashlib
import sys
import requests
import json
def calculate_hashes(file_path):
"""计算文件的 MD5、SHA-1、SHA-256 哈希值"""
md5 = hashlib.md5()
sha1 = hashlib.sha1()
sha256 = hashlib.sha256()
with open(file_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
md5.update(chunk)
sha1.update(chunk)
sha256.update(chunk)
return {
'md5': md5.hexdigest(),
'sha1': sha1.hexdigest(),
'sha256': sha256.hexdigest()
}
def query_virustotal(, file_hash):
"""通过哈希值查询 VirusTotal 文件报告,返回威胁标签与家族信息"""
url = f'https://www.virustotal.com/api/v3/files/{file_hash}'
headers = {'x-': }
try:
resp = requests.get(url, headers=headers, timeout=15)
if resp.status_code == 200:
data = resp.json()
attrs = data.get('data', {}).get('attributes', {})
# 提取社区投票标签
tags = attrs.get('tags', [])
# 提取 AV 引擎检测结果中的家族名(取第一个检测到的家族)
results = attrs.get('last_analysis_results', {})
family = None
for engine, result in results.items():
if result.get('category') == 'malicious' and result.get('result'):
family = result['result']
break
# 提取流行威胁分类标签(如 trojan、ransomware 等)
popular_threat = attrs.get('popular_threat_category', {})
threat_label = popular_threat.get('value')
return {
'tags': tags,
'family': family,
'threat_label': threat_label,
'detection_ratio': f"{attrs.get('last_analysis_stats', {}).get('malicious', 0)}/{attrs.get('last_analysis_stats', {}).get('total', 0)}"
}
elif resp.status_code == 404:
return {'error': 'VirusTotal 中未找到该哈希对应的样本记录'}
else:
return {'error': f'API 请求失败,HTTP 状态码: {resp.status_code}'}
except requests.exceptions.RequestException as e:
return {'error': f'网络请求异常: {e}'}
if __name__ == '__main__':
if len(sys.argv) != 3:
print('用法: python hash_ioc.py <样本文件路径> <VirusTotal_>')
sys.exit(1)
file_path = sys.argv[1]
= sys.argv[2]
# 1. 计算哈希
hashes = calculate_hashes(file_path)
print('=== 文件哈希 ===')
print(f"MD5 : {hashes['md5']}")
print(f"SHA-1 : {hashes['sha1']}")
print(f"SHA-256: {hashes['sha256']}")
# 2. 查询情报(优先使用 SHA-256,识别率最高)
print('\n=== VirusTotal 情报查询 ===')
result = query_virustotal(, hashes['sha256'])
if 'error' in result:
print(f"查询失败: {result['error']}")
else:
print(f"检测率 : {result['detection_ratio']} 个引擎检出")
print(f"威胁标签 : {result['threat_label'] if result['threat_label'] else '未分类'}")
print(f"家族信息 : {result['family'] if result['family'] else '未识别到明确家族'}")
print(f"社区标签 : {', '.join(result['tags']) if result['tags'] else '无'}")
运行方式
# 安装依赖(仅查询功能需要)
pip install requests
# 运行脚本,传入样本文件路径和
python hash_ioc.py /path/to/sample.exe YOUR_VT_
验证方法与判定标准
- 哈希计算验证:在 Linux/macOS 下可用系统命令交叉验证,例如
md5sum sample.exe、sha1sum sample.exe、sha256sum sample.exe,输出应与脚本结果完全一致。 - 情报查询验证:若 有效且样本已被 VirusTotal 收录,脚本将输出检测率(如 “45/72 个引擎检出”)、威胁标签(如 “trojan”)、家族信息(如 “Win32.Emotet”)。若返回 404,说明该哈希在 VirusTotal 库中无记录,可换用已知恶意样本哈希(如
44d88612fea8a8f36de82e1278abb02f,EICAR 测试文件)验证查询链路是否通畅。 - 通过条件:脚本能正确输出三种哈希且与系统命令结果一致;使用有效 查询时能返回 JSON 格式的威胁情报信息(无论是否命中),即视为本案例闭环通过。
常见问题
- API 限额:VirusTotal 社区版 API 限速 4 次/分钟,若查询频繁会返回 429 状态码,需等待后重试。
- 样本未收录:新样本或小众样本可能未被 VirusTotal 收录,此时可先上传样本获取分析报告,再使用返回的哈希进行查询。
- 哈希碰撞风险:MD5 和 SHA-1 已被证明存在碰撞攻击,实际威胁情报匹配应以 SHA-256 为准,本代码默认使用 SHA-256 查询即为此原因。