VMPWN的入门级别题目详解(二)

栏目:未来教育  时间:2023-07-31
手机版

  

  这道题应该算是虚拟机保护的一个变种,是一个解释器类型的程序,何为解释器?解释器是一种计算机程序,用于解释和执行源代码。解释器可以理解源代码中的语法和语义,并将其转换为计算机可以执行的机器语言。与编译器不同,解释器不会将源代码转换为机器语言,而是直接执行源代码。即,这个程序接收一定的解释器语言,然后按照一定的规则对其进行解析,完成相应的功能,从本质上来看依然是一个虚拟机。

  这个程序是一个brainfuck的解释器,brainfuck的语法如下所示:

  

  将这些语法翻译为c代码如下所示:

  

  使用checksec来检查程序开启了哪些保护机制

  

  所有保护全部开启 使用seccomp-tools检查程序是否开启了沙箱

  

  只允许open、openat、read、write、brk等少数系统调用,也就是说我们不能通过执行system(“/bin/sh”)或者execve系统调用来拿到shell了。

  使用IDA pro打开这个程序 查看伪代码

  

  看到std::cout以及std::string等函数,可以看出来这个程序是用c++进行编写的,相比于C语言的程序,C++的程序反编译之后分析起来难度会大一些。

  【----帮助网安学习,需要网安学习资料关注我,私信回复“资料”免费获取----】

  ① 网安学习成长路径思维导图

  ② 60+网安经典常用工具包

  ③ 100+SRC漏洞分析报告

  ④ 150+网安攻防实战技术电子书

  ⑤ 最权威CISSP 认证考试指南+题库

  ⑥ 超1800页CTF实战技巧手册

  ⑦ 最新网安大厂面试题合集(含答案)

  ⑧ APP客户端安全检测指南(安卓+IOS)

  分析一波函数L8arzn.png在a1+0x400处创建一个string类,后面的,很复杂,看不明白,应该是初始化的函数。

  然后在 sub_154B 函数中

  

  这里就是沙箱开启函数,我们一开始用 seccomp-tools 分析程序得到的沙箱规则就是在这个函数中设置的,对程序的系统调用功能进行了种种限制。

  接着输入 code,每次输入 1 字节,然后将这 1 字节拼接到 string 中, 在这里我们可以动态调试一下输入过程,因为 string 是一个类,其内部有其他成员。我们将断点下载 while 循环结束之后,即读取完了 code,我们首先输入 5 个'>',string 类在 rbp-0x40,我们查看其中内容:

  前8个字节是一个指针,指向我们输入的code存放的地址,第2个8字节是输入的字节数,后面的就是我们输入的code,这里我们只输入了5个字节,直接在存在了栈中。我们多输入一些,大于0x10个字符L8ByhF.pngL8DX24.png前8个字节变为了堆地址,我们输入的数据被存入了堆中,第2个8字节依然书我们输入的字节数,第3个8字节0x1e,应该是剩余可用空间,0x13+0x1e=0x31。 总的来说,如果输入字符数小于0x10,string类的大概成员应该如下

  如果大于0x10则为如下

  继续分析程序

  

  中间这一段 for 循环应该是遍历所有输入的 code,寻找[和],也就是寻找程序的边界,为什么是寻找程序的边界,可以再看一下 brainfuck 解释为 c 语言之后的效果。 []所包裹起来的 code,就是 while 循环之内要执行的代码。 从这个 for 循环往下,就是对 brainfuck 的解释代码,会依次判断每个字符的值,并进行相应的操作。

  首先看到对的操作L8yoqA.png会对v19进行+1操作,v19是啥呢?L863RO.pngs是最开始初始化的时候传入的一个长度为0x400的数组,这里将v19赋值为s数组的地址,每当解析到>时,就将v19往后移动一个字节,然后对v19进行判断L8cwnJ.png在if判断中存在问题,当v19指针大于string指针是退出,也就是说v19可以等于string指针,即v19可以指向string的第一个字节,存在off-by-one。如下图L82liq.pngv19可以指向画框的1字节。

  后续的其他操作就都和最开始贴出来的brainfuck语法一样了,也没有漏洞。

  接下来开始利用漏洞。

  第一步还是得先泄露libc地址。 泄露方法是通过将v19指向string的第一字节,也就是buf指针的最后1字节。L8RXuD.png在处就是main函数的返回地址,我们将buf指针的最后1字节修改为68,这样buf就会指向返回地址。 在程序的最后,会将string的数据输出L8WEDg.png而此时string的buf已经被我们指向了返回地址,输出时就会泄露出libc_start_main的地址。 在这里我们需要注意,想要buf指针能够指向栈中,我们输入的数据不能超过0x10个字节,而v19和string相差多少呢?L8fARx.pngv19是指向s的,s和string相差了0x400的距离,所以我们需要将v19增加0x400才行,但如果我们输入0x400个>,又会调用malloc,这样buf就会变成堆地址。所以这里就得了解brainfuck语法,使用[]可以达成类似于循环的效果。只需要这5个字符就可以一直循环增加v19指针,并在v19指向string的第1字节时自动停止,然后往string的第1字节写入1字节的数据,换成c的语法如下

  这看起来是一个死循环,为啥能够自动在指向string的第1个字节时自动停止呢?这是因为,当执行完>使得v19指向string后,接下来会执行+使得string的buf指针+1,变成了下图所示:LGnwfU.png于是,原本要取,因为指针+1,就会取到,从而跳出循环。 还有一点就是,因为aslr的缘故,栈地址会一直改变,所以泄露libc地址需要多试几次才能成功。 拿到libc地址之后,就可以进行利用了,由于此时string的buf指针指向的是返回地址,我们再次输入code的时候就会往返回地址上写,所以我们可以构造好orw的rop链,直接写入返回地址,然后当我们结束main函数的时候就会执行orw链。 另外,还有需要注意的地方,在程序开头和结尾,有这么几个函数 开头LBncjI.png结尾LBnoCQ.png开头的应该是构造函数,结尾的应该是析构函数。 在漏洞利用中我们将string的buf指向了返回地址,如果我们在这个时候退出了while循环,执行析构函数时就会报错,所以我们在布置完orw链后还需要对string的buf进行修正,让它指向正确的位置。

  举报/反馈

上一篇:教育部等:全面规范艺考培训行为,机构开展艺考培训须取得艺术类校外培训资质
下一篇:8月考研复习全科规划!弯道超车的时候到了!

最近更新未来教育