Trend Micro CTF 2018 Write-up

Trend Micro CTF 2018とは

Trend Micro CTF 2018 – Raimund Genes Cupは、 安全なデジタル社会の実現を目指す トレンドマイクロが主催する、 サイバーセキュリティに関する 第4回目の世界的な競技大会です

www.trendmicro.com

成績

自分はMisc100, Misc200を解き,300点獲得しました. f:id:satto1237:20180916161702j:plain

Write-up

Misc100

Category: Misc
Points: 100
Brave Challenger, welcome!

I will hand you the flag, just not on a silver platter. Closely analyze the file, peel it back layer by layer, examine it byte by byte and the flag will reveal itself.

Follow the rabbit hole, the flag is hiding at the end of the tunnel!

Get your hands dirty! Whip out all your tools! Use your hex editor! But also be careful my brave challenger, for it might blow up in your face.

Good Luck!

f:id:satto1237:20180916162526p:plain

アプローチ:これ系の問題はforemost + binwalk

とりあえず EATME.pdf が渡されるので strings してみると

> strings EATME.pdf | grep flag.txt
flag.txtUT

flag.txtが埋め込めれていることが分かるので, foremost してあげます.
./output/zip/00001462.zip を得ることができるのでunzipします.

> unzip 00001462.zip
Archive:  00001462.zip
Boooooom!
flbn.txt:  mismatching "local" filename (galf.txt),
         continuing with "central" filename version
  inflating: flbn.txt

しかし,微妙にunzipが失敗する(flbn.txtのせい)のでbinwalkを使います.

> binwalk -e  00001462.zip                                                                                                                                                   

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Zip archive data, at least v2.0 to extract, compressed size: 41, uncompressed size: 200, name: flag.txt
4220981       0x406835        End of Zip archive, comment: "Boooooom!"
4221083       0x40689B        Zlib compressed data, default compression
4221165       0x4068ED        Unix path: /Type/Metadata/Subtype/XML>>stream
4221317       0x406985        Unix path: /www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://p
4222198       0x406CF6        Zlib compressed data, default compression
4222644       0x406EB4        Zlib compressed data, default compression

./_00001462.zip.extracted/flag.txt を得ることできました.
flag.txtTMCTF{QWxpY2UgaW4gV29uZGVybGFuZA==}です.
因みにQWxpY2UgaW4gV29uZGVybGFuZA==base64Alice in Wonderlandです.

Misc200

Category: Misc
Points: 200
If you look at that Constellation the sky will open

Traffic Traffic Traffic...

this is really strange ...

hour 1...

hour 2...

hour 3...

where is the data!!!!!? AAAAAAAAAAA ...

lets take a look to the night and see if we can plot something....
Hint 1 REVERSE THE CASES - if you think the flag is in uppercase, try lowercase. If you think the flag is in lowercase, try uppercase.

アプローチ:pcap(ICMP)からデータ抽出+可視化

この問題ではtraffic.pcapproc.pyが渡されます.

まずtraffic.pcapに注目すると,ICMPで何かやってそうなことに気づきます(他のプロトコルTLSv1なので読めない) f:id:satto1237:20180916170607p:plain

ICMPのデータ部を確認すると座標のような値が流れていることに気づきます.
f:id:satto1237:20180916171152p:plain

データを抽出するためにwiresharkicmp.type == 8(ICMPのrequestのみ)というフィルタをかけて一旦pcapで保存します(icmp.pcap).
tsharkを使ってデータを抽出します.

> tshark -r  icmp.pcap -T fields -e data.data

