LoginSignup
13
7

More than 5 years have passed since last update.

Trend Micro CTF 2017 オンライン予選 Write-up

Last updated at Posted at 2017-06-25

superflipは10問解いて、29位。

Analysis-Offensive

100

問題のファイルがzipで、中にはfile_1、file_2、file_3が入っている。

file_1はJpeg画像。バイナリエディタで開くと、VHVyaW5nX01hY2hpbmVfYXV0b21hdG9uという文字列が見える。Base64で復号すると、Turing_Machine_automaton。file_2はzipで暗号化されたkey.txtが入っている。Turing_Machine_automatonで復号できる。中身は

src 192.168.30.211 dst 192.168.30.251
        proto esp spi 0xc300fae7 reqid 1 mode transport
        replay-window 32
        auth hmac(sha1) 0x2f279b853294aad4547d5773e5108de7717f5284
        enc cbc(aes) 0x9d1d2cfa9fa8be81f3e735090c7bd272
        sel src 192.168.30.211/32 dst 192.168.30.251/32
src 192.168.30.251 dst 192.168.30.211
        proto esp spi 0xce66f4fa reqid 1 mode transport
        replay-window 32
        auth hmac(sha1) 0x3bf9c1a31f707731a762ea45a85e21a2192797a3
        enc cbc(aes) 0x886f7e33d21c79ea5bac61e3e17c0422
        sel src 192.168.30.251/32 dst 192.168.30.211/32

file_3はpcapファイル。IPSecで暗号化されている。Wiresharkの設定のESPのところに↑の情報をポチポチすると、中身が読めるようになる。

HTTPでファイルをダウンロードしていて、そこには次の内容が書かれている。

M4 Navy
Reflector:C Thin, beta, I, IV, II (T M J F), Plugboard: L-X/A-C/B-Y

TMCTF{APZTQQHYCKDLQZRG}

APZTQQHYCKDLQZRG is encrypted.

前半部分は暗号化器エニグマの設定。エニグマのエミュレーターはググればたくさん出てくるけど、サイトによって設定項目がちょっと違って良く分からない。このサイトで復号した。

TMCTF{RISINGSUNANDMOON}

200

解けなかった。こんな動作をするWindowsのexeが与えられる。

C:\documents\ctf\trendmicroctf2017\offensive200>cracktheflag.exe
Validate Flag:43436447
Flag Validated!

入力した数値をnとして、以下の条件に合致すればFlag Valiadted!となる。

  • n[0:8], n[0:2], n[2:4]が素数
  • n[4:6]が2の冪乗
  • (n[0:4] ^ n[4:6]**2)>>8が0
  • ${n}Validate Flag:の文字コードの合計から0x120を引いた数が素数

nは8文字なので、全探索ができる。

def is_prime(n):
    if n==0:
        return False
    if n==1:
        return False
    i = 2
    while i*i<=n:
        if n%i==0:
            return False
        i += 1
    return True

def check(n):
    n = "%08dValidate Flag:" % n
    if not is_prime(int(n[0:2])):
        return False
    if not is_prime(int(n[2:4])):
        return False
    if n[4:6] not in ["01", "04", "09", "16", "25", "36", "49", "64", "81"]:
        return False
    if (int(n[0:4]) ^ int(n[4:6])**2) >= 256:
        return False
    if not is_prime(sum(map(ord, n)) - 0x120):
        return False
    if not is_prime(int(n[0:8])):
        return False
    return True

i = 0
while True:
    if check(i):
        print "%08d" % i
    i += 1

問題文に、「最大の値のものがフラグだよ」みたいな事が書かれている。最大のものは43436447。バリデートが通ると、flag.txtが出力されて、その中にはTMCTF{nの先頭6桁}が書かれている。

でも、TMCTF{434364}TMCTF{43436447}も通らない。なぜ……。

コード中にチェックは無いけど、n[0:6]も素数とのこと。そんなの知るか😩

追記。

このやり取りで、謎が解けた。パスワードは6桁だった。

