csapp attack lab phase4

csapp attack lab phase4

每个gadget由一系列指令字节组成,最后一个字节为0xc3,编码为ret指令。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
举个例子:
48 89 c7 是指令 movq %rax, %rdi, 对应的地址是0x400f15 + 0x3 也就是0x400f18, 是开始的指令位置。

例如:
ret编码为0xc3,nop编码为0x90。
在这里插入图片描述
在这里插入图片描述
0x4019a7 + 0x4 得到地址0x4019ab

在这里插入图片描述
48 89 c7 对应的汇编指令是 mov %rax, %rdi
在这里插入图片描述
0x4019c3 + 0x2 得到地址 0x4019c5

在这里插入图片描述
rsp 存储 0x59b997fa 是cookie 的值。
在这里插入图片描述
rip存储的值是retq时候,rsp存储mov %rax, %rdi 对应的地址.

在这里插入图片描述

汇编

ret指令

当执行汇编指令ret时,计算机会进行以下操作:

  1. 将栈顶的值弹出,并将其赋值给指令指针寄存器rip,这样程序控制流会返回到调用函数的地方。
  2. 将栈顶指针rsp增加一个合适的值,以便指向上一个函数的栈帧。这样可以清除当前函数的栈帧,为返回到上一个函数做准备。

总的来说,ret指令会对rsp和rip寄存器进行操作,以实现函数返回的功能。

在执行ret指令时,栈顶指针rsp的增加值是由调用约定(calling convention)和编译器生成的代码决定的。在一般情况下,当函数调用结束时,栈需要被恢复到调用函数之前的状态,这就需要栈指针rsp回到上一个函数的栈帧。

当使用ret指令从函数返回时,它会弹出栈顶的地址并将程序计数器设置为这个地址,以便继续执行代码。一旦ret指令执行完成,弹出的地址就不再处于栈顶位置,而是成为了程序计数器所指向的位置,因此在普通情况下无法直接通过栈来访问这个地址。

如果在函数中保存了返回地址的拷贝,或者在调用ret之前将返回地址拷贝到其他位置,那么在函数返回后仍然可以通过这些拷贝来访问返回地址。但是直接通过栈来访问ret弹出的地址是不可能的。

stack frame

在x86-64架构中,一般的调用约定是将栈帧中的参数和局部变量保存在栈上,然后通过rsp指针来访问这些参数和局部变量。当函数调用结束时,栈指针rsp需要回到上一个函数的栈帧,这个值是根据当前函数的栈帧大小来计算的。

编译器会在编译时根据函数的参数、局部变量和其他需要保存在栈上的信息来计算栈帧的大小,然后在ret指令中使用适当的偏移值来恢复栈指针rsp。这个偏移值会确保rsp指向上一个函数的栈帧,从而实现函数返回的功能。

在大多数操作系统和体系结构中,栈帧的大小都是有限制的。这个限制通常由硬件和操作系统的设计决定。

在x86-64架构中,栈帧的大小受到寄存器的位数限制。例如,在64位操作系统中,通常会有一个默认的栈大小限制,例如1MB或者8MB。这个限制可以在操作系统内核中进行配置和调整。

此外,栈的大小还受到操作系统的限制,操作系统会为每个进程分配一定大小的栈空间。如果栈帧的大小超出了这个限制,就会发生栈溢出错误。

在编写程序时,需要注意栈帧的大小限制,避免过多的局部变量或者递归调用导致栈溢出。如果需要更大的栈空间,可以通过操作系统提供的机制来调整栈大小限制。

指令

将汇编转为二进制

gcc -c phase4.s 
objdump -d phase4.o > phase4.d

phase4.s
在这里插入图片描述
phase4.d
在这里插入图片描述

以十六进制的方式打印寄存器

x/x $rsp 是 GDB 中的命令,用于查看内存中地址为 $rsp 的内容。这个命令的含义是以十六进制格式显示 $rsp 地址处的内容。$rsp 是 x86 架构中的寄存器,用于存储栈顶的地址。

link

https://zhuanlan.zhihu.com/p/60724948
https://zhuanlan.zhihu.com/p/107048472

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值