pwnable.kr uaf writeup

来源:互联网 发布:阿里云服务器硬盘扩容 编辑:程序博客网 时间:2024/05/23 18:33

核心考察点

  1. c++类的内存布局 点击详情

    c++类实例的内存块首地址存放vfptr(虚表指针)

  2. uaf漏洞

    在内存释放后,不会被“真正”释放。当申请相似大小空间内存时,刚”释放”的内存被优先分配。(遵循FIFO的原则)

    当再次通过指针访问”释放”内存时,将发生不可预知的情况。(取决于类实例内存数据如何被改动)

解题过程

1. IDA确定对象生成代码
复制源码,本地g++编译后IDA打开:
反编译代码:
这里写图片描述
通过反编译代码找到相应汇编代码:
这里写图片描述
rbp+var_60 即为Man对象实例的指针。

2.gdb确定虚表函数地址
这里写图片描述
rbx中存放的是Man对象实例的指针(即实例内存块的首地址),也是虚表指针。虚表指针指向虚函数表,虚函数表首项是give_shell函数地址。
查看虚函数表项:
这里写图片描述
虚函数表首项为give_shell的地址,第二项即为introduce的地址。
3.控制程序执行流
现在我们可以在释放两个Human对象实例后,利用新new的字符串占据”释放”的内存,改写虚表指针,使虚函数再次调用时程序控制流发生改变(此处我们的目标是执行give_shell函数)。
由第2步我们知道了虚表指针,以及虚函数项信息。当前代码流程执行introduce函数时,调用call [vfptr+8],而give_shell函数在[vfptr]处,我们可以将虚表指针vfptr前移8,此时[vfptr+8]处为give_shell的地址。
这里写图片描述
poc为当前虚表指针-8。
新分配字符串长度为0x30。(与类实例内存大小一致)
free之后要”after”分配两个字符串,第一个字符串覆写Woman实例内存,第二个字符串覆写Man实例内存(FIFO原则)。
注:此为本地测试过程,地址和类实例大小与远程实际利用时有所差别。