info registers在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
Run Code Online (Sandbox Code Playgroud)
虽然我明白了rax,rcx等等,GDB被转换为10进制的第二列中的值,这似乎并不一致.有些寄存器,即rsp并rip显示在十六进制的值相同,甚至在第二列.eflags另一方面,显示第二列中的标志.
这样做的原因是gdb什么?如果它将显示相同的信息(如果rsp和rip),是不是多余?此外,这如何概括其他架构?(以上输出适用于x86-64).
info registers命令以原始格式(十六进制)和自然格式打印输出寄存器.
自然格式基于寄存器的类型,在gdb源代码的xml文件中声明.例如,i386/64bit-core.xml包含:
<reg name="rax" bitsize="64" type="int64"/>
<reg name="rbx" bitsize="64" type="int64"/>
<reg name="rcx" bitsize="64" type="int64"/>
<reg name="rdx" bitsize="64" type="int64"/>
<reg name="rsi" bitsize="64" type="int64"/>
<reg name="rdi" bitsize="64" type="int64"/>
<reg name="rbp" bitsize="64" type="data_ptr"/>
<reg name="rsp" bitsize="64" type="data_ptr"/>
<reg name="r8" bitsize="64" type="int64"/>
<reg name="r9" bitsize="64" type="int64"/>
<reg name="r10" bitsize="64" type="int64"/>
<reg name="r11" bitsize="64" type="int64"/>
<reg name="r12" bitsize="64" type="int64"/>
<reg name="r13" bitsize="64" type="int64"/>
<reg name="r14" bitsize="64" type="int64"/>
<reg name="r15" bitsize="64" type="int64"/>
<reg name="rip" bitsize="64" type="code_ptr"/>
<reg name="eflags" bitsize="32" type="i386_eflags"/>
<reg name="cs" bitsize="32" type="int32"/>
<reg name="ss" bitsize="32" type="int32"/>
<reg name="ds" bitsize="32" type="int32"/>
<reg name="es" bitsize="32" type="int32"/>
<reg name="fs" bitsize="32" type="int32"/>
<reg name="gs" bitsize="32" type="int32"/>
Run Code Online (Sandbox Code Playgroud)
您可以看到带有type="int64"和的寄存器type="int32"在其自然输出中显示为十进制值,因为它们通常是通用寄存器,可用于引用内存和赋值.
注册时以自然格式注册type="data_ptr"并type="code_ptr"具有十六进制值,因为它们通常用于引用内存地址.
对于带有type="i386_eflags"输出的寄存器,设置为"true"的标志,因为对于这个寄存器,对于人类而言,在知道哪个标志设置为"True"而不是十六进制值时更有意义.
对于其他架构,它取决于在源代码中如何定义寄存器类型.您可以在binutils -gdb / gdb/features /中 查看ARM,ARM-64,x86-32bit和许多其他源代码.
编辑:
来源:@MarkPlotnick回答为什么gdb中的"info register ebp"没有显示十进制数?和@perror在https://reverseengineering.stackexchange.com/questions/9221/output-of-gdb-info-registers/9222#9222上回答.
对不起,我忘了提及来源.
事实上,在汇编中你只能找到三种类型的值:
通用寄存器,例如rax, rbx, ... 用于存储数值(将触发程序的行为)或内存地址(以了解读取/写入或跳转的位置)。
当然,由于大多数人习惯于将程序中使用的值使用十进制格式,因此当寄存器可能包含此类值时,显示十进制格式很重要。
现在,重要的是要知道内存地址通常以十六进制格式给出(主要是出于紧凑性原因)。而且,通用寄存器也可能包含内存地址。这就是为什么同时gdb显示十进制和十六进制格式的原因,以防万一最适合当前值。
寄存器rsp, rip(和rbp) 是特殊情况,因为它们专门用于存储地址(并且仅用于存储地址),因此将此类寄存器的内容转换为十进制格式是没有用的。这就是为什么gdb只为这些寄存器提供十六进制格式。
最后,rflags/的情况eflags有点特殊,因为该寄存器的含义是逐位相关的(见下图)。

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