CyberRebeatCTF2018 Write-up

CyberRebeatCTFとは

ennach.sakura.ne.jp

CyberRebeatは、サークルE.N.Nachが制作したノベルゲームのタイトルです。 この作品はサイバーセキュリティや、ハッカー、CTFなどを題材としており、 その題材の珍しさや高いクオリティが評価され、日本国内で各種の賞を受賞しました。 本イベントは当該作品の英語版がSteamにてリリースされたことを記念して、より多くの方にCTFを楽しんでいただこうと企画されました。

成績

1人で参加してこんな感じでした.
32位/177チーム(参加人数:270人)

f:id:satto1237:20180909160550p:plain

f:id:satto1237:20180909210959p:plain

[Exercise]

Exercise

CRCTF{CyberRebeatCTF}

CRCTF{CyberRebeatCTF} を提出するだけです.

[Crypto]

Rotation

P4P6S{9RN4RUNPXR45}

アプローチ:rot13 -> 換字式暗号
問題文的にrot13だと思ったのでrot13してみるとC4C6F{9EA4EHACKE45}になります.
次に数字は換字式暗号っぽいなと思ったので4 -> R, 6 -> T, 9 -> W, 5 -> S に変換します.
最終的にflagCRCTF{WEAREHACKERS}になります.

[Misc]

Readme

Readme.

f:id:satto1237:20180909162549j:plain

アプローチ:Electroharmonixを頑張って読む
image.jpgを見るとElectroharmonixというフォントを使ったものだと分かるので下記のサイトの変換表?を見ながらflagを読み解きます.
最終的なflagCRCTF{YOUCANPLAYCYBERREBEATINBOTHLANGUAGES}です.

www.dafont.com

[Programming]

Calculation

nc 59.106.212.75 8080

アプローチ:Pythonで自動化
nc 59.106.212.75 8080をすると四則演算が降ってくるタイプので問題です.
手でやるのはめちゃくちゃしんどいのでPythonで自動化します.
20問解くとflagがでます.
CRCTF{She calls herself a human calculator}

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from socket import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(('59.106.212.75', 8080))

def read():
    res = s.recv(4096).decode('utf-8')
    # print(res)
    return res

for i in range(100):
    print('count: {}'.format(i))
    res = read()
    problem = res.split('\n')[0]
    print(problem)
    if res == '\ufeff':
        continue
    ans = str(eval(problem))
    s.send(ans.encode('utf-8')+b'\n')
    print(ans)

Prime Factor

Answer the maximum prime factor.
nc 59.106.212.75 8081
example:
Question:120
Answer:5 (Prime Factors: 2, 3, 5)

