zoo
前言
刷到最后还是没能做出最后一题,第一次做C++的题,感觉自己太菜了,代码都读不懂,继续努力吧X
程序逻辑
IDA的逆向代码就不贴了,直接看下源代码,父类是Animal,其成员变量为name[24]和weight,此外还有两个虚函数,speak()和info()。Dog和Cat继承了Animal,各自实现了自己的speak和info
1 | char nameofzoo[100]; |
adddog()函数首先分配一个Dog(),之后读取Name,但是没有限制长度,导致构造函数里的strcpy溢出name,Cat同理,他们的地址存放在animallist里
1 | void adddog(){ |
remove()函数delete相应对象并把list清空
1 | void remove(){ |
showinfo()函数调用对象里的虚函数info()
1 | void showinfo(){ |
listn()函数调用对象里的虚函数speak()
1 | void listen(){ |
main函数先让用户输入数据到bss段上,之后选择功能执行
1 | int main(void){ |
漏洞分析
按照刚才函数的分析,adddog和addcat里存在堆溢出,c++的虚函数调用机制是每一个new的类里的fd都执行vtable,而vatable[i]是将要调用函数的函数地址,以speak为例,这里的vtable为0x403140,其内容为speak和info的实际地址。
我们可以先new2个chunk,利用堆溢出覆盖第二个chunk的fd为nameofzoo+len(shellcode)的地址,nameofzoo的数据为shellcode+nameofzoo_addr.当我们调用listen(0)的时候,实际上调用的是chunk2->nameofzoo_addr+len(shellcode)(因为push的缘故),在这里函数又找到了nameofzoo_addr作为自己的函数实际执行地址,执行speak实际执行了shellocde,这个过程可以借用一张图来说明
exp.py
1 | #coding=utf-8 |