【问题标题】:No epb/eip registers in gdb "info frame"gdb“信息框架”中没有 epb/eip 寄存器
【发布时间】:2016-10-30 07:59:17
【问题描述】:

上下文

在我的机器上发出命令info frame时(在main上有断点),输出如下:

(gdb) info frame
Stack level 0, frame at 0x7fffffffdbd0:
 rip = 0x4005b1 in main; saved rip = 0x7ffff7a53b05
 Arglist at 0x7fffffffdbc0, args: 
 Locals at 0x7fffffffdbc0, Previous frame's sp is 0x7fffffffdbd0
 Saved registers:
  rbp at 0x7fffffffdbc0, rip at 0x7fffffffdbc8

据我了解,this answereipebp 寄存器(不在我的输出中)具有以下含义:

eip 是下一条要执行的指令的寄存器(也称为程序计数器)

“ebp”是寄存器,通常被认为是这个栈帧的locals的起始地址,使用“offset”来寻址

来自this other answer,我明白了

[RIP 是] 指令指针

[...]

其中一些寄存器被设想用于特定用途,并且通常如此。最关键的是 RSP 和 RBP。

最后,info registers 给了我以下输出:

(gdb) info registers
rax            0x4005ad 4195757
rbx            0x0      0
rcx            0x0      0
rdx            0x7fffffffdcc0   140737488346304
rsi            0x7fffffffdca8   140737488346280
rdi            0x2      2
rbp            0x7fffffffdbc0   0x7fffffffdbc0
rsp            0x7fffffffdbc0   0x7fffffffdbc0
r8             0x7ffff7dd7c60   140737351875680
r9             0x7ffff7dead10   140737351953680
r10            0x7fffffffda50   140737488345680
r11            0x7ffff7a53a10   140737348188688
r12            0x4004b0 4195504
r13            0x7fffffffdca0   140737488346272
r14            0x0      0
r15            0x0      0
rip            0x4005b1 0x4005b1 <main+4>
eflags         0x246    [ PF ZF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

(注意:也尝试使用 info all-registers。输出更长,仍然没有 eip/epb ——这是我所期待的,因为根据文档,这些是向量/FPU 寄存器。)

基于这一切,我认为:

  • 在我的机器上没有 epb/eip 寄存器
  • 我的机器上总是使用 rip 而不是 eip
  • 我的机器上总是使用 rbp 而不是 ebp

问题

  1. 上述理解正确吗? (理论 B:我的机器上也有这些寄存器,但是 gcc 以这样的方式编译程序,它使用 rip 而不是 eip 和 rbp 而不是 ebp . 理论 C:由于我在函数的开头而不是在函数内部中断,因此尚未使用 eip 和 ebp;在这种情况下,rip 和 rbp 有其他用途。)
  2. (假设我的主要理论是正确的):是新机器有 eip/ebp 而不是 rbp/rip,还是新机器有两组寄存器,而旧机器只有 rbp/rip?
  3. 如果 gdb 中的info registers 没有显示寄存器,这是否意味着该寄存器在机器上不存在,或者它可能存在,但没有在被调试程序的上下文中使用? (基于GDB documentation,我猜是前者。)

背景

我正在尝试做this exercise,其要点是:

Stack4 看看覆盖已保存的 EIP 和标准缓冲区 溢出。

所以主要问题是:在这种情况下我应该选择 rip 而不是 eip? (但是,除了回答这一点,我想对背景有一个更好的了解,因此上面的问题更详细。)

【问题讨论】:

  • 尝试print $ebpprint $pc 你会得到未列出但工作的寄存器。但它不适用于eip
  • EBP 是 RBP 的下半部分。 -fomit-frame-pointer 是默认值,所以不要期望看到堆栈帧的东西。请参阅x86 tag wiki 了解 x86-64 中的一些新功能链接,以及显示什么是什么的子集的注册图表。或者build 32-bit executables,这样你就可以跟着32位教程学习了。

标签: c x86 gdb buffer-overflow


【解决方案1】:

我想,这个练习是为 i386 架构编写的,它是较旧的 32 位 x86 变体。 %ebp%eip 寄存器是这些寄存器的 32 位版本。

我想,您正在运行 x86-64,即 64 位 x86 变体。对于此版本的架构,这些寄存器扩展为 64 位,并具有新名称 %rbp%rip

在 x86-64 上编译时,通常可以为 32 位 x86 ABI 编译代码,如果您使用 gcc,则在编译时添加 -m32 标志。如果你这样做了,GDB 会显示%ebp%eip 寄存器。

一般而言,您应该将%rip 视为%eip 的64 位版本,将%rbp 视为%ebp 的64 位版本。

【讨论】:

  • 不需要想象力。在输出中看到 rip = 0x4005b1 绝对确认这是 x86-64。
  • 感谢您的回答,安德鲁。虽然没有直接说明,但我可以从你的回答中推断出我原来的问题的答案。 (1. 有点正确:虽然不存在同名的寄存器,但存在同名的 64 位版本。2. 不正确,反之亦然 :) 3. 有点正确,但有可能通过使用-m32 标志“模拟”32 位版本的寄存器)
猜你喜欢
  • 2017-03-12
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 2019-11-21
相关资源
最近更新 更多