0x00 散序
早上刚起来就在朋友圈遭受到子怡姐姐的一波暴击,之后再次被这道题蹂躏了一波,果然单身狗没人权啊。。。。。
0x01 歌
Ⅰ 检查保护
喜闻乐见保护全开。。。。
Ⅱ 静态分析
主函数看了一下,很明显是一个堆题的结构。
这题的漏洞主要有两个。
其一是在两个edit函数里,都存在着因没对输入的数组下标做检查而导致的数组越界。
看一下全局变量的上下内容,很明显可以发现当你越下界时你可以利用read函数去修改one数组也就是luckydog的指针实现任意地址写,越上界时又可以通过printf函数去泄露ELF基址。
至此利用思路大致成形。
Ⅲ 漏洞利用
既然保护全开又没给libc,第一件事当然是泄露ELF基址以此确定libc版本号。只要我们给数组的index为-4便可以很容易越界到stderr@@GLIBC_2_2_5
上去。至于stderr@@GLIBC_2_2_5便是一个IO FILE的结构体,大体结构便是如下图这样。
看到这样岂不是美滋滋,printf函数leak之后截取一下,_IO_2_1_stderr_+131
的地址不就泄露出来了吗,之后减个131不就是得到_IO_2_1_stderr
的地址了吗,到https://libc.blukat.me 查一下版本号就好。
至于getshell我们只要先执行luckydog函数
在数组one里便会存入一个0x20大小的内存块,而这个内存块的前8字节则放着另一个内存块的地址。而我们只要利用函数edit_singledog的越界修改便可以修改内存块里存着的那个内存块的地址。如果我们将其改为malloc_hook的地址,之后再利用函数edit_luckydog便可以修改malloc_hook所存的内容。
我们可以利用此将__malloc_hook的内容改为one_gadget,这样我们只需再调用一次malloc函数便可以成功getshell。当然前面我们在查libc版本时,是会给出三个可能的libc版本(64位),这里就需要你一个一个去试咯,像我这种非洲人试到最后一个才成功233333,远程的libc版本为2.27.
Ⅳ poc
1 | from pwn import* |
0x02 破
之前我是说过的,这题的漏洞主要有两个,但刚刚在上面我自始至终都只用了一个数组越界,其实还有一个漏洞就是在函数save_singledog中的越界copy。
很明显当single_num满时,当数组向前copy时会将one[1]赋值给two[79]。但这题其实只靠着数组越界便可以做出来了。
后来题目作者也说了,那个数组越界漏洞是个意外,他出题时没注意。。。。。。他的本意是想通过越界copy使两对象类型发生混淆,实现任意地址读写。