linux堆上的内存可执行吗,pwn的艺术浅谈(二):linux堆相关

这是linux pwn系列的第二篇文章,前面一篇文章我们已经介绍了栈的基本结构和栈溢出的利用方式,堆漏洞的成因和利用方法与栈比起来更加复杂,为此,我们这篇文章以shellphish的how2heap为例,主要介绍linux堆的相关数据结构和堆漏洞的利用方式,供大家参考。

0.前置知识

0.0 编译+patch方法

how2heap源码地址https://github.com/shellphish/how2heap,为了方便调试编译时使用gcc -g -fno-pie xx.c –o xx。这里先介绍一种linux下patch文件加载指定版本libc的方法,patchelf –set-interpreter 设置elf启动时使用指定ld.so(elf文件在启动时ld.so查找并加载程序所需的动态链接对象,加载完毕后启动程序,不同libc版本需要不同的加载器,不同版本libc和加载器下载地址https://github.com/5N1p3R0010/libc-ld.so),然后patchelf –set-rpath :/设置elf启动时加载指定libc。编译+patch示例

41b796d4f08407d37f113de2b0b18aef.png

0.1 linux堆管理简图及源码地址

6465547c035d172e153e2ae6e7775298.png

0.2 linux堆的数据结构

0.2.1堆块数据结构

首先介绍下linux下堆的基本数据结构。

ac1b81eeee6e31415e86a6e5bdcdc989.png

各字段含义如下:

0.mchunk_prev_size。当当前堆物理相邻的前一个堆为空闲状态时mchunk_prev_size记录前一个空闲堆的大小,当当前堆物理相邻的前一个堆为占用状态时mchunk_prev_size可用于存储前一个堆的数据。

1.mchunk_size,记录当前堆包含堆头的大小,堆的大小在申请时会进行对齐,对齐后堆的大小为2*size_t的整数倍,size_t为机器字长。mchunk_size的低三比特位对堆的大小没有影响,ptmalloc用它来记录当前堆的状态,三个比特位从高到低依次:

NON_MAIN_ARENA,记录当前堆是否不属于主线程,1 表示不属于,0 表示属于。

IS_MAPPED,记录当前堆是否是由 mmap 分配的。

PREV_INUSE,记录前一个堆是否被分配。

2.fd、bk,堆处于分配状态时,堆结构体偏移fd的位置存储数据;堆处于空闲状态时,fd、bk分别记录物理相邻的前一空闲堆、物理相邻的后一空闲堆,即用于对应空闲链表的管理

3.fd_nextsize、bk_nextsize,large chunk处于空闲状态时使用,分别用于记录前一个与当前堆大小不同的第一个空闲堆、后一个与当前堆大小不同的第一个空闲堆

0.2.2 空闲链表

理解ptmalloc堆漏洞利用的另一个比较重要的结构体是bin,为了节省内存分配开销,用户释放掉的内存并不会马上返还给系统,而是保存在相应的空闲链表中以便后续分配使用。Ptmalloc使用的空闲链表bin有四种,fastbin、samllbin、largebin、unsortedbin ,一个好的内存分配器应该是内存碎片少、且能在较低算法复杂度和较少内存分配次数的情况下满足用户使用内存(申请和释放)的需求,四种bin的实现就体现了这种思想。

3f67a9d7eeab6a77110d2415c1ef0cfe.png

为了减少内存碎片,ptmalloc在释放当前堆cur_chunk时会检测cur_chunk的prev_inuse位(标识物理相邻前一个堆(物理低地址)是否处于空闲状态)和cur_chunk的物理相邻下一个堆是否是top_chunk、物理相邻下一个堆的prev_inuse位。若cur_chunk的prev_inuse位为0则合并后向堆并将后向堆的地址作为新的合并后的堆的起始地址;若cur_chunk的物理相邻下一个堆的prev_inuse位为0则进行前向合并并将cur_chunk的地址作为新的合并后的堆的起始地址。若待释放的cur_chunk的物理相邻下一个堆为top_chunk则将cur_chunk和top_chunk合并,并将cur_chunk的地址作为新的top_chunk起点。

8d77901dcc0a185763cc9b52c0be67a9.png

Ptmalloc堆的一些参数

0) fastbin

