2015/12/5~6の間SECCON 2015 Online CTFに
チーム名BiPhoneでAkashi_SNとして5人で参加しました。
CTFは初めてまだ1ヶ月ほどにしてはまぁ解けた方かな・・・?
ちなみに順位は240位でした。

僕が解いた問題のwrite upをします。
Write up
SECCON WARS 2015

はっきりと出てくるので読み取って終わり
flag:SECCON{TH3F0RC3AVVAK3N53P7}
Unzip the file
後で他の人のwrite upを見て解きました
unzipというファイルが渡されUnzip the fileとのこと
普通に解凍しようとするとパスワードがかかっているみたい・・・
|
$ unzip unzip.zip Archive: unzip.zip [unzip.zip] backnumber08.txt password: skipping: backnumber08.txt incorrect password skipping: backnumber09.txt incorrect password skipping: flag incorrect password |
|
~$ cd pkcrack-1.2.2/test pkcrack-1.2.2/test/$ sudo make |
testディレクトリに移動して
/testでmakeすると/srcに実行ファイルが生成される
pkcrackの使い方は、
-C [暗号化されたzipファイル]
-c [暗号化されたzipファイルの中で平文がわかるファイル]
-P [平文のファイルが入っている暗号化されていないzip]
-p [平文のファイル]
-d [出力先(復号したzipファイルの名前)]
backnumber08.zipはbacknumber08.txtを普通にzip圧縮したもの
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
/pkcrack-1.2.2/src/$ pkcrack -C ./unzip.zip -c backnumber08.txt -P backnumber08.zip -p backnumber08.txt -d unzip_1.zip Files read. Starting stage 1 on Mon Dec 7 14:35:35 2015 Generating 1st generation of possible key2_5299 values...done. Found 4194304 possible key2-values. Now we're trying to reduce these... Lowest number: 984 values at offset 970 Lowest number: 932 values at offset 969 Lowest number: 931 values at offset 967 Lowest number: 911 values at offset 966 Lowest number: 906 values at offset 965 Lowest number: 904 values at offset 959 Lowest number: 896 values at offset 955 Lowest number: 826 values at offset 954 Lowest number: 784 values at offset 606 Lowest number: 753 values at offset 206 Done. Left with 753 possible Values. bestOffset is 206. Stage 1 completed. Starting stage 2 on Mon Dec 7 14:35:46 2015 Ta-daaaaa! key0=270293cd, key1=b1496a17, key2=8fd0945a Probabilistic test succeeded for 5098 bytes. Ta-daaaaa! key0=270293cd, key1=b1496a17, key2=8fd0945a Probabilistic test succeeded for 5098 bytes. Stage 2 completed. Starting zipdecrypt on Mon Dec 7 14:36:14 2015 Decrypting backnumber08.txt (5315a01322ab296c211eecba)... OK! Decrypting backnumber09.txt (83e6640cbec32aeaf10ed1ba)... OK! Decrypting flag (34e4d2ab7fe1e2421808bab2)... OK! Finished on Mon Dec 7 14:36:14 2015 |
暗号化されていないunzip_1.zipが生成される
|
~$ unzip unzip_1.zip Archive: unzip_1.zip replace backnumber08.txt? [y]es, [n]o, [A]ll, [N]one, [r]ename: y inflating: backnumber08.txt inflating: backnumber09.txt inflating: flag ~$ ls backnumber08.zip unzip.zip backnumber08.txt backnumber09.txt flag unzip_1.zip ~$ file flag flag: Microsoft Word 2007+ ~$ |
flagはwordファイルだとわかる
LibreOfficeで開いてみる
何も見えないがフォントの色を変えると出てくる
flag:SECCON{1s_th1s_passw0rd_ weak?}
Reverse-Engineering Android APK 1
これはチームメイトが前半を解いてくれ最後は僕がflagをみつけました。
なんかいいとこ取りみたい・・・
APKファイルが渡され「じゃんけんに1000回連続で勝ち続けよ」とありました
さすがにごり押しは厳しそうなのでapkファイルについて調べてたらただの圧縮ファイルであるとわかり解凍してみる。
するとclasses.dexというファイルがあってこれがアプリの本体だとわかった。
これは
dex2jarというソフトで変換できるそうなのでやってみる
|
~/dex2jar-2.0$ ./d2j-dex2jar.sh classes.dex dex2jar classes.dex -> ./classes-dex2jar.jar ~/dex2jar-2.0$ ls classes-dex2jar.jar d2j-dex2smali.bat d2j-smali.bat classes.dex d2j-dex2smali.sh d2j-smali.sh d2j-baksmali.bat d2j-jar2dex.bat d2j-std-apk.bat d2j-baksmali.sh d2j-jar2dex.sh d2j-std-apk.sh d2j-dex-recompute-checksum.bat d2j-jar2jasmin.bat d2j_invoke.bat d2j-dex-recompute-checksum.sh d2j-jar2jasmin.sh d2j_invoke.sh d2j-dex2jar.bat d2j-jasmin2jar.bat lib d2j-dex2jar.sh d2j-jasmin2jar.sh |
するとclasses-dex2jar.jarというファイルができる
これはただのzipファイルなので展開してみる
すると/com,/androidの2つのフォルダが出てくる
/com/example/seccon2015/rock_paper_scissors/MainActivity.classを
Java Decompilerというソフトで見てみると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
package com.example.seccon2015.rock_paper_scissors; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import java.util.Random; public class MainActivity extends Activity implements View.OnClickListener { Button P; Button S; int cnt = 0; int flag; private final Handler handler = new Handler(); int m; int n; Button r; private final Runnable showMessageTask = new Runnable() { public void run() { TextView localTextView = (TextView)MainActivity.this.findViewById(2131492946); MainActivity localMainActivity; if (MainActivity.this.n - MainActivity.this.m == 1) { localMainActivity = MainActivity.this; localMainActivity.cnt += 1; localTextView.setText("WIN! +" + String.valueOf(MainActivity.this.cnt)); } for (;;) { if (1000 == MainActivity.this.cnt) { localTextView.setText("SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}"); } MainActivity.this.flag = 0; return; if (MainActivity.this.m - MainActivity.this.n == 1) { MainActivity.this.cnt = 0; localTextView.setText("LOSE +0"); } else if (MainActivity.this.m == MainActivity.this.n) { localTextView.setText("DRAW +" + String.valueOf(MainActivity.this.cnt)); } else if (MainActivity.this.m < MainActivity.this.n) { MainActivity.this.cnt = 0; localTextView.setText("LOSE +0"); } else { localMainActivity = MainActivity.this; localMainActivity.cnt += 1; localTextView.setText("WIN! +" + String.valueOf(MainActivity.this.cnt)); } } } }; static { System.loadLibrary("calc"); } public native int calc(); public void onClick(View paramView) { if (this.flag == 1) { return; } this.flag = 1; ((TextView)findViewById(2131492946)).setText(""); TextView localTextView1 = (TextView)findViewById(2131492944); TextView localTextView2 = (TextView)findViewById(2131492945); this.m = 0; this.n = new Random().nextInt(3); int i = this.n; localTextView2.setText(new String[] { "CPU: Paper", "CPU: Rock", "CPU: Scissors" }[i]); if (paramView == this.P) { localTextView1.setText("YOU: Paper"); this.m = 0; } if (paramView == this.r) { localTextView1.setText("YOU: Rock"); this.m = 1; } if (paramView == this.S) { localTextView1.setText("YOU: Scissors"); this.m = 2; } this.handler.postDelayed(this.showMessageTask, 1000L); } protected void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2130968600); this.P = ((Button)findViewById(2131492941)); this.S = ((Button)findViewById(2131492943)); this.r = ((Button)findViewById(2131492942)); this.P.setOnClickListener(this); this.r.setOnClickListener(this); this.S.setOnClickListener(this); this.flag = 0; } } |
39行目にflagらしきものが・・・
$cntはカウンターだとわかった
どうやらcalc()はライブラリーから読み込んでいるらしい・・・
そういえばライブラリファイルがあったなー
/rps/lib/x86/libcalc.soをfileコマンドでたたくと
|
/CTF/seccon2015/Reverse-Engineering Android APK 1/rps/lib/x86/libcalc.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV),dynamically linked, BuildID[sha1]=841ccd3a86c678914a4dc1a17bd80647ca290916, stripped |
|
// // This file was generated by the Retargetable Decompiler // Website: https://retdec.com // Copyright (c) 2015 Retargetable Decompiler <info@retdec.com> // Address range: 0x400 - 0x405 int32_t Java_com_example_seccon2015_rock_1paper_1scissors_MainActivity_calc(void) { // 0x400 return 7; } |
calc()はいつでも7を返すということがわかり
|
SECCON{" + String.valueOf((MainActivity.this.cnt + MainActivity.this.calc()) * 107) + "}" |
ここを計算して
flag:SECCON{107749}
Command-Line Quiz
telnet caitsith.pwn.seccon.jp
User:root
Password:seccon
すべての *.txt ファイルを読め
接続しクイズの答えもわかったが回答の仕方がわからず断念・・・
Steganography 1
MrFusion.gpjbというファイルが渡され「Find image files in the file」とのこと
このファイルはgifファイルだとわかったので拡張子を変え表示してみるとSECCON{}としか描かれてないのに8Mはでかすぎるので
バイナリエディタで見てみるといろんなファイルフォーマットのヘッダーが含まれていたのでそれを仕様に沿って分けてみるてそれを合成すると

