Pwmable.tw Re-alloc
利用思路挺新奇的,学到了学到了🤙
典型菜单题,但libc版本为2.29,意味着tecache里面0x8的位置会放入key指向tecache_struct,若要想double free,只能改掉key值。
add函数:
1 | printf("Index:"); |
只允许申请两个函数,off_by_one感觉用不了了。
dele函数:
1 | printf("Index:"); |
也没有野指针?
edit函数:
1 | printf("Index:"); |
这一遍看下来发现都是利用realloc函数来完成各种操作,这里对realloc进行一个说明:
realloc第一个参数为一个指针ptr,第二个参数为size。
当ptr=NULL时相当于malloc(size)
当ptr不为null,且size不为0时,先malloc(size),再把ptr里的内容拷贝到新内存里(size大于old_size,扩容;size小于old_szie,切割)。
当ptr不为null,size=0时,相当于free(ptr)。
因此可以想到edit函数里的realloc函数的size是由我们的输入决定的,如果size为0,则free(ptr),形成UAF🎈
但还有一个问题在于没有show函数,而且只有2个能用的堆块是无法实现对stdout的劫持的。。
这道题提供了一个新的思路:改写atoll_got为printf_plt,构造fmt泄露。
由于atoll参数为&buf,改为printf的话自然形成fmt,很妙。
那接下来就是漏洞利用了,先uaf改fd为atoll_got,之后add,这样chunk0=chunk1(0x20),且tecache的0x20上残留了一个atoi_got的地址。然后edit chunk0为较大的size,并dele(0),同时edit chunk1和chunk0相等的size,同时覆盖key(不然dele(1)时会报错),之后dele(1),这样一个流程下来就使得即在0x20的tecache bin上留下地址,又清空了两个堆。
重复上面的流程使得在tecache的多个size链上留下atoll_got,方便后面的利用。
之后就是修改atoll_got为printf_plt(最好不要用0x20的那个atoll_got),从而leak。
leak完后由于atoll被改成了printf,使得我们在add时的输入要有所变化,利用printf的返回值为输出的字符串长度,我们通过add(‘a’+’\0’,’a’*0x10+’\0’)来申请出0x20大小的tecache bin,改atoll_got为system拿到shell🚩
EXP:
1 | from pwn import * |