x64dbg Automate自动化分析的利器

admin 2025年6月3日10:19:14评论25 views字数 6379阅读21分15秒阅读模式

 

用x64dbg Automate,让恶意软件分析不再繁琐!
x64dbg Automate自动化分析的利器

在当今复杂多变的网络安全领域,恶意软件分析、逆向工程和漏洞挖掘已成为网络安全专家的日常任务。然而,面对海量的样本和复杂的技术手段,传统的手动分析方法不仅耗时费力,还容易出错。如何在有限的时间内高效完成大规模分析任务,成为每一个安全从业者面临的挑战。今天,我们将为您介绍一个强大的工具——x64dbg Automate[1]。它是为x64dbg设计的自动化解决方案,基于x64dbg的命令执行引擎和插件API,提供了一个表达力强、现代化且易于使用的Python客户端库。通过强大的自动化功能,x64dbg Automate能帮助我们轻松应对恶意软件分析中的重复性工作、复杂性难题以及反调试机制,让您的分析工作变得高效且可复现。

一、背景

为什么我们需要Automate?如果要用几个关键词来概括自动化能够帮助我解决的问题,它主要涉及以下方面:

  • 减少重复性工作
  • 应对复杂性
  • 扩展分析流程和工作流
  • 提升协作能力(可复现性)
当然,相比单纯地描述,我更喜欢直接展示它的应用。因此,我们将通过一些接近真实场景的示例,看看自动化如何在这些方面发挥作用。

二、对恶意软件家族的动态分析

假设我们面临以下场景:

我们拥有大量恶意软件样本,希望能够:
1. 识别采用特定有效载荷部署机制的恶意软件家族样本。
2. 创建可复用工具,用于入口点发现、去混淆以及绕过反调试机制。
3. 创建可复用工具,用于基本分析任务(如注释代码、提取字符串、发现模块间调用等)。
为方便演示,笔者提供了一个已去除危险性的样本[2](密码:x64dbg)。有兴趣的读者可以自行下载并跟随示例操作。该样本经过简化,仅用于演示目的,但希望大家可以从中拓展思路,应用到更广泛的实际场景中。
三、快速了解目标样本

笔者先从一个目标恶意软件样本入手。分析发现,该恶意软件家族将其有效载荷嵌入到合法的MSVC编译二进制文件中(本示例中是7z.exe)。值得注意的是,它利用被篡改的 C 运行时_initterm回调函数来部署恶意载荷。

二进制文件和库以调查变更。

x64dbg Automate自动化分析的利器

恶意载荷的特征包括:
  • 自解密机制(类似“套娃”结构)
x64dbg Automate自动化分析的利器
  • 基本的反调试技术
x64dbg Automate自动化分析的利器
  • 加密字符串(已有的开源软件无法实现自动解密 )
x64dbg Automate自动化分析的利器
  • 混淆的跨模块调用
x64dbg Automate自动化分析的利器
这里笔者不再深入分析样本本身,而是专注于如何通过自动化工具提升分析效率
四、识别目标样本

笔者之前提到,我们可能拥有多个恶意软件样本,但并不确定哪些属于我们关心的恶意软件家族。第一步,我们可以编写YARA规则来筛选感兴趣的样本

示例 1:使用 YARA 规则查找可疑样本
x64dbg Automate自动化分析的利器
import yara
from pathlib import Path

rules_src = """
import "pe"

// 通过 .reloc 配置和特定加载器签名匹配来识别可疑的二进制文件
rule demo_malware_family
{
    strings:
        $loader_iter = { 48 C7 C7 00 E0 48 00 80 ?? ?? 48 FF C7 E0 F8 EB D0 }
    condition:
        $loader_iter and
        pe.is_pe and
        pe.section_index(".reloc") and
        pe.data_directories[5].size == 0 // IMAGE_DIRECTORY_ENTRY_BASERELOC
}
"""

def sample_match() -> Path:
    rules = yara.compile(source=rules_src)
    for f in Path('samples').iterdir():
        if f.is_file() and rules.match(str(f)):
            yield f

if __name__ == "__main__":
    print(next(sample_match()))
    # 输出示例:
    # PS E:reautomate-demo> python .automate.py
    # samplesdc59d01e485f2c2d0aa9176cda683dcf.exe

这里,我们使用YARA规则来匹配带有可疑.reloc配置和特定加载器签名的恶意软件样本。这样,我们可以快速筛选出感兴趣的二进制文件,减少手动分析的工作量。

五、自动化入口点发现
跟随笔者,知道其经常遇到这样的情况:为了达到某个特定的执行状态,需要执行许多步骤。这种情况在解包受保护(armored)的样本时尤为常见。
当出现这种情况时,我们希望能够最大化我在该特定执行点上所能进行的分析。有多种方法可以实现这一点,成功率各不相同(如Time-Travel Debugging)。然而,我们通常发现,最有效的方法是编写脚本记录这些步骤,并在需要时随意重放执行过程。
下次你在分析一个受保护的二进制文件时,可以考虑有哪些执行点是你希望能够快速回溯到的。这正是调试自动化的一个核心应用场景。笔者将通过示例,展示它的实现方式。
示例 2:自动遍历解密过程并找到有效载荷的入口点
x64dbg Automate自动化分析的利器
from x64dbg_automate import X64DbgClient

