RET同步代表反向工程工具同步。这是一组插件,有助于将调试会话(WINDBG/GDB/LLDB/OLLYDBG/OLLYDBG2/X64DBG)与拆卸器(IDA/GHIDRA/GHIDRA/BINARY NINJA)同步。潜在的想法很简单:从两全其美(静态和动态分析)中汲取最好的想法。
调试者和动态分析为我们提供:
!peb , !drvobj ,! !address等)拆卸器和静态分析为我们提供:
关键功能:
ret-sync是我在Quarkslab逗留期间开发和维护的QB-Sync的叉子。
调试器插件:
ext_windbg/sync :windbg扩展源文件,一旦构建: sync.dllext_gdb/sync.py :GDB插件ext_lldb/sync.py :lldb插件ext_olly1 :ollydbg 1.10插件ext_olly2 :ollydbg v2插件ext_x64dbg :x64dbg插件拆卸器插件:
ext_ida/SyncPlugin.pyext_ghidra/dist/ghidra_*_retsync.zip插件ext_bn/retsync :二进制忍者插件和库插件:
ext_lib/sync.py :独立python库IDA和GDB插件需要有效的Python设置。支持Python 2(> = 2.7)和Python 3。
Windbg/Ollydbg/Ollydbg2/X64DBG调试者的预构建二进制文件是通过Azure DevOps管道提出的:
选择最后一个构建并检查Related部分下的工件: 6 published 。

