9

我有一些将在程序中的某个点执行的代码的汇编代码。我不知道内存中代码的地址。

当前指令与输入指令匹配时是否可以使 gdb 中断?

例如,每当 gdb 到达此指令时,我希望 gdb 中断:

leaq        0x000008eb(%rip),%rax
4

3 回答 3

10

正如其他人所说,由于没有硬件支持,因此可能无法有效地做到这一点。

但是如果你真的想这样做,这个 Python 命令可以作为一个起点。程序单步执行,直到给出具有给定操作码的函数。由于每条指令的执行都返回到 python,如果目标指令距离太多指令,这将非常缓慢。但是对于或多或少的附近呼叫,它应该可以正常工作。

class ContinueI(gdb.Command):
    """
Continue until instruction with given opcode.

    ci OPCODE

Example:

    ci callq
    ci mov
"""
    def __init__(self):
        super().__init__(
            'ci',
            gdb.COMMAND_BREAKPOINTS,
            gdb.COMPLETE_NONE,
            False
        )
    def invoke(self, arg, from_tty):
        if arg == '':
            gdb.write('Argument missing.\n')
        else:
            thread = gdb.inferiors()[0].threads()[0]
            while thread.is_valid():
                gdb.execute('si', to_string=True)
                frame = gdb.selected_frame()
                arch = frame.architecture()
                pc = gdb.selected_frame().pc()
                instruction = arch.disassemble(pc)[0]['asm']
                if instruction.startswith(arg + ' '):
                    gdb.write(instruction + '\n')
                    break
ContinueI()

只需通过以下方式获取它:

source gdb.py

并将命令用作:

ci mov
ci callq

并且您将被留在使用给定操作码执行的第一条指令上。

TODO:这将忽略您的其他断点。

对于特殊的常见情况syscall,您可以使用catch syscallhttps ://reverseengineering.stackexchange.com/questions/6835/setting-a-breakpoint-at-system-call

于 2015-07-06T15:10:24.337 回答
3

我不知道内存中代码的地址。

是什么阻止您找到该地址?运行objdump -d,找到感兴趣的指令,记下它的地址。问题解决了?(这也可以简单地扩展到共享库。)

于 2012-12-25T16:04:15.973 回答
2

不,这是不可能的,而且实施起来也非常低效。

调试器通常支持两种断点:

  • 硬件断点:当某些事件发生时,调试器会要求 CPU 引发一个特殊的异常中断,比如内存中的某个位置发生了变化。
  • 软件断点:调试器用特殊的“陷阱”指令(x86 架构上的int 3/ )替换断点地址处的操作码。0xcc

匹配当前指令的操作码要么需要 CPU 支持来插入硬件断点,要么调试器需要知道地址才能使用软件断点。

理论上,调试器可以在整个内存中搜索指令的字节序列,但由于字节序列也可能出现在指令中间或数据中,因此可能会出现误报。

由于汇编指令是可变长度的,控制可以跳转到任意地址或代码可以修改自身,反汇编整个内存区域以找到某些特定指令也并非易事。

所以基本上,在任意汇编代码中可靠地找到指令的唯一方法是在指令级别上单步执行。这将是非常昂贵的,即使是一个微不足道的库调用,printf()如果你单步执行每条指令,在今天的硬件上可能需要几分钟。

于 2012-12-25T15:49:32.633 回答