学校対抗CTF大会 作問者 writeup

# はじめに
大阪大学CTFサークル Wani Hackase の Mikka です。

先日、総務省の近畿総合通信局が開催していた [学校対抗CTF大会](https://www.soumu.go.jp/soutsu/kinki/01sotsu07_01002090.html) に 主催協力 兼 参加者 として現地参加してきました。

### 大学対抗 CTF について

"7割解けるCTF"というコンセプトのもと、比較的簡単な問題を大量に解くタイプの初心者向けCTFです。

解く速度が速くはないCTF初心者でも新しい知識やアイデアにたくさん触れられるので、個人的にはかなり好きなコンセプトです。

<br>
上級者コースは作問者も参加する都合上、ABコースに分かれています。

私は初心者用と上級者Bコース用に作問して、上級者Aコースで参加しました。

# 作問者 writeup

## anon_ext

### 問題文

ファイルの開き方が分かりません！

### 作問方針

file コマンドを知ってもらい、自分でコマンドを調べて実行するという体験とともに、forensics 入門の第一歩にしてほしい。

### 解法

拡張子が不明なファイル `chal_anon_ext`が渡されます。

`file chal_anon_ext`

`chal_anon_ext: GIF image data, version 89a, 123 x 123`

と file コマンドで確認する他、バイナリエディタでヘッダに`GIF89a`とあることを確認するなどして、GIF ファイルであることを特定します。

拡張子を`.gif`に変更することで、FLAG が取れます。

~~GIF はヘッダのシグネチャが分かりやすくて好きです~~

## treasure_hunt

### 問題文

お宝というのは、どこかに埋まっているものです。

### 作問方針

解法が分からないときは一度落ち着いて、そもそも ○○ ってなんだろう？と検索する考え方を知って欲しい。

### 解法

.docx ファイルが渡されます。word で開くと

```
「ここにFLAGが隠されているらしいけど……」
「どこかに埋められているのかも！」
```

とだけ書かれています。本文から FLAG は取れそうにありません。

ところで、docx ファイルの中身は関連ファイルを zip 形式で圧縮したものになっています。
(docx についてググればどこかに書いてあるはず)

よって、拡張子を.zip に変更し、展開します。

ファイルがたくさん出てきますが、`word`ファイルの中の`document.xml`が本文に相当する部分ですので、そこを見に行きます。

FLAG がコメントアウトされて書かれています。

<br>
ところで、先生が解説中に「このwordファイルは特殊な作り方をされている」といった解説をされていましたが、一般のwordファイルでもzipにして展開できます。

## password_protected

### 問題文

パスワードで暗号化したので大丈夫！

### 作問方針

コマンドを打つ必要がない、誰でも解ける forensics 問題

### 解法

暗号化された zip ファイル`chal_password_protected`が渡されます。

展開しようとするとパスワードを求められます。

しかし、暗号化された zip ファイルは仕様上、中身のファイル名は暗号化されていないので、見ることができます。

windows ならダブルクリックする等してファイル名を確認すると、ファイル名に zip のパスワードが書かれています。

これを使えば`FLAG.png`を取り出せます。

## gitty

### 問題文

Python のプログラムを作って、git で管理しています！
https://github.com/Mikka-t/chal_gitty

### 作問方針

git に慣れてほしい。色々な所で使うので。

### 解法

`git clone`してきてもいいですが、まずは github のページを見に行きます。

![githubページ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609800/9916181d-3b56-0434-c687-c51e2385cbb7.png)

この`8 Commits`という所をクリックすると、過去のコミット(更新履歴)を見ることができます。

![commits](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609800/f6757eec-9716-472e-c2b2-45bfb06d6abd.png)

`generate_password: delete seed`という怪しげなコミットがあるのでこれを見ると、FLAG が書かれています。

<br>
他にも同じようなgit問題を作問された方がいらっしゃったみたいで、被っちゃいました。

こちらはコマンドを打つ必要がなく web 上で完結するので、初心者用に難易度を下げたものだと考えて大目に見てください……

## RingRing

### 問題文

誰かが電話をかける音が聞こえました。入力した番号が分かるかもしれません……
なお、最初の3つは「080」であることが分かっています。
画像は周波数解析ツールでこの音声を解析したときの画面です。


### 作問方針

調べるだけで解ける、ググり力を養う問題
誰でも身近にありそうなシチュエーションの問題

### 解法

wav ファイルと画像ファイルが渡されますが、wavファイルを開く必要はありません。

![周波数の画像ファイル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609800/4c168ca2-6099-7a88-dc64-6ccd40efd1d0.png)

"電話番号 周波数" で検索するなどして、[DTMF](https://ja.wikipedia.org/wiki/DTMF) の規格を調べに行きます。

wiki の DTMF マトリックスと画像を見比べると、番号が分かります。

最初の3つが080なので、最初の3つの高音は1336 Hz、低音は941 Hzと852 Hzであることが分かります。

0~9 の数字に対応する高音は3種類しかなく、低音は4種類であり、画像には全ての周波数が記録されているので、高低差を見れば全ての音の周波数が分かります。

<br>
現地会場でたまにﾋﾟﾎﾟﾊﾟﾎﾟ聞こえてきて面白かったです

## name_it

### 問題文

Ghidra, IDA, Radare2... you name it!
※Ghidra 等のリバースエンジニアリングツールの使用を前提としています

### 作問方針

初心者でも頑張れば解ける程度の上級者用 reversing 問題

### 解法

Ghidra で解析してみます。

```c
undefined8 main(int param_1,char **param_2)

{
  char *pcVar1;

  if (param_1 < 1) {
    puts("Try other execution methods.");
  }
  else {
    pcVar1 = strstr(*param_2,"nailed_it");
    if (pcVar1 == (char *)0x0) {
      puts("Oops...");
    }
    else {
      puts("Congrats!");
      pcVar1 = (char *)constructFlag();
      puts(pcVar1);
    }
  }
  return 0;
}
```

`Congrats!`というメッセージの後に`constructFlag()`が実行されているので、ここを目指すのだろうと予想がつきます。

`param_2`は関数`main`の引数なので、コマンドライン引数です。

`strstr`で`*param_2`と文字列`nailed_it`を見ており、戻り値が 0 でなければ良さそうです。

ところで、`*param_2`はコマンドライン引数が格納された配列の先頭へのポインタです。つまり`argv[0]`です。

`strstr`が 0 以外を返すのは検索文字列が見つかったとき、すなわち`argv[0]`が文字列`nailed_it`を含んでいたときです。

よって`argv[0]`、すなわち実行ファイル名に`nailed_it`が含まれていればよいことが分かります。

あとは実行ファイルの名前`chal_name_it`を`nailed_it`に変更して実行すれば FLAG が取れます。

# 上級者用問題 writeup (参加者として)

# Forensics

## 実行ログ解析 ①

```
(前略)
画像に示すファイルの拡張子を回答してください。
```

csv でログファイルが渡される。画像には`Dowload\Invoice_1016\Invoice_1016\Invoice`というファイルが写っている。

csv 内で検索すると Invoice.lnk というファイルであったことが分かる。

## 実行ログ解析 ②

```
(前略)
外部URLからマルウェアがダウンロードされたようです。ダウンロード先のドメインを回答してください。
```

目 grep してみると powershell がとても長いコマンドを実行していた。

`'70-6f-77<65Q72-`で始まっており、`-SplIT '-'-SplIT'M' `などで難読化されているのでとても怪しい。

難読化を戻して ASCII で直せば、powershell に wget コマンドを実行させていることが分かったので、そのドメインが答え。

## 実行ログ解析 ③

```
攻撃者はある脆弱性を利用して、端末AからActiveDirectoryへのアクセスを行ったようです。脆弱性をCVE ID形式(CVE-〇〇〇〇-〇〇〇〇)で回答してください。
```

地道にググっても良かったが、chatGPT に聞いてみたら答えてくれた。

問題文と、関係していそうなログをいくつか、そして lnk ファイルに攻撃コマンドが埋め込まれていること、その実行をきっかけに powershell が外部 URL からマルウェアをダウンロードしていることなど、現状を適当に説明した。

```
(前略)
この攻撃は「CVE-2020-1472」または通称「Zerologon」として知られています。
```

なお、貼り付けたログには`lsadump::postzerologon`という文字列が含まれていた。

chatGPT はこの文字列から攻撃を推測したと思われる。明らかに私の説明は不足していたので。

# Misc

## Leaked AI Key

```
アプリケーションに使っているAPI Keyが流出した模様。でも流出したAPI Keyが見つけられない。
流出したAPI Keyを教えて。
```

アプリケーションのリポジトリが.git ごと渡されている。

もしやと思って過去の commit を見ていけば、API Key が書いてある commit を発見した。

<br>
(やっべ問題被っちゃった！)

## 難読化入門

```
powershellスクリプトに正しいFLAGを入力してください
```

powershell スクリプトがそのまま渡される。

```ps
$input=Read-Host "FLAGを入力してください"
$flag=91,77,95,100,47,39,82,38,57,59,47,49,72,65,108,78,66,87,74,109
$input_char=$input.ToCharArray()
$i=1
foreach($char in $flag){
   If((((([Byte][Char]$input_char[$i-1])+$i*4-32)%96)+32) -ne $char ){
     Write-Host "WRONG"
     exit
   }
   $i=$i+1
}
Write-Host "CORRECT"
```

逆変換する。

```py
flag = [91,77,95,100,47,39,82,38,57,59,47,49,72,65,108,78,66,87,74,109]
for i, _ in enumerate(flag, start=1):
    print(chr(((flag[i-1]-32-i*4)%96)+32), end='')
```