問題文の「8 possible numeric passwords」これだと8桁の数字ではなく8個のパスワードにならない?とか、読み込み関数が読み込んだバイト数からなぜ2を引くのかとか、n[6:8]がなんとなくおざなりとか、なんで最初の6桁しか出力しないのだろう?とか、各桁の合計に「Validate Flag:」まで含めて-0x120はなんなんだとか、考えてみれば引っ掛かるところが多かったけど、すっきりした。

改行の\x0d\0xdaを含めて読み込んで、そこを\0に置き換える想定だったのか。-0x120は6桁だと、ちょうど(文字コードではなく)数字の合計になる。

def is_prime(n):
    if n==0:
        return False
    if n==1:
        return False
    i = 2
    while i*i<=n:
        if n%i==0:
            return False
        i += 1
    return True

def check(n):
    n = "%06d" % n
    if not is_prime(int(n[0:2])):
        return False
    if not is_prime(int(n[2:4])):
        return False
    if n[4:6] not in ["01", "04", "09", "16", "25", "36", "49", "64", "81"]:
        return False
    if (int(n[0:4]) ^ int(n[4:6])**2) >= 256:
        return False
    if not is_prime(sum(map(int, n))):
        return False
    if not is_prime(int(n[0:6])):
        return False
    return True

for i in xrange(10**6):
    if check(i):
        print "%06d" % i

これで、

020201
021101
021701
025301
025309
234149
234749
236749

と8個の数字が出力される。TMCTF{236749}が答えでしょう。

300

ネイティブコードを使ったAndroidアプリ。Googleと違って、x86の.soは入っていなかった。CentOS 7ならばEPELリポジトリを追加して、binutils-arm-linux-gnuを入れると、arm-linux-gnu-objdumpでARMのコードが逆アセンブルできる。

$ sudo yum install epel-release
$ sudo yum --enablerepo=epel install binutils-arm-linux-gnu
$ arm-linux-gnu-objdump -d libnative-lib.so | c++filt

ARMのコードを読むのがつらくなって終了。

400

(たぶん)このコンテスト唯一のpwn問題。珍しいWindows。どこに脆弱性があるかすら分からずに終了。

Analysis-Defensive

100

pcapファイルだけからフラグを探せ、とのこと。けっこうサイズが多くて面食らうが、「そもそも外とのやり取りは関係無いだろ」と思い、プライベートIPアドレスでの通信に絞ると、FTPでファイルをダウンロードしている。インストーラーっぽいWindowsのexe。起動しても何も起こらなかったけど、Explzhで開くと、中のファイルが取り出せた。

hwe4te.exeとpython27.dll。去年と同様に、unpy2exeを使おうとしたけど、x64だからかパッカーが使われているからか、うまく行かなかった。そのまま実行しても何かPythonのエラーが出る。実行中ならpycがメモリ中にあると考えて、デバッガで途中まで実行して、メモリをダンプした。pycのシグネチャ(?)である、12 34 56 78で検索したら、近くにそれっぽいVE1DVEZ7Q0FCMjNWMDAwMEMxfQ==という文字列があったので、復号したらフラグになった。ラッキー。

TMCTF{CAB23V0000C1}

200

鍵をMD5でハッシュ化してそれを使ってRC4で暗号化するPowerShellのコードが出てきた。MD5とRC4は削られていて、自分で実装しろとのこと。PowerShellは分からないので、Pythonで実装してみたけど、どうにも動かない。悩んだ末、鍵のchchesでググってみたら、この名前のマルウェアがあるらしい。このサイトのコードを見て、PowerShellのSubstringは(開始位置, 末尾位置)ではなく、(開始位置, 長さ)であることに気が付いた。

import hashlib

def RC4(data, key):
    S = range(256)
    j = 0
    for i in range(256):
        j = (j + S[i] + ord(key[i%len(key)])) % 256
        S[i], S[j] = S[j], S[i]
    j = 0
    i = 0
    res = ""
    for d in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        res += chr(ord(d) ^ S[(S[i] + S[j]) % 256])
    return res

key = "Y2hjaGVz"
key = key.decode("base64")
#key = hashlib.md5(key).hexdigest().decode("hex")[8:16]
key = hashlib.md5(key).hexdigest()[8:24]
open("plain", "wb").write(RC4(open("data", "rb").read(), key))