アプローチ:そこそこ速い素因数分解アルゴリズムを使う
基本的な流れはCalculation と同じですが,弱い(遅い)素因数分解アルゴリズムを使うと計算が終わらないので注意する必要があります.
自分はsympyというPythonのライブラリを使いました.
25問解くとflagがでます.
CRCTF{I'm a calculating type by nature.}
Number Theory — SymPy 1.3 documentation

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from sympy import factorint
from socket import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(('59.106.212.75', 8081))

def read():
    res = s.recv(4096).decode('utf-8')
    # print(res)
    return res


for i in range(100):
    print('count: {}'.format(i))
    res = read()
    print(res)
    if res == '\ufeff':
        continue
    number = res.split('\n')[0]
    print(number)
    prime_dict = factorint(int(number))
    ans = str(max(prime_dict.keys()))
    print(ans)
    s.send(ans.encode('utf-8')+b'\n')

Visual Novels

nc 59.106.212.75 8082
あるユーザーは"Reading Power"を持っている。
これはVisualNovelを月にどのくらい読めるかを示している。
彼がたくさんのVisualNovelを持っているとき、彼はどの組み合わせでプレイすればその月の満足度を最大にできるか。
最大の満足度を答えよ。

example:
Reading Power = 30
Games([size, satisfaction]) =
[10, 1],
[21, 2],
[12, 3],

Answer : 4

アプローチ:パースしてDPする
基本的に前の2問と同じですが,典型的なナップサック問題を解く必要があるので条件をパースしてDPします.
10問解くとflagがでます.
CRCTF{Believe in the high efficiency processor installed in your head.}

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from socket import *
import re
import numpy as np

s = socket(AF_INET, SOCK_STREAM)
s.connect(('59.106.212.75', 8082))

def read():
    res = s.recv(4096).decode('utf-8')
    # print(res)
    return res

def dp(power, sizes, satisfactions):
    dp_table = [[0 for j in range(power + 2)] for i in range(len(sizes))]
    backtrack = [[0 for j in range(power + 2)] for i in range(len(sizes))]

    # initialization
    for y in range(power + 1):

        if sizes[0] <= y + 1:
            dp_table[0][y] = satisfactions[0]
            backtrack[0][y] = 1
        else:
            backtrack[0][y] = 0

    # DP construction
    for k in range(1, len(satisfactions)):
        for y in range(power + 1):
            if y - sizes[k] < 0: # out of range
                dp_table[k][y] = dp_table[k - 1][y]
                backtrack[k][y] = 0
                continue
            left = dp_table[k - 1][y]
            right = dp_table[k - 1][y - sizes[k]] + satisfactions[k]
            if left < right: # update
                dp_table[k][y] = right
                backtrack[k][y] = 1
            else:
                dp_table[k][y] = left
                backtrack[k][y] = 0

    argmax = []
    prev = backtrack[len(satisfactions) - 1][power - 1]
    argmax.append(prev)

    tmp_power = power - 1

    for k in range(len(satisfactions) - 2, -1, - 1):
        if prev is 1: # case previous item was selected
            tmp_power -= sizes[k + 1]
            prev = backtrack[k][tmp_power]
        else:
            prev = backtrack[k][tmp_power]
        argmax.append(prev)
    argmax.reverse()

    # print(dp_table)
    # print(backtrack)
    print(argmax)
    arr_argmax = np.array(argmax)
    arr_satisfactions = np.array(satisfactions)
    ans = np.dot(arr_argmax, arr_satisfactions)

    print(ans)
    return ans


for i in range(100):
    print('count: {}'.format(i))
    sizes = []
    satisfactions = []
    res = read()
    if res == '\ufeff' or res == '\n':
        continue

    print(res)
    lines = res.split('\n')
    for line in lines:
        if 'Power' in line:
            power = int(line.split(' ')[-1])
        if '?' in line:
            break
        if line.count(',') > 1:
            num_list = [ x for x in re.split('[, ]', line) if len(x) > 0]
            sizes.append(int(num_list[0][1:]))
            satisfactions.append(int(num_list[1][:-1]))
    ans = str(dp(power, sizes, satisfactions))
    s.send(ans.encode('utf-8')+b'\n')
    print('send')

[Recon]

Tweet

Let's check our official twitter account!

アプローチ:Twitterを見に行く
CRCTF{CyberRebeatCTF_has_started!}

CyberRebeatScripts

Do you know Github?

アプローチ:Githubリポジトリを見に行く
delete FLAGというcommitがあるので編集差分を確認します.
CRCTF{I cut down her gag in a single strike}

github.com

ChangeHistory

I changed my history on Github!

アプローチ:gitの使い方のお勉強

当該リポジトリに行ってみると怪しいissueがたってる.

github.com

とりあえずgit cloneしてgit loggit reflogをしてみるが手がかりなし.
git refloglocal logしか取得できなかったのでなんとかremote logを取得する方法を調べる.

stackoverflow.com

上記サイトによるとcurl https://api.github.com/repos/ennach/ChangeHistory/eventsしてcommit idc476614bc439fe1910e494422b3aa207b776d486のURLを見つけるといいらしい.

https://api.github.com/repos/ennach/ChangeHistory/commits/c476614bc439fe1910e494422b3aa207b776d486

上記サイトで変更前のデータが見れるのでflagがとれる
CRCTF{the timer is set to 120 seconds}

[Stegano]

Secret.pdf

It's a secret pdf!

アプローチ:とりあえずopen
とりあえずopen secret.pdfする
flag部分が黒塗りされてるが文字選択でぬける.
CRCTF{I don't know of a time without the internet}

f:id:satto1237:20180909171815p:plain

Alpha

f:id:satto1237:20180909172105p:plain

アプローチ:alpha.pngのα値を調べる
問題名的にpngのα値を調べろということっぽいので簡単なスクリプトを書いて調べる(スクリプト書くよりも既存のツールを使ったほうが速いです).
ほとんどのPixelのα値が253であることが分かる.
怪しいのでα値が253以外のPixelを抜き出すスクリプトを書く.
CRCTF{ALPHA_IS_THE_NAME_OF_A_HACKER_IN_CYBERREBEAT} f:id:satto1237:20180909172431p:plain

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PIL import Image
import numpy as np

img = Image.open('./alpha.png')

size = img.size

flag_img = Image.new('RGBA',size)

for x in range(size[0]):
    for y in range(size[1]):
        #ピクセルを取得
        rgba = img.getpixel((x,y))
        #print(rgba)
        if rgba[3] != 253:
            flag_img.putpixel((x,y),(255,255,255,255))
        else :
            flag_img.putpixel((x,y),(0,0,0,255))
        
flag_img.show()
flag_img.save('./flag_img.png')

[Trivia]

Monero

ウェブ上からMoneroを発掘するソフトウェア。
日本で、自身のウェブサイト上にこのソフトを設置した何人かのユーザが逮捕されている。
フラグはすべて小文字。
例: CRCTF{abcdefgh}

アプローチ:日頃からセキュリティ関連のニュースをチェックしておく
これはcoinhiveのことですね.
CRCTF{coinhive}

Crossword

crossword_text.txt
FLAG:CRCTF{ABCDEFGH}
Flag format: all lowercase

f:id:satto1237:20180909173123p:plain

横
1. ___ はCyberRebeatにおける特殊なコードネーム。CyberRebeatは、ハッカーたちがこれを打倒する物語。『ぴったりだと思わないか、ええっ、英雄(ヒーロー)?』
5. CyberRebeat作中における、とあるハッカーの切り札。______はネットに接続された多数のデバイスで、それぞれがひとつあるいは複数のBOTを実行している。
8. heroine.png / 彼女の名前:____ Amamiya
10. CyberRebeatシナリオライターの代表作:__:____ ~親愛なるあなたへ~
11. CyberRebeatのキャッチフレーズ:We are h_____.
15. W_______はWindowsを実行しているコンピュータをターゲットとした、データを暗号化しBitcoinでの身代金支払いを要求するランサムウェアです。
16. CyberRebeatのシナリオライター
18. CRCTFを主催している同人サークル
19. 運営協力 : __________ Institute, Ltd., Aqutras Inc.
20. ______ はインターネットとセキュリティソフトウェアのクライアントのSSL 3.0へのフォールバックを利用した中間者攻撃です。
21. __________はBashdoorとも呼ばれ、Unix Bashシェルのセキュリティバグの一種であり、2014年9月24日にはじめて公表されました。

縦
2. Operation ______は、中国北京のElderwood GroupのようなAPTが人民解放軍と連携して行った一連のサイバー攻撃のこと。
3. CyberRebeatで利用しているゲームエンジン
4. CyberRebeatのイラストレーター:Kikyo ______
6. smile.min.svg
7. _____ Rain は、米国連邦政府が定義した2003年からのアメリカのコンピュータシステムに対する一連の組織的な攻撃のこと。
9. CyberRebeatのデザインおよび背景イラスト担当
12. 翻訳協力 : __________
13. CRCTFを主催している同人サークルが制作したノベルゲームの名称
14. https://store.____________.com/app/825320/CyberRebeat_The_Fifth_Domain_of_Warfare/
17. heart.png

アプローチ:クロスワードを解く

2. Aurora
3. Unity
4. Manose
10. Re:LieF
11. hackers
12. SekaiProject
13. CyberRebeat
14. steampowered
15. wannacry
18. e.n.nach
19. activedefence
20. poodle
21. Shellshock

CRCTF{ABCDEFGHI}
CRCTF{submarine}

フラグはCRCTF{submarine}になります.

[Web]

White page

http://hidden-field.cyberrebeat.adctf.online/index.php
id: Hiro
password: LittleGarden

f:id:satto1237:20180909173742p:plain

アプローチ:curlでid,passをPost
Webサイトにアクセスしてみると問題名の通り,White pageになっています(Loginボタンがあるだけ).
ソースコードを確認しみてると以下のようになっています.

<body>
  <form action="index.php" method="post">
   <input type="text" name="id" style="visibility:hidden" />
   <input type="text" name="password" style="visibility:hidden" />
   <button>LOGIN</button>
  </form>
</body>

id,passwordの入力フォームがvisibility:hiddenになっているため,このままでは入力できないことがわかります.
そのため,curlを使用してid, passwordPOSTします.
curl http://hidden-field.cyberrebeat.adctf.online/index.php -X POST -d "id=Hiro&password=LittleGarden"
ログインに成功してflagがとれます.
CRCTF{All I typed were four letters.}

Let's Tweet!

http://tweet.cyberrebeat.adctf.online/LetsTweet.php
LetsTweet.php

アプローチ:ついーとする
この問題は正直よく分かりませんでした.
phpソースコードを確認するとtest.dbを読み込んでいることが分かるのでディレクトリトラバーサルtest.dbを抜こうとしたのですが,Not Foundが返ってきて詰みました.
仕方なく,ツイートのリンクを使ってflagをとりました.
CRCTF{Thank_you_for_your_tweet!}

Uploader

Find the secret file.
http://sqli.cyberrebeat.adctf.online/index.php
id: guest
pass: guest

f:id:satto1237:20180909175342p:plain

アプローチ:SQLi -> Blind SQLi
とりあえずFile Name :SQLiしてみるとharadaというユーザがsecret.zipをアップロードしていることが分かります.

f:id:satto1237:20180909175444p:plain

次に問題文にあったid,passでログインしてみるとsample.zippasswordを閲覧できることがわかります.
そのため,haradapassを探し出し,ログインに成功したらsecret.zipunzipできることがわかります. f:id:satto1237:20180909175821p:plain

haradapassを探すためにBlind SQLiしなければいけないのですが,自分はSQLi Beginnerなのでsqlmapに頼りました.

qiita.com

上記のサイトを参考にUsersテーブルdumpします.

sqlmap -u 'http://sqli.cyberrebeat.adctf.online/index.php' --data 'file_name=aaa&search=search' --dump -T Users

f:id:satto1237:20180909180318p:plain

userid password
guest guest
harada seishin0129

pass:seishin0129を使ってuser:haradaとしてログインするとzippasswordを得ることができます.

f:id:satto1237:20180909180625p:plain

上記のpasssecret.zipunzipしてあげるとflagがとれます.
CRCTF{Today's_internet_is_full_of_concerning_vulnerabilities}

[Binary]

0完
f:id:satto1237:20180909181011p:plain

1問目のSimpleBinaryを解きながら「これのどこがシンプルなんだよ???」とキレてた.
Binary全然わからん…Binary強くなりたい…

まとめ

  • 土日を持っていかれた
  • 生活リズムが崩壊した(現在インターン中なので月曜の朝がつらそう)
  • Binaryぜんぜんわからん
  • CTFを始めて数ヶ月経って少しずつ解ける問題が増えてきたことを実感できたので嬉しかった
  • CyberRebeatめっちゃ気になる

store.steampowered.com