satto1237’s diary

s4tt01237’s diary

ラーメンとかCTFとかセキュリティとか

SECCON 2018 Write-up

はじめに

10/27,28に開催されたSECCON 2018に研究室の同期とm45kというチームで参加しました.

SECCON 2018 Online CTF

成績

3問解いて 183位 / 653チーム でした. f:id:satto1237:20181029160547p:plain f:id:satto1237:20181029231926p:plain

Write-up

自分が解いた Runme, Boguscrypt についてのWrite-up です.

Runme [Reversing]

Run me.

アプローチ:Stackの確認
ダウンロードしたファイルを調べてみると32bit版 Windowsの実行ファイルだということが分かりました.

> file runme.exe_b834d0ce1d709affeedb1ee4c2f9c5d8ca4aac68
runme.exe_b834d0ce1d709affeedb1ee4c2f9c5d8ca4aac68: PE32 executable (console) Intel 80386, for MS Windows

諸事情でWindows環境を用意できなかったのでEasyWine.appを利用して実行してみると

f:id:satto1237:20181029233207p:plain

このままでは実行できないことが分かります.

そこで,idaを利用して実行ファイルを解析します.

f:id:satto1237:20181029234019p:plain

不自然なほど関数があるので1つずつ中身を確認していきます.

f:id:satto1237:20181029234331p:plain

いくつかの関数を確認するとflagが1文字ずつPushされていることに気づくので1文字ずつ読み取っていきます.
SECCON{Runn1n6_P47h}

Boguscrypt [Crypto]

Boguscrypt
Hey, Can you decrypt the file?

アプローチ:rev/pcap

zipファイルを解凍すると

> file challenge.pcap
challenge.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144)
> file dec
dec: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=83c20d8c2abda1f5e7505bc9f11723e6f59ce129, not stripped
> file flag.txt.encrypted
flag.txt.encrypted: data

pcap, 実行ファイル, テキストファイルを入手することができます.
Crypto問なのにバイナリファイルの解析しなきゃいけないのか…とちょっとテンションが下がりました.

とりあえずdecを実行してみると

> ./dec
Key?:Crypto

Keyの入力を求められ,適当な文字列を入力するとflag.txt.encryptedからflag.txtが生成されます.
ここで何通りかのKeyを入力して遊んでみるとflag.txtに変化が生じていないことに気づきます.

問題名のBogusは「偽の、いんちきな」という意味なので,Keyflag.txtの生成に無関係であることが予想できます.
gdbを使用して詳しくdecの動作を確認してみると, gethostbyaddrcallしていることに気づきます.

[----------------------------------registers-----------------------------------]
EAX: 0xf7fb5948 --> 0x804ba60 ("ubuntu")
EBX: 0x0 
ECX: 0x0 
EDX: 0x0 
ESI: 0xf7fb3000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0xffffcfb8 --> 0x0 
ESP: 0xffffaf20 --> 0xffffaf30 --> 0x200007f 
EIP: 0x80486e1 (<main+100>:   cmp    DWORD PTR [esp+0x1c],0x0)
EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x80486d5 <main+88>:   mov    DWORD PTR [esp],eax
   0x80486d8 <main+91>:   call   0x80484c0 <gethostbyaddr@plt>
   0x80486dd <main+96>:   mov    DWORD PTR [esp+0x1c],eax
=> 0x80486e1 <main+100>:   cmp    DWORD PTR [esp+0x1c],0x0
   0x80486e6 <main+105>:  jne    0x80486fe <main+129>
   0x80486e8 <main+107>:  mov    DWORD PTR [esp],0x8048a15
   0x80486ef <main+114>:  call   0x8048550 <herror@plt>
   0x80486f4 <main+119>:  mov    eax,0x1
[------------------------------------stack-------------------------------------]
0000| 0xffffaf20 --> 0xffffaf30 --> 0x200007f 
0004| 0xffffaf24 --> 0x4 
0008| 0xffffaf28 --> 0x2 
0012| 0xffffaf2c --> 0x0 
0016| 0xffffaf30 --> 0x200007f 
0020| 0xffffaf34 --> 0x0 
0024| 0xffffaf38 --> 0x0 
0028| 0xffffaf3c --> 0xf7fb5948 --> 0x804ba60 ("ubuntu")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x080486e1 in main ()