fastbin是保存一些较小堆(32位系统默认不超过64字节,64位系统默认不超过128字节)的单链表结构。由于fastbin中相同index链接的都是相同大小的堆,ptmalloc认为不同位置的相同大小的堆没有区别,因此fastbin使用lifo的方法实现,即新释放的堆被链接到fastbin的头部,从fastbin中申请堆也是从头部取,这样就省去了一次遍历单链表的过程。fastbin的内存分配策略是exact fit,即只释放fastbin中跟申请内存大小恰好相等的堆。

1) smallbin

smallbin中包含62个循环双向链表,链表中chunk的大小与index的关系是2* size_t* index。由于smallbin是循环双向链表,所以它的实现方法是fifo;smallbin的内存分配策略是exact fit。

3176438dc5474dd89265b7e22037ff40.png

从实现中可以看出smallbin链接的chunk中包含一部分fastbin大小的堆,fastbin范围的堆是有可能被链入其他链表的。当用户申请smallbin大小的堆而smallbin又没有初始化或者申请大于smallbin最大大小的堆时,fastbin中的堆根据prev_inuse位进行合并后会进入如上unsortedbin的处理流程,符合smallbin或largebin范围的堆会被链入相应的链表。

2) largebin

largebin包含63个循环双向链表,每个链表链接的都是一定范围大小的堆,链表中堆的大小按从大到小排序,堆结构体中的fd_nextsize和bk_nextsize字段标识链表中相邻largechunk的大小,即fd_nextsize标识比它小的堆块、bk_nextsize标识比它大的堆块。

对于相同大小的堆,释放的堆插入到bin头部,通过fd、bk与其他的堆链接形成循环双向链表。

Largebin的分配策略是best fit,即最终取出的堆是符合申请内存的最小堆(记为chunk)。若取出的chunk比申请内存大至少minsize,则分割chunk并取合适大小的剩余堆做为last remainder;若取出的chunk比申请内存不大于minsize,则不分割chunk直接返回做为用户申请内存块。

3) unsortedbin

unsortedbin可以视为空闲chunk回归其所属bin之前的缓冲区,分配策略是exact fit。可能会被链入unsortedbin的堆块是申请largebin大小堆块切割后的last remainder;释放不属于fastbin大小且不与topchunk紧邻的堆块时会被先链入unsortedbin;在特定情况下将fastbin内的堆合并后会进入unsortedbin的处理流程(特定情况为申请fastbin范围堆fastbin为空;申请非fastbin范围smallbin的堆但smallbin未初始化;申请largechunk)

1.how2heap调试

1.0 First_fit

这个程序阐释了glibc分配内存的一个策略:first fit,即从空闲表中取出的堆是第一个满足申请内存大小的堆(fastbin、smallbin exact fit,largebin best fit)

c08b0cc3730215550208efe2dd24d38a.png

Shellphish给出的例子中先申请了0×512和0×256大小的两个堆,然后释放掉0×512大小的堆(申请0×256大小的堆的作用是避免释放不是mmap分配的堆a的时候合并到topchunk),实例中再次申请0×500大小的堆由于largebin的best fit分配策略glibc会分割堆后返回堆a,即堆c等价于堆a,这时我们输出堆a的内容即输出修改后的堆c的内容。

glibc的first fit分配策略可用于use after free(uaf,释放后重用)的利用,即修改新分配堆的内容等价于修改被释放的堆,uaf一般是由于释放堆后指针未置零造成的,不过在uaf的利用过程中我们一般使新分配的堆的大小等于被释放的堆的大小。

1.1 fastbin_dup

fastbin下doublefree的一个示例(未加tcache机制)。

f7da6eab571f6cd6fe4a22981f9be2ad.png

Shellphish给出的例子中先申请了3个0×8大小的堆(同样地申请c的原因是避免合并到topchunk),然后释放a(此时再次释放a构成doublefree双重释放,但是由于glibc在释放fastbin大小的堆时检查且仅检查fastbin头部的堆和要释放的堆是否相等,若相等则报错),为了绕过glibc在释放堆时对bin头结点的检查,我们free(b),此时fastbin如下(b=0×602020,a=0×602000;由于fastbin是单链表且LIFO,后释放的b被插入到链表头)

b0c1ce6cf484fa441770b0ecdf101574.png

然后我们再次free(a),由于此时bin头结点指向b,所以对头结点的检查被绕过,free(a)之后

909cca6814f8990d16a5234b30686769.png

可以看到此时fastbin中有两个a,如果此时我们申请三个0×8大小的堆,则依次从fastbin头部取得到a、b、a三个堆。

1.2 fastbin_dup_into_stack