34:2e:34:38:36:39:31:30:2c:33:2e:30:30:30:30:36:30
34:2e:32:30:35:34:31:30:2c:31:2e:34:34:30:30:30:30
33:2e:38:31:31:36:37:30:2c:30:2e:35:30:39:36:35:30
31:2e:30:32:37:32:39:30:2c:33:2e:30:33:38:35:38:30
32:2e:37:37:38:30:32:30:2c:30:2e:30:30:38:33:31:30
35:2e:39:37:37:30:36:30:2c:32:2e:35:32:35:32:31:30
34:2e:31:31:32:39:33:30:2c:34:2e:34:38:30:31:32:30
37:2e:30:31:31:39:37:30:2c:33:2e:30:32:37:31:37:30
36:2e:35:31:30:34:36:30:2c:32:2e:39:33:30:33:30:30
36:2e:39:39:38:36:31:30:2c:32:2e:35:32:37:38:35:30
34:2e:38:30:34:30:31:30:2c:35:2e:30:31:33:39:37:30
37:2e:30:37:33:32:34:30:2c:33:2e:35:33:37:36:31:30
33:2e:38:32:31:37:34:30:2c:30:2e:30:30:30:37:30:30
33:2e:35:36:38:31:36:30:2c:34:2e:39:39:37:30:35:30
...

ここで抽出したデータを適当なスクリプトを書いて座標データに変換します.

import codecs

fr = open('hex.txt','r')
fw = open('test_2.txt','a')
for row in fr:
    hex = ''.join(row.strip().split(':'))
    print(hex)
    text = codecs.decode(hex, 'hex_codec').decode('utf-8')
    print(text)
    fw.write(text + '\n')

fr.close()
fw.close()

多分xxd -p -rをうまく使うとワンライナーで書けると思う
のですが改行周りがめんどくさくなってスクリプト書きました.

座標データを抽出できたのでtraffic.pcapと一緒に渡されたproc.pyを確認します.

import matplotlib.pyplot as plt
import seaborn as sns; sns.set()  # for plot styling
import numpy as np
from sklearn.datasets.samples_generator import make_blobs
from numpy import genfromtxt

#humm, encontre este codigo en un servidor remoto
#estaba junto con el "traffic.pcap"
# que podria ser?, like some sample code 

_data2 = np.genfromtxt('test_2.txt', delimiter=',')
db = DBSCAN(eps=10000, min_samples=100000).fit(my_data2)
labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linsspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):   
    class_member_mask = (labels == k)
    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)
             

             
#NOTE: what you see in the sky put it format TMCTF{replace_here}
#where "replace_here" is what you see
plt.title('aaaaaaaa: %d' % n_clusters_)
plt.show()

コメントを読むとICMPから得た座標データを投げてあげると文字が浮かび上がり,それがflagになるようです.
早速実行しようとしますが,いくつかのエラーがでて実行できません(未定義の変数の使用,DBSCANのimport, DBSCANパラメータの不適切な設定).
そのため,以下のように書き直します.

import matplotlib.pyplot as plt
import seaborn as sns; sns.set()  # for plot styling
import numpy as np
from sklearn.datasets.samples_generator import make_blobs
from numpy import genfromtxt
from sklearn.cluster import DBSCAN

#humm, encontre este codigo en un servidor remoto
#estaba junto con el "traffic.pcap"
# que podria ser?, like some sample code

# _data2 = np.genfromtxt('test_2.txt', delimiter=',')
my_data2 = np.genfromtxt('test_2.txt', delimiter=',')
#eps=10000, min_samples=100000
db = DBSCAN().fit(my_data2)
labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    class_member_mask = (labels == k)
    # xy = X[class_member_mask & core_samples_mask]
    xy = my_data2[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)



#NOTE: what you see in the sky put it format TMCTF{replace_here}
#where "replace_here" is what you see
plt.title('aaaaaaaa: %d' % n_clusters_)
plt.show()

上記のプログラムを実行すると以下のような画像を得ることができます.

f:id:satto1237:20180916174022p:plain

直感で左右反転させます.

f:id:satto1237:20180916174440p:plain

FLAG:1と読めますね.
問題文のヒントに従うと,TMCTF{flag:1}が得られます.

今回の問題とはあまり関係ないですが,DBSCANは密度ベースのクラスタリングアルゴリズムです.
以下の動画が参考になると思います.

www.youtube.com

まとめ

  • 全体的に難しくて簡単な問題しか解けなかった
  • 今回もBinary問題から逃げてしまった
  • Analysis-offensive100で変な音をずっと再生してたら具合悪くなった上に結局解けなかった
  • 0完は回避できたので良かった(CBCTFの悲劇を繰り返さずにすんだ)