TSG LIVE! 6 CTF Writeup

# 概要

[TSG LIVE! 6 CTF](https://live-ctf.tsg.ne.jp/) に1人チームで参加した。
結果は150点で、50チーム (正の点数を取ったのは24チーム) 中16位だった。

[問題&PoCファイル](https://github.com/tsg-ut/tsg-live-ctf-6)

# 解けた問題

## Truth about Pi (Web)

サーバーのプログラムを表すと考えられるJavaScriptのソースファイルと、2個のjsonファイルが与えられた。

以下のJavaScriptコードの`index`に当てはまるデータをフォームから送り、`digit`が0になるようにするとflagが得られる。

```js
const pi = Math.PI.toString();
const digit = parseInt(get(pi, index));
```

ここで使われている`get()`関数は、[Lodashの`_.get()`](https://lodash.com/docs/4.17.15#get)であると考えられる。
この関数は、文字列で表されたオブジェクトのプロパティを取得できるようだ。

Firefoxのブラウザーコンソールでいろいろ試した所、`index`に`valueOf.length`を入れれば0が得られることがわかった。

フォームの入力欄は`type="number"`となっているので、ここを開発者ツールで`type="text"`に書き換えた後、
`valueOf.length`を入力して送信することで、flagが得られた。

```
TSGLIVE{I_have_ZERO_knowledger_about_ZERO}
```

## Single RSA (Crypto)

3個の数値`N, e, c`が書かれたテキストファイルと、それを生成したと考えられるPythonのソースコードが与えられた。

このソースコードによれば、素数`p`を用いて、`N`は`p`、`e`は固定、`c`は`flag`を`e`乗して`N`で割った余りとなっている。
また、`d = pow(e, -1, phi)`という意味深な文が書かれていた。 (`phi`は`p`から1を引いた値である)

Pythonのインタラクティブモードを用い、この`d`を計算した後、`c`を`d`乗して`N`で割った余りを求め、
その値を文字列(以下のコードでは`ans`)に変換することで、flagが得られた。

```py
ans = ""
value = pow(c, d, N)
while value > 0:
  ans = chr(value & 0xff) + ans
  value >>= 8
```

```
TSGLIVE{Two_heads_are_better_than_one,_even_if_the_one's_a_poor_cryptographer's.}
```

# 解けたかと思った問題

## decompile me (Rev)

ELFファイル`bf`と、それを生成したと考えられるPythonのソースコード`compiler.py`が与えられた。
ELFファイルをTDM-GCCの`objdump`を用い、
`-d`オプションや`-D`オプションで逆アセンブルしようとしたが、結果は空だった。
そこで、

```
C:\MyInstalledApps\TDM-GCC-64\bin\objdump -m i8086 -M x86-64 -b binary -D bf > dump.txt
```

というコマンドを実行したところ、逆アセンブルを行うことができた。

さらに、`compiler.py`を読むと、単純なパターンに基づいてBrainf*ckのプログラムを変換しているようだった。
そこで、それに合わせて、逆アセンブル結果からBrainf*ckのプログラムを出力する以下のプログラムを書き、実行した。

<details><summary>parse.pl</summary><div>

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

use strict;
use warnings;

my @prev = ();
while(my $line = <STDIN>) {
	chomp($line);
	if ($line =~ /inc\s+\%rbx/) {
		print ">";
	} elsif ($line =~ /dec\s+\%rbx/) {
		print "<";
	} elsif ($line =~ /inc\s+\%al/) {
		print "+";
	} elsif ($line =~ /dec\s+\%al/) {
		print "-";
	} elsif ($line =~ /syscall/) {
		if ($prev[@prev - 4] =~ /mov\s+\$0x0/) {
			print ",";
		} elsif ($prev[@prev - 4] =~ /mov\s+\$0x1/) {
			print ".";
		}
	} elsif ($line =~ /je/) {
		print "[";
	} elsif ($line =~ /jne/) {
		print "]";
	}
	push(@prev, $line);
}
```

</div></details>

その結果、以下の出力が得られた。 (見やすいように手動で改行を補っている)

<details><summary>得られたBrainf*ckのプログラム</summary><div>

```brainfuck
>,>>+++++++[<++++++++++++>-]<[<->-]<[<+>[-]]<
>,>>+++++++[<++++++++++++>-]<-[<->-]<[<+>[-]]<
>,>>+++++++[<++++++++++>-]<+[<->-]<[<+>[-]]<
>,>>+++++++[<+++++++++++>-]<-[<->-]<[<+>[-]]<
>,>>++++++++[<+++++++++>-]<+[<->-]<[<+>[-]]<
>,>>+++++++[<++++++++++++>-]<++[<->-]<[<+>[-]]<
>,>>+++++++[<++++++++++>-]<-[<->-]<[<+>[-]]<
>,>>+++++++++++[<+++++++++++>-]<++[<->-]<[<+>[-]]<
>,>>+++++++[<+++++++++>-]<-[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>+++++++[<+++++++++++++>-]<[<->-]<[<+>[-]]<
>,>>++++++[<++++++++++>-]<[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>+++++++[<+++++++++>-]<-[<->-]<[<+>[-]]<
>,>>+++++[<+++++++++>-]<[<->-]<[<+>[-]]<
>,>>+++++++[<+++++++++++++>-]<++[<->-]<[<+>[-]]<
>,>>++++++[<++++++++++>-]<[<->-]<[<+>[-]]<
>,>>++++++[<+++++++>-]<+[<->-]<[<+>[-]]<
>,>>+++++++++[<++++++++++++++>-]<-[<->-]<[<+>[-]]<
>+<[>->>++++++[<+++++++++++++>-]<.>>+++++++[<++++++++++>-]<+.>>++[<+++++>-]<.<<<<[-]]>[->++++++++[<++++++++++>-]<-.>>+++++[<+++++++++++++++>-]<.>>++[<+++++>-]<.>]
```

</div></summary>

このプログラムの出力を[オンラインBrainf*ckデバッガ](http://moon.kmc.gr.jp/~prime/bf/env/)に入れ、
flagの書式に基づく適当な入力`TSGLIVE{aaa}`を入れて実行したところ、生成されたBrainf*ckのプログラムは
「正解の文字を作り、それが入力と一致しているか比較する」という動作を繰り返しているようだった。

さらに、ブレークポイント(上記ツールでは`@`)を追加して観察したところ、正解の文字は`[<->-]`の直前で完成するようだった。
そこで、この位置にデータを出力する命令`.`を追加して実行したところ、以下のflagのような文字列が得られた。

```
TSGLIVE{>+++++++[<++++++++++++>-]<+}
```

これを提出しようとしたところ、競技の終了時刻を約7分過ぎており、提出ができなかった。
したがって、これが本当に正解のflagかはわからない。

# 反省

制限時間が短いにもかかわらず、1問(b64dir)に固執して時間を無駄に使ってしまった。
そのためか、flagのような文字列が得られたのに提出ができないという事態を発生させてしまった。
このような場合は、問題は最初に一通り読み、解けそうな問題から取り組むべきだっただろう。