介绍
国赛2019的一道题,虚拟了stack和buffer,所以利用方式比较神奇。
分析程序
程序模拟了三个部分text代码段,stack栈,buffer缓冲区。
其中text和stack是用户自定义的。
代码有以下几种:
push
将stack上值取出放入buffer中pop
将buffer上值取出放入stack中add/sub/mul/div
从buffer取出两个值,相加/减/乘/除后放回buffer中load
从buffer中读入一个值作为index,将buffer中这个index所对应位置的值写入buffer中save
从buffer中读入一个值作为index,再从buffer中读一个值,写入buffer中这个index所对应的位置
利用方式
很明显的看出load和save的时候,没有对index做检查,所以可以造成buffer周围的任意读写,我们分一下几步来完成攻击。
- 修改模拟stack的位置到got表上。
- push,将got上
puts
函数的地址的值放入buffer中 - sub,将
puts
函数的地址改为system
函数的地址 - pop,将
system
函数的地址写回got表上puts
的位置 - program name设为’/bin/sh’,输出程序名的时候即可getshell
稍微解释一下exp中的攻击指令和stack上的值。push
将stack上第一个值(puts和system的偏移)放入buffer中push
将stack上第二个值(got表中puts函数的位置)放入buffer中push
将stack上第三个值(buffer相对于模拟的stack的地址的偏移,因为堆上面是保存了模拟的stack的地址的)放入buffer中save
将相对于模拟stack的偏移读出,再将got表位置读出,然后将模拟的stack的地址改为got表,现在模拟的stack就被改到got表上了push
将模拟栈上的值写入buffer中,因为栈现在在got表上,所以会将puts的地址写到buffer上sub
将puts和system的偏移读出,将puts的地址读出,做减法,再写回buffer上,此时buffer上就只有一个system的地址pop
读出buffer上system的地址,写会模拟stack上,因为模拟stack现在在got表上,所以将puts的地址改为了system的地址
模拟stack上第四个值为9999是因为push是会检查栈是否为空。检查方式为读入模拟stack中数据时会有一个变量记录一共读入了多少个数据,每次push都会减1,所以我们只要多读入几个数据即可让这个变量不减为0。
脚本
1 | #!/usr/bin/env python2 |