2. 字符串提取与线索发现

任务目标

从给定的恶意样本二进制文件中提取可打印ASCII字符串,筛选出URL、IP地址、文件路径等关键线索,并基于上下文判断这些线索在恶意行为中的潜在用途。本案例使用一个模拟的恶意脚本样本作为输入,聚焦于字符串提取与线索分析的方法论。

环境与依赖

  • 操作系统:Linux(或任何支持Python 3的环境)
  • Python 3.6+,无需第三方库(仅使用标准库re、string、binascii)
  • 样本文件:sample.bin(由本案例提供的生成脚本创建)

样本准备

为便于复现,先构造一个包含典型恶意线索的模拟样本文件。该样本并非真实恶意软件,仅用于演示字符串提取流程。

# 生成模拟样本 sample.bin
python3 -c "
import struct
content = b'\x00\x01' + b'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' + b'\x00\x00' + \
          b'http://evil.example.com/payload.exe' + b'\x00' + \
          b'C:\\Users\\Public\\malware.dll' + b'\x00' + \
          b'192.168.1.105:8443' + b'\x00' + \
          b'cmd.exe /c whoami' + b'\x00\xff\xfe' + \
          b'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run' + b'\x00'
with open('sample.bin', 'wb') as f:
    f.write(content)
print('sample.bin created, size:', len(content))
"

关键完整代码

以下脚本实现字符串提取、线索筛选与分类输出:

import re
import string

def extract_ascii_strings(data, min_len=4):
    """提取长度≥min_len的可打印ASCII字符串(含制表符与换行)"""
    result = []
    cur = []
    for byte in data:
        ch = chr(byte)
        if ch in string.printable and ch not in '\x0b\x0c':
            cur.append(ch)
        else:
            if len(cur) >= min_len:
                result.append(''.join(cur))
            cur = []
    if len(cur) >= min_len:
        result.append(''.join(cur))
    return result

def classify_indicators(strings):
    """对提取的字符串进行线索分类"""
    indicators = {'url': [], 'ip': [], 'filepath': [], 'registry': [], 'command': []}
    url_re = re.compile(r'https?://[^\s]+', re.I)
    ip_re = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}(?::\d+)?\b')
    filepath_re = re.compile(r'[A-Za-z]:\\[^\s]+|/[A-Za-z0-9_\-/]+\.\w+')
    registry_re = re.compile(r'SOFTWARE\\|HKEY_|CurrentVersion\\Run', re.I)
    cmd_re = re.compile(r'(cmd\.exe|powershell|whoami|net user|taskkill)', re.I)

    for s in strings:
        if url_re.search(s):
            indicators['url'].append(s)
        elif ip_re.search(s):
            indicators['ip'].append(s)
        elif registry_re.search(s):
            indicators['registry'].append(s)
        elif filepath_re.search(s):
            indicators['filepath'].append(s)
        elif cmd_re.search(s):
            indicators['command'].append(s)
    return indicators

def main():
    with open('sample.bin', 'rb') as f:
        data = f.read()
    strings = extract_ascii_strings(data)
    print("=== 提取到的全部字符串(长度≥4)===")
    for s in strings:
        print(f"  {s!r}")

    ind = classify_indicators(strings)
    print("\n=== 关键线索分类 ===")
    for cat, items in ind.items():
        if items:
            print(f"[{cat.upper()}]")
            for item in items:
                print(f"  {item}")

if __name__ == '__main__':
    main()

运行方式

# 1. 生成样本
python3 -c "..."  # 使用上方样本准备命令

# 2. 运行提取脚本(保存为 extract_strings.py 后执行)
python3 extract_strings.py

验证方法与判定标准

运行后应观察到以下输出特征,满足即判定通过:

  • 提取的字符串列表中包含'http://evil.example.com/payload.exe'、'C:\\Users\\Public\\malware.dll'、'192.168.1.105:8443'等完整字符串;
  • 分类结果中:url类包含上述HTTP链接;ip类包含192.168.1.105:8443;filepath类包含Windows路径;registry类包含SOFTWARE\Microsoft\Windows\CurrentVersion\Run;command类包含cmd.exe /c whoami;
  • 无字符串被遗漏或错误分类(例如URL不应同时出现在filepath中)。

线索潜在用途分析

基于提取结果,可做如下推断(结合恶意代码分析经验,非实测结论):

  • URL(http://evil.example.com/payload.exe):可能为下载后续恶意载荷的C2地址或分发源;
  • IP:端口(192.168.1.105:8443):可能是内网横向移动的目标或C2回连地址;
  • 文件路径(C:\Users\Public\malware.dll):指示恶意DLL的落地位置,Public目录常被选为低权限可写路径;
  • 注册表项(...\CurrentVersion\Run):典型的持久化机制,用于开机自启动;
  • 命令(cmd.exe /c whoami):侦察命令,用于获取当前用户权限信息。

这些线索共同勾勒出恶意样本的初步行为链:下载→落地→持久化→侦察。实际分析中应结合动态行为或沙箱报告进一步验证。

常见问题

  • 中文或Unicode字符串未提取:本方法仅提取ASCII可打印字符,如需提取UTF-16LE等编码字符串,需额外处理(如先解码再提取);
  • 短字符串被过滤:min_len=4会忽略过短字符串,若需提取如xor等短关键字,可调低阈值;
  • 分类重叠:例如URL中包含IP时,当前逻辑优先匹配URL,避免重复分类;若需多标签,可改为独立匹配。