flagかと思ってsubmitしたがincorrectばっかりだった
結局できず断念
//gpjbはg(mp)p(ng)j(peg)b(mp)の略だったようでbmpが足らなかったから不正解だったみたい
—-後で解いてみた
binwalkという便利なコマンドがあるらしい
なんでもファイルを解析してくれるみたいfileコマンドの強いやつって感じかな?
aptでgetできるものはバージョンが古いみたいなので
ここからホームディレクトリにダウンロードして
|
~$ cd binwalk-2.0.0.tar/binwalk-2.0.0 binwalk-2.0.0.tar/binwalk-2.0.0 $ ./configure binwalk-2.0.0.tar/binwalk-2.0.0 $ make binwalk-2.0.0.tar/binwalk-2.0.0 $ sudo make install |
これでインストールできbinwalkで実行できる
binwalkでMrFusion.gpjbを解析してみると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
$ binwalk MrFusion.gif DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 GIF image data, version "89a", 1280 x 720 6943 0x1B1F PNG image, 1280 x 720, 8-bit colormap, interlaced 7194 0x1C1A Zlib compressed data, compressed, uncompressed size >= 922950 9727 0x25FF JPEG image data, JFIF standard 1.01 26632 0x6808 PC bitmap, Windows 3.x format, 1280 x 720 x 24 2791486 0x2A983E GIF image data, version "89a", 1280 x 720 2794240 0x2AA300 PNG image, 1280 x 720, 8-bit colormap, interlaced 2794491 0x2AA3FB Zlib compressed data, compressed, uncompressed size >= 922950 2796217 0x2AAAB9 JPEG image data, JFIF standard 1.01 2813627 0x2AEEBB PC bitmap, Windows 3.x format, 1280 x 720 x 24 5578481 0x551EF1 GIF image data, version "89a", 1280 x 720 5580896 0x552860 PNG image, 1280 x 720, 8-bit colormap, interlaced 5581147 0x55295B Zlib compressed data, compressed, uncompressed size >= 922950 5583378 0x553212 JPEG image data, JFIF standard 1.01 5601221 0x5577C5 PC bitmap, Windows 3.x format, 1280 x 720 x 24 8366075 0x7FA7FB GIF image data, version "89a", 1280 x 720 8368830 0x7FB2BE PNG image, 1280 x 720, 8-bit colormap, interlaced 8369081 0x7FB3B9 Zlib compressed data, compressed, uncompressed size >= 922950 8371932 0x7FBEDC JPEG image data, JFIF standard 1.01 |
このようにファイルフォーマットごとに表示してくれます
(ZlibはPNGに使われている圧縮方法なのでZlibのところは無視する)
gif→png→jpeg→bmp→gif→png→・・・のように繰り返している
|
#coding: UTF-8 a = [0,6943,9727,26632,2791486,2794240,2796217,2813627,5578481,5580896,5583378,5601221,8366075,8368830,8371932,8388384] #アドレス b = ['gif','png','jpg','bmp'] #拡張子 f = open("MrFusion.gif", "rb") #ファイルの読み込み for x in range(len(a)-1): open('result{:02d}.{}'.format(x, b[x % 4]), 'wb').write(f.read(a[x + 1] - a[x])) |
pythonのコードを書いて実行
|
~/ctf/a$ ls MrFusion.gif split.py ~/ctf/a$ python split.py ~/ctf/a$ ls MrFusion.gif result03.bmp result07.bmp result11.bmp split.py result00.gif result04.gif result08.gif result12.gif result01.png result05.png result09.png result13.png result02.jpg result06.jpg result10.jpg result14.jpg ~/ctf/a$ |
分割されたファイルが出力される
最初と最後のファイルをネガポジ変換しすべてjpgに変換して
SiriusCompで比較明合成
Please input flag like this format–>SECCON{*** ** **** ****}
形式が指定されていたので
flag:SECCON{OCT 21 2015 0728}
4042
謎の文章が2005年に古代遺跡から発見された。
4042?2005?古代遺跡?ということでとりあえずググってみた

東ソー?
RFC4042
2005 年のエープリルフール発行のジョーク RFC です。
UCS4 や UCS2(Unicode) のエンコード方法である UTF-9 や UTF-18 を規定しています。 PDP-10 などの8bitベースではないマシンのためのエンコーディング…?
ジョーク・・・
このファイルはUTF-9で書かれているのか・・・
rfc4042.txtにUTF-9からUCS-4に変換するコードが書かれている
|
/* Return UCS-4 value from UTF-9 string (C version) * Accepts: pointer to pointer to UTF-9 string * Returns: UCS-4 character, nonet pointer updated */ UINT31 UTF9_to_UCS4 (UINT9 **utf9PP) { UINT9 nonet; UINT31 ucs4; for (ucs4 = (nonet = *(*utf9PP)++) & 0xff; nonet & 0x100; ucs4 |= (nonet = *(*utf9PP)++) & 0xff) ucs4 <<= 8; return ucs4; } |
Last Challenge (Thank you for playing)
規則性にのっとて変換するだけ
flag:SECCON{SEEYOUNEXTYEAR}
終わり
初めてにしてはできたかな~
でも疲れた
視野は広くしないと