0x00 简介
一道uaf
和double free
题目,跟以前做的套路不太一样。
0x01 题目
1.1 add函数逻辑
1 | for ( i = 0; i <= 4; ++i ) |
- 申请8个字节的空间,把地址放在ptr[i]中
- 在前4个字节放入一个输出函数
- 申请一个
size
大小的空间,把地址放在后4字节中
可以把ptr看成这样一个结构体的指针数组
后面Print
直接就用了这个结构题里的函数指针进行输出的1
2
3
4typedef struct ptr{
void *func_puts;
char *content;
}*ptr;
1.2 Delete函数逻辑
1 | printf("Index :"); |
- 判断要删除的id是否在范围内
- 然而删除后却并没有把已经删除的部分置为NULL
0x02 漏洞利用
本题的关键点是,当某一次申请的content大小也为8时,将有机会分配到之前释放过的note块。这样通过向content中写入内容相当于修改note块。由此达到目的。(反正跟我原来想的完全不同,看来以后做题还是多想题目给的本身的特点,总是用套路会束缚思维)
system函数地址泄露: print_note的打印功能可以帮助泄露地址。例如,先add note0,大小为128,再add note1,大小为128。delete note1,note0.此时再申请add note2,大小为8. 那么note2的note块就是note0块,note2的content块就是note1块(fastbin的原则是LIFO)。此时向content2中写入puts函数地址(保持不变,还是原来的)和free@got地址,这样在调用 print note2时,就会将free函数的实际地址泄露,再根据偏移泄露system函数地址。
system函数调用: 同理,这个操作与地址泄露相似,delete note2,add note3,也是要求content大小为8,这次将puts函数地址位置覆写成泄露的system函数地址和将要执行的指令。
然而改成system后,函数的参数还是自己,这样肯定不行。
1 | if ( ptr[v1] ) |
为了解决这个问题,这里涉及到Linux连续执行多条命令时的参数截断
即,如果将puts
函数地址覆盖为system
地址,system
的参数是system
函数地址本身,这样肯定不行。但是使用连续执行多条命令的’ ; ‘,第一条执行错误会被忽略,然后执行下一条,因此可以将content
位置覆盖成 ‘;sh\0’
.
0x03 EXP
1 | from pwn import * |