Tahoo!!

自分の勉強していること(コンピュータ関連 / ネットワーク / セキュリティ / サーバ)や趣味について書いていきます

CSAW CTF 2015 Writeup

CSAW CTF 2015に参戦した結果と、数問問題を解いたWriteup。

今回は、解散したと思われるチーム********で出場してた。今回のメンバーは自分一人。 (実はこのチーム名で細々といろいろなCTFに出てるw)

f:id:takahoyo:20150923000541p:plain

結果は、大して難しくない問題を解いて、1000ptくらい。順位は1367位中361位。 やはりBinary(Exploit, Reversing)に全く手が出ないのがつらいところ。 Webは、昔よりは少し解けそうな感じになってきたかなあという感じ。

今回は自分の力試し的なところがあったのだが、やはりパケット問題以外のジャンルがまともに解けないので全然ダメ。

ここからは、簡単な問題ばかりだけどWriteupを書く。

Trivia

セキュリティに纏わる知識を問うクイズ。 知ってれば一瞬、わからなくてもググれば大抵何とかなる。

Trivia 1 (10pt)

This family of malware has gained notoriety after anti-virus and threat intelligence companies claimed that it was being used by several Chinese military groups.

結構ググったけどわからなかった…

Trivia 2 (10pt)

No More Free __!

この言葉は"No More Free"でググると、候補に"No More Free Bugs"って出てきたかな思ったので入れた通った。

FLAG : Bugs

Trivia 3 (10pt)

This mode on x86 is generally referred to as ring -2.

SMM (System Management Mode)。 smmがFLAGだった。

FLAG : smm

Trivia 4 (10pt)

This vulnerability occurs when the incorrect timing/sequence of events may cause a bug.

Race Condition。

FLAG: race condtion

Trivia 5 (10pt)

On Windows, loading a library and having it’s code run in another process is called _ .

DLL Injection。

FLAG: DLL Injection

Math aside, we’re all black hats Now (10pt)

This Pentesting expert supplied HBO’s Silicon Valley with technical advice in season 2. The flag is his twitter handle.

“HBO’s Silicon Valley pentest"でググる → "Rob Fuller"が引っかかるので、"Rob Fuller"で再びググる → 本名でTwitterやってるので検索に引っかかる。

Rob Fuller (@mubix) | Twitter

FLAG: mubix

Recon

「偵察」とかそんな感じのジャンル。ある特定の人物の情報からFLAGを探す。

Julian Cohen (100pt)

彼のTwitterを見たら、flagを既につぶやいてた。

https://twitter.com/HockeyInJune/status/641716034068684800

FLAG : flag{f7da7636727524d8681ab0d2a072d663}

Alexander Taylor (100pt)

http://fuzyll.com/csaw2015/start にアクセスすると、次のようなメッセージが表示される。

CSAW 2015 FUZYLL RECON PART 1 OF ?: Oh, good, you can use HTTP! The next part is at /csaw2015/.

Alexander Taylor の2013年のプロフィールを見ると、University of South Floridaの学生だったことがわかる。 ここの大学にあるhacking clubは調べると、"Whitehatters Computer Security Club"(WCSC) らしいので、"/csaw2015/wcsc"のpathにアクセスしてみると、次の問題メッセージがあった。

CSAW 2015 FUZYLL RECON PART 2 OF ?:TmljZSB3b3JrISBUaGUgbmV4dCBwYXJ0IGlzIGF0IC9jc2F3MjAxNS88bXkgc3VwZXIgc21hc2ggYnJvdGhlcnMgbWFpbj4uCg==

Base64でメッセージの一部がエンコードされているので、適切な方法でデコードすると次のような文章になる。

$ echo 'TmljZSB3b3JrISBUaGUgbmV4dCBwYXJ0IGlzIGF0IC9jc2F3MjAxNS88bXkgc3VwZXIgc21hc2ggYnJvdGhlcnMgbWFpbj4uCg==' | base64 -D
Nice work! The next part is at /csaw2015/<my super smash brothers main>.

彼のHN (fuzyll) と super smash brothers で検索すると、yoshiを使ってる動画が一番上に来るので、"/csaw2015/yoshi"のpathにアクセスしてみると、PNG形式のヨッシーの画像が。