fastbin下doublefree的利用示例(未开启tcache机制)。主要思路是在doublefree时我们有一次修改一个存在于fastbin链表的堆的机会,然后通过伪造堆的内容可以使得fastbin链入伪造的堆,再次申请内存可以得到伪造地址处的堆。

0c07229cb8a0082a09e239359484613e.png

示例中先申请了3个0×8大小的堆,然后通过free(a)、free(b)、free(a)构成一次doublefree(原理同fastbin_dup),此时fastbin的连接状态是a->b->a。再次申请两个0×8大小的堆,由于fastbin的lifo,此时fastbin中只剩a,且此时堆a存在于fastbin和用户申请的堆中,即我们可以控制一个存在于fastbin的堆的内容。容易想到的一种利用方式是伪造fastbin链表的内容,进而达到在伪造地址处申请堆的效果。

示例中在栈中伪造了一个0×20大小的堆(伪造堆头如下图选中部分,其中a=0×405000,&stack_var=0x00007fffffffdfb0),此时堆a的fd指向&stack_var,即fastbin:a->stack_var,此时第二次申请不超过0×18大小的堆(64位系统,跟申请堆时字节对齐有关,返回的堆的大小会被转化成满足条件的最小2*size_sz的倍数,最大0×10+8,8字节可占用下一个堆的prev_size)即可返回栈地址处的伪造堆。

586af5b4b896d3c49707f2bc06d60b46.png

1.3 fastbin_dup_consolidate

fastbin attack构成doublefree的一个示例。原理是利用申请一次largebin大小的堆会将fastbin的堆进行合并进入unsortedbin的处理流程,此时再次free fastbin中的堆会绕过free时对fastbin链表头节点的检查进而构成一次doublefree。

5ff0388b087726d06e9bbb7552180d5e.png

从下图free的流程中我们可以看出free时只会检查释放fastbin大小的堆时被释放的堆是否和fastbin的头结点是否一致,而在申请0×400的largechunk时,fastbin链表非空,fastbin中的堆会进行合并并且进入unsortedbin的处理流程,在unsortedbin的处理流程中符合fastbin大小的堆会被放入smallbin,这样就绕过了free时对fastbin头结点的检查,从而可以构成一次对fastbin大小的堆的doublefree。

a4962b7d98b0e253c7d7a86d2f858ffc.png

1.4 unsafe_unlink

堆可以溢出到下一个堆的size域且存在一个指向堆的指针时堆溢出的一种利用方式。

3dd772aad0ff5ec978d65ebc0b6e57a2.png

Unsafe unlink利用的前提是可以溢出到下一个堆的size域,利用的大致思路是在chunk0构造fakechunk且fakechunk可以绕过unlink双向链表断链的检查,修改chunk1的pre_size使之等于fakechunk的大小,修改chunk1中size域的prev inuse位为0以便free(chunk1)时检查前后向堆是否空闲时(这里是后向堆,即物理低地址)触发unlink双向链表断链构成一次任意地址写。下面看一下unlink的具体细节和原理。

示例中首先申请了两个0×80大小的堆chunk0和chunk1(非fastbin大小,因为fastbin大小的堆为了避免合并pre_inuse总是为1),然后在chunk0中构造fake_chunk

4cbcdd09c9ea7138726030f8d7d8d78e.png

需要注意的是,我们构造的fake chunk的起点是chunk0的数据部分即fd,fake chunk的prev size和size域正常赋值即可(最新的libc加入了cur_chunk’size=next_chunk’s prev_size),fake chunk中关键的部分是fake data,这一部分要绕过unlink双向链表断链的检查,即fd->bk=p&&bk->fd=p

708e926605ff6466d6a8be5c913c400a.png

chunk的结构体如下

6ca08ee6c41157b9173983a8e8101969.png

所以由结构体的寻址方式可得

(fd->bk=fd+3* size_t)=p

(bk->fd=bk+2* size_t)=p

所以可得

fd=p-3* size_t

bk=p-2* size_t

即fakechunk中fd和bk域如上构造即可绕过unlink双向链表的断链检查。

构造完fakechunk还需要修改下chunk1的prevsize和size的数据,

首先是prevsize要修改成fakechunk的大小(包含堆头,原因是glibc寻找下一个堆的宏如下,即将当前堆偏移size的数据视为下一个堆)

0ed83bcec04aa892fa14c30d90b84d47.png

chunk1 size部分的inuse位要置0,即标识物理相邻低地址堆为空闲状态(这也是unlink无法使用fastbin大小的堆的原因,fastbin大小的堆为了减少堆合并的次数inuse位总是置1)

