本文将重点展示我在x64dbg Automate开发过程中的设计思路与功能亮点。这个自动化解决方案基于x64dbg的命令执行引擎和插件API,旨在提供富有表现力、现代化且易于使用的Python客户端库。该项目已被广泛应用于恶意软件分析、逆向工程和漏洞挖掘等场景。
背景:为什么要自动化?
自动化方案主要解决以下核心问题:
-
减少重复性工作 -
应对复杂场景 -
扩展工作流和分析规模 -
协同合作(可复现性)
相比文字描述,我更喜欢通过实际案例演示自动化如何在这些领域发挥作用。
恶意软件家族的动态分析
假设我们有一个庞大的恶意软件样本库,需要:
-
识别采用特定载荷部署方式的同源样本 -
创建可复用的工具用于入口点发现、反混淆和反调试绕过 -
开发基础分析工具(注释标注、字符串提取和跨模块调用追踪)
演示用样本下载链接https://x64dbg.com/blog/public/files/dc59d01e485f2c2d0aa9176cda683dcf.zip
(密码:x64dbg)。该样本经过简化处理以便演示,建议读者自行拓展应用场景。
快速概览
初步分析显示该恶意软件家族将有效载荷嵌入合法的MSVC编译二进制文件(本例为7z.exe)。注意被篡改的C运行时_initterm回调函数用于部署恶意载荷。
载荷具备以下特征:
-
俄罗斯套娃式自解密机制
-
基础反调试
-
加密字符串(FLOSS工具无法识别)
-
混淆的跨模块调用
接下来将重点演示自动化分析流程。
目标样本识别
首先使用Yara规则筛选目标家族样本:
# 示例1:使用Yara识别目标样本import yarafrom pathlib import Pathrules_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}"""defsample_match() -> Path: rules = yara.compile(source=rules_src)for f in Path('samples').iterdir():if f.is_file() and rules.match(str(f)):yield fif __name__ == "__main__": print(next(sample_match()))# 输出:# PS E:reautomate-demo> python .automate.py# samplesdc59d01e485f2c2d0aa9176cda683dcf.exe
自动化入口点定位
在分析加壳样本时,通过脚本实现关键执行状态的快速回放:
# 示例2:穿透多层解密定位载荷入口点from x64dbg_automate import X64DbgClientdefseek_payload_entrypoint(client: X64DbgClient):# 定位载荷内存页 module_base, _ = client.eval_sync("mod.main()") payload_mem_page = [mem for mem in client.memmap() if'.reloc'in mem.infoand 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()# 逐层穿透解密逻辑whileTrue: 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超出预期范围') ins = client.disassemble_at(addr)ifnot ins.instruction.startswith('mov rcx,'):breakwhileTrue: 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__":# ... client = X64DbgClient(r'E:rex64dbg_devreleasex64x64dbg.exe') client.start_session(str(sample)) seek_payload_entrypoint(client) client.detach_session()
载荷注释标注
通过自动化脚本标注加密字符串和混淆调用:
# 示例3:自动标注字符串和调用from x64dbg_automate.models import ReferenceViewRefdefannotate_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') + 1for ix, i in enumerate(range(0, len(obf_str) - char_size, char_size)): obf_str[i] = (obf_str[i] - (0xCC + (ix * 13))) & 0xFF decoded_str = obf_str.decode('utf-16-le').rstrip('x00') if char_size == 2else obf_str[0:-2].decode() client.set_comment_at(mem.base_address + str_loc - 2, f"加密字符串: '{decoded_str}'") refs.append(ReferenceViewRef( address=mem.base_address + str_loc - 2, text=f"加密字符串: '{decoded_str}'" ))# 混淆调用解析 obf_call_pattern = bytes.fromhex('49 BF DE C0 AD DE DE C0 AD DE')for i in range(len(payload) - len(obf_string_pattern)):if payload[i:i + len(obf_call_pattern)] == obf_call_pattern: obf_call_qw = client.read_qword(mem.base_address + i - 8) resolved_qw = (obf_call_qw - 0xDEADC0DEDEADC0DE) & 0xFFFFFFFFFFFFFFFF resolved_sym = client.get_symbol_at(resolved_qw) client.set_label_at(mem.base_address + i + 13, f'{resolved_sym.decoratedSymbol}_{mem.base_address:X}') refs.append(ReferenceViewRef( address=mem.base_address + i + 13, text=f"混淆调用: '{resolved_sym.decoratedSymbol}'" )) client.gui_show_reference_view("混淆元素汇总", refs)if __name__ == "__main__":# ... annotate_strings_and_calls(client) client.detach_session()
标注效果示意图:
引用视图展示:
反调试绕过
通过脚本自动化处理反调试检测:
# 示例4:反调试绕过defbypass_anti_debug(client: X64DbgClient): client.hide_debugger_peb() # 隐藏调试器PEB信息# 拦截FindWindowW检测 addr, _ = client.eval_sync('LoadLibraryExW') client.set_breakpoint(addr, singleshoot=True) 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("预期检测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()
完整工作流
通过上述演示,我们实现了:
-
关键执行状态的脚本化到达 -
可复用的分析步骤记录 -
自动化注释和反混淆 -
反调试措施的自动化处理
这些技术不仅适用于恶意软件分析,也可应用于其他逆向工程场景。欢迎访问Automate的安装指南(https://dariushoule.github.io/x64dbg-automate-pyclient/installation
)和快速入门https://dariushoule.github.io/x64dbg-automate-pyclient/quickstart
开始您的自动化分析之旅!🎉
原文始发于微信公众号(独眼情报):使用 x64dbg Automate 进行大规模分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论