pwnable靶场ak-WP (5)passcode 篡改GOT

发布于 2021-09-01  62 次阅读


写在前面

这个的预期解实在是太骚了(对于目前的菜鸡的我而言),朝着三种比较常规的简单思路去做,发现都无法利用,最后看完预期解WP人都傻了,但是拓宽了很大的思路,记录如下

错误解

拿到题目第一反应一般都是welcom和login函数处于相同ebp上面,而且name变量有一个大得可疑的缓冲区,于是想要去溢出

但是计算过后会发现虽然缓冲区很大,但是正好差4,无法溢出

然后会去在scanf下手,但是仔细看会发现(可能不太好看出来;IDA标红了,提示未初始化的局部变量)这里的scanf其实是错误用法,我们实际上不能向这两个int变量输入目标值

然后笔者就没辙了2333

预期解

记录一下别的师傅的预期解

r00tk1t师傅的笔记非常让人拓宽眼界

另外非常感谢LIGHTFOOT姐姐的笔记,可谓是循循善诱

首先,身为二进制安全选手,要转变对scanf这类函数的看法,因为这种函数能做到一个非常重要而敏感的作用:写入

而且不一定只是写入大量数据从而溢出这么简单(事实上scanf也不能溢出,gets才可以)

在本题中,仅仅用一个scanf函数,便控制了两个写入操作,最终使得system函数执行

理论操作如下

首先我们要观察出,这里的scanf被程序员(程序开发者)误用了,他传过去的实际上是int,但是会被解读为指向目标IO区域的指针

这点非常重要

如果是一个正常使用的scanf,我们就不能进行GOT覆盖操作了,因为向scanf传递的地址是addr(伪)指令动态获取的,存放这个int变量的地址早就定好了,根本不存在覆写,即使覆写也只是覆写了这个地址处的变量,而这个地址是定死的,指向特定局部变量

换句话来说,这种误用本质上产生了一个非常高危的敏感行为——将一个可以作为全局地址的指针暴露在可被覆写的局部变量栈上

这在实际生产中基本等同于任意代码执行漏洞,具体到本题中,我们也确实拉起了system进程

那么接下来怎么办?

首先找system函数的地址,然后找到前面一句传参的地址,记下后者的地址

我们在找到fflush的地址——这个函数可以理解为出题人特意为我们留下的90 90空闲区

我们现在要做的是:

首先,在welcome中,用name覆盖掉passwd1的内容,这个内容覆盖为fflush的GOT地址,由于ebp相同且局部变量堆栈不清空,这种覆盖很好实现

第二部,scanf做出敏感操作:向fflush写入内容,具体写入的内容是system函数前面的传参指令的地址

这样,我们就会向 fflush 处写入 system 地址——scanf不一定只操作一个地址

小细节

我们向程序输入的任何内容都是默认视作字符的,至于数字或者0x,\x这类东西,能够被解释为特殊意义,完全是程序内部操作

如果仅仅是程序获取输入内容的话,它获取到的仅仅是字符而已

我们在pwntool写的时候可以用0x十六进制,但是像这种,中间还需要操作一下scanf的,而且scanf的format还是%d

这时就需要输入十进制了

134514147

解题脚本

from pwn import *

#conn=remote("128.61.240.205",9000)
conn=ssh('passcode',"128.61.240.205",2222,"guest")
# conn=ssh('root',"192.168.84.129",22,"1")
p=conn.process("./passcode")
p.sendline('AAAA'*24+p32(0x0804A004))
p.sendline('134514147')
print(p.recvall())