ホスト名を変更して再度decを実行してみるとflag.txtに変化が生じていることが確認できます.
このことからchallenge.pcapからホスト名を探しだし,該当ホスト名でdecを実行するとflag.txtを正常にデコードできることが分かります.

challenge.pcapを眺めてると怪しいホスト名(cur10us4ndl0ngh0stn4m3)が見つかります f:id:satto1237:20181030001731p:plain

ホスト名をcur10us4ndl0ngh0stn4m3に変更してdecを実行するとflag.txtが正常にデコードできます.
SECCON{This flag is encoded by bogus routine}

お気持ち表明

取り組んだけど解けなかった問題とコンテスト終了後に解けた問題について書きます.

Classic Pwn [Pwn]

1番時間をかけた問題
returnアドレスのオフセットもlibc_baseもあってるはずなのに上手く行かなかった.
Pwnの勉強がんばります.

QRChecker [QR]

知ってたのに気づけなかった
news.yahoo.co.jp

mnemonic [Crypto]

Read me.

{
    "japanese": [
    [
        "d3a02b9706507552f0e70709f1d4921275204365b4995feae1d949fb59c663cc",
        "ふじみ あさひ みのう いっち いがく とない はづき ますく いせえび たれんと おとしもの おどろかす ことし おくりがな ちょうし ちきゅう さんきゃく こんとん せつだん ちしき ぬいくぎ まんなか たんい そっと",
        "338c161dbdb47c570d5d75d5936e6a32178adde370b6774d40d97a51835d7fec88f859e0a6660891fc7758d451d744d5d3b1a1ebd1123e41d62d5a1550156b1f"
    ],
    [
        "dfc9708ac4b4e7f67be6b8e33486482cb363e81967a1569c6fd888b088046f7c",
        "ほんやく ごうきゅう おさめる たこやき ごかん れいぎ やせる ふるい まんなか てんない だんろ さうな きぼう よくぼう しのぐ よけい こんき みうち らくご いわかん いこく あたためる のはら たぶん",
        "bdadda5bbff97eb4fda0f11c7141bc3ce3de0fef0b2e4c47900858cec639c10187aee4695b1ba462b1dd34b170b62801e68c270b93af62629f4964947a620ed9"
    ],
    [
        "c0f...",
        "??? とかす なおす よけい ちいさい さんらん けむり ていど かがく とかす そあく きあい ぶどう こうどう ねみみ にあう ねんぐ ひねる おまいり いちじ ぎゅうにく みりょく ろしゅつ あつめる",
        "e9a..."
    ],
    ],
    "flag": "SECCON{md5(c0f...)}"
}

アプローチ:BIP39

textファイルを見ても正直よく分からないのでmnemonic encodeとかでググります.
すると,なんやかんやでBIP39の日本語ワードリストを利用したMnemonicであることが分かります.

Seed phrase - Bitcoin Wiki

textファイルの???日本語ワードリストの単語に置き換えて,BIP39 Seedを計算し,先頭がe9aとなる単語を探索してる最中にコンテストが終了しました.

コンテスト終了後に気づいたのですが,11bit毎にhexを日本語に置き換えているだけなので全探索をせずとも???はワードリストの0xc0f >> 1番目の単語(はいれつ)であることが分かります.

以下スクリプトです.

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

import hashlib
import binascii
import mnemonic

if __name__ == '__main__' :
    WORDS = u' とかす なおす よけい ちいさい さんらん けむり ていど かがく とかす そあく きあい ぶどう こうどう ねみみ にあう ねんぐ ひねる おまいり いちじ ぎゅうにく みりょく ろしゅつ あつめる'
    KEY = 0xc0f

    m = mnemonic.Mnemonic('japanese')
    first_word = m.wordlist[KEY>>1]
    entropy = binascii.hexlify(m.to_entropy(first_word + WORDS))
    hash = hashlib.md5(entropy).hexdigest()
    print('SECCON{' + hash + '}')
> python  solve.py
SECCON{cda2cb1742d1b6fc21d05c879c263eec}

SECCON{cda2cb1742d1b6fc21d05c879c263eec}

まとめ

  • 今年のSECCONは難しかったらしい(初参加なので違いが分からなかった)
  • Pwn, Rev偏重なので低レイヤ強くならないと楽しめないことが分かった
  • CryptoがBoguscrypt以外暗号通貨問だったのでつらかった(分かんねぇ〜〜〜〜〜〜〜)
  • 低レイヤの勉強頑張ります