Tahoo!!

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

setodaNote CTF Writeup (Network)

この記事は setodaNote CTFのNetworkジャンルのWriteup記事です。

Host (30pts, 296solves)

問題ファイルは pcapファイル。

Wiresharkで開くと一つのHTTP通信だけが記録されていることがわかる。リクエストヘッダの Host:がFLAG

f:id:takahoyo:20210905101250p:plain

flag{ctf.setodanote.net}

tkys_never_die (50pts, 344solves)

問題ファイルは pcapファイル。

Wiresharkで開くと、/flag.html/flag.png にアクセスしているHTTPリクエストが記録されている。

flag.html にはFLAGはなく、flag.png にFLAGがありそう。

PNGをダウンロードしているHTTPレスポンスの "Portable Network Graphics" を右クリックして、"Export Packet Bytes" をクリックして、PNGをflag.pngというファイル名でエクスポートする。

f:id:takahoyo:20210905101353p:plain

エクスポートされた画像にFLAG

flag{a_treasure_trove}

echo_request (120pts, 249solves)

問題ファイルは pcapファイル。

echo requestといえばICMPなので、Wiresharkで開いてicmp でフィルタしてみる

98bytesのICMP通信と60bytesのICMP通信がある。それぞれのICMPのデータ部を見ると、98bytesの通信はpingコマンドを実行したときに発生する通信と同じだが、60bytesの通信を見ると1byteしかデータがなく不審である。60bytesの通信のデータ部のHex dumpを見ていくと f,l,a… と変化しているので、これを取り出せば良さそう。

f:id:takahoyo:20210905101423p:plain

Wiresharkでこのデータ部を一つずつ目で見ていくのは非効率なので、tsharkの-T fields -e を用いてデータを出力する。

$ tshark -r echo_request.pcap -Y 'icmp and frame.len == 60' -T fields -e data.data
2e
2e
2e
2e
2e
66
6c
61
...

あとは出力されたデータをCyberChefなどで改行を消してASCIIに変換すれば良いが、LinuxだとOneLinerで取り出せるので楽。

$ tshark -r echo_request.pcap -Y 'icmp and frame.len == 60' -T fields -e data.data | tr -d '\n' | xxd -r -p
.....flag{ICMP_Tunneling_T1095}.....

stay_in_touch (150pts, 160solves)

問題ファイルは pcapファイル。

SMTPIMAPの通信が記録されているため、メールのやり取りを記録したキャプチャファイルだと思われる。SMTPはメール転送の部分は暗号化されており中身が見れないが、IMAPは平文で流れており中身が見れる。

適当なIMAPパケットを右クリックし、"Follow" -> "TCP Stream" を起動。メールのやり取りがUTF-8で行われているためデフォルトの状態だとASCIIでデコードするため読める状態ではないが、"Show data as" の部分を "UTF-8" に変えるとメールの中身が読めるようになる。

f:id:takahoyo:20210905101502p:plain

Follow TCP Stream画面左下の "Stream" の番号を変化させて他のメールを読んでいくと、Stream 12のメールにZIPファイルが添付されている。

f:id:takahoyo:20210905101511p:plain

CyberChefなどでBase64をデコードすると、直前の Content-Type にも書かれているようにZIPファイルが復元できる。

https://gchq.github.io/CyberChef/#recipe=Find_/_Replace(%7B'option':'Regex','string':'%5C%5Cn'%7D,'',true,false,true,false)From_Base64('A-Za-z0-9%2B/%3D',true)

f:id:takahoyo:20210905101641p:plain

ZIPファイルにはパスワードがかかっているが、ファイルが添付されているメールの本文に「パスワードは別に送ります。」と書いてあり、Steram 14にパスワードが書いてある。

f:id:takahoyo:20210905101656p:plain

このパスワードを使うとZIPが解凍出来てFLAG

flag{SoNtOkIhAmOuKaTaHoUmOtSuMuRuNoSa;)}

いわゆるPPAPを行うリスクを身を持って感じられる問題だったと思います。

yes_you_can (150pts, 68solves)

問題ファイルはpcapファイル、ではなくテキストのログファイル。

(1628245600.155918) vcan0 095#800007F400000017
(1628245600.157006) vcan0 1A4#000000080000003E
(1628245600.157018) vcan0 1AA#7FFF00000000673F
(1628245600.157020) vcan0 1B0#000F0000000175
(1628245600.157023) vcan0 1D0#000000000000000A
(1628245600.158095) vcan0 166#D0320027
(1628245600.160232) vcan0 158#0000000000000028
(1628245600.160243) vcan0 161#000005500108002B
(1628245600.160245) vcan0 191#010010A141001A
(1628245600.160247) vcan0 133#00000000B6
...

