gdb`信息寄存器`的输出

逆向工程 数据库 登记
2021-06-17 03:12:16

在 gdb 中运行信息寄存器后,我们得到类似于以下的输出:

rax            0x1c 28
rbx            0x0  0
rcx            0x400a60 4196960
rdx            0x7fffffffde88   140737488346760
rsi            0x1  1
rdi            0x400932 4196658
rbp            0x0  0x0
rsp            0x7fffffffde68   0x7fffffffde68
r8             0x400ad0 4197072
r9             0x7ffff7dea560   140737351951712
r10            0x7fffffffdc30   140737488346160
r11            0x7ffff7732dd0   140737344908752
r12            0x4007f0 4196336
r13            0x7fffffffde80   140737488346752
r14            0x0  0
r15            0x0  0
rip            0x7ffff7732dd0   0x7ffff7732dd0
eflags         0x202    [ IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0

虽然我确实理解 for rax、rcx 等,但 GDB 正在将第二列的值转换为十进制,但这似乎不一致。一些寄存器,即 rsp 和 rip 显示相同的十六进制值,即使在第二列中也是如此。另一方面,eflags 显示第二列中的标志。

gdb 这样做的原因是什么?如果它要显示相同的信息(在 rsp 和 rip 的情况下),这不是多余的吗?另外,这如何推广到其他架构上?(以上输出适用于 x86-64)。

来源我重新问了这个问题,因为我认为我会从逆向工程的角度找到更具体的答案。

1个回答

事实上,在汇编中你只能找到三种类型的值:

  1. 数值;
  2. 内存地址;
  3. 指令(操作码)。

通用寄存器,例如rax, rbx, ... 用于存储数值(将触发程序的行为)或内存地址(以了解读取/写入或跳转的位置)。

当然,由于大多数人习惯于将程序中使用的值使用十进制格式,因此当寄存器可能包含此类值时,显示十进制格式很重要。

现在,重要的是要知道内存地址通常以十六进制格式给出(主要是出于紧凑性原因)。而且,通用寄存器也可能包含内存地址。这就是为什么同时gdb显示十进制和十六进制格式的原因,以防万一最适合当前值。

寄存器rsp, rip(和rbp) 是特殊情况,因为它们专门用于存储地址(并且仅用于存储地址),因此将此类寄存器的内容转换为十进制格式是没有用的。这就是为什么gdb只为这些寄存器提供十六进制格式的原因

最后,rflags/的情况eflags有点特殊,因为该寄存器的含义是逐位相关的(见下图)。

EFLAGS 位/位详细信息

因此,给出十进制、十六进制或二进制格式对用户来说并不是真正有用的(除非您可以立即将数字与标志相关联)。但是,提供设置为“true”的标志列表(这是[ IF ]您在示例中看到的)会更有用然而,gdb给出了 的十六进制值,eflags因为它可以被访问并用作程序中的值(我已经看到了这个用于混淆目的)。