plainはpcapファイルで、まさにchchesの通信をしている。復号すると、フラグが出てくる。こっちは鍵のBase64デコードは不要。

cookie = "asdf=d01J5ln6eJxopAgX2SgmLRYGt5X70XRw4HL6sFoDbvWD5yQ=;qwer=fJDeRjsja7z8wcPVLrZzm6jYl3UsvQC9AoduZgL24n1NYs8=;zxcv=/vox+i3on9Iy1U+2itypfjagJ06762d9yfkxI/LgSq3a2PJXwdnQ8BhDI9ofW9HXXSQMaEXBkYdrun+F+xIi3a+3TvHY"
cookie = cookie.split(";")
d = ""
for c in cookie:
    print RC4(c[5:].decode("base64"), hashlib.md5(c[:4]).hexdigest()[8:24])
AWIN7-PC*1234*TMCTF{e3526984696
bc9f89ac88d4f72abe24}?361846839
?C:\Users\win7\AppData\Local\Temp?1.7.3 (1024x768)*6.1.7601.17514

TMCTF{e3526984696bc9f89ac88d4f72abe24}

300

暗号化プログラムと暗号化されたファイルが与えられて復号する問題。32ビットの鍵とxor → 鍵を右巡回シフトを繰り返している。暗号化されたファイルはZIPで、先頭4バイトはPK\x01\x02なので、鍵が分かる。300点問題にしては簡単すぎるような……。

import struct

f1 = open("flag.enc", "rb")
f1.read(16)
f2 = open("flag.zip", "wb")
key = struct.unpack("<I", f1.read(4))[0] ^ 0x04034b50
f2.write(struct.pack("<I", 0x04034b50))
while True:
    d = f1.read(4)
    if d=="":
        break
    key = key>>5 | key<<(32-5) & 0xffffffff
    f2.write(struct.pack("<I", struct.unpack("<I", d)[0]^key))

TMCTF{mai1-is-n0t-f1y}

400

SMB通信のpcapからペイロードを探して解析しろという問題。WannaCryだかEternalBlueだか関連だろうか。分からん。

Forensic

100

ASfsbGivEQsT2aQPHzaB.gzpgs.trendmicro.co.jpのような存在しないドメインに対して、延々とDNSクエリを投げている。集めてBase64で復号したけど何も出てこない。良く見ると/+が含まれていない。Base58だった。ビットコインで使われているやつ。

import re

d = open("output.pcap", "rb").read()
r = re.findall(r"(\w+).gzpgs", d)
data = "".join(r[::2])

C = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
org = 0
for d in data:
    org = org*58 + C.index(d)

print ("%x"%org).decode("hex")

TMCTF{DNSTunnelExfil}

200

被害者のメモリイメージから何かを探せという問題。分からん。

300

ランサムウェアをcuckooで解析した結果と、ランサムウェアで暗号化されたファイルからファイルを復元しろという問題。cuckooは、ウイルス対策ソフトウェアに良く出てくる、このウイルスはこのファイルを開いてこのレジストリに値を書き込み~みたいなことを調べてくれるらしい。

インストールが面倒そうなので、reports/report.jsonを眺めていたら、復号しなければいけないJPEGをランサムウェアが読み込んだときのログも残っていた。ファイルの内容も載っているので、そのまま開いてみたら……。

惜しい。thumbs.dbも同様に暗号化されていて、暗号化前のファイルを(JPEGの前の余計な部分を削って)開いてみると、

image.png

こっちは気合いで読める。TMCTF112242317。なぜか{}が無いので補う。

TMCTF{112242317}

400

メールにフロッピーディスクのイメージが添付されている。マウントしても空だけど、FTK Imagerだとnorns.exeが取り出せる。このnorns.exeはPEヘッダが後ろの方にあるので、16bit環境で実行して何かしたりするのだろうか?

Reversing

100

zipの中にzipが入っていて、その中にrarが入っている。rarの中にはexeファイルとzipファイル。exeファイルを実行すると、

Please find sweets name starting from m for biscuit2.