Ghidra插件的预构建插件存档在ext_ghidra/dist中提供。
ret-sync应该为大多数用户提供典型设置的开箱即用:同一主机上的调试器和拆卸器,模块名称匹配。
不过,在某些情况下,可以使用特定的配置。为此,扩展名和插件在用户主目录中检查了名为.sync的可选全局配置文件。它必须是有效的.INI文件。
此外,IDA和GHIDRA插件还首先在IDB或Project Directory( <project>.rep )中查找配置文件,以允许本地,每个IDB/Project,设置。如果存在本地配置文件,则忽略了全局配置文件。
在这些配置文件中声明的值覆盖默认值。请注意,默认情况下创建NO .sync文件。
下面我们详细介绍了配置文件有用/需要的三个常见方案:
[INTERFACE]部分用于自定义与网络相关的设置。让我们假设一个人想将IDA与在虚拟机(或另一个主机)中运行的调试器同步,常见的远程内核调试方案。
只需创建两个.sync文件:
[INTERFACE]
host=192.168.128.1
port=9234
它告诉ret-sync IDA插件在端口9234上在接口192.168.128.1上聆听。毋庸置疑,必须从远程主机或虚拟机可以达到此接口。
[INTERFACE]
host=192.168.128.1
port=9234
它告诉RET-Sync调试插件,以连接到先前配置为在此接口中收听的RET-Sync IDA插件。
注意:您必须在此处指定一个真实的IP,并且不要使用0.0.0.0 。这是因为该变量均由多个源用于绑定和连接,因此使用0.0.0.0会导致奇怪的错误。
[ALIASES]
ntoskrnl_vuln.exe=ntkrnlmp.exe
[ALIASES]部分用于自定义拆卸器(IDA/GHIDRA)使用的名称,以将模块注册到其调度员/程序管理器中。
默认情况下,拆卸器插件使用输入文件的名称。但是,可能已事先重命名该文件,并且不再匹配实际过程的名称或调试器所看到的已加载模块。
在这里,我们只需告诉调度程序即可匹配名称ntkrnlmp.exe (真实名称),而不是ntoskrnl_vuln.exe (IDB名称)。
QT创建者调试前端更改GDB命令输出的方式。由于这将干扰同步,因此存在使用原始GDB输出进行同步而不是临时文件的选项。在.Sync配置文件中使用
[GENERAL]
use_tmp_logging_file=false
如果您希望将目标用于目标的QT调试前端。
/proc/<pid>/maps在某些情况下,例如在Qemu中通过串行或原始固件调试嵌入式设备,GDB不知道PID,无法访问/proc/<pid>/maps 。
在这些情况下, [INIT]部分用于将自定义上下文传递给插件。它允许覆盖某些字段,例如PID和内存映射。
.sync内容摘录:
[INIT]
context = {
"pid": 200,
"mappings": [ [0x400000, 0x7A81158, 0x7681158, "asav941-200.qcow2|lina"] ]
}
映射中的每个条目是: mem_base , mem_end , mem_size , mem_name 。
在某些情况下,例如调试嵌入式设备或连接到简约的调试界面,绕过拆卸器插件中实现的自动地址重新打开功能可能更方便。
当前仅针对Ghidra支持use_raw_addr选项。在.Sync配置文件中使用:
[GENERAL]
use_raw_addr=true
IDA 7.X需要分支。对于较旧版本(6.9倍),请参见存档的版本ida6.9x 。
对于IDA安装,请将Syncplugin.py和retsync文件夹从ext_ida复制到IDA插件目录:
C:Program FilesIDA Pro 7.4plugins%APPDATA%Hex-RaysIDA Proplugins~/.idapro/pluginsAlt-Shift-S )或Edit中运行插件 - > Plugins - > ret-sync [sync] default idb name: ld.exe
[sync] sync enabled
[sync] cmdline: "C:Program FilesPython38python.exe" -u "C:UsersuserAppDataRoamingHex-RaysIDA Propluginsretsyncbroker.py" --idb "target.exe"
[sync] module base 0x100400000
[sync] hexrays #7.3.0.190614 found
[sync] broker started
[sync] plugin loaded
[sync] << broker << dispatcher not found, trying to run it
[sync] << broker << dispatcher now runs with pid: 6544
[sync] << broker << connected to dispatcher
[sync] << broker << listening on port 63107
要解决IDA扩展问题的问题,请在文件retsync/rsconfig.py中提供两个选项:
LOG_LEVEL = logging.INFO
LOG_TO_FILE_ENABLE = False
将LOG_LEVEL值设置为logging.DEBUG使插件更详细。
将LOG_TO_FILE_ENABLE设置为True值触发了从broker.py和dispatcher.py将异常信息记录到专用文件中。日志文件是在%TMP%文件夹中生成的,并具有名称模式retsync.%s.err 。
要么使用ext_ghidra/dist文件夹中的预构建版本,要么遵循指令构建它。每个扩展构建仅支持插件文件名中指定的Ghidra版本。例如ghidra_9.1_PUBLIC_20191104_retsync.zip用于Ghidra 9.1公共。
apt install gradle$GHIDRA_DIR ) cd ext_ghidra
gradle -PGHIDRA_INSTALL_DIR= $GHIDRA_DIRFile - > Install Extensions... ,单击+标志,然后选择ext_ghidra/dist/ghidra_*_retsync.zip ,然后单击“确定”。这将有效地将retsync文件夹从ZIP提取到$GHIDRA_DIR/Extensions/Ghidra/ [*] retsync init
[>] programOpened: tm.sys
imageBase: 0x1c0000000
Alt+s )/Disable( Alt+Shift+s )/RESTART( Alt+r )同步。 Windows > RetSyncPlugin也可以找到状态窗口。您通常希望将其放在侧面,以将其与Ghidra环境窗口集成在一起。
二进制忍者支持是实验性的,请确保备份分析数据库。
ret-sync最少需要二进制忍者2.2版,以及Python 3(不支持Python 2)。
ret-sync尚未通过二进制忍者的插件管理器分发;需要手动安装。只需将ext_bn文件夹的内容复制到二进制忍者插件文件夹中,例如:
%APPDATA%Binary Ninjaplugins
重新启动二进制忍者后,控制台窗口中应存在以下输出:
[sync] commands added
Loaded python3 plugin 'retsync'
使用预构建的二进制文件,或使用ext_windbg中提供的Visual Studio 2017解决方案(请参阅https://docs.microsoft.com/en-us/visalstudio/releasenotes/vs2017-relnotes,如果需要时)。
这将构建x64releasesync.dll文件。
您将需要将结果sync.dll文件复制到适当的windbg扩展路径中。
对于windbg的早期版本,这就是这样(例如,请小心x86 / x64口味)
C:Program Files (x86)Windows Kits10Debuggersx64winextsync.dll
用于存储扩展程序的文件夹似乎基于路径,因此您需要将其放置为查询位置之一。
一个例子是将其放在这里:
C:UsersuserAppDataLocalMicrosoftWindowsAppssync.dll
.load命令) 0:000> .load sync
[sync.dll] DebugExtensionInitialize, ExtensionApis loaded
0:000> !sync
[sync] No argument found, using default host (127.0.0.1:9100)
[sync] sync success, sock 0x5a8
[sync] probing sync
[sync] sync is now enabled with host 127.0.0.1
例如在IDA的输出窗口中
[*] << broker << dispatcher msg: add new client (listening on port 63898), nb client(s): 1
[*] << broker << dispatcher msg: new debugger client: dbg connect - HostMachineHostUser
[sync] set debugger dialect to windbg, enabling hotkeys
如果WindBG的当前模块与IDA文件名匹配
[sync] idb is enabled with the idb client matching the module name.
注意:如果收到以下错误,则是因为您尚未将文件复制到上述步骤中的正确文件夹中。
0: kd> .load sync
The call to LoadLibrary(sync) failed, Win32 error 0n2
"The system cannot find the file specified."
Please check your debugger configuration and/or network access.
下面的误差通常意味着WINDBG试图加载扩展的不正确风味,例如: x64代替x86 sync.dll 。
0:000> .load sync
The call to LoadLibrary(sync) failed, Win32 error 0n193
"%1 is not a valid Win32 application."
Please check your debugger configuration and/or network access.
由于WindBG预览从同一目录加载插件( x86和x64 ),因此可以重命名x86文件sync32.dll 。
0:000> .load sync32
ext_gdb/sync.py复制到您选择的目录 gdb> source sync.py
[sync] configuration file loaded 192.168.52.1:9100
[sync] commands added
但是,LLDB支持是实验性的:
~/.lldbinit中添加) lldb> command script import sync
OLLYDBG 1.10支持是实验性的:
但是,OLLYDBG2支持是实验性的:
基于testplugin,https://github.com/x64dbg/testplugin。 X64DBG支持是实验性的:
pluginsdk ”目录粘贴到“ ext_x64dbgx64dbg_sync ”中.d32或.dp64 )。对于以命令行为导向的调试者(主要是WINDBG和GDB), RET-Sync公开了一组命令,以协助进行反向工程任务。
下面的命令是通用的(WINDBG和GDB),请注意!在WINDBG上需要前缀(例如:GDB中的sync , !sync )。
| 调试器命令 | 描述 |
|---|---|
synchelp | 显示带有简短说明的可用命令列表 |
sync | 开始同步 |
syncoff | 停止同步 |
cmt [-a address] <string> | 在拆卸器中的当前IP上添加评论 |
rcmt [-a address] | 在当前IP中重置评论 |
fcmt [-a address] <string> | 为当前IP所在的函数添加功能注释 |
raddr <expression> | 添加评论,并从表达式中评估的重新反驳地址 |
rln <expression> | 从给定地址的拆卸器中获取符号 |
lbl [-a address] <string> | 在当前IP中添加标签名称 |
cmd <string> | 在调试器中执行命令,并在当前IP中添加其输出作为注释。 |
bc <||on|off|set 0xBBGGRR> | 在拆卸器中启用/禁用路径着色 |
idblist | 获取连接到调度程序的所有IDB客户端的列表 |
syncmodauto <on|off> | 基于模块名称启用/禁用拆卸器自动开关 |
idbn <n> | 将Active IDB设置为nth客户端 |
jmpto <expression> | |
jmpraw <expression> | 如果启用了IDB,则将拆卸器的视图与结果地址同步。 |
translate <base> <addr> <mod> | 反弹有关其模块的姓名和偏移的地址 |
windbg特定命令:
| 调试器命令 | 描述 |
|---|---|
curmod | 显示用于当前指令偏移的模块信息(用于故障排除) |
modlist | 调试器标记语言(DML)增强的模块列表,用于更平滑的活动IDB切换 |
idb <module name> | 将给定模块设置为活动IDB(请参阅lm的modlist增强版本) |
modmap <base> <size> <name> | 综合(“伪造”)模块(使用其基础地址和大小定义)添加到调试器内部列表中 |
modunmap <base> | 在基地地址上删除先前映射的合成模块 |
modcheck <||md5> | 用于检查当前模块是否确实与IDB的文件匹配(例如:模块已更新) |
bpcmds <||save|load|> | bpcmds包装器,保存和重新加载.bpcmds (断点命令列表)输出到当前IDB |
ks | 调试器标记语言(DML)增强KV命令的输出 |
GDB特定命令:
| 调试器命令 | 描述 |
|---|---|
bbt | 美丽的回溯。类似于GDB中的BT ,但请求拆卸器的符号 |
patch | 基于实时上下文中拆卸器中的补丁字节 |
bx | 类似于GDB X,但使用符号。该符号将通过拆卸器解决 |
cc | 继续符合拆卸器 |
Overwrite idb name输入字段旨在更改默认的IDB名称。它是插件用于向调度程序注册的名称。 IDB自动开关基于模块名称匹配。如果名称相互冲突(例如foo.exe和foo.dll ),则可以用来简化匹配。请注意,如果您在同步活动时修改输入字段,则必须与调度程序重新注册;这可以简单地使用“ Restart ”按钮完成。
为了提醒您,默认情况下可以使用.sync配置文件别名。
ret-sync在IDA中定义了这些全球捷径:
Alt-Shift-S运行RET-Sync插件Ctrl-Shift-S切换全局同步Ctrl-H切换十六进制射线同步调试工具栏中还可以使用两个按钮,以切换全局和十六进制射线同步。
Syncplugin.py还注册调试器命令包装器Hotkeys。
F2在光标地址设置断点F3在光标地址设置一声断点Ctrl-F2在光标地址设置硬件断点Ctrl-F3在光标地址设置一击硬件断点Alt-F2翻译(在调试器中折叠)当前光标地址Alt-F5去Ctrl-Alt-F5 -run(仅GDB)F10单步F11单个跟踪这些命令仅在当前IDB处于活动状态时可用。如果可能的话,他们也已为其他辩论者实施。
一旦Retsyncplugin打开,您可以通过简单的Drag'n'Drop将其添加到CodeBrowser窗口中:

