type
status
date
slug
summary
tags
category
icon
password
这里写文章的前言:
一个简单的开头,简述这篇文章讨论的问题、目标、人物、背景是什么?并简述你给出的答案。
可以说说你的故事:阻碍、努力、结果成果,意外与转折。
house of系列
之前在堆的基础解法那里简单说了一下有关于堆的利用,从这里开始新起一章,这章主要讲一讲有关于house of的各各系列的手法与对应的libc版本。
关于这里的手法的具体例子可以再这里查看,下面我就开启有关我对这里面的各中手法的理解与在做题时遇到的问题做一个具体的说明。
House Of Einherjar
这种利用方法与之前的方法有所不同的在于,其用到了一个之前没有过多使用,并且尽可能规避的有个chunk,
这个chunk就是我们之前有所提到的,在所有我们自行申请堆的chunk只外的有程序在malloc我们申请的一个chunk时会与这个chunk一起从程序中为我们产生的top chunk。不过在正常情况下产生的这个top chunk,并不能直接供我们使用,只是作为一个chunk的后备资源,在后面如果我们有再次malloc的时候程序可以直接从top chunk中取出对应的chunk大小,从而使我们能快速申请到对应的chunk,不必在从程序中拿取chunk。
正常情况下程序中的top chunk都有在malloc函数执行后就固定产生的大小,这个大小是固定的,如果程序申请的新的chunk的大小小于这个top chunk的大小,程序便会直接先从top chunk中分配出来使用,如果大于这个top chunk的大小则会从新向程序申请。
这里便是我们这种手法的关键所在,关于我们能从top chunk中申请到多大的chunk这个是由top chunk的size决定的, 那这样如果我们能在top chunk的前一个chunk中存在堆溢出,那我们就可以修改top chunk中的size的大小,然后再在程序的其他地方比如栈或bss数据段等地址伪造一个fake_chunk ,然后让这个伪造的chunk和之前的存在堆溢出的chunk,一同被释放,并吧我们伪造的chunk到存在堆溢出的chunk的这一段距离都当做之前fake_chunk的大小一同free进入到top chunk中(top chunk相近的chunk free掉会直接与top chunk合并),这样就能导致top chunk的大小被远远放大,导致其起始地址直接从我们伪造的chunk开始。那这样之后我们在向程序申请chunk,程序便会从我们之前伪造的chunk的地址开始申请,使得我们可以控制栈或bss的地址进行我们想要的操作。
大致的过程就是上面的内容,当重点在于如何操作下面便是这种方法的具体操作。
简单来说也就是这幅图的内容,
- 在栈或bss中(更具题目需要)构造fake_chunk
大致要像这个一样,prev_size随便,size后面要计算的可以先放放,之后的4个位置都要放的是我们构造的fake_chunk的头地址,
- 计算fake_chunk的size和靠近top chunk的chunk(下面叫chunk_b)的prev_size 大小(这两个大小相同),并修改chunk_b的size的最后一位为0
这里为了让从fake_chunk到我们的top chunk的内容都能被程序放入到top chunk中,就要把从fake_chunk到chunk_b的距离计算出来然后放入fake_chunk的size和chunk_b的prev_size位置。
距离=chunk_b的头地址-fake_chunk头地址
这里要用小的地址-大的地址,得到的才是正确的地址,最后的结果要想上面的一样。
- free掉chunk_b
将chunk_b释放之后,由于我们修改了chunk_b的size 和prev_size的大小,使得程序将它free后会仍为从这个chunk到我们伪造的chunk都是free_chunk,从而使程序开启chunk的合并机制。并导致从我们的fake_chunk开始的头地址被当做top chunk的头地址,然后便可以在下一次malloc时,就从我们fake_chunk的头地址开始分配,从而达到我们控制栈或bss段的地址。
以上便是这个手法的利用,相对来说是一个比较攻击力大的手法,在ctfwiki上有一题,一会可以供我们分析一下。
2016 Seccon tinypad
House Of Force
这种方法对于堆的利用相对来说过程是比较简单的一种,不过由于程序的条件实行条件比较苛刻,故利用的地方不算特别多,并且这种手法的使用相对来说也有一定复杂的地方,故这种手法具体将通过题目来进行详解。
这种手法简单来说就是,通过堆溢出,修改top chunk的size的值为0xffffffffffffffff/0xffffffff(64位或32位的-1)
然后将可以向程序申请一个很大很大的chunk,由于top chunk被我们修改为这个在程序中被认为是无限大的数字,所以我们的申请一定会被满足,而对于超出程序中原本top chunk的大小的内容,程序便会从其他地方拿却使用,故这里我们便可以直接申请一个到我们目标地址的chunk,然后就可以对这个地址进行修改和输入数据,由于我们的申请的内容一定是从程序中去申请而不向内核申请(top chunk的大小被我们修改为程序的最大值),故我们甚至可以直接申请到栈或bss等其他地址。从而满足我们后门的操作。
这个手法的利用相对来说比较简单,当条件比较苛刻
- 首先,需要存在漏洞使得用户能够控制 top chunk 的 size 域。
- 其次,需要用户能自由控制 malloc 的分配大小
- 第三,分配的次数不能受限制
只有能满足这3点才算能使用这种手法的题目。
这里还有一个需要注意的地方,那就是这种手法只能在libc-2.23到libc-2.27这里面的版本使用,像libc-2.29及以上的版本就不能使用这种攻击手法
HITCON training lab 11
这道题是ctfwiki上的题目相对来说是一到,比较简单的题目,
他的漏洞在于第3个选项时,用于修改堆的内容的函数。这里我们看下面的从18到21行,可以看出来,这里对于我们需要新输入到程序中的内容的大小,是由我们自行输入的,并且对大小并没有一个是非的检查,这里存在一个堆溢出的漏洞,我们可以先输入一个巨大的数字从而形成堆溢出,
再看其他的函数就是正常的一个show函数,一个malloc函数,一个change函数,一个free函数,整个程序的漏洞就在于我们刚刚说的堆溢出,并且这里有关于堆的大小申请是由我们自行输入决定的。并且在程序中还存在一个后门函数,于是我们的重点就在于如果使程序能够跳转执行我们的后门函数。
这里回到主函数中就会有所发现,这个当我们选择5时,程序便会执行v4[1],而这个v4就是程序在一开始申请的第一个chunk的指针,故这里我们可以像是否能修改第一个chunk的内容为我们后门函数的地址然后执行5选项,那目的就打成了。
现在我们的目标就是如果拿到第一个chunk_v4的控制权。结合之前的堆溢出漏洞,其实这里可以使用unlink的方法,不过既然我们已经学了House Of Force的手法,那这里就使用一下这种方法。
这里的思路简单讲一下就是
- 先申请一个chunk(这里大小不限选0x30)
- 通过堆溢出修改top chunk的size为0xffffffffffffffff
- 计算从top chunk的头地址到到我们需要的chunk的头的地址的距离大小
这里为0x20+0x40
- 使用 house of force 技巧,我们需要绕过 request2size(req) 宏,这里由于 -0x60 是16字节对齐的,所以只要减去 SIZE_SZ 和 MALLOC_ALIGN_MASK 大小即可得出需要 malloc 的大小,然后我们再次分配就能分配到 chunk_v4处。
故这里的真实要申请地址为
关于这个0x17的值,准确来说可以是0x8~0x17中的任意一个数字就可以
- 在决定这个数字后向程序申请这个大小的chunk(就是要负数),便可以将chunk_v4包裹其中
- 在申请一个chunk输入后门函数的地址,然后执行5,变调用后门函数
exp
关于这道题的重点在于修改top chunk的堆的申请,一定要注意是距离的负数-0x8,申请这个之后的在申请的就是我们要的目标地址。
2016 BCTF bcloud
这道题相对来说就是上一道题的翻版,不过这道题的难点在于对程序中的漏洞的修找,这里我就是在寻找漏洞的时候出了一定的问题,导致一开始做的时候并没有做出来,后面看了一下别人的分析+自己在仔细调试才把这道题的问题完整明白。看来对C语言的理解和汇编的理解还是有点差了,之后要找时间再重新学一下。
利用步骤如下:
- 1.通过名字leak堆地址
- 2.通过host and org 改大top_chunk->size
- 3.移动top_chunk
- 让再申请的内存在覆盖到bss段中 list_len 和noet位置的内存
- 让noet指向函数的got表
- 4.把free改成printf
- 5.利用 假free 函数把atoi地址printf出来
- 6.利用 atoi 得到system地址
- 7.把atoi改成system
House Of Lore
这种手法主要用于对libc-2.27及以下的版本中的small bin的机制中的漏洞从而进行攻击的一种手法,简单来说就是我们通过修改出在small bin中的chunk的bk位数据,使其指向我在栈或bss段中伪造的fake_chunk,然后由于在libc2.27及以下的libc版本中对这个chunk的检查不足,导致我们的这个fake_chunk会被程序认为是small bin上的一个free chunk。使得我们能在后面通过malloc将我们伪造的chunk申请出来供我们使用。
基本原理
如果在 malloc 的时候,申请的内存块在 small bin 范围内,那么执行的流程如下
从下面的这部分我们可以看出
如果我们可以修改 small bin 的最后一个 chunk 的 bk 为我们指定内存地址的 fake chunk,并且同时满足之后的 bck->fd != victim 的检测,那么我们就可以使得 small bin 的 bk 恰好为我们构造的 fake chunk。也就是说,当下一次申请 small bin 的时候,我们就会分配到指定位置的 fake chunk。
当然具体的利用条件必然不会这么简单,还是有很多要注意的地方,具体的跟具以下的这个脚本分析
这是一个C语言的脚本,我们将跟具这个具体分析一下有关于这个House of Lore手法的具体利用
最开始这里我们要申请一个大小在(0x80~0x390),只有在这个范围的chunk才会进入到small bin中,这里我们申请0x100的大小的堆块,然后在申请一个比较大的堆块用于使0x100这个堆块在后面我们free时不会被top chunk合并
之后我们便可以在栈或bss段上伪造我们的fake_chunk,
在这个手法中我们需要注意的就是这个fake_chunk,需要俩个不同地址的chunk相互结合才能形成有效的攻击,
这里我们假设这两个fake_chunk为stack_buffer_1和stack_buffer_2
这里这两个的要求各不相同,stack_buffer_1至少要4个字节,而stack_buffer_2至少要3个字节
在stack_buffer_1中要放入的数据为
在stack_buffer_2中要放入的数据为
0x7fffffffddd0为stack_buffer_1,0x7fffffffddb0为stack_buffer_2
在伪造完这两个fake_chunk后,我们在free那个0x100的chunk,使其进入unsortedbin中
然后在向程序申请一个比较大的chunk,使其进入smallbin中
在完成这几步后就要修改这个smallbins中的chunk了,
这是未修改的chunk
此时的chunk还在正常的smallbins chnk,而我们的目的就是要修改这个chunk的bk(第4个)指针为我们刚刚伪造的stack_buffer_1的头地址,修改,结果如下
对应的heap和bin中也有相应的变化
可以看到在smallbins中明显多了一行,并且这一行里面虽然0x603000依然为第一个但我们刚刚伪造的两个栈上的chunk也被放入了其中,这样我们的基本目的就完成了,成功吧我们伪造的chunk都放入了smallbins中,之后只要我们把这个栈上的地址申请出来,那这个攻击的目的就达到了。
我们首先把之前那个0x100的chunk mallc出来(通过malloc(0X100)),使得bin中为如下情况
然后在malloc(0X100),就可以使程序把stack_buffer_1(0x7fffffffddd0)当做新的chunk给我们使用
至此,这个手法的基本过程结束,后面的就是通过栈上的这个chunk,从而劫持程序的执行流。
简单来讲这个手法通过伪造chunk1,和chunk2。
修改smallbins中的chunk使bk指针其指向chunk1的头地址,
然后就把chunk1当做正常堆的chunk拿出来供我们使用。
这个手法虽然限制比较多
- libc-2.27及以下
- 能修改free chunk的bk位,这个free chunk为smallbins
- 有足够的地方伪造chunk1和chunk2
不过攻击力还是比较强大
House Of Rabbit
这是一个对堆的利用姿势,目的在于使用满足条件的情况,绕过堆块的地址随机化保护(ASLR)达到任意地址分配的目的。
使用这个手法需要3个条件
- 可以分配任意大小的堆块并且释放,主要包括三类fastbin大小的堆块、smallbin大小的堆块、较大的堆块(用于分配到任意地址处)
- 存在一块已知地址的内存空间,并可以任意写至少0x20长度的字节
- 存在fastbin dup、UAF等漏洞,用于劫持fastbin的fd指针。
当存在上述三个条件时,即可使用House Of Rabbit攻击方法
这里干脆直接把提出这个手法的那道题拿上来分析一下
HITB CTF 2018 mutepig
这道题怎么说呢,比较恶心,没有输出的内容,调试的时候太难受了,不能直接使用gdb调试,只能在脚本中调,确实不太容易。
简单讲一下这个题目的基本流程,是个选项题,还是基本的3个选项,
第一个选项用于创建chunk,但是
这里用于创建chunk的大小是固定的,大小只能为1时的0x10,2时的0x80,3时的0xA00000以及0x3419时的0xFFFFFFFFFFFFFF70LL,并且这里的chunk的数量也只能是10个有以下。在创建好的同时还会直接向这个chunk里面读入数据,
其次是选项2这个选项2的主要作用就是free chunk,同时这里也是存在UAF漏洞的
其次是选项3,这里先读入一个序数,然后向这个序号的chunk读入最多8个字节的数据,然后又向bss段上的0x602120这里读入最多0x48字节的数据。
题目提供分配大小为0x10、0x80、0xa00000、0xffffffffffffff70大小的堆块,并且没有开启PIE保护,还存在UAF漏洞,完全满足该利用方法需求,通过将内存地址分配回bss段低地址部分的堆地址指针数组,覆写数组内容为free@got,利用编辑功能,将其内容改为system@plt,在free时可以拿到shell
那就具体看一下具体流程,
- 增大malloc函数中 mmap分配阈值
这里我们向程序申请0xa00000的堆块,堆块由mmap分配,并且mp_.max_mmaped_mem变成0xa10000,当free以后再次malloc(0xa00000)时,系统会首先通过sbrk扩大top块进行分配,当最后一次free后,top大小变成0xa20c31 > 0xa00000,这样我们下次申请这个大小的chunk是程序会使用比较大的top chunk。
- 申请小堆块并放入fastbin
首先malloc(0x20) ,再次malloc(0x80),这两块都是由top直接切割得到,保证small bin大小的块挨着top。
- 伪造堆块并劫持至fastbin
在一个已知地址的内存处(如未开启PIE的程序BSS段)伪造两个连续的堆块,一个堆块大小是0x11,紧挨着是0xfffffffffffffff1,这样可以保证后续操作可以覆盖到任意地址。更重要的是这个0x11的小块即是大块的前块,也是大块的后块,可以保证在malloc中通过检查。
利用漏洞劫持fastbin,将大小为0xfffffffffffffff1的堆块,挂到fastbin上去。
- 利用malloc_consolidate使伪造堆块进入unsorted bin
在free函数中,当释放的块大于 65536时,会触发malloc_consolidate,这个函数用于对fastbin合并,并放到unsorted bin中
而在malloc_consolidate()中,会循环处理各fastbin堆块,当堆块与top相邻时,与top合并。否则,将堆块放入unsorted bin中,并设置pre_size和pre_inuse位,此时较小的堆块变成 0xffffffffffffffff0 0x10
将程序中的chunk全部与top chunk合并
使得将大小为0xfffffffffffffff1的堆块从fastbin中转到unsortedbin中
- 分配内存 使伪造堆块进入large bin
当伪造的堆块进入unsorted bin时,并不能达到目的,需要进一步使堆块进入large bin,此时需要将伪造的堆块大小改为0xa00001,其目的有两个,1是绕过程序对unsorted bin中内存块大小小于av->system_mem的检测;2是使程序放入large bin的最后一块(>0x800000)
- 任意内存分配
当伪造堆块进入large bin最后一个队列时,将伪造堆块的大小改回0xfffffffffffffff1,此时在申请任意长度的地址,使堆块地址上溢到当前堆地址的低地址位置,从而可以分配到任意地址,达到内存任意写的目的。
exp
这道题就是这个手法比较明显的使用,借助这种手法这道题的完整就如此,
这里由于这道没有任何的输出导致我们在注入数据时要注意需要时间空格
这里我当时最开始做的时候就是被这个问题卡了很久,想这种对于数据的注入如果没有注入成功的可以考虑,要么使用更具收到的数据在发送,或者就是这个加时间间隔。
其次这道还有一个问题就是在选项3的向堆块注入数据时只能是8个字节但是在我们注入8个字节会把换行符一起读进去,因此要在那加上
[:-1]
防止读入的数据不对House Of Roman
这种手法主要是关于堆的布局的一种比较奇妙的方法,
主要特点是不需要
leak libc
的地址,通过 堆内存的布局 和 堆相关的漏洞(uaf
等) 就可以 getshell
这里还是以这个手法的提供者里的那道题来具体分析一下这种手法的思路和特点,
这里是这个提出者自己写的有关于这种手法的分析,
具体的题目和exp可以再这里下载,
new_chall
先简单看一下这道题的整体流程,也是一个经典的选项题,有3个选项
Malloc
, 用户输入size
, 然后malloc(size)
, 大小不限
Write
, 往指定heap_ptr
写入size+1
字节数据,一字节溢出
Free
, 调用free
释放掉heap_ptr
,不过没有清零,double free
和uaf
(Write
时只是校验 指针是否为0
).
漏洞的话有两个
1,选项2的函数中用于向堆块输入数据,这里有一个一字节的溢出,
2,在第3个选择中用于free掉chunk,这里直接使用free函数,没有清空指针UAF漏洞
由于这道题没有将堆块中的内容输出的函数,不过有off-by-one和UAF的漏洞,并且这里的堆块的大小和要创建的堆块的位置都是可以由我们自己决定的(0~0x13这几个位置随便选),那这里其实就可以考虑使用House of Roman这种手法了。
这种手法的核心思路就是利用局部写 减少随机化的程度,从而给出爆破的可能。(这里我到做到后面的时候其实感觉就是通过大量的运行是程序和我们的猜测相同,但我们要利用这种手法使尽可能多的位置上的数据相同)
这个手法的重点在于其中的堆块的分布,这里我们就直接用这道题来讲解
- 首先分配
3
个chunk (A , B, C)
,大小分别为0x20, 0xd0, 0x70
这里分配这3个chunk时,输入的长度都用真实大小-8,便于后面的溢出
2. 在
B + 0x78
处设置 p64(0x61)
, 作用是 fake size
,用于后面 的 fastbin attack
用于在后面伪造一个chunk,这个0x61就是这个伪造chunk的size段
3. 释放掉
B
, B
进入 unsorted bin
, 此时 B+0x10
和 B+0x18
中有 main_arean
的地址
4. 再次分配
0xd0
, 会分配到 B
, 此时 B+0x10
和 B+0x18
中 main_arean
的地址依然存在
5. 然后分配
3
个 0x70
的 chunk (D , E, F)
, 为后续做准备。后面这两个chunk可以放后面一点,用于与top chunk隔开,已经备用
6. 在
A
触发 单字节溢出,修改 B->size = 0x71
,注意这里我们修改后会在B下面多出一个chunk,这个就是我们之前输入的0x61形成的fake_chunk.然后释放
C , D
, 此时 C , D
进入 fastbin
, 同时D中bk指针指向的c的头部 D->fd = C
.我们在利用
uaf
,部分地址写,修改D的bk指针的最后两位把 B
链入到 fastbin
(把0x60f59a3290f0修改为0x60f59a329020)
- 此时 B->size = 0x71 ,同时 B + 0x78 为 p64(0x61) (第2步设置), 这就成功伪造了一个 0x70 大小的 fastbin。 此时 B->fd 为 main_arean 的地址,于是通过 修改 低 2个字节,可以修改到 malloc_hook - 0x23 处 ( malloc_hook - 0x23 + 0x8 处的值为 p64(0x7f) )
通过修改
B->fd
的低 2
字节, 使得 B->fd= malloc_hook - 0x23
这里注意一定要让修改后的fastbin中的紫色的这个地址为
_IO_wide_data_0+301
否则后面的分配会出问题- 然后分配
3
次0x70
的chunk
, 就可以拿到包含malloc_hook
的chunk
, 此时malloc_hook
内容为0
0x78e3c8fc3afd这个地址被程序当做chunk分配给了我们,我们将其放置在0位上。
free
掉E
,进入fastbin
,利用uaf
设置E->fd = 0
, 修复了fastbin
这是一个很奇妙的思路,因为我们之前的操作会让我们的fastbin中有垃圾数据,这样就可以修复这个fastbin了
- 然后利用
unsorted bin
修改malloc_hook
内容为main_arean
的地址
使用上面的命令使得chunk_1的chunk进入unsortedbin,形成如下情况
然后修改这个chunk_1的fd指针指向
__memalign_hook
这个位置,(其实也是修改最后几个数字,从0x78e3c8fc3b78修改为0x78e3c8fc3b00)修改完之后,在申请一个0x70大小的chunk,然后程序会把__memalign_hook这个当成unsortedbin中的新chunk,使得在下一行__malloc_hook中存入0x78e3c8fc3b78 (main_arena+88)这个数据
- 修改
malloc_hook
的低三个字节 ,使得malloc_hook
为one_gadget
的地址
这里就有要注意的一个点,这里one_gadget有不同的地方,因此有的时候要记得换,并且这个我们是吧one_gadget注入到
malloc_hook
的低三个字节中,这是此时
malloc_hook
中的情况,我们要修改为完整的one_gadget,然而由于aslr等地址随机化的存在,会导致我们向上面其中\x8e
这里其实我们能知道的就是e
这个数字,但是由于输入时我们必须要输入两个数字,故这个8
其实是我们猜的,我们只有大量的运行这个脚步,使得我们能让地址随机化的其中刚刚好就是这个8
.- 然后
feee
两次同一个chunk
,触发malloc_printerr
,执行__malloc_hook
中的地址getshell
。(这里我一开始想直接调用malloc函数触发__malloc_hook
,但不知道为什么好像这种方法实现不了)
我们之前说个由于开启
aslr
后,需要跑很多次才能拿到shell,可以直接执行下面的命令完整exp
这道题基本就代表了House-Of-Roman这种手法的利用,通过fastbin和unsortedbin的利用,和奇妙的堆布局,使得在
__malloc_hook
中由程序放入main_arena+88
这个地址,然后我们修改最后几个字节为one_gadget,这里注定有个数字为我们猜的,因此我们要多运行几次脚本,使得我们的猜测正确。House of pig
这个手法是目前我所接触到的libc版本最大的利用手法,
并且也是比较复杂的手法,要利用这种手法的条件还是比较苛刻的,一共有3种
- 能够泄露 glibc内存和堆内存。
- 目标程序存在 UAF漏洞,或者能够使用已有漏洞修改已经释放的 chunk,写入的大小无限制或者限制比较宽松。
- 目标程序使用的是calloc函数分配内存
一般来说当程序中同时有这几个条件,并且还是在libc2.31及其以上版本运行的pwn题中可以考虑使用这种手法来进行拿到shell。
这个手法的提出是在xctf 2021 final的同名题目中提出的,原本想就使用这题分析这个手法的,无赖这道题是个c++的pwn的题,本人目前能力有限,暂时没有整出来那道题,这里留个记录,在之后把那道题整完,在分析一波。
这个手法的具体利用过程如下
- 先用 UAF 漏洞泄露 libc 地址 和 heap 地址
- 再用 UAF 修改 largebin 内 chunk 的 fd_nextsize 和 bk_nextsize 位置,完成一次 largebin attack,将一个堆地址写到
__free_hook-0x8
的位置,使得满足之后的 tcache stashing unlink attack 需要目标 fake chunk 的 bk 位置内地址可写的条件
- 先构造同一大小的5个 tcache,继续用 UAF 修改该大小的 smallbin 内 chunk 的 fd 和 bk 位置,完成一次 tcache stashing unlink attack,由于前一步已经将一个可写的堆地址,写到了
__free_hook-0x8
,所以可以将__free_hook-0x10
的位置当作一个 fake chunk,放入到 tcache 链表的头部,但是由于没有 malloc 函数,我们无法将他申请出来
- 最后再用 UAF 修改 largebin 内 chunk 的 fd_nextsize 和 bk_nextsize 位置,完成第二次 largebin attack,将一个堆地址写到
_IO_list_all
的位置,从而在程序退出前 flush 所有 IO 流的时候,将该堆地址当作一个 FILE 结构体,我们就能在该堆地址的位置来构造任意 FILE结构了
- 在该堆地址构造 FILE 结构的时候,重点是将其 vtable 由 _IO_file_jumps 修改为 _IO_str_jumps,那么当原本应该调用 IO_file_overflow 的时候,就会转而调用如下的 IO_str_overflow
- 而该函数是以传入的 FILE 地址本身为参数的,同时其中会连续调用 malloc,memcpy,free 函数,且三个函数的参数又都可以被该 FILE 结构中的数据控制,那么适当的构造 FILE 结构中的数据,就可以实现利用 IO_str_overflow 函数中的 malloc 申请出那个已经被放入到 tcache 链表的头部的包含
__free_hook
的 fake chunk
- 紧接着可以将提前在堆上布置好的数据,通过 IO_str_overflow 函数中的 memcpy 写入到刚刚申请出来的包含
__free_hook
的这个 chunk,从而能任意控制__free_hook
,这里可以将其修改为 system 函数地址
- 最后调用 IO_str_overflow 函数中的 free 时,就能够触发
__free_hook
,同时还能在提前布置堆上数据的时候,使其以字符串 “/bin/sh\x00” 开头,那么最终就会执行 system(“/bin/sh”)
这里我拿之前在网上找的一个这个手法的验证代码来简单分析这个手法的使用
注意:vtable字段不是直接改为_IO_str_overflow函数地址,而是改为_IO_str_jumps。
我们在堆上伪造的
_IO_FILE_plus
结构可以使用如下模板这个手法由于针对的libc版本比较高,故需要大量的使用到io_file的结构中的功能,这个结构由于我之前并没有学过,导致这个手法虽然知道该怎么做,到具体的原因还是不过清楚。这个等后面具体的学习一下io_file这个结构在回来重新理解一下。
- 作者:wgiegie
- 链接:https://tangly1024.com/article/68926489-6f75-42d4-93e7-9075e244d1b4
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。