House of force

溢出修改topchunk的size,分配一个使size_t溢出的evil_size,使下一次分配在目标位置,进行修改。

1
2
3
4
5
6
7
8
9
/*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = dest - 2sizeof(long) - old_top - 2sizeof(long)
* req = dest - old_top - 4*sizeof(long)
*/

Bctf2016 bcloud

分析

1
2
3
4
5
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x8047000)

程序一开始让输入name、org、hostname,输入字符串函数存在null byte overflow。

输入name函数中,字符串数组在栈中后部紧邻指针变量,所以strcpy会将该指针一并拷贝入0x40的空间(实际可用0x44),并且null byte覆盖topchunk的最低字节。可以泄露堆的地址

输入org、hostname函数中,存在同样问题,可覆盖的更多的字节。可以覆盖topchunk的size

程序功能菜单

1
2
3
4
5
6
1.New note
2.Show note
3.Edit note
4.Delete note
5.Syn
6.Quit

new note: 读入size存入全局数组,分配size+4的空间将指针也存入全局数组,读入字符串

show note: 打印WTF? Something strange happened.

edit note: 修改存储的内容,根据size数组和指针数组

delete note: free分配的空间

syn: 修改sync标识。在这里没用

思路

在input_name函数中,泄露堆的地址,由此可以计算evil_size;在input_orghost中覆盖topchunk的size为0xffffffff。使用atoi_got、free_got覆盖bss段所存储的全局指针数组,使用edit note函数将free_got处修改为puts_plt,使用delete note函数泄露libc base,最后使用edit note 修改atoi_got为system函数地址。

House of force

这个手法还是比较简单的,就是一开始没有找到漏洞。。只发现了null byte overflow。

使用input_orghost函数覆盖topchunk->size为0xffffffff,接下来就是计算evil_size了。

泄露的heap地址为分配的第一个0x40地址,称之为leak_heap。leak_heap+0x40就是此时的topchunk,后来又分配了两个0x40,此时topchunk = leak_heap + 0x40 + 0x48*2。到目标地址,还需要分配两个chunk,也就有两个8字节的头,new note中又加了4字节,所以evil_size = dest_addr - topchunk - 8*2 - 4

exp中,直接发送这个负值就可以,int到size_t,其中所存的数字没有变化,只是两种类型的解读不一样。原来我想发送unsigned值(evil_size&0xffffffff),结果发现32位程序中atoi只会将其解析为4字节int最大的正数,即0x7fffffff。

exploit

Reference

  1. how2heap house_of_force.c
  2. https://uaf.io/exploitation/2016/03/20/BCTF-bcloud.html