-
use after free
free之后的变量,该变量的堆内存处的内存指针还在指向该内存处,所以当我们下一次申请同样大小的变量时,可以申请到上一个变量的位置
使用gdb可视化观察堆
-
free()
-
观察堆
set disassembly-flavor intel
set pagination off
disassembly main
info proc mapping 查看内存映射
deine hook-stop
x/56wx 0x804c000
x/3i $eip
end
查看第一次malloc(32),该快已被标记not free
查看strcpy之后
每个地址4字节,每行16字节,即0x10大小
free(c)
现在就有个了新的块叫fastbins,这个c作为头
free(b)
链表fastbins:c←b
free(a)
链表fastbins:c←b←a
unlink (): 如果刚释放的堆块要与前面或者后面的堆块进行合并操作,那么需要把前面或者后面的堆块从双向链表中摘取下来,合成更大的堆块插入到别的bin之中,将空闲堆块从bin里面摘取下来的操作就是unlink
/* consolidate backward 往前合并*/ //先检查要free chunk的上一个chunk是不是 in_use,不是的话就往下操作 if (!prev_inuse(p)) { //取p的前一个chunk的size prevsize = prev_size(p); //free_chunk的size + 上一个chunk的size size += prevsize; //p指向上一个chunk的开始处 p = chunk_at_offset(p, -((long)prevsize)); if (__glibc_unlikely(chunksize(p) != prevsize)) //检查前后改变的chunk的size大小跟prev_size是不是相等 malloc_printerr("corrupted size vs. prev_size while consolidating"); unlink(av, p, bck, fwd); //这个就是我们要利用的地方了,下面有详解 }
P是从block we want to free的prevsize找到的previous block
FD是通过P的fd找到的,BK是通过P的bk找到的
用gdb模拟攻击
set {int}0x804c054=100,使得size这里的最尾位为0(freed)
再把prevsize设成0x10因为我们想要创造一个fake chunk,然后往前数0x10大小的chunk的size改成0x11代表in use.
然后把GOT表的put函数地址搞来,放在前面那个假装in use块的fd处
bk放heap里放shellcode的地址
注意一下,chunk空闲的时候FD和BK才发挥作用,如果非空闲那么从FD开始就是usedata了
-
free的时候会检查能否向前和向后合并
来自 :https://wooyun.js.org/drops/堆溢出的unlink利用方法.html
1)检查是否可以向后合并
首先需要检查
previous chunk
是否是空闲的(通过当前chunk size
部分中的flag
最低位去判断),当然在这个例子中,前一个chunk
是正在使用的,不满足向后合并的条件。2)检查是否可以向前合并
在这里需要检查
next chunk
是否是空闲的(通过下下个chunk
的flag的最低位去判断) ,在找
下下个chunk
(这里的下、包括下下都是相对于chunk first
而言的)的过程中,首先
当前chunk+当前size
可以引导到下个chunk
,然后从
下个chunk的开头+下个chunk的size
就可以引导到下下个chunk
。但是我们已经把
下个chunk的size
覆盖为了-4,那么它会认为
下个chunk
从prev_size
开始就是下下个chunk
了,既然已经找到了
下下个chunk
,那就就要去看看size
的最低位以确定下个chunk
是否在使用,当然这个size
是-4
,所以它指示下个chunk
是空闲的。在这个时候,就要发生向前合并了。即
first chunk
会和first chunk
的下个chunk
(即second chunk
)发生合并。在此时会触发unlink(second)
宏,想将second
从它所在的bin list
中解引用。具体如下
-
how computer handle negative values
cale in 32 bit : 0xFFFF FFFC + 0x64 = 0x60
the same to :-0x4 + 0x64 = 0x60
Null-Bytes :0xFFFF FFFC = -4
所以现在有两个要求:
1.因为要用双链表merge所以得size>80(因为要避免单链表fastbin < 80)
2.set prev not in use,last bit of the block we going to free is set to 0.
所以我们需要两个fake chunk,第一个用来伪造FD和BK来覆盖上GOT函数地址,第二个用来把size的最低位设为0.
而在查找size时候是用加offset来做的,不关心我们用了多大的size
然后我们把offset/size设成0xFFFF FFFC导致最后的结果为-4
这时候查找nextchunk的时候会找到我们仍set的ffff fffc的地方
然后就向后合并unlink了
-
利用unlink把shellcode写进put函数
Use After Free
最新推荐文章于 2024-04-21 16:41:46 发布