最后构造的fakechunk+chunk1部分数据如下,chunk0堆头0×405000,fakechunk堆头0×405010,chunk1堆头0×405090,图中选中部分为fakechunk

60e6b87ae0b9e9b9ae557130fcb3b5e1.png

其中fakechunk的fd要使用指向堆节点的指针(如指向该节点的全局变量,非堆地址)的原因是unlink源码中传入的第二个参数是struct malloc_chunk * p。下面分析下unsafeunlink是如何导致任意地址写的。阅读源码可以发现smallbin范围内非fastbin范围的堆在unlink时只检查了双向链表的完整性,然后执行了双向链表摘除节点的操作。

d5ef08fa43e407f2bb37494d1f2f509e.png

断链的过程

fd->bk=bk 即(fd->bk=p)=(bk=p-2* size_t)

bk->fd=fd 即(bk->fd=p)=(fd=p-3* size_t)

最终相当于

p=p-3* size_t

即获得了两个相等的指针(struct malloc_chunk * p),试想如果此时我们可以修改一个指针指向的地址同时可以修改另一个指针指向的内容不就可以构成一次任意地址写了吗?巧的是(;p)我们恰好可以达到这样的效果。

此时我们修改fake_chunk[3]为要写的地址,修改fake_chunk[0]为要写的地址的内容即可。原因是fake_chunk[3]-3*size_t=fake_chunk,这里相当于给fake_chunk指向一个新的地址;fake_chunk[0]访问的是&fake_chunk[0]地址处的值,即上一步修改的地址处的内容。这样就构成了一次任意地址写^.^

fc68db5743b02ef413bbd62bdbd0089e.png

1.5 house_of_spirit

利用fastbin范围的堆释放时粗糙的检查可以在任意地址处伪造fastbin范围fakechunk进而返回fakechunk的一种利用方式。思路是在指定地址处伪造fastbin范围的fakechunk,释放掉伪造的fakechunk,再次申请释放掉的fakechunk大小的堆即可得到fakechunk。

a6c254fcca296813a304de2918b48720.png

其中fastbin范围的堆释放时的检查如下图所示,

ecf2ff9550eb41e9fd13907d4807676c.png

我们构造的fakechunk只需要绕过free时的检查即可:

0.2*size_sz

1.伪造的fakechunk不能是fastbin的头结点,即不能直接构成doublefree

利用house of spirit可以得到fakechunk处的堆,同时如果我们有fakechunk处写的权限利用fastbinattack即可劫持控制流。

1.6 poison_null_byte

由于glibc在返回用户申请的堆时不恰当的更新堆的presize域和错误的计算nextchunk的位置可以导致一次堆重叠。

方法是先申请堆然后释放掉中间位置的一个堆bchunk(假设堆的大小都如图所示),假设存在一个off by null的漏洞,由于前一个堆是占用状态时prevsize域用来存储前一个堆的数据,这样我们可以从achunk溢出到bchunk的size域最低位将其置0。

此时申请一个0×100大小的堆会返回释放掉的bchunk位置的堆。原因是在申请一个smallbin且非fastbin范围的堆时会检查smallbin是否为空,本例中smallbin为空则执行smallbin的初始化过程,即将可能的fastbin中的堆进行合并进入unsortedbin的处理流程,申请的堆的大小是smallbin范围,此时会取largebin头结点的一个堆进行切割返回(同样地为了减少内存碎片,largebin的堆从大到小排序)。这里largebin中只含一个0×200大小的堆,则直接对其进行切割然后返回给用户。

e097eff2cebc3352ae5adf10e2f2085b.png

然后再次申请一个0×80大小的堆。原因是0×100+0×80+两个堆头=0×200使之结束的位置正好落于cchunk

这时free(b1)、free(c)释放掉两个堆,由于nextchunk即cchunk的preinuse为0会触发前向合并(向物理高地址)过程。原因是fake了一个cchunk的presize,系统修改的是我们的fake presize,即下图的0xf0,系统依然认为bchunk的位置有一个0×210的fakechunk。

922faf7ef9ebb8fc547acffa78023699.png

此时再次申请一个0×300大小的堆,由于合并后bchunk和cchunk的大小为0×300,系统会返回合并后的bchunk。又由于此时b2chunk没有被释放处于占用态,b2chunk位于合并的bchunk内,此时构成一次堆重叠。

1.7 house_of_lore

