【问题标题】:Smart disassembly of TBB in ARM Thumb?ARM Thumb 中的 TBB 智能拆解?
【发布时间】:2017-07-15 05:18:23
【问题描述】:

在ARM中,TBB(table branch byte)基本上是一个switch指令,它根据传入的索引(switch value)从指令之后的表中获取一个跳转地址,然后跳转到该地址。 ARM docs

我正在尝试自动反汇编 TBB(和 TBH)表,因此它们不会作为指令进行反汇编,而是在表格之后继续反汇编。问题是,TBB 表是可变长度的,并且没有边界检查。边界检查必须在 TBB 之前手动(或由编译器)完成。

表格没有终止符,表格内的任何字节都是有效的跳转偏移量。代码在表格之后立即重新开始。

那么,有没有人遇到(或可以想到)一种自动确定 TBB 表长度的方法?我最好的办法是在默认情况下搜索导致 TBB 的说明,但这似乎是一种不精确的方法。

【问题讨论】:

  • 简单的第一个检查是验证表中的值是否指向程序代码。
  • @Jester 对于任何可能的字节偏移,这通常都是正确的。但是,你给了我一个想法。必须至少有一个分支,并且该偏移量至少可以让您了解表格的结束位置。不过,不能保证就在桌子后面。
  • 哦,表只有字节偏移,没有指针。太糟糕了。
  • @Jester 对,表条目是单字节 PC 相对跳转偏移量。实际代码中的字节,被解释为偏移量,很可能会让你得到一些你可以解释为指令的东西。 Thumb 是一个密集的指令集。相反,100 次中有 99 次分支表也可能是有效指令。我没有符号,我只需要遵循我所知道的代码即可。
  • 它就像任何其他的反汇编一样,有些东西你不模拟就无法弄清楚,即使在那里你也不能总是得到它。很明显,某些文件格式(elf)留下了关于哪些部分是或可能是的线索,例如从 elf 反汇编的混合 arm 和 thumb 代码是正确的(除了他们试图反汇编的只读常量)。我的猜测是你正在做的事情没有足够的细节,即使你模拟了导致这个表的所有代码,仍然有一定百分比的出错机会。

标签: assembly arm disassembly thumb


【解决方案1】:

这是我正在尝试的一种可能的方法,它似乎有效,至少对于一些表现良好的分支表来说是这样。解码 TBB 后,我开始循环分支字节。对于每一个,我找到它对应的地址,并跟踪这些地址中的最低地址(最接近分支表的末尾)。我还检查每个分支地址是否在当前解码的分支字节之后,因为表末尾可能有零填充。

这取决于表的末尾和表中引用的代码的开头之间没有任何代码或数据。例如,如果默认情况紧跟在表之后,但没有从表中引用,这将遇到问题。对于我必须测试的示例,编译器将默认情况放在其他情况的末尾。

我正在使用 Capstone 进行反汇编,这里有一些无需太多上下文就应该有意义的代码:

case ARM_INS_TBB:
// Table branch byte
if(insn->detail->arm.op_count == 1 &&
        insn->detail->arm.operands[0].type == ARM_OP_MEM &&
        insn->detail->arm.operands[0].mem.base == ARM_REG_PC){
    // PC relative TBB
    u64 min = U64_MAX;
    // loop over table bytes
    for(u64 i = 0; ; ++i){
        // check if current table byte is before minimum branch target
        if(insn_addr + insn->size + i < min){
            // get branch address from table byte
            u64 branchaddr = insn_addr + insn->size +
                (binary_image[insn_addr + insn->size + i] << 1);
            // check if branch address is larger than the 
            // location of the previous table byte
            if(branchaddr > insn_addr + insn->size + i){
                // new lower address branch target
                min = branchaddr;
                // do something with the code at branchaddr
            } else {
                break;
            }
        } else {
            break;
        }
    }
}
// Instructions immediately after this are junk, stop parsing
return;
break;

【讨论】:

    猜你喜欢
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多