マカロン? 別になぞなぞということはなくて、デバッガで追ってみると↑の文言を出力した後に、macaronという文字列をメモリ中に生成している。

zipを解凍すると、biscuit3、biscuit4、biscuit5というファイルが出てくる。biscuit3はJPEGファイルだけれど、末尾にzipが付いていて、中のファイルにはcreamと書かれている。biscuit4はテキストファイル。

Please create flag.

hint:

Flag = TMCTF{biscuit3_ biscuit5}

biscuit5はexeで、メモリ中にchouxという文字列を生成している。TMCTF{cream_ choux}が通らないと思ったらヒントが間違えていた。_の後のスペースは要らないし、順番が逆。

TMCTF{choux_cream}

200

こんなファイル。RFID?

Using Clock:64, Invert:0, Bits Found:625
ASK/Manchester - Clock: 64 - Decoded bitstream:
1110111110111000
1010011110111010
 :

300

The power of Powershell!という問題文。問題の中身はPowerShellで何かをするバッチファイル。無理矢理解いた。

PowerShellには-encの後にBase64エンコードしたプログラムを渡して実行するという機能がある。時刻でゴニョゴニョした5文字の文字列をpの前に付けてPowerShellに渡している。まあ、文字数だけあっていればとりあえず復号はできる。なぜかBase64デコードができなくて、良く見たら、pの中に%が入っていた。どう処理して良いか分からず、pには周期性があるので、辻褄が合うように適当に埋めた。

PowerShellの文法が独特でなかなか読みづらいけど、雰囲気としては、

$sc32 = [System.Convert]::FromBase64String($env:l+$env:O);

をメモリ中に書き込んでそのまま実行しているらしい。loにも%が含まれているけれど、こっちは問題のバッチファイルの前半をコマンドプロンプトに貼り付けて、echo %l%%o%で綺麗に取り出せる。後はこれをBase64デコードして、適当なx86の実行ファイルをデバッガで実行してメモリに貼り付けて実行した。

image.png

TMCTF{HelloThere!ItIsMeAgain!}

400

こんなんが出てくる。手を付ける暇が無かった。

image.png

IoT/OSINT/SCADA

このカテゴリは0点だった(◞‸◟)

100

このフィッシングサイトの犯人を探せという問題。

  1. Whoisのメールアドレス
  2. ググルと別のサイトのWhoisが出てくる https://pastebin.com/TyEDZsaA
  3. https://t3m4haxor.wordpress.com/
  4. Twitterアカウント https://twitter.com/T3M4haxor/status/851503574580420611

から先が分からず。T3M4haxorのフォローイーかフォローワから辿ったりするのかな?

200

メールから犯人を探せと。分からん。

300

解けなかった。

スイッチにバッグドアが仕掛けられて~。問題のpcapファイルを見ると、スイッチの設定のダウンロードをアップロードしていて、アップロードをしたファイルには/etc/passwdが含まれている。

root:FVKARGRgureGENX:0:0:root:/:/bin/echo
bin:*:1:1:bin:/bin:
ftp:*:0:0:anon ftp:/:
nobody:*:99:99:Nobody:/:
admin:pkHZ3El6hq38o:101:101:Switch Administrator:/home/admin:/usr/local/bin/adminsh
cli:DWf6h7EDMc2bE:102:101:Switch Administrator CLI:/home/admin:/usr/local/bin/cfgcli
TMCTF:MFzbJnLcqzlvo:0:0:Hold the backdoor:/home/admin:/bin/sh
sertest::99:99:Factory Test:/:/usr/local/bin/loopsertest /dev/ttyS00
guest:*:500:500:guest:/:
PPPLink:*:601:601:PPPLink:/:

これがバックドアだろうけど、この先が分からない。SSHはパスワードが分かっても通信を復号できたりはしないし。

/etc/sysconfig/network の1行目と2行目が逆になるのは何か関係があるのだろうか?

HOSTNAME=ET-9MS-1
GATEWAY=192.168.63.2