利用伪造smallbin链表来最终达到一次任意地址分配内存的效果。前提是可以在要分配的地址处伪造堆(修改结构体中fd、bk的指向),且可以修改victim堆(被释放的smallbin堆)的bk指针。

15221c415177a1d3979e54e30e34cc16.png

方法是在要分配的内存地址(如栈地址)处构造一个fake smallbin chunk链,使之如下图所示。

0668e9196d55f3948b3bc5db3df9bd88.png

然后申请一个堆防止释放victim的时候合并到topchunk,释放掉victim,此例中victim会进入fastbin链表。

再次申请一个largechunk,触发fastbin的合并过程并使fastbin的堆进入unsortedbin的处理流程,victim处于smallbin的范围最终被链入smallbin头结点。而由于我们事先构造了如上的fake smallbin链,此时smallbin的链接情况是smallbin:victim->stack_buf1->stack_buf2。

由于smallbin的exact fit和fifo策略,此时申请一个victim大小的堆会直接返回bin结点bk指向的victim(bin的结构体是mchunkptr*),然后断链并修改bin的bk指针指向victim的bk节点即stack_buf1。glibc取smallbin的chunk源码如下。

70bb05f7607295282babb89cc9d8cf24.png

此时stack_buf1的结构如下(其中0x7fffffffdfb0=stack_buf1,0x7ffff7dd4b98=smallbin,0x7fffffffdf90=stack_buf2),即此时smallbin:stack_buf1->stack_buf2

b3fc3fe09750f889228b3fe6ecc366ff.png

这样此时再申请一个victim大小的堆直接取smallbin的bk指向的stack_buf1即得到相应地址处的堆,达到了任意地址分配内存的效果。

1.8 overlapping_chunks

通过修改一个位于空闲链表的堆的size域可以构成一次堆重叠

79f4f65bd1a18d8ee9c260b63a952780.png

过程如上。修改位于bin的p2的size域,修改后p2结构如下(p2=0×405110,选中部分为p2 data部分)

8d912a074867ad93e62c0dbd4357090c.png

此时申请一个修改后的p2 size的堆会得到从p2位置起始的fake size大小的堆p4,如下图

1f92ba04b6651e1ab0e2b0fb8f2f15e9.png

1.9 overlapping_chunks_2

通过堆溢出修改下一个占用态堆的size域构成一次堆重叠

4e68a7296b24803420412c243d061f7b.png

shellphish给出的示例中先free掉p4(我个人感觉这一步是没有必要的,shellphish可能是出于演示的目的考虑?因为稍后可以看到我们可以观察到p5的prevsize在free(p2)后会发生变化,如果有小伙伴看到这里可以一起交流,snip3r[at]163.com)。free p4后p5的prevsize为3f0

2a9d523d32e5801777ff1a6ce978935b.png

然后修改p2的size域为p2+p3+标志位,释放掉。此时glibc会认为p2的size域的大小包围的堆是要被释放的,会错误的修改p5的prevsize值。free p2后p5的prevsize为bd0

8acd7561c1b7e46d7b3190d0ae2b634c.png

此时由于物理相邻的前向堆p4处于空闲态,fake p2会和p4合并链入largebin。然后申请2000大小的largechunk会将上述合并后的堆切割后返回p2起始的堆,从而构成一次堆重叠。

1.10 house_of_force

利用topchunk分配内存的特点可以通过一次溢出覆盖topchunk的size域得到一次任意地址分配内存的效果。

24f613a3c870b493054fd9f5d4030408.png

首先通过一次堆溢出覆盖topchunk的size域为一个超大的整数(如-1),避免申请内存时进入mmap流程。

然后申请一个evilsize大小的堆改变topchunk的位置。evilsize的计算如下,这么计算的原因是当bin都为空时会从topchunk处取堆

9d883ce2bc6b193c16f762f332e4ba1c.png

修改topchunk到目标地址后在申请一次堆即可对目标地址处的内存进行改写。

1.11 unsorted_bin_into_stack

通过修改位于unsortedbin的堆的size域和bk指针指向目标fakechunk,在目标地址构造fakechunk(构造size和bk指针。我们也可以不修改victim的size,malloc两次得到目标地址的fakechunk;原理都是构造fake unsortedbin链表)可以得到一次任意地址申请内存的机会。

84736b8f5b102d1eada4d097c806cd4d.png

其中如果要伪造victim的size的话要满足check 2*SIZE_SZ (> 16 on x64) && < av->system_mem

通过溢出修改位于unsortedbin的victim的size和bk,并构造fakechunk,最终构造出如下fake smallbin链表

