b00ks

这道题是我在接触堆以后学习的第一道题,先大概看了一遍wiki里面堆和ptmalloc的前置知识,其实吸收得不是很好,做题的时候遇到了很多基础性的问题,所以看题解和自己调试花了非常多时间,我会把一些我解决的非常基础的问题也记录下来。


这题做到一半发现偏移地址不太对,才知道堆题大多数都需要更换程序链接的libc,因为不太了解libc链接机制,顺便又把《程序员的自我修养》后面几章给看完了。这题在wiki上没有提供libc版本,又因为我对patchelf原理不太熟悉,导致我在这里卡了很久,后面是到buuctf上打,有提供libc版本。

在我的另一篇博客记录了更换libc的过程


首先是应该看ida,都知道漏洞是出在自定义read函数上,它这里多输入了一个数,且自增后将指针指向的值修改为0,这就是溢出了单字节。

然后是create book的数据结构,是在这一段

1
2
3
4
5
6
7
8
9
10
11
v3 = malloc(0x20uLL);
if ( v3 )
{
*((_DWORD *)v3 + 6) = v1; //==*((_QWORD *)v3 + 3) = v1;
//des_size
*((_QWORD *)off_202010 + v2) = v3; //把book指针放到author_name后或前一个book后
*((_QWORD *)v3 + 2) = v5; //des_ptr
*((_QWORD *)v3 + 1) = ptr; //name_ptr
*(_DWORD *)v3 = ++unk_202024; //id
return 0LL;
}

那么我们用gdb一步一步调试分析利用

1、由于第一步操作是输入author_name,所以这里溢出的单字节会被后面放入的指针覆盖,所以随便写点就可以,这里写入‘A’*32。

2、create两个book,并且第二个book分配较大内存以便后续利用(如0x21000),查看内存分析结构,这里开启了PIE,所以关闭一下ASLR,这样会同时使PIE无法启用,调试更方便。

用search找到author name的位置

查看author name地址中的内容

这里的book由于是不确定的空间大小,根据c语言的结构体,这里会分配一个指向book内存的指针放在这个结构内,也是上面*((_QWORD *)off_202010 + v2) = v3;的结果,因此这里是指向book1内存的指针,然后进入这个指针观察。

那么回到author name的内存,因为后面紧跟着book1 ptr,因此溢出的单字节可以对book1 ptr进行修改,由于小端序,会将最后两位修改为00,这时候我们修改一下author_name,就可以覆盖book1的最后一位,修改后的地址刚好在book1_des的内容里面,就可以在book1_des里伪造一个fake_chunk,由于ASLR,每次运行程序的地址都不一样,我们在fake_chunk里放入当下book2的内容地址并且泄露出来,就可以计算出根据libc和mmap分配内存的固定偏移,这样在重新运行的时候就能根据固定偏移算出libcbase,从而修改free_hook为system函数。

注意这里我写入了payload=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)以后发现它有些移位,这是book1大小不同导致的,所以前面要填充一部分deadbeef使fake_chunk刚好在这个指针指向的内存上,而这也是book1不能设置太大的原因,否则单字节覆盖后的指针不一定会指向book1_des内的空间。

这里看到libc_base是0x7fddf35b2000,而输出book1_name得到的内容是book2_name_ptr,输出book1_des得到的内容是book2_des_ptr,这里的book2_des_ptr为0x00007fddf356e010

到这里遇到了一点问题不能继续,我会在查阅资料后完善这篇文章。


b00ks
http://example.com/2021/08/31/b00ks/
作者
Magnesium
发布于
2021年8月31日
许可协议