IDA实操技巧:深度剖析Dridex家族木马分析
字数 3741
更新时间 2026-04-02 13:36:18

Dridex 木马逆向分析与配置提取深度教学

一、 木马概述

Dridex 是一种起源于 2014 年的银行木马,是 GameOver Zeus 的继承者。其主要目标是窃取在线银行用户的登录凭证、银行账户信息,并实施金融欺诈。该木马主要通过包含恶意 Office 宏、PDF 或嵌套可执行文件的钓鱼邮件进行传播。

二、 核心分析目标

  1. 配置提取:木马通常配置多个 C2 服务器。动态分析可能无法捕获全部 C2 地址。通过静态提取配置,可一次性获取完整的 C2 列表,用于封锁和监测。
  2. 功能分析:深入理解其加载、解密、注入和执行流程。

分析样本哈希c7990f1e72fdfa84552f02f9d11cabb74251b0508291af5366fefcee646f9c91

三、 静态分析实战

阶段一:Shellcode 提取与分析

  1. 初步检查

    • 确认样本为 32 位 PE 文件。
  2. IDA 初步分析

    • 用 IDA 打开样本,发现字符串隐藏、函数符号混淆处理得非常彻底,增加了分析难度。
    • 在浏览时,发现函数 sub_55303C 频繁出现,其特征是带有两个 16 进制参数。
  3. 关键技巧:IDA 设置优化

    • 问题:IDA 默认以十进制显示数字,对包含大量硬编码常量的恶意代码分析不便。
    • 解决:在 Hex-Rays 反编译器插件设置中,将 Default radix 修改为 16,使所有数字以十六进制显示。
  4. 识别 API 哈希解析

    • 进入 sub_55303C 函数,发现大量操作 PEB (Process Environment Block) 的代码,这是典型的 API Hashing 手法(用于隐藏 API 函数名,规避静态检测)。
    • 使用 HashDB 插件进行识别。对参数执行 “HashDB Hunt Algorithm”。
    • 常见问题:首次 Hash 可能无法找到正确算法,原因通常是未设置正确的 XOR Key。
    • 解决:在函数 sub_5503C4 中发现异或密钥 0x7AF3DA47。在 HashDB 中右键设置此值为 Xor Key,再次执行 Hash 搜索。
    • 结果:成功识别出 CRC32 算法。随后可使用 m 键为参数重命名为具体的 API 函数名。
    • 遗留问题:像 V5 这类变量需要手动赋值具体的 API 函数指针,此过程可考虑编写脚本自动化,后续探讨。
  5. 自动化辅助分析:使用 CAPA 插件

    • 鉴于样本极其复杂,需借助工具快速定位关键功能。使用 FLARE capa explorer IDA 插件。
    • 安装
      1. 在 IDA 的 Python 环境中安装 flare-capa 库。
      2. capa_explorer.py 脚本放入 IDA 插件目录。
      3. 重启 IDA,在插件菜单中找到 “FLARE capa explorer”。
    • 使用:加载与 flare-capa 版本对应的规则库(capa-rules)。成功加载后,插件会高亮显示敏感功能,如:
      • RC4 加密算法
      • aPlib 压缩算法
      • XOR 异或操作
    • 根据经验,加密算法附近常存在待解密的数据。通过交叉引用向上回溯,定位到函数 sub_552154,其附近存在可疑数据块。
  6. 数据定位与导出

    • 在数据段(如 .data 节)发现多处加密数据块,例如:
      • 0055A060
      • 0055AF80
      • 0055B840
      • 0055B980
      • 0055C560
      • 0055C660
    • 使用 IDA 的 Edit -> Export data 功能,以十六进制格式导出选中数据。

阶段二:数据解密流程推演

  1. 数据存储结构假设:经验表明,此类木马常采用 “密钥+数据” 的拼接存储方式,密钥位于数据块起始部分。
  2. 密钥提取:对每个加密数据块,取前 0x30 (48) 个字节,进行字节反转(Reverse) 后作为 RC4 算法的密钥。剩余部分为密文。
  3. 解密验证
    • 使用 CyberChef 或编写 Python 脚本进行验证。
    • 步骤
      1. 截取数据前 96 个十六进制字符(即 48 字节),进行反转。
      2. 将反转后的密钥与后续密文,送入 RC4 解密算法。
      3. 解密输出多为 Base64 编码的字符串。
  4. 完整流程猜想:结合附近存在的 mw_aplib 函数引用,推断完整的数据处理链为:
    原始数据 → RC4解密 → Base64解码 → aPlib解压 → Shellcode

阶段三:核心功能逆向

  1. 定位注入逻辑:函数 sub_5479A4 包含大量与进程注入相关的 API 调用,是分析重点。
  2. 结构体分析:许多函数操作一个 this 指针。为提高可读性,应为其创建结构体(struct),并合理定义成员变量。
  3. API 类型标准化:使用 ApplyCalleeType 插件,输入 API 名称,可自动应用正确的函数原型,极大提升反编译代码的可读性。
  4. 关键函数符号恢复
    • sub_5502D4 -> mw_get_api_by_hash_v2
    • sub_54201C -> mw_get_inject_api
    • sub_54C2C4 -> mw_wrap_GetHandleInformation
    • sub_5510C8 -> mw_get_integrity_level (获取进程完整性级别)
    • sub_553998 -> mw_time_operator (时间操作)
    • sub_5521F8 -> mw_get_proc_info (获取进程信息)
    • sub_5520FC -> mw_get_proc_bit (判断进程位数 32/64)
    • sub_54FB80 -> mw_wrap_get_proc_bit
    • sub_54F6E4 -> mw_base64_decode
  5. 逻辑串联:通过分析 sub_54FB80 的交叉引用,发现其根据当前进程位数(32/64位),选择不同的加密数据块(如 0055A0600055A6C0)进行解密,最终将解密出的 Shellcode 注入到目标进程。