昨年のHoliday Hack ChallengeでCAN (Car Area Network) のログを解析する問題が出題されて、その時と同じフォーマットだったので、(問題名的にも)すぐにCANのログであることには気づけた。

ただ、ログをただ見ててもどこにFLAGがあるか見当がつかずアイディアもなかったので、ここでだいぶ時間を食った。

いろいろ考えて、とりあえずログを読み込んでリプレイ出来ないか試してみることにした。リプレイ出来る方法を探したところ @shutingrz 氏の以下のブログにとてもわかりやすくまとめられていた。

https://www.shutingrz.com/post/can-training-first/

ここにまとめられてる手順に沿ってCANのシミュレーション環境をKali Linux上に構築。シミュレータを起動し、CANのログをリプレイする。

./icsim vcan0
canplayer -I dump.log 

f:id:takahoyo:20210905101800p:plain

ここでシミュレータを見ると速度の情報が変化してるので、速度情報で何かを伝えようとしているのでは?と推測した。

本来であればログの中からICSimの速度情報をしながら調べるのだろうが、これも@shutingrz 氏がブログにまとめてくれており、ID(ログ上では# の前の値)が0x244 のログが速度情報のデータであることがわかる。

www.shutingrz.com

そこで、IDが 0x244 のログをgrepで抽出してみる。

$ grep -E "244#0000" 
...
(1628245605.005261) vcan0 244#0000006600
(1628245605.020564) vcan0 244#0000006600
(1628245605.035802) vcan0 244#0000006600
(1628245605.051115) vcan0 244#0000006600
(1628245605.061376) vcan0 244#0000006600
(1628245605.076673) vcan0 244#0000006600
(1628245605.091981) vcan0 244#0000006600
(1628245605.102269) vcan0 244#0000006600
...

データ部が5bytesで、1-3byte目、5byte目が 00 のデータにASCIIぽい数字が入っている。この特徴のデータ抽出し、重複を取ってみる。0x66がf、0x6CがlなのでASCIIぽい。

$ grep -E " 244#000000[0-9A-Fa-f]{2}00" dump.log | cut -d'#' -f2 | uniq
0000000100
0000006600
0000006C00
0000006100
0000006700
0000007B00
0000006300
0000006100
0000006E00
0000005F00
0000006200
0000007500
0000007300
0000005F00
0000006800
0000006100
0000006300
0000006b00
0000006900
0000006E00
0000006700
0000007D00
0000000100

あとは4byte目だけ抜き取って、xxdでASCIIに戻せばFLAGが得られた。

$ grep -E " 244#000000[0-9A-Fa-f]{2}00" dump.log | cut -d'#' -f2 | uniq | sed -r 's/000000([0-9A-Fa-f]{2})00/\1/' | tr -d '\n' | xxd -r -p 
flag{can_bus_hacking} 

digdig (200pts, 121solves)

問題ファイルはpcapファイル。

開くとDNS通信が記録されている。

f:id:takahoyo:20210905101833p:plain

3番目のパケットを見ると、00500000LFI2358AA31.setodanote.net を名前解決しようとしている通信が見つかる。この名前解決の結果を見ると、103.101.116.102 となっている。

一見すると正常なアドレスを返しているように見えるが、Packet BytesでHex Dumpを見ると getf となっており、何かのデータを送っているように見える。次のパケットも同様に確認してみるとHexの部分が lagとなっており、getflag と送っているのがわかる。

f:id:takahoyo:20210905101843p:plain

このように、長いサブドメインの名前解決やレスポンスに意味のあるデータが含まれているのはDNSトンネリングで使われる手法である。名前解決AレコードとAAAAレコードで行われているが、今回の問題ファイルにはAAAAレコードの名前解決のレスポンスには特に意味のあるデータが含まれてないので、dns.qry.type == 1 でフィルタする。

フィルタ後、改めて名前解決しているドメインを見ると、005aa0 で始まるドメインの名前解決を大量に行っている。これらのサブドメインは毎回微妙に異なっているため、何かのデータを送っていると推測できる。

f:id:takahoyo:20210905101913p:plain

tsharkでこの名前解決を行っているドメインを引っこ抜いて、サブドメインの部分を抽出してみる。

$ tshark -r digdig.pcap -Y "ip.addr == 192.168.224.20 and dns.qry.type == 1 and dns.a == 172.16.107.128" -T fields -e dns.resp.name | cut -d'.' -f1
005aa002735f69735f44414d
005aa00663655f7472795f53
005aa0034d595f464c41477d
005aa0085f746861747d2066
005aa00a6c61677b444e535f
005aa00b5333637572313779
005aa0076f7272795f666f72
005aa00420666c6167206973
005aa0096c61672069732066
005aa00c5f5431303731217d
005aa011797d323232323232
005aa00d20666c6167206973
005aa00f335f6b33795f3135
005aa00e20666c61677b3768
005aa001666c61677b546869
005aa0105f35336375723137
005aa000666c616720697320
005aa00520666c61677b4e69

出力結果をCyberChefに入れて、Hexdumpを見てみる

https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_Hex('Auto')To_Hexdump(16,false,false,false)

f:id:takahoyo:20210905101934p:plain

flagのようなデータが見えるが正しい順番になってなさそう。

Hexをよく見ると4byte目が0x00~0x11のデータになっているので、この番号順にデータを並び替えてみる。(ここは手動で頑張った

flag is flag{This_is_DAMMY_FLAG} flag is flag{Nice_try_Sorry_for_that} flag is flag{DNS_S3cur17y_T1071!} flag is flag{7h3_k3y_15_53cur17y}222222

いくつかdummyのFLAGがあるが、flag{DNS_S3cur17y_T1071!} がFLAGだった。

flag{DNS_S3cur17y_T1071!}

flag{} がFLAGのフォーマットですって言っておいて、flag{} のフォーマットのdummyを混ぜるのは如何なものかと思った。。

Logger (250pts, 115solves)

問題ファイルはpcapファイル。

Wiresharkで開くと、USBとのデータのやり取りが記録されていることがわかる。

f:id:takahoyo:20210905102047p:plain

USBの通信データというと、PCとUSBメモリのデータをやり取りやマウスやキーボードのやり取りが記録されていることが考えられるが、大きな通信データをやり取りはしてないので、キーボードやマウスのやり取りであると考えられる。

キーボードやマウスなどのUSBデバイスは、デバイスからデータを送信するので、2.1.1(USBデバイスのアドレス)からhostへ送られているデータを見てみる。Leftover Capture Data の1byte目と3byte目が変化しており、これはUSBキーボードでキーを打った時のデータである。

ちなみに自分の著書である「セキュリティコンテストのためのCTF問題集」で紹介している問題の類題だったので、見た瞬間すぐにわかった(宣伝)

今回は本で紹介したsolverを流用して問題を解いた。(solverがなぜこうなるかは、本を読んでもらうか、他のサイトを見てもらいたい…

本に載ってるsolverはPython 2系で動くように書いたいたので、Python 3系で動くように修正して使用した。

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

from scapy.all import *

keymap = { 0x04: ('a', 'A'), 0x05: ('b', 'B'), 0x06: ('c', 'C'),
           0x07: ('d', 'D'), 0x08: ('e', 'E'), 0x09: ('f', 'F'),
           0x0a: ('g', 'G'), 0x0b: ('h', 'H'), 0x0c: ('i', 'I'),
           0x0d: ('j', 'J'), 0x0e: ('k', 'K'), 0x0f: ('l', 'L'),
           0x10: ('m', 'M'), 0x11: ('n', 'N'), 0x12: ('o', 'O'),
           0x13: ('p', 'P'), 0x14: ('q', 'Q'), 0x15: ('r', 'R'),
           0x16: ('s', 'S'), 0x17: ('t', 'T'), 0x18: ('u', 'U'),
           0x19: ('v', 'V'), 0x1a: ('w', 'W'), 0x1b: ('x', 'X'),
           0x1c: ('y', 'Y'), 0x1d: ('z', 'Z'), 0x1e: ('1', '!'),
           0x1f: ('2', '@'), 0x20: ('3', '#'), 0x21: ('4', '$'),
           0x22: ('5', '%'), 0x23: ('6', '^'), 0x24: ('7', '&'),
           0x25: ('8', '*'), 0x26: ('9', '('), 0x27: ('0', ')'),
           0x28: ('\x0a', '\x0a'), 0x29: ('\x1b', '\x1b'),
           0x2a: ('\x08', '\x08'), 0x2b: ('\x09', '\x09'),
           0x2c: ('\x20', '\x20'), 0x2d: ('-', '_'),
           0x2e: ('=', '+'), 0x2f: ('[', '{'), 0x30: (']', '}'),
           0x31: ('\\', '|'), 0x33: (';', ':'), 0x34: ("\'", '\"'),
           0x35: ('`', '~'), 0x36: (',', '<'), 0x37: ('.', '>'),
           0x38: ('/', '?') }


def read_usbdata_from_pcap():
    pcap = rdpcap("logger.pcap")
    usb_data = []
    for pkt in pcap:
        buf = pkt['Raw'].load
        if buf[22] == 1:
            usb_data.append(buf[27:])
    return usb_data


def analyze_usb_data(usb_data):
    flag = ""
    for d in usb_data:
        if len(d) == 0:
            continue
        if d[2] == 0 or not(0 in d[3:8]):
            # No Event
            continue
        if d[0] == 2 or d[0] == 32:
            # press shift-key
            # binary -> int
            c = keymap[ord(chr(d[2]))][1]
            flag += c
        else:
            # Not press shift-key
            # binary -> int
            c = keymap[ord(chr(d[2]))][0]
            flag += c
    print(flag)


def main():
    data = read_usbdata_from_pcap()
    analyze_usb_data(data)


if __name__ == '__main__':
    main()

solverを動かすと以下のような文字を打っていることが復元でき、FLAGがわかる。

One popular bbut unverified explanatioon for the QWERTY arrangement is that it wwas designed to reduce the likelihood of flag{QWE_keyb0ard_RTY} internal clashhing of typebars by placing commonly ussed combinatiioons of letters farther froom each oher inside the machine.

FLAG

flag{QWE_keyb0ard_RTY}

tkys_not_enough (250pts, 80solves)

問題ファイルはpcapファイル、と思いきやWiresharkで開いてみると「Wiresharkで開けるフォーマットで無い」と怒られる。

fileコマンドでファイルの種類を見てみる。よくわからないフォーマット。

$ file tkys_not_enough.pcap
tkys_not_enough.pcap: dBase III DBT, version number 0, next free block index 524288, 1st item "e"

次にバイナリエディタで見てみる。少し見ていくと、マルチバイトで文字が記録されており、Windowsのpathのようなものが見えるので、Windows環境で取得したデータでないかと予測がつく。

f:id:takahoyo:20210905102130p:plain

ここで、「そういえば、WindowsWiresharkが入ってなくてもパケットキャプチャする方法があったなぁ」というのを思い出す。具体的には netsh trace start capture=yes とコマンドを実行することで、ETL形式で保存される。

https://www.vwnet.jp/Windows/WS16/2017013001/PacketCapture.htm

ETL形式のファイルはMicrosoftGitHubで公開している変換ツールを使用することで、Wiresharkで開くことができるpcapngに変換できる。

https://github.com/microsoft/etl2pcapng

> etl2pcapng.exe tkys_not_enough.etl tkys_not_enough.pcapng
IF: medium=eth  ID=0    IfIndex=15
Converted 58 frames

Wiresharkで開いてみると、500/tcpへの通信がいくつか記録されている。IPsecで使用されるISAKMPプロトコルとして認識され、いくつかのパケットはMalformed Packetとなっているが、画面下部のPacket Bytesでバイナリを見ると実際はHTTP通信であることがわかる。

f:id:takahoyo:20210905102145p:plain

これはWiresharkが本来500/tcpを使用するISAKMPとして誤って解析している結果である。該当のパケットを右クリックして、"Decode As…" を選択、正しいプロトコルとして認識させてあげる。

f:id:takahoyo:20210905102201p:plain

以上のような設定にすると、Wiresharkが正しくHTTPとして認識してくれてパケットを読むことができる。

f:id:takahoyo:20210905102211p:plain

あとは、正しく読めるようになったHTTPパケットを読んでいくと、FLAGを見つけることができる。(普通に平文でFLAGが置いてあるように見えるが、gzipで圧縮されていたのでstringsでは超能力者じゃない限りは見つけることができない。

f:id:takahoyo:20210905102222p:plain

FLAG

flag{netw0rk_shell_2000}

パケットキャプチャというと pcapフォーマットが使われていることが多いのでpcapのイメージが強いと思うが、このように他にも通信を記録するフォーマット(手段)があるというのは非常に勉強になる問題だったと思う。