题目介绍
题目是一个表单程序,功能是一个图书管理系统。
1 | 1. Create a book |
程序提供了创建、删除、编辑、打印、修改author name的功能,除了 canary 外,其他保护全开
1 | Arch: amd64-64-little |
首先程序会要求输入author name,存到bss 段 unk_202040
中,限制大小为32,用自己构造的函数读取,接下来看create函数的功能:输入book name’s size 然后 malloc(size)
,读入name,限制长度是32,接着输入description’s size 也同样malloc(size)
,读入description,不限制长度。接下来为book结构体申请一个0x20的空间
1 | book = malloc(0x20uLL); |
book结构体的指针会存到unk_202060处,也就是authon name 紧跟着的后面
漏洞
程序的主要漏洞就存在其自己构造的read函数中,因为对边界处理不当,导致写入时存在1个字节的溢出,即off-by-one
1 | signed __int64 __fastcall my_read(_BYTE *a1, int a2) |
事实上,当写入author name最长长度32时,my_read 读入的结束符'\x00'
是写到0x56260bc1b060
上的,即unk_202040 + unk_202060
也就是book_addr ,那么,当写入book1时,’\x00’就会被覆盖为book1的地址,通过打印author name就可以获得一个堆地址book1_addr。
1 | pwndbg> x/10gx 0x56260bc1b040 |
off-by-one 覆盖指针低字节
程序提供了一个change 功能,用于修改author name,所以可以通过修改author name 将book1的低字节覆盖为’\x00’,覆盖之后这个指针会指向book1 的 description ,程序同样也提供了edit功能修改description中的内容,所以我们可以在description 中布置数据伪造一个book结构,这个book结构 中的name 和 description 指针均可以直接抑制。
再次调用printf()函数打印将可直接得到book2_name_addr (这里需要注意的是,对于book2需要申请一个非常大的空间,才能使用堆块mmap分配,才能够泄漏libc base addr
)在gdb中下断,用得到的book2_name_addr - libcbase 即可得到到libcbase 的偏移,这个偏移是不变的,而且每个人的环境不同偏移也可能不一样,这样就拿到了libcbase了。
因为程序开户了RELOR,got表不可改,但是可以改写__free_hook
或__malloc_hook
结合前面泄漏的libcbase可以得到onegadget 地址,最后通过修改book1跟book2的description实现任意地址写,将__free_hook
内容写入为onegadget,free即可调用onegadget(free时,如果 __free_hook
不为空,即执行free_hook
)
exp:
1 | #coding:utf-8 |