「きっと、この画像のコメントにでも何か書いてあるんだろうな」と思って、バイナリエディタで画像を開くとPNGのコメント部分に次のメッセージが埋め込まれていた。

CSAW 2015 FUZYLL RECON PART 3 OF ?: Isn’t Yoshi the best?! The next egg in your hunt can be found at /csaw2015/

DEFCONのWriteupを調べたら、過去にRSAEnigma暗号の問題が出ていた。 この情報から、"/csaw2015/enigma"のpathにアクセスすると4番目のメッセージが表示された。

CSAW 2015 FUZYLL RECON PART 4 OF 5: Okay, okay. This isn’t Engima, but the next location was “encrypted” with the JavaScript below: Pla$ja|p$wpkt$kj$}kqv$uqawp$mw>$+gwes6451+pla}[waa[ia[vkhhmj

また、メッセージの一部は、以下のスクリプトによって暗号化されているらしい。

var s = "THIS IS THE INPUT"
var c = ""
for (i = 0; i < s.length; i++) {
    c += String.fromCharCode((s[i]).charCodeAt(0) ^ 0x4);
}
console.log(c);

1文字ずつ文字コードと0x4をXORすることで暗号化していることは明白なので、Pythonで適当にsolverを書いた。(jsの実行環境用意するより、Pythonスクリプト書くほうが早かった)

a = "Pla$ja|p$wpkt$kj$}kqv$uqawp$mw>$+gwes6451+pla}[waa[ia[vkhhmj"
b = ""
for c in a:
  b += chr(ord(c)^0x4)
print b

実行すると、次のようなメッセージが復号される。

The next stop on your quest is: /csaw2015/they_see_me_rollin

あとは、"/csaw2015/they_see_me_rollin"にアクセスするとFLAGが書いてあるページに辿り着いた。

CSAW 2015 FUZYLL RECON PART 5 OF 5: Congratulations! Here’s your flag{I_S3ARCH3D_HI6H_4ND_L0W_4ND_4LL_I_F0UND_W4S_TH1S_L0USY_FL4G}!

FLAG : flag{I_S3ARCH3D_HI6H_4ND_L0W_4ND_4LL_I_F0UND_W4S_TH1S_L0USY_FL4G}!

Forensics

Keep Calm and CTF (100pt)

某チームの回答状況見たら1分で解いてたので、「あーどうせstringsで一発だろ」と思って、stringsコマンドを使ってみる。

$ strings img.jpg
JFIF
XExif
h1d1ng_in_4lm0st_pla1n_sigh7
$3br
%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
#N%%
…

それっぽい文字列が出てきたので、submitしたら得点貰えたw

入れた後に、Exifっていう文字列のあとに入ってたのでexiftoolで見たら、案の定EXIFだった。

$ exiftool img.jpg
ExifTool Version Number         : 10.00
File Name                       : img.jpg
Directory                       : .
File Size                       : 92 kB
File Modification Date/Time     : 2015:09:19 07:49:31+09:00
File Access Date/Time           : 2015:09:21 12:47:49+09:00
File Inode Change Date/Time     : 2015:09:21 12:47:13+09:00
File Permissions                : rw-r-----
File Type                       : JPEG
File Type Extension             : jpg
MIME Type                       : image/jpeg
JFIF Version                    : 1.01
X Resolution                    : 72
Y Resolution                    : 72
Exif Byte Order                 : Big-endian (Motorola, MM)
Resolution Unit                 : inches
Y Cb Cr Positioning             : Centered
Copyright                       : h1d1ng_in_4lm0st_pla1n_sigh7
Image Width                     : 600
Image Height                    : 700
Encoding Process                : Baseline DCT, Huffman coding
Bits Per Sample                 : 8
Color Components                : 3
Y Cb Cr Sub Sampling            : YCbCr4:2:0 (2 2)
Image Size                      : 600x700
Megapixels                      : 0.420
FLAG: h1d1ng_in_4lm0st_pla1n_sigh7

Flash (100pt)

まずは手始めにfileコマンド。

$ file flash_c8429a430278283c0e571baebca3d139.img
flash_c8429a430278283c0e571baebca3d139.img: x86 boot sector, mkdosfs boot message display, code offset 0x3c, OEM-ID "mkfs.fat", sectors/cluster 4, root entries 512, Media descriptor 0xf8, sectors/FAT 256, heads 64, sectors 262144 (volumes > 32 MB) , serial number 0xa0f1dff7, unlabeled, FAT (16 bit)

FAT16らしい。 とりあえず、最初にFTK Imagerを使ってイメージの中身を見てみたが、特に怪しい情報がなかった。 そこでstringsコマンドを使って、flagを探してみるとすぐに見つかった。

$ strings flash_c8429a430278283c0e571baebca3d139.img | grep "flag{"
flag{b3l0w_th3_r4dar}

あとでバイナリエディタで見てみたけど、何でここに入ってるんだってところにあった。 FAT16のフォーマット調べればわかったのだろうか…

FLAG : flag{b3l0w_th3_r4dar}

Transfer (100pt)

pcapということで、とりあえずWiresharkで開く。 Wiresharkで開くと、TwitterGoogleFacebookなど様々なサービスにhttpでアクセスしてhttpsにリダイレクトされるというトラフィックが記録されているのがわかる。 ただの目眩ましだと思ったので、怪しいIPアドレスの通信がないか、Statistics機能を使って調べてみる。

f:id:takahoyo:20150924110825p:plain

よく見るとこの中に一つだけprivate IP address <-> private IP address な通信があり、これは作問者が意図して発生させた通信でないかと考えられる。 そこで、このIPアドレスでフィルタリングして通信を見てみる。

f:id:takahoyo:20150924111205p:plain

80/tcpで何やらHTTP以外の通信をしているようなので、"Follow TCP Stream"機能を使って内容を見てみると、次のようなPythonスクリプトと、このスクリプトを使ってエンコードされたと思われる文章が出てきた。

import string
import random
from base64 import b64encode, b64decode

FLAG = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'

enc_ciphers = ['rot13', 'b64e', 'caesar']
# dec_ciphers = ['rot13', 'b64d', 'caesard']

def rot13(s):
    _rot13 = string.maketrans( 
        "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", 
        "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
    return string.translate(s, _rot13)

def b64e(s):
    return b64encode(s)

def caesar(plaintext, shift=3):
    alphabet = string.ascii_lowercase
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    table = string.maketrans(alphabet, shifted_alphabet)
    return plaintext.translate(table)

def encode(pt, cnt=50):
    tmp = '2{}'.format(b64encode(pt))
    for cnt in xrange(cnt):
        c = random.choice(enc_ciphers)
        i = enc_ciphers.index(c) + 1
        _tmp = globals()[c](tmp)
        tmp = '{}{}'.format(i, _tmp)

    return tmp

if __name__ == '__main__':
    print encode(FLAG, cnt=?)

ここでは、FLAGがencode関数によってエンコード処理がされているので、これを解析してデコードすることでFLAGが得られると考えられる。 この処理を整理すると次のようになる。

  1. rot13, base64, シーザー暗号のどれかでエンコードする
  2. エンコードした方式に対応する番号(rot13: 1, base64: 2, シーザー: 3)を先頭につける
  3. 1,2をcntで与えられた回数繰り返す

よって、一番最初に出てくる数字からエンコード方式を判断し、エンコードされた文をデコードする処理を繰り返して行えば良い。

今回は、デコードするために上記のスクリプトを基にして次のようなスクリプトを書いた。

import string
import random
from base64 import b64encode, b64decode

flag = '2Mk16Sk5iakYxVFZoS …(略)… BUVlVaUmVsQlJQVDA9'

def rot13(s):
    _rot13 = string.maketrans( 
        "ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", 
        "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
    return string.translate(s, _rot13)

def b64d(s):
    return b64decode(s)

def caesard(plaintext, shift=3):
    alphabet = string.ascii_lowercase
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    table = string.maketrans(shifted_alphabet,alphabet)
    return plaintext.translate(table)

def decode(en, cnt=50):
    tmp = en
    for cnt in xrange(cnt):
        t = tmp[0] 
        if t == '1':
            tmp = rot13(tmp[1:])
        elif t == '2':
            tmp = b64d(tmp[1:])
        elif t == '3':
            tmp = caesard(tmp[1:])
        else:
            break
        print cnt
    return tmp

if __name__ == '__main__':
    print decode(flag, 100)

これを実行すると、FLAGが出てきた。

FLAG: flag{li0ns_and_tig3rs_4nd_b34rs_0h_mi}

Airport (200pt)

配布されているファイルを展開すると、空港の写真4枚とsteghide.jpgというファイルが出現した。 steghide.jpgは名前からして、steghideというステガノツールを使ってflagをこの画像ファイルに隠してあるんじゃないかなと推測。 steghideを動かせる環境があったので、そこからファイルを取り出そうにもパスフレーズがわからない。

最近よくctf4bの関連で飛行機によく乗るからかもしれないが、「空港って3文字のユニークな空港コードあるよなー。これ繋いだらどうだろうか」という勘が働いて、空港を調べた。

最初の3枚はgoogleの画像検索でどの空港か特定出来たが、最後の1枚は画像検索でもダメ。

f:id:takahoyo:20150924023200p:plain

ここで4枚目の写真の左上をよく見ると、"409"と"7"という道路が通っているのがわかる。 この情報から、"highway 409 airport"で検索し、写真と似たような地図の空港を特定することが出来た。

ここまで見つけた4つの空港を空港コードに変換すると次のようになる。

これらをつなげると"HAVHKGLAXYYZ"となり、これがsteghideのパスフレーズだった。

$ steghide extract -sf steghide.jpg
Enter passphrase: HAVHKGLAXYYZ
wrote extracted data to "key.txt".
$ cat key.txt
iH4t3A1p0rt5
FLAG: iH4t3A1p0rt5

Crypto

ones_and_zer0es (50pt)

拡張子が、.mpegになっているが、バイナリエディタで開くと普通にテキストだったので、テキストエディタで開く。 テキストの内容は、0と1だけで構成されている。

何となく8bit毎に数字に直して、ASCIIに戻すと文字列になりそうな気がしたので、次のようなスクリプトを書いてみた。

python
#! /usr/bin/env python

a = '0110011001101100…(略)…0111001100101110'
flag = ''

i = 0
while i < len(a):
    flag += chr(int(a[i:i+8], 2))
    i = i + 8

print flag

すると、次にような文字列が復元された。

flat{People always make the best exploits.} I've never found it hard to hack most people. If you listen to them, watch them, their vulnerabilities are like a neon sign screwed into their heads.

最初の一文がflatになっていて通らなかったので、これをflagに直したら通った。

FLAG: flag{People always make the best exploits.}

whiter0se (50pt)

これも拡張子が.m4vとなっているが、ただのテキストファイル。

EOY XF, AY VMU M UKFNY TOY YF UFWHYKAXZ EAZZHN. UFWHYKAXZ ZNMXPHN. UFWHYKAXZ EHMOYACOI. VH'JH EHHX CFTOUHP FX VKMY'U AX CNFXY FC OU. EOY VH KMJHX'Y EHHX IFFQAXZ MY VKMY'U MEFJH OU.

単一換字暗号ぽい。 このような暗号を解読するには便利な解読ツールがあるので、便利ツールを使ってみる。

quipqiup - cryptoquip and cryptogram solver

f:id:takahoyo:20150924174127p:plain

“Note: The flag is the entire thing decrypted"とあるので、この解読結果がFLAGだった。

FLAG: BUT NO, IT WAS A SHORT CUT TO SOMETHING BIGGER. SOMETHING GRANDER. SOMETHING BEAUTIFUL. WE'VE BEEN FOCUSED ON WHAT'S IN FRONT OF US. BUT WE HAVEN'T BEEN LOOKING AT WHAT'S ABOVE US.

zer0-day (50pt)

これも拡張子が.aviとなっているが、(ry

RXZpbCBDb3JwLCB3ZSBoYXZlIGRlbGl2ZXJlZCBvbiBvdXIgcHJvbWlzZSBhcyBleHBlY3RlZC4g VGhlIHBlb3BsZSBvZiB0aGUgd29ybGQgd2hvIGhhdmUgYmVlbiBlbnNsYXZlZCBieSB5b3UgaGF2 ZSBiZWVuIGZyZWVkLiBZb3VyIGZpbmFuY2lhbCBkYXRhIGhhcyBiZWVuIGRlc3Ryb3llZC4gQW55 IGF0dGVtcHRzIHRvIHNhbHZhZ2UgaXQgd2lsbCBiZSB1dHRlcmx5IGZ1dGlsZS4gRmFjZSBpdDog eW91IGhhdmUgYmVlbiBvd25lZC4gV2UgYXQgZnNvY2lldHkgd2lsbCBzbWlsZSBhcyB3ZSB3YXRj aCB5b3UgYW5kIHlvdXIgZGFyayBzb3VscyBkaWUuIFRoYXQgbWVhbnMgYW55IG1vbmV5IHlvdSBv d2UgdGhlc2UgcGlncyBoYXMgYmVlbiBmb3JnaXZlbiBieSB1cywgeW91ciBmcmllbmRzIGF0IGZz b2NpZXR5LiBUaGUgbWFya2V0J3Mgb3BlbmluZyBiZWxsIHRoaXMgbW9ybmluZyB3aWxsIGJlIHRo ZSBmaW5hbCBkZWF0aCBrbmVsbCBvZiBFdmlsIENvcnAuIFdlIGhvcGUgYXMgYSBuZXcgc29jaWV0 eSByaXNlcyBmcm9tIHRoZSBhc2hlcyB0aGF0IHlvdSB3aWxsIGZvcmdlIGEgYmV0dGVyIHdvcmxk LiBBIHdvcmxkIHRoYXQgdmFsdWVzIHRoZSBmcmVlIHBlb3BsZSwgYSB3b3JsZCB3aGVyZSBncmVl ZCBpcyBub3QgZW5jb3VyYWdlZCwgYSB3b3JsZCB0aGF0IGJlbG9uZ3MgdG8gdXMgYWdhaW4sIGEg d29ybGQgY2hhbmdlZCBmb3JldmVyLiBBbmQgd2hpbGUgeW91IGRvIHRoYXQsIHJlbWVtYmVyIHRv IHJlcGVhdCB0aGVzZSB3b3JkczogImZsYWd7V2UgYXJlIGZzb2NpZXR5LCB3ZSBhcmUgZmluYWxs eSBmcmVlLCB3ZSBhcmUgZmluYWxseSBhd2FrZSF9Ig==

どう見てもbase64なので、ファイル内の"\n"をすべて消去して、base64コマンドでデコードする。

$ base64 -D -i eps1.9.txt
Evil Corp, we have delivered on our promise as expected. The people of the world who have been enslaved by you have been freed. Your financial data has been destroyed. Any attempts to salvage it will be utterly futile. Face it: you have been owned. We at fsociety will smile as we watch you and your dark souls die. That means any money you owe these pigs has been forgiven by us, your friends at fsociety. The market's opening bell this morning will be the final death knell of Evil Corp. We hope as a new society rises from the ashes that you will forge a better world. A world that values the free people, a world where greed is not encouraged, a world that belongs to us again, a world changed forever. And while you do that, remember to repeat these words: "flag{We are fsociety, we are finally free, we are finally awake!}

最後の1文にFLAGがあった。

FLAG: flag{We are fsociety, we are finally free, we are finally awake!}

notesy (100pt)

flagのフォーマットがflag{}じゃなくて、何を答えれば良いかわからない、いわゆるク○問。

Hintで、ABCD…XYZを読み上げる動画があったので、ABCD…XYZをすべて突っ込んでみた。 大文字だけでなく、小文字はすべて大文字に変換され、記号などは変換されないのようなので、ABCD…XYZを入力することで、実質すべての文字の対応テーブルを入手したことになる。

f:id:takahoyo:20150924200404p:plain

本当に何を答えれたら良いかわからなかったが、ABCD…XYZまでの文字を変換した文字を入れた通った。

FLAG: UNHMAQWZIDYPRCJKBGVSLOETXF

Web

Lawn Care Simulator (200pt)

下にある"Careers"のメニューから行けるページ(jobs.html)というページに、Gitのスキルを持ってる人間が欲しいみたいなことが書いてあったのでGitが使われてることが推測できる。 そこで、/.gitに移動してみたところ、"403 Forbidden"が返ってきたので、.gitディレクトリ下にあるファイルを手元のgit環境を基にダウンロードした。 ここで、"git clone"を使ってソースコードをダウンロードすることが出来たらしいのだが、git力が足りなくてここで足止めとなってしまった。