Ghidra逆向实战:分析一个恶意样本

这篇记录用 Ghidra 分析一个 Windows 恶意样本的完整过程,从导入到最终提取 IOC。样本来自公开的恶意软件库,仅作学习用途。

样本基本信息

拿到样本后第一步是收集基本信息,不急着丢进 Ghidra:

  • 文件类型:PE32 executable (GUI), Intel 80386
  • SHA256a1b2c3d4...(已脱敏)
  • 文件大小:约 180KB
  • 编译时间戳:2022-03-15(PE header 中的 TimeDateStamp)
  • 导入表:kernel32.dll, ws2_32.dll, advapi32.dll, wininet.dll
  • 壳检测:无明显加壳痕迹,节区熵值正常

导入了 ws2_32.dllwininet.dll,说明有网络通信能力。advapi32.dll 暗示可能操作注册表或服务。

初步用 DIE (Detect It Easy) 扫了一下,没有识别到已知壳,PEiD 签名也没匹配到编译器特征,可能是自定义构建或者做了轻度混淆。

Ghidra 导入与初始分析

在 Ghidra 中新建项目,导入样本。Ghidra 自动识别为 PE32,用默认的 x86 语言导入。导入后执行 Auto Analysis,勾选所有默认分析器。

分析完成后,Ghidra 识别出了约 320 个函数。先看几个关键窗口:

Program Trees — 查看 PE 节区。.text 节占大头,.rdata 中有字符串和导入表,.data 节很小。没有异常节区名。

Symbol Tree — 导入函数列表。重点关注:

  • InternetOpenA, InternetConnectA, HttpOpenRequestA, HttpSendRequestA — HTTP 通信
  • WSAStartup, socket, connect, send, recv — 原始 socket
  • RegSetValueExA, RegOpenKeyExA — 注册表操作
  • CreateProcessA — 进程创建
  • VirtualAlloc, VirtualProtect — 内存操作(可能有代码注入行为)

字符串搜索

在 Ghidra 中打开 Defined Strings 窗口(Window -> Defined Strings),按长度排序后看有意义的字符串。

发现了几个关键字符串:

  • Mozilla/5.0 (Windows NT 10.0; Win64) — User-Agent 伪装
  • Software\Microsoft\Windows\CurrentVersion\Run — 注册表自启动路径
  • POST — HTTP 方法
  • /gate.php — 疑似 C2 通信路径
  • Content-Type: application/x-www-form-urlencoded
  • cmd.exe
  • tasklistsysteminfoipconfig — 系统信息收集命令

部分字符串看起来是 Base64 编码或者 XOR 混淆过的,需要进一步分析。

加密 / 混淆识别

交叉引用那些乱码字符串,追踪到一个函数(Ghidra 自动命名为 FUN_00401a30)。反编译后发现是一个 XOR 解密循环:

反编译伪代码显示该函数接收一个字节数组和长度参数,然后用一个固定的密钥字节序列逐字节异或。密钥在 .rdata 段中硬编码。

这个函数在程序启动初期被调用了十多次,解密出各种配置字符串。我在 Ghidra 中给它重命名为 xor_decrypt,方便后续引用。

用 Ghidra 的 Python 脚本功能,批量提取所有被解密的字符串:在 Script Manager 中编写一个简短的 Jython 脚本,模拟 XOR 解密逻辑,对每个调用点的参数进行解码。解密结果中包含了两个 IP 地址和一个域名。

关键逻辑还原

结合字符串和函数调用关系,还原出主要行为流程:

1. 初始化阶段

  • 调用 xor_decrypt 解密所有配置字符串
  • 通过 GetComputerNameAGetUserNameA 获取机器名和用户名
  • 执行 systeminfoipconfigtasklist 收集环境信息

2. 持久化

  • 将自身复制到 %APPDATA% 目录下,文件名伪装为 svchost.exe
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run 写入注册表项,实现开机自启动

3. C2 通信

  • 用 WinINet API 向 C2 服务器发送 HTTP POST 请求
  • URL 路径为 /gate.php
  • 上传数据包含:机器指纹(机器名 + 用户名的 hash)、系统信息、运行进程列表
  • 数据经过 Base64 编码后作为 POST body 发送
  • 解析服务器响应,支持的指令包括:
    • exec — 执行命令(通过 cmd.exe /c
    • download — 下载并执行文件
    • update — 自更新
    • uninstall — 自删除

4. 通信备份

  • 如果 HTTP 方式连接失败,会降级到原始 TCP socket 方式连接备用地址
  • 连接间隔有随机抖动,大约 5-15 分钟轮询一次

IOC 提取

从分析中提取到的 IOC (Indicators of Compromise):

网络指标

  • C2 域名:通过 XOR 解密获得(此处脱敏)
  • C2 IP 地址:两个备用 IP(此处脱敏)
  • 通信路径:/gate.php
  • User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64)

主机指标

  • 注册表键:HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsUpdate
  • 文件路径:%APPDATA%\svchost.exe
  • 互斥量(Mutex)名:通过分析 CreateMutexA 调用获得

行为特征

  • 执行 systeminfoipconfig /alltasklist 进行侦察
  • HTTP POST 到 /gate.php,Body 为 Base64 编码数据
  • XOR 加密配置字符串,密钥为固定字节序列

分析总结

这是一个典型的 RAT (Remote Access Trojan) 样本,功能结构清晰:

  • 信息收集 + 持久化 + C2 通信 + 远程命令执行
  • 混淆程度较低,只用了简单的 XOR 加密配置字符串
  • 没有反调试 / 反虚拟机手段,分析难度不大
  • 整体代码量不大,手工逆向就能完成,适合入门练手

Ghidra 在这次分析中表现不错,反编译质量基本可读,交叉引用和脚本功能帮了大忙。对于免费工具来说,已经非常够用了。