cc204ee56a3d8b7edcd6b942b0ffe827.png

在下一次申请内存时glibc遍历unsortedbin找到exact fit的堆块并返回,最终可以得到目标地址处的伪造堆。

1.12 unsorted_bin_attack

通过伪造unsortbin链表进行unsortedbin attack泄露信息(libc基址)的一种方法。

8ac85a5b22bc6a14f1520ed8a6bf0cd4.png

方法是构造如下fake unsortedbin链表,

5128eefe9759d4581dbcb22a057eca78.png

这样在申请得到victim后会将victim断链,从而target_addr fake chunk的fd会指向相应的bin,进而可以泄露libc基址。(当然也可以泄露bk之类位置的其他信息,如果有的话;p)

1.13 large_bin_attack

利用malloc进行unsortedbin处理时插入largebin通过修改largebin链表上的堆的bk、bk_nextsize均可以得到任意地址写的机会。

aec5e864f6e79b2873feddff784eac9d.png

首先要申请如上图3个堆和相应的为了避免合并到topchunk的barrier(只申请barrier3应该就够用了,shellphish这么写可能是在之后复杂的申请释放中不在考虑合并到topchunk的情况),其中p1要保证是smallbin且非fastbin范围(且保证在后续申请堆时堆大小够用),p2、p3要保证是largebin范围。

(1)然后依次释放p1、p2,由于非fastbin范围的堆在释放后会首先链入unsortedbin,此时unsortedbin的情况是。(简单说就是unsortedbin:p2->p1,其中各个指针的指向如图)

ba49cc265b1e30f35c3f1e6baba7df01.png

(2)此时申请一个0×90大小的堆,从glibc的源码中可以看到遍历unsortedbin的过程是从bin头结点的bk指针开始遍历。这样取到的第一个堆是0×320大小的p1,p1满足0×90的申请,glibc会从p1中分割出0×90的大小,然后继续遍历unsortedbin直至遍历结束;此时得到链表的第二个堆0×400大小的p2,p2非smallbin范围且largebin为空,被链入largebin

1f61a2bb41fb01cee32ed17d1df841cf.png

此时unsortbin:(p1-0×90),largebin:p2.

(3)然后释放0×400大小的p3,p3非fastbin范围被链入unsortedbin头结点(fd指向p3)。

(4)此时利用溢出或其他手段修改largebin中的p2的bk、bk_nextsize(或、且)和size。可以看到p2修改前的size为0×411,shellphish把它修改成了0x3f1,这样做是因为largebin中链接的一定范围的堆是从大到小降序排列的,修改后0×400大小的p3被链入largebin时会被链入头结点。

在做好以上的准备工作后再次申请一个0×90大小的堆,同(2)过程依然由p2分割得到堆,由于p3>修改后的p2的size,p3被链入largebin头结点。链入的过程类似unlink,类似的我们得到了一次任意地址写的机会。

f3f7cd9605f766d11fa4a5a446db4ec4.png

1.14 house_of_einherjar

利用一次off by null修改下一个占用态chunk的prev_inuse位,同时修改下一个下一个占用态chunk的prev_size值,利用top chunk和后向合并(物理低地址)机制得到一次任意地址分配内存的机会。这种off by null利用的前提是可以在目标地址处(最终分配内存的地址处)构造fakechunk。

f727d5041aa4dcec7f9a53e1e7150ae1.png

利用的方法是在目标地址处构造fakechunk,由于稍后会看到fakechunk处会触发unink,为了绕过双向链表完整性的检测fd、和bk均可置为fakechunk。其中设置fakechunk的prev_size和size的值是可以但没必要的。

由于占用态的堆prev_size会用来存储前一个堆的数据,所以天然的prev_size域可以修改;当存在off by null时可以将下一个占用态堆的prev inuse置0。我们修改a的prev_size为fake_size,b的prev_inuse为0。这时我们释放掉b,由于b和topchunk紧邻,b会和topchunk合并;同时由于b的prev_inuse为0会触发后向合并(物理低地址),glibc寻找下一个空闲堆的方式是chunk_at_offset(p, -((long) prevsize)),即将当前位置偏移prev_size的位置视为nextchunk,这样(b+b.prev_size)得到下一个堆位于fakechunk,合并到topchunk并最终得到新的topchunk起点为fakechunk。此时再次申请堆从topchunk处取即可得到target处的fakechunk。

bd173f23675b82760bd69a18a374c690.png