如果要查看几个模块,则需要在同一codebrowser查看器中打开文件,只需将“ drop”拖放到codebrowser窗口中的其他磁盘,以获取上述结果。
ret-sync定义了吉德拉的这些全球捷径:
Alt-S启用同步Alt-Shift-S禁用同步Alt-R重新启动同步Alt-Shift-R重新加载配置还实现了对调试器命令的绑定。它们类似于IDA扩展名(“ GO”命令除外)。
F2在光标地址设置断点Ctrl-F2在光标地址设置硬件断点Alt-F3在光标地址设置一声断点Ctrl-F3在光标地址设置一击硬件断点Alt-F2翻译(在调试器中折叠)当前光标地址F5去Alt-F5 -Run(仅GDB)F10单步F11单个跟踪ret-sync在二元忍者中定义了这些全球捷径:
Alt-S启用同步Alt-Shift-S禁用同步还实现了对调试器命令的绑定。它们类似于IDA扩展名的。
F2在光标地址设置断点Ctrl-F2在光标地址设置硬件断点Alt-F3在光标地址设置一声断点Ctrl-F3在光标地址设置一击硬件断点Alt-F2翻译(在调试器中折叠)当前光标地址Alt-F5去F10单步F11单个跟踪 [WinDbg]
0:000:x86> pr
eax=00000032 ebx=00000032 ecx=00000032 edx=0028eebc esi=00000032 edi=00000064
eip=00430db1 esp=0028ed94 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
image00000000_00400000+0x30db1:
00430db1 57 push edi
0:000:x86> dd esp 8
0028ed94 00000000 00433845 0028eebc 00000032
0028eda4 0028f88c 00000064 002b049e 00000110
0:000:x86> !cmt 0028ed94 00000000 00433845 0028eebc 00000032
[sync.dll] !cmt called
[IDA]
.text:00430DB1 push edi ; 0028ed94 00000000 00433845 0028eebc 00000032
[WinDbg]
0:000:x86> !rcmt
[sync] !rcmt called
[IDA]
.text:00430DB1 push edi
[WinDbg]
0:000:x86> !fcmt decodes buffer with key
[sync] !fcmt called
[IDA]
.text:004012E0 ; decodes buffer with key
.text:004012E0 public decrypt_func
.text:004012E0 decrypt_func proc near
.text:004012E0 push ebp
注意:呼叫此命令而无需重置该函数的评论。
[WinDbg]
0:000:x86> !lbl meaningful_label
[sync] !lbl called
[IDA]
.text:000000000040271E meaningful_label:
.text:000000000040271E mov rdx, rsp
[WinDbg]
0:000:x86> pr
eax=00000032 ebx=00000032 ecx=00000032 edx=0028eebc esi=00000032 edi=00000064
eip=00430db1 esp=0028ed94 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
image00000000_00400000+0x30db1:
00430db1 57 push edi
[sync.dll] !cmd r edi
[IDA]
.text:00430DB1 push edi ; edi=00000064
[WinDbg]
0:000> !idblist
> currently connected idb(s):
[0] target.exe
[WinDbg]
0:000> !syncmodauto off
[IDA]
[*] << broker << dispatcher msg: sync mode auto set to off
[WinDbg]
0:000:> !idbn 0
> current idb set to 0
在此示例中,当前的活动IDB客户端将设置为:
[0] target.exe.
Alt-F2快捷方式)中使用,重新反映有关其模块的姓名和偏移的地址。 ! -a --address地址应作为十六进制价值通过。命令解析基于Python的argparse模块。停止线解析使用-- 。
[WinDbg]
0:000:x86> !cmt -a 0x430DB2 comment
该地址必须是有效的指令的地址。
与主机同步:
gdb> sync
[sync] sync is now enabled with host 192.168.52.1
<not running>
gdb> r
Starting program: /bin/ls
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".
使用命令,没有“!”前缀
(gdb) cmd x/i $pc
[sync] command output: => 0x8049ca3: push edi
(gdb) synchelp
[sync] extension commands help:
> sync <host>
> syncoff
> cmt [-a address] <string>
> rcmt [-a address] <string>
> fcmt [-a address] <string>
> cmd <string>
> bc <on|off|>
> rln <address>
> bbt <symbol>
> patch <addr> <count> <size>
> bx /i <symbol>
> cc
> translate <base> <addr> <mod>
(gdb) bt
#0 0x0000000000a91a73 in ?? ()
#1 0x0000000000a6d994 in ?? ()
#2 0x0000000000a89125 in ?? ()
#3 0x0000000000a8a574 in ?? ()
#4 0x000000000044f83b in ?? ()
#5 0x0000000000000000 in ?? ()
(gdb) bbt
#0 0x0000000000a91a73 in IKE_GetAssembledPkt ()
#1 0x0000000000a6d994 in catcher ()
#2 0x0000000000a89125 in IKEProcessMsg ()
#3 0x0000000000a8a574 in IkeDaemon ()
#4 0x000000000044f83b in sub_44F7D0 ()
#5 0x0000000000000000 in ()
F3设置单发断点和F5继续进行的替代方法。如果您更喜欢从GDB进行操作,这将很有用。 (gdb) b* 0xA91A73
Breakpoint 1 at 0xa91a73
(gdb) c
Continuing.
Breakpoint 1, 0x0000000000a91a73 in ?? ()
(gdb) cc
[sync] current cursor: 0xa91a7f
[sync] reached successfully
(gdb)
lldb> process launch -s
lldb> sync
[sync] connecting to localhost
[sync] sync is now enabled with host localhost
[sync] event handler started
lldb> synchelp
[sync] extension commands help:
> sync <host> = synchronize with <host> or the default value
> syncoff = stop synchronization
> cmt <string> = add comment at current eip in IDA
> rcmt <string> = reset comments at current eip in IDA
> fcmt <string> = add a function comment for 'f = get_func(eip)' in IDA
> cmd <string> = execute command <string> and add its output as comment at current eip in IDA
> bc <on|off|> = enable/disable path coloring in IDA
color a single instruction at current eip if called without argument
lldb> cmt mooo
Alt+s )/Disable( Alt+u )同步。 Ctrl+s )/Disable( Ctrl+u )同步。由于OLLYDBG2 API的BETA状态,仅实现了以下功能:
F7 ; F8用于步进]CTRL+;这是给出的CTRL+: ] 使用插件菜单或命令enable(“ !sync" )或禁用(“ !syncoff ”)同步。
使用命令
[sync] synchelp command!
[sync] extension commands help:
> !sync = synchronize with <host from conf> or the default value
> !syncoff = stop synchronization
> !syncmodauto <on | off> = enable / disable idb auto switch based on module name
> !synchelp = display this help
> !cmt <string> = add comment at current eip in IDA
> !rcmt <string> = reset comments at current eip in IDA
> !idblist = display list of all IDB clients connected to the dispatcher
> !idb <module name> = set given module as the active idb (see !idblist)
> !idbn <n> = set active idb to the n_th client. n should be a valid decimal value
> !translate <base> <addr> <mod> = rebase an address with respect to local module's base
注意:使用来自拆卸器(IDA/GHIDRA, Alt-F2快捷方式)的!translate命令,将使拆卸器窗口“跳”到特定地址(相当于X64DBG命令行中运行障碍的等效)。
即使没有完整的调试环境或使用自定义工具,即使使用RET-Sync核心功能(与拆卸器,符号分辨率同步,符号分辨率)也可能需要使用。为此,提取了简约的Python库。
下面的示例说明了Python库的使用情况,该脚本浏览了基于事件的日志记录/跟踪工具的输出。
from sync import *
HOST = '127.0.0.1'
MAPPINGS = [
[ 0x555555400000 , 0x555555402000 , 0x2000 , " /bin/tempfile" ],
[ 0x7ffff7dd3000 , 0x7ffff7dfc000 , 0x29000 , " /lib/x86_64-linux-gnu/ld-2.27.so" ],
[ 0x7ffff7ff7000 , 0x7ffff7ffb000 , 0x4000 , " [vvar]" ],
[ 0x7ffff7ffb000 , 0x7ffff7ffc000 , 0x1000 , " [vdso]" ],
[ 0x7ffffffde000 , 0x7ffffffff000 , 0x21000 , " [stack]" ],
]
EVENTS = [
[ 0x0000555555400e74 , "malloc" ],
[ 0x0000555555400eb3 , "open" ],
[ 0x0000555555400ee8 , "exit" ]
]
synctool = Sync ( HOST , MAPPINGS )
for e in EVENTS :
offset , name = e
synctool . invoke ( offset )
print ( " 0x%08x - %s" % ( offset , name ))
print ( "[>] press enter for next event" )
input ()虽然最初专注于动态分析(DEBUGGERS),但可以扩展插件设置并与其他工具集成。
其他资源:
与GDB:
与windbg:
g ')的命令字符串,IDA的客户端插件即使被通知。如果这些事件太多,这可能会导致重大减速。已经实施了有限的修复程序,最好的解决方案仍然是暂时同步。与Ghidra:
与ida:
冲突:
.sync配置文件来定义其他端口。 [INTERFACE]
host=127.0.0.1
port=9234
ret-sync是免费软件:您可以将其重新分配和/或根据免费软件基金会发布的GNU通用公共许可证的条款(该许可证版本3版本)或(在您的选项上)任何以后版本。
该程序的分布是希望它将有用的,但没有任何保修;即使没有对特定目的的适销性或适合性的隐含保证。有关更多详细信息,请参见GNU通用公共许可证。
您应该已经收到了GNU通用公共许可证的副本以及此计划。如果没有,请参见http://www.gnu.org/licenses/。
二进制忍者插件按MIT许可发布。
向布鲁斯·丹(Bruce Dang),斯特尔(Stalkr), @ivanlef0u,达米安·阿玛(DamienAumaître),塞巴斯蒂安·雷纳德(SébastienRenaud)和凯文·szkudlapski, @ m00dy ,@saidelike,xavier mehrenberger,ben64,ben64,raphaëligo,raphaëlRigo,jiss,jiss for他们的善意,善良,反馈和反馈和反馈。伊尔法克·吉尔法诺夫(Ilfak Guilfanov),伊戈尔·斯科辛斯基(Igor Skochinsky)和阿诺德·迪德(Arnaud Diederen)在IDA的内部和出色的支持下提供了帮助。感谢Jordan Wiens和Vector35。最后,也感谢所有贡献者和所有报告问题/错误的人。