阶段四:编写完整解密脚本

  1. RC4 解密函数
    def rc4_decrypt(key: bytes, data: bytes) -> bytes:
        S = list(range(256))
        j = 0
        out = bytearray()
        # KSA
        for i in range(256):
            j = (j + S[i] + key[i % len(key)]) % 256
            S[i], S[j] = S[j], S[i]
        # PRGA
        i = j = 0
        for byte in data:
            i = (i + 1) % 256
            j = (j + S[i]) % 256
            S[i], S[j] = S[j], S[i]
            out.append(byte ^ S[(S[i] + S[j]) % 256])
        return bytes(out)
    
  2. aPlib 解压:使用标准的 aPlib 解压库(如 github.com/snemes/aplib)。
  3. 完整解密步骤
    • 读取加密数据。
    • 取前 48 字节,反转后作为 RC4 密钥。
    • 用 RC4 解密剩余数据。
    • 对解密结果进行 Base64 解码。
    • 注意:解码后的数据前 4 字节可能是压缩数据长度,实际解压时需要跳过这4个字节:decompressed_data = decompress(decoded_data[4:])
    • 最终得到可执行的 Shellcode 二进制数据。

阶段五:自动化提取 C2 配置

  1. 寻找 C2 解密函数:定位到函数 sub_5513A4 (mw_rc4_decrypt),查看其所有交叉引用,找到解密网络相关字符串(如 "GET"/"POST")和 C2 地址的地方。
  2. 定位 C2 数据结构:在数据段(如 0055D02C)附近,可发现 IP:Port 格式的数据。特征数字 0x1BB (443) 指示 HTTPS 端口。
  3. 提取特征码
    • 在引用 C2 数据表的代码处提取机器码特征:
      \xbb\x20\xd0\x55\x00\x89\x45\x00\x0f\xb7\x53\x04\x89\x10\x0f\xb6\x4b\x0b\x83\xf9\x0a\x7f\x03\x8a\x53\x0b\x0f\xb6\x53\x0b\x85\xd2\x7e\xb9\x8d\x74\x24\x0c
    • 特征中 \xbb 后的4字节(小端序)为 C2 数据表的虚拟地址(VA)。
  4. 编写提取脚本
    import re, pefile, struct
    def extract_c2(file_data):
        ip_parse_egg = rb'\xbb(....)\x89\x45\x00\x0f\xb7\x53\x04\x89\x10\x0f\xb6\x4b\x0b\x83\xf9\x0a'
        pe = pefile.PE(data=file_data)
        match = re.search(ip_parse_egg, file_data, re.DOTALL)
        if not match:
            return []
        # 获取C2表地址
        table_addr = struct.unpack('<I', match.group(1))[0]
        # 转换VA为文件偏移
        table_offset = pe.get_offset_from_rva(table_addr - pe.OPTIONAL_HEADER.ImageBase)
        ip_table_offset = table_offset + 0xb
        # 读取C2数量
        ip_table_length = file_data[ip_table_offset]
        ip_table_offset += 1
        c2_list = []
        for _ in range(ip_table_length):
            ip = '.'.join(map(str, file_data[ip_table_offset:ip_table_offset+4]))
            port = struct.unpack('<H', file_data[ip_table_offset+4:ip_table_offset+6])[0]
            c2_list.append(f"{ip}:{port}")
            ip_table_offset += 6
        return c2_list
    
  5. 执行结果:运行脚本即可输出所有 C2 服务器的 IP 地址和端口。

四、 总结与关键点

  1. 对抗技巧:Dridex 综合使用了 API Hashing、字符串加密、多段加密 Shellcode、aPlib 压缩等多种反分析技术。
  2. 分析方法
    • 环境配置:设置 IDA 以十六进制显示常量。
    • 工具链:结合 HashDB 识别 API 哈希,使用 CAPA 快速定位功能代码,利用 ApplyCalleeType 规范化类型。
    • 结构体重建:为频繁操作的 this 指针创建结构体,是理解复杂逻辑的关键。
    • 猜证结合:基于经验假设(如密钥位置、数据格式),并通过编写脚本快速验证。
  3. 自动化提取:核心配置(如 C2)通常以加密形式存储在 .data 等节区。通过定位解密函数、分析数据引用模式、提取特征码,可以编写脚本实现配置的批量、自动化提取,极大提升分析效率。
  4. 纵深分析:从简单的字符串解密,到理解进程位数判断、数据选择、解密链、最终注入执行的完整逻辑,体现了对复杂木马进行系统性逆向工程的完整思路。
相似文章
相似文章
 全屏