usr/apache/conf/httpd.confScoreBoardFileという文字列を見つけて、「このCTFのスコアサーバーにバックドアがある!?」と面白くなったけど、これは普通のApacheの設定項目らしい。残念。

400

Hueで情報漏洩しているから何とかしろや、という問題。ログを見るとたしかにsatが激しく変化している。

Misc

100

問題のpcapファイルがWiresharkで開けない。リトルエンディアンのファイルなのにシグネチャがビッグエンディアンなのが原因で、先頭のA1 B2 C3 D4D4 C3 B2 A1にすると開ける。

だいたいがHTTPSの通信で読めないけれど、最後の方でFTPでkeylog.txtをダウンロードしている。

CLIENT_RANDOM 9563c57725522ab0cebb420f2ff549cdcc214d05a2b7aa5601f1935bcd1ac7c3 c5e10df5dbd09bd97b5ea6f1b291d8cac7066178d6805cf371e12ea1095131d1e6096132d7d0e072c78005f6d1b7fe5b
CLIENT_RANDOM f51ac603ddd9c6d8146cd03028f129365e32a928a08629892be4c26a454634bb 0a9dea018920113ec333446e1a185fd072444a1db9d7a8a9b9b21f2472f39db3f92929a25e3d634d58259537a3b47d60
CLIENT_RANDOM 3e401f34cc591c8a35aeedaddf181f7c458a84e058392735d74679eb0393431a 89d66ea9f10d711b6ff8c54c86474096252b8e8173aa271d8441b38c720d9d4a5b569b14cb1d898df16473ebfa23a1d2
CLIENT_RANDOM 0e2d5ecede1cf0f7d1d75329e3e386e160d99ac89e0ec09187651096d79ba35a afe74535c230c9d7e5f08ace8ce02d8200b8078854e41c30703f7da4ab7bd405788956805e9403996aa9412e2a26d545
CLIENT_RANDOM 89e8225f13ed1b39406f25c3f634f0ec91da0be693b7dcb9044efbbf2fe9363e 60b8b92fd58faabbfe00bec7fbf1c39db21030ff3c215c079176be6bcfe167df4114f1950790aaf432312a1397be2cb6
CLIENT_RANDOM 55d1989b2b9005b72599552ff352c4eef03bdb7153aaddd9942d69a19441fdaf 07cc14d902872bbdbdf5d05463a918c585604d373d7524ff405c396a2d4adafffd82b6136de4b7204d33fd9f2ff8f113
CLIENT_RANDOM 3cd78f4befe06bdb4c5559930817c8056aa14fe0c6a67d806ea0cc34c317fa51 ac7be48df12853bae2896042829a2011225e56ccdb63a05520b574b6d9f4aedd3f6c8377d47130e995f16a588dad5858
CLIENT_RANDOM cfaf0c18297c00ba7541ae55012df1fe825727a32ab94e38e1aeb985f9cf3ce5 3f81b68f0b9df5b719a54bb364505cb29209ae7a30d0525bb5a873e375bdbc9ac77ff24aa21def886d61f7cdcc0b06d5
CLIENT_RANDOM a77cdcf8084d073ec7059933e454408e25c6a01c8dbb888e9a3a862b609d8503 b5e7230fc735a87666fd2aee430917fd97bcf5f961b4099b979453b51176c0496629fe5af17da7f52204953782c90fdb
CLIENT_RANDOM d2d06ea94000a9204ea9e2d8272e77e4758958caaff0e9b4bfa7dbe4228d9251 bb716b4ff6de9730d0cd85446f3b5682b9055a54ac071279326ad2739083f54f0d13e689b47fcbb88a0dddb9ddd44175
CLIENT_RANDOM 4955c52a45946483854a4f333493870baa838a5c54c7112252a2828931393cd3 45aef6edb24a058b613559847db56db375b2f4286f9633f26735799ac2e8b0679853e72c1ec4188908bfa9b021c829cd
CLIENT_RANDOM 2acd97c21e8d33bb349d9612cb5b6220f10e5e4106d9449bf7dc5c933292f59e f70dc2ce8a96da62b9c6c5e2dea8aa776a666908c46a34d71dd297a002ba9e6a55b39e1cc8e845a7e058c779b400f82f

