#ctf-wiki
##off-by-one
1-只能修改一个字节,溢出可控字节,通过修改堆块大小造成堆重叠从而覆盖或泄露其他数据。
2-溢出NULL字节可以使prev_inuse位被清0,前块会被认为是free块,从而造成堆重叠。
下面以该题作为演示
Asis CTF 2016 b00ks
__int64 __fastcall over_one(_BYTE *chunk, int size)
{
int i; // [rsp+14h] [rbp-Ch]
if ( size <= 0 )
return 0LL;
for ( i = 0; ; ++i )
{
if ( read(0, chunk, 1uLL) != 1 )
return 1LL;
if ( *chunk == 10 )
break;
++chunk;
if ( i == size )
break;
}
*chunk = 0;
return 0LL;
}
这里最后有NULL溢出。
.data:0000000000202010 chunk_array dq offset unk_202060 ; DATA XREF: find_temp:loc_B38↑o
.data:0000000000202010 ; delet:loc_C1B↑o ...
.data:0000000000202018 off_202018 dq offset unk_202040 ; DATA XREF: change+15↑o
这里可以发现off_202018(author)与chunk_array只相差了0x20个字,因此我们可以写入0x20个字符,然后打印溢出chunk_array所存储的地址。
关键的地方来了,我们可以通过适当的调整size大小,使得prt_des的后两位正好是00,然后再修改author,使得chunk_array【0】指向了ptr_des。若此时我们再在des中伪造了一个结构体,并使chunk_array可以索引到book2,这样就形成了堆重叠。可以分配edit book1 ,book2来修改free_hook。
那么我们先create两个book,经过调试发现,当name_size为0x20时ptr_des的位置符合需求。而第二个book有通过vmmap泄露libc_base 的功能,所以需要很大的空间,使系统单独映射一段内存从而泄露libc
1.首先通过填满author泄露chunk_array【1】所存储的struct_book1 的地址。

2.在book1的des段填充数据使其存储book2的ptr_name ptr_des
3.然后通过打印泄露出book2的各种地址
4.之后再次填充author使得chunk_array【1】指向了book1的des段。
5.最后edit_book1写入free_hook,再edit_book2写入one_gadget,然后执行free函数即可get_shell

调试libc偏移