这样通过反推target=b_chunk_header-fake_size得到fake_size=b_chunk_header-target。

2.总结

本文到这里就结束了,linux pwn基础知识的介绍到这里也就结束了,但是glibc还在不断更新,堆管理一些细节也在不断微调,一些新的提高性能的机制如tcache也开始应用于新版本的libc,关于不断更新的新版本libc的漏洞利用方式的探索还远远没有结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382955.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

manjaro linux下载软件,manjaro linux

manjaro linux下载。manjaro linux是基于Arch Linux开发的Linux操作系统&#xff01;对于裸服务器、虚拟机、IaaS 和 PaaS 方面都得到了加强&#xff0c;而且内置了强大的数据中心满足商业的各种要求&#xff0c;是强大的混合云平台和物理系统&#xff01;manjaro linux介绍man…

linux 安装qt 4.6软件,QT学习之一:Linux下安装QT之版本qt-4.6.3

在Linux中分别安装应用于不同平台的QT&#xff1a;PC&#xff1b;嵌入式X86&#xff1b;ARM。这三者PC版、嵌入式X86版和ARM版的区别主要体现在&#xff1a;当configure时分别加了不同的参数&#xff0c;具体区别是&#xff1a;PC平台&#xff1a;在linux中全安装qt&#xff0c…

linux kill命令使用方法,Linux初学者的killall命令(8个例子)

Linux初学者的killall命令(8个例子)我们已经讨论了kill命令 &#xff0c;如果你想在Linux中终止进程&#xff0c;你可以使用kill命令 。 但是&#xff0c;还有一个命令行实用程序可以用于相同的目的&#xff1a; killall 。 在本教程中&#xff0c;我们将使用一些易于理解的示例…

c语言 字符串 url,如何对URL字符串进行百分号编码

在和web服务进行交互时&#xff0c;我们经常需要对URL中的特定字符和传输的表单数据进行百分号编码。例如&#xff0c;’&’在百分号编码时会变成’%26’。搞清楚 URL中哪部分的哪些字符应该进行百分号编码了并不是件易事。最好的资料好像是RFC 3986和W3C HTML5。出于兴趣和…

击鼓传花击鼓次数相同c语言,JavaScript 实现击鼓传花游戏

大家小时候应该都玩过击鼓传花(Hot Potato)的游戏吧&#xff01;一群小孩围成一个圆圈&#xff0c;把花尽快的传给旁边的人。某一时刻传花停止&#xff0c;这时花在谁手里&#xff0c;谁就退出圆圈结束游戏。重复此过程&#xff0c;直到剩下最后一个孩子&#xff0c;即为胜者。…

前端的c语言面试题,前端工程师面试题汇总(选择题)

前端工程师面试题汇总(选择题)时间&#xff1a;2017-12-05 来源&#xff1a;前端工程师面试题推荐作为一名前端工程师&#xff0c;我们必不可少的就是参加面试&#xff0c;面试过程中会遇到各类奇葩的问题&#xff0c;今天小编为大家汇总了一些相关的问题&#xff0c;希望可…

android 磁场传感器 罗盘,Android开发获取重力加速度和磁场强度的方法

本文实例讲述了Android开发获取重力加速度和磁场强度的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;Android获取重力加速度和磁场强度主要依靠&#xff1a;Sensor.getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic)输入数据&am…

html在线编辑器 asp.net,ASP.NET网站使用Kindeditor富文本编辑器配置步骤

1. 下载编辑器下载 KindEditor 最新版本&#xff0c;下载页面: http://www.kindsoft.net/down.php2. 部署编辑器解压 kindeditor-x.x.x.zip 文件&#xff0c;将editor文件夹复制到web目录下3、在网页中加入(ValidateRequest"false")4、引入脚本文件(XXX部分需要修改)…

html中通过定位 实现下拉,JS+CSS相对定位实现的下拉菜单

本文实例讲述了JSCSS相对定位实现的下拉菜单。分享给大家供大家参考。具体如下&#xff1a;这里使用的是相对定位&#xff0c;不过效果还可以&#xff0c;用时候再修整一下&#xff0c;这个只是实现了大概功能&#xff0c;还有许多细节没有修饰。运行效果截图如下&#xff1a;在…

html页面包含头文件,Web前端技术:HTML部分---Head标签中包含的头文件标签,body标签包含的内部标签...