これはHTTPSの通信で使われている鍵なので、これをWiresharkの設定 → Protocols → SSL → (Pre)-Master-Secret log filenameに指定すると通信内容が見られるようになる。HTTP2。HTTPのようにファイルをまとめて保存ができなさそうなので、ポチポチ保存してgzip復号してとすると

この画像は視覚暗号で、2枚をピッタリ重ねるとフラグが浮かび上がってくる。

TMCTF{CanYouSeeThis?}

200

解けなかった。

フィッシングメールの解析。メール中の http://www.pokemongolegendaryclaim.com/index.html を見に行くと「他の問題のフラグを入力してね。フラグをあげるよ」というサイトが出てくる。このドメインはWhoisプロテクトされているけど、IPアドレスを引いて、逆引きすると、mocos.kitchenというドメインもこのサーバーに割り当たっていることが分かる。こっちのWhoisを見ると、管理者はKEITARO YAMAZAKIさん。tyageさん( https://twitter.com/tyage )の本名らしい。あとはtyageさんの何かのアカウントからフラグを……。

         \   ∩─ー、    ==== 
           \/ ● 、_ `ヽ   ====== 
           / \( ●  ● |つ 
           |   X_入__ノ   ミ   そんな餌で俺様が釣られクマ―― 
            、 (_/   ノ /⌒l 
            /\___ノ゙_/  /  ===== 
            〈         __ノ  ==== 
            \ \_    \ 
             \___)     \   ======   (´⌒ 
                \   ___ \__  (´⌒;;(´⌒;; 
                  \___)___)(´;;⌒  (´⌒;;  ズザザザ

運営はちゃんとドメインを確保してから問題文に書いてほしい(´・_・`)

300

有限差分法を実装したけど、正しくないから直せ。

与えられたプログラムを実行すると、SimpleHarmonicOscillator.csvとDampedOscillator.csvが出力され、画面にはTMCTF{-1154738479}と出てくる。

プログラムを解析すると、こんな処理をしている。

def f1(d, y, v, n):
    for i in range(n+1):
        # SimpleHarmonicOscillator.csv
        print "%d,%e,%e" % (i, i*d, y)
        y, v = y+d*v, v-d*y
    return v

def f2(d, y, v, n):
    for i in range(n+1):
        # DampedOscillator.csv
        print "%d,%e,%e" % (i, i*d, y)
        y, v = y+d*v, v-(v*10+y*16)*d
    return v

print f1(0.1047197551196597659, 1., 0., 180)
print f2(0.2857142857142856984, 1., 0., 7)

image.png

有限差分法は正しく実装されている気がするけど……と思ったけど、有限差分法ではそもそも近似解しか出ないから、厳密な数値解を出せという問題だった。まあ、たしかに振幅がだんだん大きくなっていくのはおかしい。フラグの生成には、$nd$と$f(nd)$が使われている。f1のほうは適当にdを小さくしていくと、1に収束することがわかる。問題はf2。大学の講義でやった気がする。懐かしい。

問題の数式は、

\frac{dy}{dt} = v \\
\frac{dv}{dt} = -10v-16y

ということを表している。ここから$v$を消すと、

\frac{d^2y}{dt^2} + 10\frac{dy}{dt} + 16y = 0

導出方法は知らないけど、この形の微分方程式の一般解は、 $y^2+10y+16=0$の解である$y=-2, -8$を使って次のように書ける。

y = C_1 e^{-2t} + C_2 e^{-8t}

$t=0$のとき、$y=1$、$\frac{dy}{dt}=v=0$という初期条件から、$C_1$と$C_2$が求められる。

y = \frac{4}{3} e^{-2t} - \frac{1}{3} e^{-8t}

これに、$t=dn=7$を代入すると答えは0.0244208143399struct.pack("<d", y(2)).encode("hex")でバイナリ表現b101ba1bc501993fを調べて、デバッガでf11=000000000000f03fと一緒に書き換え、出てきたフラグは正しいフラグだった。

TMCTF{15041707}

400

出てきたのが後のほうだし、全く手を付けていなかった。

13
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
7