作为帖子“使用QEmu监视器接口从二进制文件中提取执行跟踪信息?”的答案,一位PANDA作者概述了如何使用QUEMU记录执行跟踪信息。

我想这样做使用PANDA。

我发现QEMU函数cpu_memory_rw_debug(env, pc, buf, size, is_write);允许访问来宾的内存。但是,由于操作码的大小不同,我不知道要读取多少内存。

PANDA提供了panda_disas函数:


void panda_disas(FILE *out, void *code, unsigned long size);


在长度为字节的虚拟地址代码处写来宾代码反汇编的文本表示形式。确定指令的大小?

由于PANDA_CB_INSN_EXECPANDA_CB_INSN_TRANSLATE没有提供指令的大小,我认为它必须在CPUState中。但找不到任何东西。

还有其他方法还是我缺少什么?

#1 楼

目前,PANDA尚未提供有关单个指令级别的指令大小的信息(在翻译之前尚不清楚)。但是,您可以做的一件事是,一旦QEMU使用PANDA_CB_AFTER_BLOCK_TRANSLATE转换了整个基本块的大小,然后查看tb->size字段。然后,您可以缓存该块的反汇编,并在PANDA_CB_BEFORE_BLOCK_EXEC回调中将其打印出来。您必须对其稍作调整才能获得完整的指令跟踪,但是它应该演示该原理。


评论


谢谢!我的最后一个想法是使用顶石。但是这样:1.)从PC开始获取15个字节(最大i386操作码长度); 2。让capstone分解整个15个字节; 3。)获取第一个结构(从返回的结构数组中获取); 4。 )使用此结构中的.size信息。参见capstone-engine.org/lang_c.html。你怎么看?也可以尝试用它制作一个插件,以便其他人可以重复使用代码...但是,您的解决方案可能具有更好的性能,因为您可以避免反汇编两次或更多次相同的指令。

– gogo_gorilla
16年4月1日在13:25



您的策略大部分应该起作用。一个极端的情况是,如果您尝试在未映射下一页的页面边界附近读取15个字节。真正的指令可能不会越过页面边界,但是尝试读取15个字节将失败。我认为真正的解决方案是向PANDA添加AFTER_INSN_TRANSATE回调,以提供以字节为单位的指令大小(因为QEMU的翻译器此时将具有该信息)。

–布伦丹·多兰·加维特(Brendan Dolan-Gavitt)
16年4月1日在15:02



Capstone相当重。如果仅需要查找指令长度,则可能需要使用更轻量的解决方案,例如github.com/greenbender/lend。

–詹森·格夫纳(Jason Geffner)
16年4月1日在15:08

@ BrendanDolan-Gavitt我喜欢您的建议,将AFTER_INSN_TRANSATE回调添加到PANDA。但是,我无法找到qemu拥有此信息的正确位置。它在target-i386 / translate.c中吗?您能指出我正确的位置吗?

– gogo_gorilla
16-4-3在9:32



@ BrendanDolan-Gavitt我的猜测:大小可以在target-i386 / translate.c中的函数disas_insn(DisasContext * s,target_ulong pc_start)的末尾获得。 disas_insn返回s-> pc(在解析操作码时逐字节递增)。这意味着size = s-> pc-pc_start请告诉我我是否错了。

– gogo_gorilla
16-4-3在14:28