PWN堆house of spirit
前言
-
学习了
UAF
、double_free
、unlink
、off-by-one
,之后基本上对堆稍微有点了解。 -
个人感觉,堆漏洞的成因就是
UAF
和堆溢出
,而栈的漏洞的成因基本上就是栈溢出
,其他的就是格式化字符串漏洞
,漏洞的成因感觉就是这几种。但是利用方式很多,所以学来学去都是在学被人挖掘出来的利用方法。在学这些利用方法的时候会不由感慨,那些开创漏洞利用的人脑洞真大。所以怎么感觉pwn到最后变misc
那些脑洞题了… -
初步了解了一些漏洞成因和漏洞利用后,就可以开始学习
house of
系列的利用方法了。目前打算主线直接学习house of
系列,按照Glibc堆利用之house of系列总结 - roderick - record and learn!这篇文章的顺序学习,学到哪些利用,之前没涉及到的再分出支线去学习。 -
堆的漏洞利用可以进行以下三种分类:这些分类相互有交集,并不互相独立,目前我做的是使用
house of
系列进行堆利用的分类,等house of
系列学习完之后,有时间再进行其他的分类glibc
版本对应的漏洞利用,具体可以看how2heap
这个github仓库shellphish/how2heap: A repository for learning various heap exploitation techniques.house of
分类的漏洞利用bins_attack
以及其他的attack
介绍
-
house of
系列就是堆利用和IO利用的一个称呼,和xxx的家
根本连边都沾不上。 -
house of sprirt
的利用范围是glibc2.23---至今
-
漏洞成因是堆溢出,所以漏洞的利用技巧可能会用上
off-by
的技巧或者unlink_attack
的技巧和UAF
的漏洞 -
针对的是
fast_bin attack
和tcache_bin_attack
-
主要就是想尽办法伪造
fake_chunk
然后通过一些堆风水(堆排布),利用fast_bin
或者利用tcache_bin
机制将堆申请到fake_chunk
上,之后再进行一系列的操作
示例
- 这里的实验就不怎么详细讲了,自行体会,细讲的地方都会放在支线中仔细讲解。这里的实验内容主要以堆的检查机制为主,加深堆排布的感觉
实验1
- 在ubuntu16.04的Docker环境下使用
gcc
编译如下程序,从该示例上看house of sprirt
有点像double free
的利用,但是house of sprirt
可以在没有UAF
漏洞的情况下进行利用,因为是对已分配的堆块进行内容上的修改,而不是对已释放的堆块进行内容上的修改
1 |
|
题目
house_of_sprirt_level1
- 本题来自:2014_hack.lu_oreo,本题的libc是
Ubuntu GLIBC 2.23-0ubuntu10
,由于不想找该文件,就直接用Docker中的glibc文件,堆管理器应该没太大改动(都是glibc2.23版本的)。 - 使用Docker命令将文件复制到Docker容器里面
docker cp ./oreo 2aeebfd7bb0f:/home/ctf/house-of/house-of-sprirt
- 题目附件:https://wwsq.lanzoue.com/iUdaf2d8rych 密码:9951
分析1
- 先查看一下文件,发现是32位的程序
- 使用IDA将这个32位的程序进行逆向操作,main函数就一个开始,main函数没啥好看的
- 然后进入
run()
函数,该函数名称是我逆向该程序时重新命名过的,发现是一个堆菜单题目,并且每个函数的功能我都重命名过了
- 在看函数之前,先进行逆向了解程序中出现的结构体。这样更有助于我们读懂程序
- 首先查看到
dword_804A288
这个位置,该变量是一个字符串指针的全局变量,所以给它重命名位char_ptr
-
再看到这里
dword_804A2A4
,通过解读程序可以得知这个应该是32位的整型或者无符号整型,作用是统计add的次数重命名为int32_v1
-
再看到这边
dword_804A2A0
,通过程序解读,可以知道该变量也是一个32位的整型或者无符号整型,作用是统计delete的次数,重命名为int32_v2
-
再看到
dword_804A2A8
,发现该变量也是一个字符串指针,用于指向unk_804A2C0
,所以将dword_804A2A8
命名为edit_ptr
,将unk_804A2C0
命名为edit_context
-
修改完之后来分各个函数的作用
add
函数- 申请固定大小的
0x38
(10进制为56)大小的堆块,实际的堆块size位应该为0x41
- 然后在堆块内部程序会将其分为三部分,一部分是
description
(char_ptr开始),一部分是char_ptr
(存放前一个堆块的指针,从char_ptr+13
开始,占4字节),还有一部分是name
(char_ptr+25开始) - 这里可以注意到在对name输入的时候存在溢出
- 申请固定大小的
- 所以该堆块的用户使用的区域结构如下如下
- 接下来查看
show
函数,就是将已申请的堆块从后往前打印出来
delete
函数,按照后申请的堆块先释放的原则将已经申请的堆块全部释放,并且将char_ptr
设置为0,增加一次free
操作的次数
edit
函数,edit
函数并不是修改已申请的堆块,而是修改一个全局变量(应该是一个字符数组),用一个字符串指针指向全局变量字符数组
stats
函数,展现edit_ptr
指向地址的内容和展现申请堆块的次数和释放堆块的次数
利用1
- 我们在
add
函数中会发现溢出点,
house_of_sprirt_level2
- 在ubuntu16.04的环境下编译该程序
1 | #include<stdio.h> |