1、Head标签中包含的 头文件标签的作用&#xff1a;(1)title标签&#xff1a;定义网页的标题。(2)meta标签&#xff1a;一般用于定义页面的特殊信息&#xff0c;例如页面的关键字、页面描述等(3)link标签&#xff1a;用于引入外部样式文件(CSS 文件)。(4)style标签&#xff1a;…

HTML如何做个播放器图表,Web绘图神器之ECharts-ts文件播放器

前言最近在做一个项目需要用到大量的图形报表来展示数据。就去对比了一些前端图形报表框架&#xff0c;有Highcharts、Echarts、Three.js。发现Three.js比较笨重&#xff0c;不太适合数据展示&#xff0c;做前端动画还是比较好。而highcharts、echarts比较轻量级拿来就用比较方…

计算机网络原码反码补码,计算机的原码和反码及补码到底是什么

数据在计算机里面都是以0和1存储和运算的&#xff0c;这是冯诺依曼体系的基础。比如一个数在计算机中若有正负之分&#xff0c;则用一个数的最高位(符号位)用来表示它的正负&#xff0c;其中0表示正数&#xff0c;1表示负数。原码就是整数绝对值的二进制形式&#xff0c;为了解…

关于计算机应用基础问题,《计算机应用基础》习题及问题详解

《计算机应用基础》习题及问题详解 (17页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;19.90 积分实用文档第一章 计算机基础知识填空题&#xff1a;1. 信息技术在现代工业工程中的应用十分广泛&…

计算机网络安全本科大学排名,2021网络工程专业大学排名 最好大学排行榜

2021网络工程专业大学排名 最好大学排行榜2021-06-11 19:35:09文/丁雪竹网络工程专业在全国最好的大学是哪几所呢&#xff0c;最好的大学排名是什么样呢&#xff0c;小编整理网络工程专业大学最好大学排行榜&#xff0c;仅供参考&#xff01;网络工程专业最好大学排行榜在网络工…

20线程测试cpu性能软件,评测平台介绍、CPU多线程性能测试

2、平台介绍及CPU性能测试AMD AM3平台CPUAMD FX-8150(4模块/8核)AMD FX-8350(4模块/8核)主板华硕 Crosshair V Formula(BIOS版本&#xff1a;1605)Intel LGA1155平台CPUIntel Core i5 3570K(4核/4线程)Intel Core i7 3770K(4核/8线程)主板华硕 P8Z77-V Deluxe共用配件硬盘主盘&…

大型网站服务器 pdf,大型网站服务器容量规划[PDF][145.25MB]

内容简介内 容 提 要本书讲解了用数学回归分析方法来做服务器容量规划的思路&#xff0c;让读者掌握服务器容量规划的量化方法&#xff1b;模型的选择是服务器容量规划的关键&#xff0c;不同的程序有不同的模型。本书使用nginxPHPMySQL为实例演示了具体的规划过程&#xff0c;…

穿越火线全部服务器都显示爆满,穿越火线大区全部爆满,频道挤不进去背后的故事!...

大家好我是小包子&#xff0c;穿越火线经历了十一周年&#xff0c;盛典游戏更新后&#xff0c;我们发现游戏基本上所有大区都呈现爆满的盛世。我们热爱的穿越火线又回来了吗&#xff1f;6月小包子曾爆料CF启动量超过吃鸡跃居第二&#xff0c;射击游戏第一&#xff0c;重回巅峰的…

服务器加根网线用不用修改路由器,安装设置无线路由器需要用几根网线?

“安装设置无线路由器需要用几根网线&#xff1f;看到网上安装设置路由器的教程&#xff0c;有的说需要两根网线&#xff0c;有的说需要一根网线&#xff0c;请问到底应该使用一根还是两根呢&#xff1f;”其实这个问题的答案并不是唯一的&#xff0c;使用一根还是两根&#xf…

大数运算#

大数&#xff0c;就是C/C中利用基本类型所不能存储的数字&#xff0c;少则数十位&#xff0c;大则几万位&#xff0c;如何存储和计算大数就是本文的内容。 在C和C中&#xff0c;没有存储大数的数据结构&#xff0c;就算 unsigned long long也只能表示19位的数字  如果我们用d…

linux之缓冲区

行缓冲。在这种情况下&#xff0c;当在输入和输出中遇到换行符时&#xff0c;标准I/O库执行I/O操作。这允许我们一次输出一个字符&#xff0c;但只有在写了一行之后才进行实际I/O操作。当流涉及一个终端时&#xff0c;通常使用行缓冲。 第一个例子&#xff1a;&#xff08;he…