我正在使用线性反汇编程序(beaEngine),每当我进入跳转表部分时,都会收到错误消息(或错误的解码,因为beaEngine错误地认为这是代码)。

将此部分识别为跳转表?跳转表的特征是什么?

通过第三方应用程序找到的跳转表的示例:

.text:600F49CB                 dd offset loc_600F496E  
.text:600F49CB                 dd offset loc_600F4984  
.text:600F49CB                 dd offset loc_600F4979  
.text:600F49CB                 dd offset loc_600F4979  
.text:600F49CB                 dd offset loc_600F4984  
.text:600F49CB                 dd offset loc_600F499E   
.text:600F49CB                 dd offset loc_600F499E   
.text:600F49CB                 dd offset loc_600F498F   
.text:600F49CB                 dd offset loc_600F498F   


在为了澄清和回答注释中提出的问题:此可执行文件确实具有重定位表。但是,beaEngine似乎并没有使用它,因为我向它提供了字节流,而不是整个二进制流。对于我检查过的一个示例,它似乎确实有效。

评论

至少尝试提供您找到的跳转表的示例。

此可执行文件是否有重定位表? beaEngine找到它时会使用它吗?

#1 楼

跳转表在重定位表中脱颖而出,因为它们是紧密包装的代码地址的数组,而“常规”代码引用之间的间隔更大,操作码或其他数据在它们之间。

但是,从镜头的角度看,vtables(用于C ++样式对象的虚拟函数表)和功能表(用于在某些库中大量使用的C样式对象)看起来与跳转表几乎完全相同搬迁。区别在于后两种类型的“代码地址数组”包含函数地址,而跳转表条目通常指向函数。

但是,如果不分析引用它们的代码,则很难分析跳转表。 。这意味着从重定位表中收集的信息在这种情况下更适合于辅助任务,例如告诉您反汇编程序可能错过的潜在跳转表,而不是用于主要分析。

评论


除非在跳转表中使用了本地/相对跳转。然后它将不在重定位表中。

–棘轮怪胎
16年1月7日,11:32

@棘手怪胎:是的,的确如此。这就是为什么研究目标编译器的行为值得付出的原因,因为目标编译器倾向于在其跳转调度代码中仅利用目标处理器体系结构提供的可能性的一小部分。通常,他们为此使用非常固定的代码模式-比使用源语言编写并编译分派代码要固定得多。

– DarthGizka
16年1月7日,11:44

#2 楼

恕我直言,没有简单的方法可以做到这一点。最好是编写智能反汇编程序,以便它可以找到并推断表的大小。例如,跳转表代码的特征之一:

and eax, NUMBER_OF_CASES
jmp dword ptr ds:[eax*4 + switch_table_start_addr]


另一种快速且容易出错的方法可能是查找具有最小RVA和最大RVA的DWORD行范围,例如:

dd IMAGEBASE+0x1000
dd IMAGEBASE+0xXXXX
dd IMAGEBASE+0xYYYY
dd IMAGEBASE+0xFFFF
...


,但这可能会发现与开关表无关的更多数据,尤其是在大型应用中。

#3 楼

好吧..我确实发现确实如您所说的一个jmp表示一个跳转表。

所以我现在要做的是


寻找那些跳转
/>解析先前的操作码并查找“ cmp”,它表示switch语句中的“默认”部分(因此,它表示跳转表的大小,因为它是案例数* 4(32位)) 。
计算跳转表的开始地址和结束地址。

现在我有一个不同的问题。.
我所描述的通常适用于切换(比如说1-10)。但是当它不连续时,编译器会创建一个“ switch语句的间接表”,它看起来有些不同,而且我不知道如何计算其大小。

有什么想法吗?这些东西没有标准吗?我怎么知道我是否已经涵盖了跳转表的所有选项?

评论


索引表的大小由查找指令之前的指令隐含。通常情况是“锚定”减法,并将其与表中的最高索引(或其大小,视情况而定)进行比较。在索引表中找到的最大值-最小值始终恒定为0-表示实际跳转表的大小。

– DarthGizka
16年1月5日在13:13

#4 楼

Cristina Cifuentes和Mike Van Emmerik(1999年第七届国际程序理解研讨会)的论文“从二进制代码恢复跳转表案例陈述”(1999年第七届国际程序理解研讨会的论文集)中对此进行了详细讨论。从反向工程的角度来看,这很有意思。了解编译器通常如何将switch语句映射到机器代码(它们并不总是映射到单个跳转表)也很有用。罗伯特·伯恩斯坦(Robert Bernstein)的论文“为案例陈述生成良好的代码”(软件:实践与经验,1985年10月)对此进行了详细讨论。