恶意代码分析
恶意代码分析:静态分析、动态分析、沙箱、逆向工程与恶意软件分类
1. 恶意软件分类
1.1 按行为分类
| 类型 | 行为 | 示例 |
|---|---|---|
| 病毒 | 感染宿主文件 | CIH |
| 蠕虫 | 自我传播 | WannaCry |
| 木马 | 伪装合法软件 | Emotet |
| 勒索软件 | 加密勒索 | Ryuk |
| Rootkit | 隐藏自身 | Sony Rootkit |
| RAT | 远程控制 | Gh0st |
1.2 按目标分类
| 类型 | 目标 | 示例 |
|---|---|---|
| 银行木马 | 网银 | Zeus |
| 勒索软件 | 数据 | LockBit |
| 间谍软件 | 信息 | Pegasus |
| 僵尸网络 | 控制 | Mirai |
| APT | 持续渗透 | Stuxnet |
2. 静态分析
2.1 文件特征
# 文件类型
file malware.exe
# 哈希
sha256sum malware.exe
# 字符串提取
strings malware.exe | grep -i "http\|password\|key"
# PE头分析
python pefile.py malware.exe
2.2 反汇编
| 工具 | 说明 |
|---|---|
| IDA Pro | 专业反汇编 |
| Ghidra | NSA开源 |
| Radare2 | 命令行 |
| Binary Ninja | 现代 |
2.3 签名检测
# YARA 规则
rule Malware_Detector {
meta:
description = "Detects known malware"
strings:
$s1 = "cmd.exe /c" ascii
$s2 = { 6A 40 68 00 30 00 00 }
condition:
any of them
}
3. 动态分析
3.1 沙箱分析
| 沙箱 | 特点 |
|---|---|
| Cuckoo Sandbox | 开源 |
| Joe Sandbox | 商业 |
| ANY.RUN | 交互式 |
| Hybrid Analysis | 在线 |
3.2 行为监控
# 进程监控
Process Monitor (ProcMon)
# 网络监控
Wireshark / tcpdump
# 注册表监控
Regshot
# API 调用追踪
API Monitor
3.3 网络行为分析
- DNS 请求
- HTTP/HTTPS 通信
- C2 通信模式
- 数据外传
4. 逆向工程
4.1 脱壳
| 壳 | 工具 |
|---|---|
| UPX | upx -d |
| Themida | 手动脱壳 |
| VMProtect | 困难 |
| ASPack | 脱壳工具 |
4.2 调试
# x64dbg 调试
1. 设置断点
2. 单步执行
3. 查看寄存器和内存
4. 分析算法逻辑
4.3 反混淆
- 字符串解密
- 控制流还原
- API 调用恢复
5. 勒索软件分析
5.1 常见勒索软件家族
| 家族 | 加密算法 | 特点 |
|---|---|---|
| WannaCry | AES+RSA | 利用EternalBlue |
| Ryuk | AES-256 | 针对性攻击 |
| LockBit | AES+RSA | RaaS模式 |
| Conti | ChaCha8+RSA | 双重勒索 |
5.2 分析要点
- 加密算法和密钥管理
- 文件扩展名修改
- 勒索信内容
- C2 通信方式
- 是否可解密
6. 威胁情报生产
6.1 IOC 提取
| IOC类型 | 示例 |
|---|---|
| 文件哈希 | SHA256 |
| IP地址 | C2服务器 |
| 域名 | DGA域名 |
| URL | 下载地址 |
| 互斥量 | 运行标识 |
| 注册表键 | 持久化 |
6.2 情报共享
- STIX/TAXII 标准
- MISP 平台
- OpenIOC 格式
静态分析基础
基本写法:文件类型识别
file <文件>
# 识别恶意软件文件类型
file suspicious.exe
基本写法:计算文件哈希
sha256sum <文件>
# 计算文件 SHA256 哈希用于查重
sha256sum suspicious.exe
基本写法:计算 MD5 哈希
md5sum <文件>
# 计算 MD5 哈希便于查询
md5sum suspicious.exe
基本写法:提取可打印字符串
strings <文件> | head -50
# 提取文件中的可读字符串
strings suspicious.exe | head -50
基本写法:提取长字符串
strings -n 10 <文件>
# 提取长度超过 10 的字符串
strings -n 10 suspicious.exe
基本写法:查看文件大小
ls -la <文件>
# 查看文件大小与权限
ls -la suspicious.exe
YARA 规则匹配
基本写法:扫描文件
yara <规则文件> <目标文件>
# 使用 YARA 规则扫描恶意软件
yara malware_rules.yar suspicious.exe
基本写法:递归扫描目录
yara -r <规则文件> <目录>
# 递归扫描目录下所有文件
yara -r malware_rules.yar /malware_samples/
基本写法:显示匹配的规则
yara -s <规则文件> <目标文件>
# 显示匹配规则与匹配字符串
yara -s malware_rules.yar suspicious.exe
基本写法:使用多个规则文件
yara -r <规则目录> <目标文件>
# 使用规则目录中所有规则文件
yara -r /rules/ suspicious.exe
基本写法:编译规则加速扫描
yarac <规则文件> <编译文件>
# 预编译规则提高扫描速度
yarac malware_rules.yar compiled.yarc
yara compiled.yarc suspicious.exe
VirusTotal 查询
基本写法:使用 API 查询哈希
curl "https://www.virustotal.com/api/v3/files/<哈希>"
# 通过哈希查询 VirusTotal 报告
curl -H "x-apikey: <API_KEY>" "https://www.virustotal.com/api/v3/files/abc123"
基本写法:上传文件扫描
curl -X POST "https://www.virustotal.com/api/v3/files" -F "file=@<文件>"
# 上传文件到 VirusTotal 扫描
curl -X POST -H "x-apikey: <API_KEY>" "https://www.virustotal.com/api/v3/files" -F "file=@suspicious.exe"
基本写法:获取分析结果
curl "https://www.virustotal.com/api/v3/analyses/<分析ID>"
# 获取上传文件的分析结果
curl -H "x-apikey: <API_KEY>" "https://www.virustotal.com/api/v3/analyses/analysis_id"
基本写法:使用 vt-cli 工具
vt scan file <文件>
# 使用 VirusTotal CLI 工具扫描
vt scan file suspicious.exe
基本写法:查询文件信息
vt file <哈希>
# 查询文件详细信息
vt file abc123def456
沙箱分析
基本写法:使用 Cuckoo 沙箱
cuckoo submit <文件>
# 提交文件到 Cuckoo 沙箱分析
cuckoo submit suspicious.exe
基本写法:指定分析选项
cuckoo submit --options <选项> <文件>
# 指定分析机器与超时
cuckoo submit --options timeout=300,machine=win10 suspicious.exe
基本写法:查看分析任务
cuckoo tasks list
# 列出所有分析任务
cuckoo tasks list
基本写法:查看分析报告
cuckoo report <任务ID>
# 查看指定任务分析报告
cuckoo report 123
基本写法:导出分析结果
cuckoo report <任务ID> -f <格式>
# 导出 JSON 格式分析报告
cuckoo report 123 -f json > report.json
动态分析基础
基本写法:跟踪系统调用
strace -f -o <输出文件> <程序>
# 跟踪程序所有系统调用
strace -f -o syscall.log ./suspicious
基本写法:跟踪库函数调用
ltrace -f -o <输出文件> <程序>
# 跟踪库函数调用
ltrace -f -o libcall.log ./suspicious
基本写法:过滤特定系统调用
strace -e trace=<调用类型> <程序>
# 仅跟踪网络相关系统调用
strace -e trace=network -f ./suspicious
基本写法:跟踪文件操作
strace -e trace=file <程序>
# 仅跟踪文件相关操作
strace -e trace=file -f ./suspicious
基本写法:跟踪进程创建
strace -e trace=process <程序>
# 跟踪进程创建相关操作
strace -e trace=process -f ./suspicious
网络行为分析
基本写法:抓取程序网络流量
tcpdump -i any -w <输出文件> & <程序>
# 抓取程序运行时的网络流量
sudo tcpdump -i any -w traffic.pcap &
./suspicious
基本写法:分析 DNS 请求
tshark -r <PCAP文件> -Y "dns.qry.name"
# 分析程序发起的 DNS 请求
tshark -r traffic.pcap -Y "dns.qry.name" -T fields -e dns.qry.name
基本写法:分析 HTTP 请求
tshark -r <PCAP文件> -Y "http.request"
# 分析程序发出的 HTTP 请求
tshark -r traffic.pcap -Y "http.request" -T fields -e http.host -e http.request.uri
基本写法:统计连接目标
tshark -r <PCAP文件> -T fields -e ip.dst | sort | uniq -c
# 统计程序连接的目标 IP
tshark -r traffic.pcap -T fields -e ip.dst | sort | uniq -c | sort -rn
基本写法:提取 C2 通信特征
tshark -r <PCAP文件> -Y "tcp.port == 443" -T fields -e ip.dst
# 提取可能的 C2 服务器地址
tshark -r traffic.pcap -Y "tcp.port == 443" -T fields -e ip.dst | sort -u
文件行为监控
基本写法:监控文件创建
inotifywait -m -r <监控目录>
# 实时监控目录中文件创建事件
inotifywait -m -r /tmp -e create,modify,delete
基本写法:使用 auditd 监控
auditctl -w <目录> -p war -k malware
# 使用审计系统监控目录
sudo auditctl -w /tmp -p war -k malware
基本写法:查看文件创建事件
ausearch -k malware
# 查询监控到的文件操作
sudo ausearch -k malware
基本写法:监控进程文件操作
lsof -p <PID>
# 查看进程打开的所有文件
lsof -p 1234
基本写法:持续监控进程文件操作
lsof -r -p <PID>
# 持续监控进程文件操作变化
lsof -r -p 1234
注册表与配置分析(Windows)
基本写法:导出注册表快照
reg export HKLM <文件>
# 导出注册表快照用于对比(Windows 环境)
reg export HKLM\Software hklm_backup.reg
基本写法:对比注册表变化
fc <原文件> <新文件>
# 对比注册表快照查找修改
fc original.reg modified.reg > changes.txt
基本写法:使用 regripper 分析
regripper -r <注册表文件> -f <插件>
# 使用 RegRipper 分析注册表文件
regripper -r NTUSER.DAT -f userassist
基本写法:提取自启动项
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"
# 查看注册表自启动项
reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run"
基本写法:查看服务
sc query state= all
# 查看所有系统服务
sc query state= all
内存分析
基本写法:使用 vol.py 分析内存
vol.py -f <内存镜像> imageinfo
# 使用 Volatility 分析内存镜像基本信息
vol.py -f memory.dump imageinfo
基本写法:列出进程
vol.py -f <内存镜像> --profile=<配置> pslist
# 列出内存中的所有进程
vol.py -f memory.dump --profile=Win10x64 pslist
基本写法:查找隐藏进程
vol.py -f <内存镜像> --profile=<配置> psxview
# 检测隐藏进程
vol.py -f memory.dump --profile=Win10x64 psxview
基本写法:提取进程内存
vol.py -f <内存镜像> --profile=<配置> memdump -p <PID> -D <目录>
# 提取指定进程的内存
vol.py -f memory.dump --profile=Win10x64 memdump -p 1234 -D /tmp/
基本写法:扫描网络连接
vol.py -f <内存镜像> --profile=<配置> netscan
# 扫描内存中的网络连接
vol.py -f memory.dump --profile=Win10x64 netscan
恶意软件脱壳
基本写法:使用 upx 脱壳
upx -d <文件>
# 脱壳 UPX 加壳的程序
upx -d packed.exe
基本写法:查看 PE 节区熵
python3 -c "import pefile; pe=pefile.PE('<文件>'); ..."
# 计算各节区熵值判断是否加壳
python3 -c "
import pefile, math
pe=pefile.PE('suspicious.exe')
for s in pe.sections:
data=s.get_data()
ent=-sum(data.count(bytes([b]))/len(data)*math.log2(data.count(bytes([b]))/len(data)) for b in range(256) if data.count(bytes([b])))
print(f'{s.Name.decode()} 熵值: {ent:.2f}')
"
基本写法:使用 diStorm 反汇编
python3 -c "from distorm3 import Decode; ..."
# Python 使用 diStorm 反汇编代码
python3 -c "
from distorm3 import Decode
code=b'\\x48\\x89\\xe5'
for ins in Decode(0x1000, code):
print(ins)
"
基本写法:使用 pefile 查看入口点
python3 -c "import pefile; pe=pefile.PE('<文件>'); print(hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint))"
# 查看 PE 文件入口点判断是否加壳
python3 -c "import pefile; pe=pefile.PE('suspicious.exe'); print('入口点:', hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint))"
自动化分析流水线
基本写法:批量计算哈希
for f in <目录>/*; do sha256sum "$f"; done
# 批量计算目录中所有文件哈希
for f in /malware/*; do echo "$(sha256sum "$f" | cut -d' ' -f1) $f"; done > hashes.txt
基本写法:批量提取字符串
for f in <目录>/*; do echo "=== $f ==="; strings "$f"; done
# 批量提取所有样本的字符串
for f in /malware/*; do echo "=== $f ==="; strings -n 8 "$f"; done > all_strings.txt
基本写法:批量 YARA 扫描
yara -r -s <规则文件> <目录>
# 批量扫描目录下所有文件
yara -r -s /rules/*.yar /malware_samples/ > yara_results.txt
基本写法:自动化分析脚本
./analyze.sh <文件>
# 自动化分析脚本示例
# #!/bin/bash
# echo "文件类型: $(file -b $1)"
# echo "SHA256: $(sha256sum $1 | cut -d' ' -f1)"
# echo "字符串数: $(strings $1 | wc -l)"
# yara rules.yar $1
基本写法:提交到沙箱批量分析
for f in <目录>/*; do cuckoo submit "$f"; done
# 批量提交文件到沙箱分析
for f in /malware/*; do cuckoo submit "$f"; sleep 60; done