关于调试:如何中断GDB中特定操作码的指令?

How to break on instruction with a specific opcode in GDB?

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

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

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

1
leaq        0x000008eb(%rip),%rax

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

但是,如果您真的想这样做,可以将此Python命令作为起点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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.\
')
        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 + '\
')
                    break
ContinueI()

只需提供以下信息即可:

1
source gdb.py

并使用以下命令:

1
2
breaki mov
breaki callq

您将留在以给定操作码执行的第一条指令上。

待办事项:这将忽略您的其他断点。

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


I don't know the address of the code in memory.

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


不,这是不可能的,并且实现起来效率也很低。

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

  • 硬件断点:调试器要求CPU在发生某些事件(例如更改内存中的某些位置)时引发特殊的异常中断。
  • 软件断点:调试器用特殊的"陷阱"指令(x86体系结构上的int 3 / 0xcc)替换断点地址处的操作码。

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

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

由于汇编指令的长度是可变的,因此控制可以跳转到任意地址或代码可以对其进行修改,因此分解整个内存区域以查找某些特定指令也不是一件容易的事。

因此,基本上,可靠地找到任意汇编代码中指令的唯一方法是在指令级别上单步执行。这将是非常昂贵的,如果单步执行每条指令,即使是琐碎的库调用(例如printf())也可能在当今的硬件上花费数分钟。