SECCON 2016 オンライン予選に参加しました(1)
会社のチームで参加して37位でした。 私はどうでもよい問題しか解けませんでした(x_x)
(Forensics:100) VoIP
Wiresharkでpcap開いて、[Telephony]->[RTP]->[RTP Stream]で再生して聴き取るだけ。 VとRの発音聴き取れるかだけの問題だった。
VはBなの?とか、Rは「アー」としか聴き取れず愕然とした。
SECCON{9001IVR}
9001IVRて何ですか???
(Crypto:100) Vigenere
解いたと思ったら、チームメイトに先を越されてた(第一弾)。 問題中の?文字の数は信じずに解いた。
問題
Vigenere k: ???????????? p: SECCON{???????????????????????????????????} c: LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ k=key, p=plain, c=cipher, md5(p)=f528a6ab914c1ecf856a1d93103948fe |ABCDEFGHIJKLMNOPQRSTUVWXYZ{} -+---------------------------- A|ABCDEFGHIJKLMNOPQRSTUVWXYZ{} B|BCDEFGHIJKLMNOPQRSTUVWXYZ{}A C|CDEFGHIJKLMNOPQRSTUVWXYZ{}AB (省略)
write-up
vigenere.py
# -*- coding: utf-8 -*- # see https://ja.wikipedia.org/wiki/%E3%83%B4%E3%82%A3%E3%82%B8%E3%83%A5%E3%83%8D%E3%83%AB%E6%9A%97%E5%8F%B7 def shift(char, key, chars, rev=False): if not char in chars: return char if rev: return chars[(chars.index(char) - chars.index(key)) % len(chars)] else: return chars[(chars.index(char) + chars.index(key)) % len(chars)] def encrypt(plain, key, chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): return ''.join([shift(plain[i], key[i % len(key)], chars) for i in range(len(plain))]) def decrypt(encrypted, key, chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ"): return ''.join([shift(encrypted[i], key[i % len(key)], chars, rev=True) for i in range(len(encrypted))])
writeup.py
# -*- coding: utf-8 -*- import vigenere import itertools import hashlib chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ{}" crypt = "LMIG}RPEDOEEWKJIQIWKJWMNDTSR}TFVUFWYOCBAJBQ" plain = "SECCON{" #----------- # 前半のキーを既知の平文"SECCON{"を元に求める key = [] for index, c in enumerate(crypt): if index >= len(plain): break for k in chars: p = vigenere.decrypt(c, k, chars) if p == plain[index]: key.append(k) continue front_key = "".join(key) print "front_key => %s" % front_key #----------- # 後半のキーの組み合わせを平文のmd5sumを手がかりに考える # itertoolを使った直積の求め方 see : http://qiita.com/junkls/items/10384950963056cc8e08 def solve(lengthmax, md5sum): for i in range(1,lengthmax+1): keys = list(itertools.product(chars,repeat=i)) for k in keys: true_key = "%s%s" % (front_key, "".join(k)) p = vigenere.decrypt(crypt, true_key, chars) if p[-1] == '}' and md5sum == hashlib.md5(p).hexdigest(): return p return "unsolve" print "solve!!! => %s" % solve(5, md5sum = "f528a6ab914c1ecf856a1d93103948fe")
実行結果(writeup.py)
~/D/c/vigenere ❯❯❯ time python writeup.py front_key => VIGENER solve!!! => SECCON{ABABABCDEDEFGHIJJKLMNOPQRSTTUVWXYYZ} python writeup.py 162.40s user 1.10s system 99% cpu 2:43.75 total
悩んだとこ
Vigenere暗号の問題は、今まで[Vigenere][Online]でググって出てきたサイトで適当に解いてました。これらのサイトはA-Za-zな文字列を対象にしていることが多く、今回の問題を解けるサイトが見つからず、[Vigenere][Python]でググって出てきたサイトを参考にスクリプト書きました。
また、前半の鍵(=VIGENER)を求めた後に後半の鍵をどう作るか悩んで、?の数を信じてforで回すのはクソダサいと思って、標準ライブラリでいいのないかなと探してitertoolに辿り着きました。
最初、後半の鍵を直積(=itertools.product)ではなく組み合わせ(=itertools.combinations)や順列(=itertools.permutations)を使ってflagにたどり着かない!!!(鍵はVIGENERECODEです。後半がECODEなので組み合わせではもちろんダメで、順列も惜しくもダメだった)とアホみたいに悩んでました。。。落ち着いてドキュメント読みましょう。
pythonを立ち上げて、下記を入力してみましょう。イテレータとかジェネレータとか知らなくても望んだものが得られます。素晴らしい。
import itertools list(itertools.product("ABCDE",repeat=3))
(Forensics:100) Memory Analysis
これも解いたと思ったら、チームメイトに先を越されてた(第二弾)。
問題
Memory Analysis Find the website that the fake svchost is accessing. You can get the flag if you access the website!! memoryanalysis.zip The challenge files are huge, please download it first. Hint1: http://www.volatilityfoundation.org/ Hint2: Check the hosts file password: fjliejflsjiejlsiejee33cnc
write-up
環境
$ uname -a Linux ubuntu 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux $ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS" $ sudo apt-get install volatility
Downloadしたメモリイメージがどのプラットフォームの環境のものか確認する。'WinXPSP2x86'か'WinXPSP3x86'のどちらかを選べばよいとわかる。
$ volatility -f forensic_100.raw imageinfo Volatility Foundation Volatility Framework 2.5 INFO : volatility.debug : Determining profile based on KDBG search... Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86) AS Layer1 : IA32PagedMemoryPae (Kernel AS) AS Layer2 : FileAddressSpace (/mnt/hgfs/juns/Downloads/forensic_100.raw) PAE type : PAE DTB : 0x34c000L KDBG : 0x80545ce0L Number of Processors : 1 Image Type (Service Pack) : 3 KPCR for CPU 0 : 0xffdff000L KUSER_SHARED_DATA : 0xffdf0000L Image date and time : 2016-12-06 05:28:47 UTC+0000 Image local date and time : 2016-12-06 14:28:47 +0900
ヒントにhostsを見ろと書かれているので、hostsファイルを抜き出す。 crattack.tistory.comがhostsファイルに登録されていることがわかる。
$ volatility -f forensic_100.raw --profile=WinXPSP3x86 filescan | grep hosts Volatility Foundation Volatility Framework 2.5 0x000000000217b748 1 0 R--rw- \Device\HarddiskVolume1\WINDOWS\system32\drivers\etc\hosts $ volatility -f forensic_100.raw --profile=WinXPSP3x86 dumpfiles -Q 0x000000000217b748 --dump-dir=. Volatility Foundation Volatility Framework 2.5 DataSectionObject 0x0217b748 None \Device\HarddiskVolume1\WINDOWS\system32\drivers\etc\hosts $ cat file.None.0x819a3008.dat # Copyright (c) 1993-1999 Microsoft Corp. # # This is a sample HOSTS file used by Microsoft TCP/IP for Windows. # # This file contains the mappings of IP addresses to host names. Each # entry should be kept on an individual line. The IP address should # be placed in the first column followed by the corresponding host name. # The IP address and the host name should be separated by at least one # space. # # Additionally, comments (such as these) may be inserted on individual # lines or following the machine name denoted by a '#' symbol. # # For example: # # 102.54.94.97 rhino.acme.com # source server # 38.25.63.10 x.acme.com # x client host 127.0.0.1 localhost 153.127.200.178 crattack.tistory.com
メモリイメージ中にcrattack.tistory.comが含まれてないかgrepすると、URLが出て来る。
$ fgrep -a http://crattack.tistory.com forensic_100.raw Referer: http://crattack.tistory.com/entry/Data-Science-import-pandas-as-pd (省略)
hostsファイルに書かれている情報を、自分のPCにも登録して、上記のURLへアクセスするとテキストファイルが落ちてきて、その中にflagが書かれている。
SECCON{_h3110_w3_h4ve_fun_w4rg4m3_}
悩んだとこ
hostsファイルに書かれているcrattack.tistory.comのサイトが実際に韓国語のサイトで存在していること、また153.127.200.178のサイトがnginxで立てられたサイトで存在していため、最後のfgrepする前にこの2つのサイトにflagがあるのでは?と色々とアクセス試してしまいました。funできなかったよ。
Anti-Debuggingもuncomfortable webも先に解かれてたので、チームで取り組む場合はちゃんとチャット見ないとですね。 とはいえ、exploitと100点以上の問題には手出せなかったので精進します。