def seek_payload_entrypoint(client: X64DbgClient):
    # 定位有效载荷所在的内存页
    module_base, _ = client.eval_sync("mod.main()")
    payload_mem_page = [mem for mem in client.memmap() if '.reloc' in mem.info 
                        and mem.base_address > module_base][0]
    
    # 在有效载荷的内存页上设置执行断点
    client.set_memory_breakpoint(payload_mem_page.base_address, bp_type='x', restore=False)
    client.go() # 运行到程序入口点
    client.wait_until_stopped()
    client.go() # 运行到内存断点
    client.wait_until_stopped()

    # 遍历 N 层解密过程,找到最终入口点
    while True:
        addr = client.get_reg('rip')

        # 确保当前指令地址仍在解密函数内
        if addr < payload_mem_page.base_address 
            or addr >= payload_mem_page.base_address + payload_mem_page.region_size:
            raise ValueError('解密遍历失败,rip 超出预期范围')

        # 如果当前指令不是 "mov rcx, XYZ",则找到入口点
        ins = client.disassemble_at(addr)
        if not ins.instruction.startswith('mov rcx,'):
            break

        # 否则,继续单步执行,遍历下一层
        while True:
            addr += ins.instr_size
            ins = client.disassemble_at(addr)
            if ins.instruction.startswith('jmp'):
                client.set_breakpoint(addr, singleshoot=True)
                client.go()
                client.wait_until_stopped()
                client.stepi()
                break

    # 现在可以自由分析有效载荷的入口点了
    client.stepi()

if __name__ == "__main__":
    # 启动 x64dbg 并附加到目标进程
    client = X64DbgClient(r'E:rex64dbg_devreleasex64x64dbg.exe')
    client.start_session(str(sample))
    seek_payload_entrypoint(client)
    client.detach_session()

自动化使我们能够断开客户端,并对有效负载本身进行进一步分析。由于已经完成了解密的繁重工作,我们现在可以毫无顾虑地进行调试,因为我们随时都能轻松回到关键位置。

x64dbg Automate自动化分析的利器
六、Payload注释

在入口点检查样本时,可以发现一些可重复的特征,这些特征可以用于识别字符串和调用。

我们深知,反复逆向解析字符串和模块间调用是多么令人头疼的事情。通过可重复使用的自动化手段来标注字符串并标记调用,可以大大减轻这项工作的枯燥程度。

让我们来看一下在我们的样本中,这种自动化是如何实现的:

示例 3:标注有效负载中的字符串和调用
x64dbg Automate自动化分析的利器
from x64dbg_automate.models import ReferenceViewRef

def annotate_strings_and_calls(client: X64DbgClient):
    mem = client.virt_query(client.get_reg('rip'))
    payload = client.read_memory(mem.base_address, mem.region_size)
    refs = []

    # 查找字符串解密器
    obf_string_pattern = bytes.fromhex('49 09 C6 49 81 CE CC 00 00 00 EB')
    for i in range(len(payload) - len(obf_string_pattern)):
        if payload[i:i + len(obf_string_pattern)] == obf_string_pattern:
            str_loc = i + len(obf_string_pattern) + 1
            str_size = payload[str_loc - 1]
            obf_str = bytearray(payload[str_loc:str_loc + str_size])
            char_size = int(obf_str[-3:] == b'x00x00x00') + 1

            for ix, i in enumerate(range(0, len(obf_str) - char_size, char_size)):
                obf_str[i] = (obf_str[i] - (0xCC + (ix * 13))) & 0xFF
            obf_str = obf_str.decode('utf-16-le' if char_size == 2 else 'utf-8').rstrip('x00')

            client.set_comment_at(mem.base_address + str_loc - 2, f"解码字符串: '{obf_str}'")
            refs.append(ReferenceViewRef(
                address=mem.base_address + str_loc - 2,
                text=f"解码字符串: '{obf_str}'"
            ))

    # 在 GUI 中显示标注信息
    client.gui_show_reference_view("混淆调用和字符串", refs)

if __name__ == "__main__":
    annotate_strings_and_calls(client)
    client.detach_session()

这样之后,我们就在应用数据库中收集了大量有用的注释和提示。而分析的恶意软件样本越多,自动化分析的价值就越大。

x64dbg Automate自动化分析的利器

此外,我们还可以在参考视图(reference view)中看到对分析结果的摘要展示。

x64dbg Automate自动化分析的利器
七、绕过反调试

在此阶段单步执行有效负载时,发现了两种反调试机制。我们需要修改脚本,使其不仅能绕过解密过程,还能绕过反调试,从而实现无障碍的调试。

示例 4:绕过反调试机制
x64dbg Automate自动化分析的利器
def bypass_anti_debug(client: X64DbgClient):
    client.hide_debugger_peb()  # 绕过 PEB 反调试

    addr, _ = client.eval_sync('FindWindowW')
    client.set_breakpoint(addr, singleshoot=True)
    client.go()
    client.wait_until_stopped()
    if client.read_memory(client.get_reg('rdx'), 12) != 'x64dbg'.encode('utf-16-le'):
        raise ValueError("FindWindowW 预期检测 x64dbg")

    client.write_memory(client.get_reg('rdx'), 'zzz'.encode('utf-16-le'))
    client.ret()
    client.stepi()

if __name__ == "__main__":
    bypass_anti_debug(client)
    client.detach_session()
八、总结

通过本次实践,笔者展示了x64dbg Automate的一些强大应用场景。笔者不仅仅使用脚本自动化了整个分析流程,使我们能够轻松进入复杂的执行状态。同时,还以可复现的方式记录了分析步骤,从而为重用、调整和协作提供了可能。

九、相关链接
[1]2025 年 3 月 4 日,作者:darbonzo.
https://x64dbg.com/blog/2025/03/04/analysis-at-scale-with-x64dbg-automate.html
[2]https://x64dbg.com/blog/public/files/dc59d01e485f2c2d0aa9176cda683dcf.zip.
 

原文始发于微信公众号(山石网科安全技术研究院):x64dbg Automate--自动化分析的“利器”

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年6月3日10:19:14
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   x64dbg Automate自动化分析的利器https://cn-sec.com/archives/3871532.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息