ARM64架构Buffer Overflow场景无法覆盖$pc寄存器问题求助
问题解答
调试思路正确性判断
你的核心思路是正确的:ARM64架构下ret指令会直接将x30(链接寄存器LR)的值加载到PC寄存器,只要覆盖栈上存储的x30值为win函数的地址0x4005e4,就能控制程序执行流跳转到win函数。
当前问题排查
你现在没有成功覆盖的原因主要有两个:
断点位置错误
你将断点设置在了main+32(ret指令)位置,此时前序指令ldp x29, x30, [sp], #96已经执行完成,栈上存储的旧x29、x30值已经被加载到寄存器中,你看到的寄存器值是加载后的结果,无法反映栈上的真实存储内容。
你需要将断点调整到main+28(也就是ldp指令执行前),此时查看sp+8地址处的内存,就能判断输入内容是否覆盖了x30的存储位置。偏移计算错误
从给出的汇编代码可以推导栈布局:
- main函数开头通过
stp x29, x30, [sp, #-96]!申请了96字节栈空间,旧x29存储在sp+0位置,旧x30存储在sp+8位置 - buffer的起始地址为
sp+0x20(对应汇编指令add x0, sp, #0x20)
你可以通过以下两种方式快速得到准确的覆盖偏移:
- 梯度测试:依次输入72、80、88、96字节的
a,每次断点在main+28位置查看sp+8处的内存是否为全0x61,找到刚好覆盖的临界长度 - 模式串测试:使用pwntools的循环模式串快速计算偏移,示例代码如下:
from pwn import * # 生成150字节唯一模式串 pattern = cyclic(150) # 计算偏移方法:断点在ldp前查看sp+8的值,用cyclic -l [值] 得到偏移量
最终利用方法
拿到准确偏移offset后,构造payload发送即可:
payload = b'a' * offset + p64(0x4005e4)
发送payload后程序执行ret时,就会将覆盖后的x30值加载到PC,跳转到win函数执行。
内容的提问来源于stack exchange,提问作者Augustus923
相关产品推荐
相关产品推荐

