­
This is Google's cache of http://akashisn.azurewebsites.net/. It is a snapshot of the page as it appeared on Feb 1, 2016 02:37:46 GMT.
The current page could have changed in the meantime. Learn more
Full versionText-only versionView sourceTip: To quickly find your search term on this page, press Ctrl+F or ⌘-F (Mac) and use the find bar.

Akashi_SNの日記

おもにCTF関係のことを書いていきます

SECCON 2015 Online CTF write up

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

Write up


SECCON WARS 2015


https://youtu.be/8SFsln4VyEk
Youtubeのリンクがあるだけ・・・
とりあえず見てみるとStarWarsをもじったみたいな動画があり途中からQRコードが見え始める。
とにかくダウンロードしてフレームごとに分けてみる
背景だけ動いているのでもしやこれは比較明合成が使えるのではと思い
僕がよく星の写真を撮るときに使うSiriusCompを使ってみたら
output_comp
はっきりと出てくるので読み取って終わり
flag:SECCON{TH3F0RC3AVVAK3N53P7}

Unzip the file


 
後で他の人のwrite upを見て解きました
unzipというファイルが渡されUnzip the fileとのこと
普通に解凍しようとするとパスワードがかかっているみたい・・・
1
2
3
4
5
6
$ 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
backnumber08.txtをとりあえず検索してみると
http://2014.seccon.jp/mailmagazine/backnumber08.txt
このようにヒットする
ファイルの中身がわかっているので既知平文攻撃だとわかる
これはpkcrackというツールで解析できるみたい
とりあえずソースをダウンロードして
1
2
~$ 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が生成される
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
~$ 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で開いてみる
何も見えないがフォントの色を変えると出てくる
Screenshot from 2015-12-07 14-57-31
flag:SECCON{1s_th1s_passw0rd_ weak?}

Reverse-Engineering Android APK 1


これはチームメイトが前半を解いてくれ最後は僕がflagをみつけました。
なんかいいとこ取りみたい・・・
APKファイルが渡され「じゃんけんに1000回連続で勝ち続けよ」とありました
さすがにごり押しは厳しそうなのでapkファイルについて調べてたらただの圧縮ファイルであるとわかり解凍してみる。
するとclasses.dexというファイルがあってこれがアプリの本体だとわかった。
これはdex2jarというソフトで変換できるそうなのでやってみる
1
2
3
4
5
6
7
8
9
10
11
~/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というソフトで見てみると
MainActivity.class
Java
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コマンドでたたくと
file
1
/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
32bitのelfだとわかったのでRetargetable Decompilerというオンラインのデコンパイラーでデコンパイルしてみると
libcalc.soのソースの一部
C
1
2
3
4
5
6
7
8
9
10
//
// 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を返すということがわかり
MainActivity.class
Java
1
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はでかすぎるので
バイナリエディタで見てみるといろんなファイルフォーマットのヘッダーが含まれていたのでそれを仕様に沿って分けてみるてそれを合成すると
output_comp
flagかと思ってsubmitしたがincorrectばっかりだった
結局できず断念
//gpjbはg(mp)p(ng)j(peg)b(mp)の略だったようでbmpが足らなかったから不正解だったみたい
—-後で解いてみた
binwalkという便利なコマンドがあるらしい
なんでもファイルを解析してくれるみたいfileコマンドの強いやつって感じかな?
aptでgetできるものはバージョンが古いみたいなのでここからホームディレクトリにダウンロードして
1
2
3
4
~$ 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→・・・のように繰り返している
split.py
Python
1
2
3
4
5
6
7
8
9
10
#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のコードを書いて実行
1
2
3
4
5
6
7
8
9
~/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で比較明合成
result
Please input flag like this format–>SECCON{*** ** **** ****}
形式が指定されていたので
flag:SECCON{OCT 21 2015 0728}

4042


謎の文章が2005年に古代遺跡から発見された。
これは何を意味している?
no-network.txt
4042?2005?古代遺跡?ということでとりあえずググってみた
1449733739419
東ソー?
1449733917783
おっなんかヒットした
https://www.ietf.org/rfc/rfc4042.txt
RFC4042・・・?
とりあえずググってみた
RFC4042–Google検索
1449736342896

RFC4042

2005 年のエープリルフール発行のジョーク RFC です。
UCS4 や UCS2(Unicode) のエンコード方法である UTF-9 や UTF-18 を規定しています。 PDP-10 などの8bitベースではないマシンのためのエンコーディング…?
ジョーク・・・
このファイルはUTF-9で書かれているのか・・・
rfc4042.txtにUTF-9からUCS-4に変換するコードが書かれている
UTF-9 to UCS4
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   /* 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}

終わり


初めてにしてはできたかな~
でも疲れた
視野は広くしないと

CpawCTF write up

CpawCTFをやってみたので
出来ているやつからwrite upを書いていきます
出来次第追加していきます

Q1

テスト問題
書いてあるやつを提出

Q6

シーザー暗号なので
http://www.rot-n.com/ここでcpaw{}になるやつを探す
rot23で変換

Q7

fileコマンドをたたくと32bitのelfだとわかるのでlinuxで実行

Q8

fileコマンドをたたくとmicrosoftのwordのファイルだとわかる
拡張子を.docにして開く

Q9

ページのソースを表示する
XHTML
1
2
3
<meta name="keyword" content="ctf,flag">
    <meta name="description" content="flag is cpaw{9216ddf84851f15a46662eb04759d2bebacac666}">
    <meta name="author" content="takahoyo">

Q10

画像のEXIF情報を見る

Q11

wiresharkで開く

Q12

google検索

Q14

C++のsortを使う
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <algorithm>
 
using namespace std;
 
int main (){
int a[72]={15,1,93,52,66,31,87,0,42,77,46,24,99,10,19,36,27,4,58,76,2,81,50,102,33,94,20,14,80,82,49,41,12,143,121,7,111,100,60,55,108,34,150,103,109,130,25,54,57,159,136,110,3,167,119,72,18,151,105,171,160,144,85,201,193,188,190,146,210,211,63,207};
sort(a,a+72, greater<int>());
for(int i=0;i<72;i++)
cout<<a[i];
cout<<endl;
return 0;
}

Q15

Fiddlerなどでキャプチャー
1
2
3
4
5
6
7
8
HTTP/1.1 302 Found
Server: nginx
Date: Sat, 30 Jan 2016 15:25:48 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 0
Connection: keep-alive
X-Flag: cpaw{4re_y0u_1ook1ng_http_h3ader?}
Location: http://q9.ctf.cpaw.site

Q16

NetworkMinerで開き
ファイルを開き
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</head>
<body>
    <div class="container-narrow">
      <div class="masthead">
        <h3 class="muted">Capture The Flag</h3>
      </div>
      <hr>
      <div class="jumbotron">
        <h1>Capture The Flag</h1>
        <p class="lead">フラグが欲しかったら下のボタンを押すんだ!!</p>
        <p><img id="image1" class="img-rounded" id="image1" src="./img/image.jpg"/></p>
        <p><a class="btn btn-large btn-success" onclick="OnButtonClick();">ボタン</a></p>
      </div>
      <hr>
      <div class="footer">
        <p>© 2015 takahoyo</p>
      </div>
    </div>
    <script src="./js/button2.js"></script>
</body>
</html>
これのjsを読んでいるところを
1
2
3
<script type="text/javascript">
      button2. 内容
</script>
とする

Q17

検索するとhttps://twitter.com/_n4nu_/status/653601102441525248
これがヒットする

Q18

fileコマンドをたたくとtcpdump capture fileと出るのでwiresharkで開くことが出来なかった
バイナリエディタで開くとlovelive!がいっぱいあるその中に違うやつがあるので
lovelive!に含まれるやつをすべて空白に置換すると
CCCPPPAAAWWW{{{MMMGGGRRREEEPPP}}}
3文字を1文字にする

Q22

1
SELECT * FROM  palloc_home;
これを入力する

Q28

Wiresharkで開くとtcpとftpでの通信が見られる
ftpにログインできている
USER cpaw_user
PASS 5f4dcc3b5aa765d61d8327deb882cf99
でftpでログインするflagは同じディレクトリに隠しファイルである

Q24

Q22で出てきたurlに行き
1
'OR 1=1 --
これを入力する

まだまだ・・・

8946 write up

8946という常時開催CTFをやってみたので
このサイトでは、セキュリティーに関連する問題を解くことができ、ハッキングを通してセキュリティを学ぶ事ができます。
…8946より
出来ているものからwrite upを書いていきます。
随時追加していきます

take#1

ソースを読むとパスワードチェックというのがある
そこに書いてあるパスワードとidを入力

take#2

password.jsという明らかに怪しいjsを読み込んでいる
そこに書いてあるパスワードとidを入力

take#3

パスワードのメモにあるやつはbase64という変換方式で変換されている
逆変換して提出

take#4

ここのやつはmd5ハッシュ値というもので変換されている
md5は逆変換は出来なく変換データベースにあるものならgoogleで検索すると出てくる
検索して出てくるものを提出

take#5

sqlインジェクション
というものをするid欄に
1
' OR 1=1--
を入力するそして出てきたもので退会していないアカウントでログイン

take#6

basic認証は.htpasswdというファイルにパスワードが保存されているが、
今回はhtpassed.txtというファイル名
そこにアクセスし書いてあるのを提出

take#7

take7.phpのCookieを見るとtake7_login_statusが0となっていたのでそれを1に書き換えてアクセス

take#8

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//パスワードチェック
function fnFormSubmit(){
//-------------------------------------------------------------------------------------
var id   = 'admintake8'; //IDの設定
var pass = (Math.round(8%2)*(88951634/2))+(6660/4)*4/3+6726; //パスワードの設定
//-------------------------------------------------------------------------------------
if (document.form1.id.value == id &amp;&amp; document.form1.pass.value == pass) {
alert('Congratulations! 正解!!');
}
else {
alert('残念!');
}
document.form1.submit();
}
ここを計算して終わり

take#9

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var now = new Date();
var seconds = now.getSeconds();//秒数取得
function fn_timer(){
now = new Date();
seconds = now.getSeconds();
document.getElementById("sec").innerHTML = seconds;//秒数を画面に表示
setTimeout('fn_timer()',1);
}
 
//入力されたナンバーのチェック
function fn_check(){
//入力されたナンバー
var input_no = document.form1.input_no.value;
var answer = ( ( seconds * ( seconds - 1 ) ) / 2 )*(input_no % 2);
if (answer==990) {
document.form1.answer_val.value = seconds;
}
document.form1.submit();
}
ここを計算したやつをタイミングよく提出

take#10

普通に
1
' OR 1=1--
を入力すると
1
窶サ ッ闍ア謨ー蟄励〒蜈・蜉帙@縺ヲ縺上□縺輔>縲
というように文字化けしているここにあるようにutf-8をsjisで読んでいる
5C問題というやつでsjisなどのマルチバイト文字などで発生する
1
ソ' OR 1=1#
これを入力して終わり

take#11

urlでファイルが指定されているのでそこを
password.txtにする
1
index.php?file=password.txt

take#12

svnの管理フォルダを見るみたい
hack/svn/.svn/
にアクセスして書いてあるのを提出

take#13

ファイルはjpgではなくpsdなのでgimpなどで開くと別レイヤーに「RDPのデフォルトのポート番号は?」と書かれている
3389番ポートなので提出

take#14

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
  $url = 'http://www.hackerschool.jp/hack/take14.php';
    $headers = array(
      'Referer: http://www.hackerschool.jp/hack/take14.php',
      'Cookie: PHPSESSID=自分のPHPSSID',
    );
    $data = array(
      'input_id' => '8946',
  );
  $options = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($data),
    'header' => implode("\r\n", $headers),
  ));
  echo file_get_contents($url, false, stream_context_create($options));
?>
javascriptを通らずに直接POSTを送ると思ったけど
XSSの問題だったみたい
XHTML
1
"><script>function  fnFormSubmit(){document.form1.submit();}</script>
これをID欄に入力して8946を入力するって正解ページに書かれているけどなんかできない

take#15

WiresharkなどでキャプチャーしてNetworkMinerで表示するとtake15_answer.htmlがあるのでそれを提出

take#16

1
2
3
if (binary(parseInt(document.form1.input_id.value))==10001011110010) {
alert('Congratulations! 正解!!');
}
2進数を10進数に変換して終わり

take#17

javascriptが2つ書かれているときは後に書かれたほうが実行されるので
input_id=13579となる
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
  $url = 'http://www.hackerschool.jp/hack/take17.php';
    $headers = array(
      'Referer: http://www.hackerschool.jp/hack/take17_dummy_referrer/',
      'Cookie: PHPSESSID=自分のPHPSSID',
    );
    $data = array(
      'input_id' => '13579',
  );
  $options = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($data),
    'header' => implode("\r\n", $headers),
  ));
  echo file_get_contents($url, false, stream_context_create($options));
?>

take#18

PHP
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
<?php
$pre="angou_value";
$ans="           ";
for($i=0;$i<strlen($pre);$i++){
$y=' ';
if($pre[$i]=='a') $y='z';
if($pre[$i]=='b') $y='y';
if($pre[$i]=='c') $y='x';
if($pre[$i]=='d') $y='w';
if($pre[$i]=='e') $y='v';
if($pre[$i]=='f') $y='u';
if($pre[$i]=='g') $y='t';
if($pre[$i]=='h') $y='s';
if($pre[$i]=='i') $y='r';
if($pre[$i]=='j') $y='q';
if($pre[$i]=='k') $y='p';
if($pre[$i]=='l') $y='o';
if($pre[$i]=='m') $y='n';
if($pre[$i]=='n') $y='m';
if($pre[$i]=='o') $y='l';
if($pre[$i]=='p') $y='k';
if($pre[$i]=='q') $y='j';
if($pre[$i]=='r') $y='i';
if($pre[$i]=='s') $y='h';
if($pre[$i]=='t') $y='g';
if($pre[$i]=='u') $y='f';
if($pre[$i]=='v') $y='e';
if($pre[$i]=='w') $y='d';
if($pre[$i]=='x') $y='c';
if($pre[$i]=='y') $y='b';
if($pre[$i]=='z') $y='a';
if($pre[$i]=='_') $y=' ';
$ans[$i]=$y;
}
echo $ans;
?>
これを実行して
zmtlf ezofv
を提出

take#19

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$url = 'http://www.hackerschool.jp/hack/take19.php?id=1&id2=99';
$headers = array(
        'Referer: http://www.hackerschool.jp/hack/take19.php',
'Cookie: PHPSESSID=自分のPHPSSID',
);
$data = array(
'input_id' => 'abcd',
     'ymd' => date('Y/m/d'),
     'pass' => str_rot13("whitehackerz"),
    );
$options = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($data),
    'header' => implode("\r\n", $headers),
    ));
    echo file_get_contents($url, false, stream_context_create($options));
?>
書いてあるとおりにリクエストを送る

take#20

urlがindex.pl?file=main.txtとなっておりperlのopen関数が使われていることが分かる
open関数にはこのように”|”を挟むことで任意のコマンドを実行できる脆弱性がある
index.pl?file=main.txt|lsで見てみると
main.txt
password.inc
があることが分かるので
ファイルを表示するコマンドはcatなので
index.pl?file=main.txt|cat%20password.inc
こうすると出てくる

take#21

htmlのヘッダーを見ると
PASSWORD(take#21):8946passTake21

take#22

表示されているパスワードを入力しようとすると3文字までしか入力できない
XHTML
1
<input type="text" name="pass" value="" style="" maxlength="3">
maxlength=”3″で文字数制限がかかっているのでそれを消して入力

take#23

f12を押して表示

take#24


take#25

PHP
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
<?php    
  $arr1[] = 'ぁ';
  $arr1[] = 'あ';
  $arr1[] = 'ぃ';
  $arr1[] = 'い';
  $arr1[] = 'ぅ';
  $arr1[] = 'う';
  $arr1[] = 'ぇ';
  $arr1[] = 'え';
  $arr1[] = 'ぉ';
  $arr1[] = 'お';
  $arr1[] = 'か';
  $arr1[] = 'が';
  $arr1[] = 'き';
  $arr1[] = 'ぎ';
  $arr1[] = 'く';
  $arr1[] = 'ぐ';
  $arr1[] = 'け';
  $arr1[] = 'げ';
  $arr1[] = 'こ';
  $arr1[] = 'ご';
  $arr1[] = 'さ';
  $arr1[] = 'ざ';
  $arr1[] = 'し';
  $arr1[] = 'じ';
  $arr1[] = 'す';
  $arr1[] = 'ず';
  $arr1[] = 'せ';
  $arr1[] = 'ぜ';
  $arr1[] = 'そ';
  $arr1[] = 'ぞ';
  $arr1[] = 'た';
  $arr1[] = 'だ';
  $arr1[] = 'ち';
  $arr1[] = 'ぢ';
  $arr1[] = 'っ';
  $arr1[] = 'つ';
  $arr1[] = 'づ';
  $arr1[] = 'て';
  $arr1[] = 'で';
  $arr1[] = 'と';
  $arr1[] = 'ど';
  $arr1[] = 'な';
  $arr1[] = 'に';
  $arr1[] = 'ぬ';
  $arr1[] = 'ね';
  $arr1[] = 'の';
  $arr1[] = 'は';
  $arr1[] = 'ば';
  $arr1[] = 'ぱ';
  $arr1[] = 'ひ';
  $arr1[] = 'び';
  $arr1[] = 'ぴ';
  $arr1[] = 'ふ';
  $arr1[] = 'ぶ';
  $arr1[] = 'ぷ';
  $arr1[] = 'へ';
  $arr1[] = 'べ';
  $arr1[] = 'ぺ';
  $arr1[] = 'ほ';
  $arr1[] = 'ぼ';
  $arr1[] = 'ぽ';
  $arr1[] = 'ま';
  $arr1[] = 'み';
  $arr1[] = 'む';
  $arr1[] = 'め';
  $arr1[] = 'も';
  $arr1[] = 'ゃ';
  $arr1[] = 'や';
  $arr1[] = 'ゅ';
  $arr1[] = 'ゆ';
  $arr1[] = 'ょ';
  $arr1[] = 'よ';
  $arr1[] = 'ら';
  $arr1[] = 'り';
  $arr1[] = 'る';
  $arr1[] = 'れ';
  $arr1[] = 'ろ';
  $arr1[] = 'ゎ';
  $arr1[] = 'わ';
  $arr1[] = 'ゐ';
  $arr1[] = 'ゑ';
  $arr1[] = 'を';
  $arr1[] = 'ん';
  $arr1[] = 'ゔ';
  $arr1[] = 'ゕ';
  $arr1[] = 'ゖ';
  $arr1[] = '゛';
  $arr1[] = '゜';
  $arr1[] = 'ゝ';
  $arr1[] = 'ゞ';
  
  $arr2 = $arr1;
  $arr3 = $arr1;
  $arr4 = $arr1;
  $count= count($arr1)-1;
  echo $count;
 
  for($a = 0; $a <= $count; $a++){
    for($b = 0; $b <= $count; $b++){
      for($c = 0; $c <= $count; $c++){
        for($d = 0; $d <= $count; $d++){
          $arr = $arr1[$a].$arr2[$b].$arr3[$c].$arr4[$d];
          $arr0 = md5($arr);
          if($arr0 === "表示されているハッシュ値"){
            exit($arr);
          }    
        }
      }  
    }
  }
  echo $arr0;
?>
これを実行

take#26

JavaScript
1
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('7 6(){c.b("l+m+j",7(){i.k("g").f="<9 a=\'5 5-e\'>d&#h;&#z;&#2;&#4;&#w;&#0; &#v;&#8;&#1;&#n; &#x;&#y;&#A;&#3;&#2;&#4;&#2; &#u;&#0;&#t;&#8;&#1;&#3;&#p;&#1;&#0;? (o / q)</9>"})}r.s=6;',37,37,'1072|1085|1086|1090|1075|alert|init|function|1077|div|class|add|shortcut|Hint|info|innerHTML|hint|65306|document||getElementById|Shift|Alt|1100|MM|1080|DD|window|onload|1083|1042|1044|1076|1057|1074|1050|1103'.split('|'),0,{}))
このように難読化されたコードがあるので
javascriptを整形するやつで整形すると
XHTML
1
<div class='alert alert-info'>Hint&#65306;&#1050;&#1086;&#1075;&#1076;&#1072; &#1044;&#1077;&#1085;&#1100; &#1057;&#1074;&#1103;&#1090;&#1086;&#1075;&#1086; &#1042;&#1072;&#1083;&#1077;&#1085;&#1090;&#1080;&#1085;&#1072;? (MM / DD)</div>
htmlのタグがあるのでchromeなどで開くと
1
Когда День Святого Валентина? (MM / DD)
このようになるのでロシア語を翻訳すると
バレンタインはいつ?(00/00)で
なので02/14を提出

take#27

JavaScript
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
setInterval('timer()',1000);
 
setInterval('fn_timer()',1);
 
var time = 0;
 
function timer() {
 
    time++;
 
    if (time == 60) time = 0;
 
    document.getElementById("timer").innerHTML = time;
 
}
 
function fn_timer() {
 
    now = new Date();
 
    seconds = now.getSeconds();
 
    document.getElementById("sec").innerHTML = seconds;
 
}
 
function fnFormSubmit () {
 
    pass = seconds * (time + 1) * (document.form1.pass.value % 2);
 
    if (pass == 437 && time % 2 == 0) {
 
     document.form1.sec.value = seconds;
 
document.form1.timer.value = time;
 
        alert('Congratulations!');
 
    } else {
 
        alert('残念!');
 
    }
 
    document.form1.submit()
 
}
2つの数字の差が23か19の時に1を入力

take#28

ILSpyで逆コンパイルすると
C#
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
namespace Decompile
{
internal class Take28
{
public static void Main(string[] args)
{
int i = 0;
string b = "getTake28Password";
string arg = "geTX5bZt";
Console.WriteLine("Input the keyword!");
while (i < 3)
{
if (Console.ReadLine() == b)
{
Console.WriteLine(string.Format("The password is {0} !", arg));
IL_71:
Console.ReadLine();
return;
}
if (i < 2)
{
Console.WriteLine("Sorry. Try again.");
}
 
i++;
}
Console.WriteLine("Wrong keyword. Abort.");
goto IL_71;
}
}
}
このようにコードが出てくる
答えを聞かれてるのでargの方を提出

take#29


take#30

全探索だけど
C++
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
#include <iostream>
 
using namespace std;
 
int Prime(int n){
    int i;
 
    if(n < 2)
        return 0;
    else if(n == 2)
        return 1;
 
    if(n % 2 == 0)
        return 0;
 
    for(i = 3; i <= n / i; i += 2)
         if(n % i == 0)
            return 0;
    return 1;
}
int main(){
int j=0,i=0;
while(j!=8946){
i++;
if(Prime(i)==1){
j++;
}
}
cout<<i<<endl;
return 0;
}

take#31

バイナリエディタなどで見る

take#32


take#33

画像のEXIF情報を見る

take#34


take#35

ケータイの端末ID・ユーザIDの取得についてまとめてみましたにあるようにdocomoで15文字なのでFOMA端末製造番号だとわかる
User Agentを
1
DoCoMo/2.0 P902i(c100;TB;W24H12;ser365079045783623;iccxxxxxxxxxxxxxxxxxxxx)
これにしてアクセス

take#36


take#37


take#38

書いたファイルに.htmlを追加している
追加されないように%00を最後に書いて提出する
これはnullバイト攻撃といって文字列の最後を表す%00を認識してしまうからおこる問題

take#39


take#40


take#41


take#42

User Agentを8946に変更する

take#43


take#44

$successにtrueを代入する
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
  $url = 'http://www.hackerschool.jp/hack/take44.php';
    $headers = array(
      'Referer: http://www.hackerschool.jp/hack/take44.php',
      'Cookie: PHPSESSID=自分のPHPSSID',
    );
    $data = array(
      'input_id' => 'a',
      'pass' => 'b',
      'success' => 'true',
  );
  $options = array('http' => array(
    'method' => 'POST',
    'content' => http_build_query($data),
    'header' => implode("\r\n", $headers),
  ));
  echo file_get_contents($url, false, stream_context_create($options));
?>

take#45


take#46

md5関数に配列を渡すとFalseとなることを利用
XHTML
1
2
3
4
<input type="text" name="input_id" value="" style="">
これを
<input type="text" name="input_id[]" value="" style="">
これにするだけ

take#47

whoisで検索
答えが更新されていないみたいで
×2016/07/31
○2014/07/31
になってる

take#48

urlにgetでnoにdXduc3kgNDg7がわたされている
Base64でデコードすると
uwnsy 48;
ヒントによるとuwnsyはprintのことらしいのでシーザー式暗号だとわかる
uwnsyはprintを5文字ずらしている
print get_pass();
を変換すると
uwnsy ljy_ufxx();
こうなり
Base64でエンコードしnoに渡すとtake#の後にpassが出てくる

take#49


take#50


take#51

google翻訳にかけてみるとフランス語だとわかる
フランスからアクセスする

take#52


take#53


take#54


take#55


take#56


take#57


take#58

みかか暗号でググる

take#59

ググると村上春樹の1Q84が出てくる

take#60


take#61


take#62


take#63

Fiddlerなどで見ているとログインできない時は302を返しているがmenu.phpの内容が見れている
管理ユーザー管理admin_user.phpにアクセスしたらadminのパスワードが書かれたものが302で返ってくるのでそれを見る

おわり

全完への道は長い・・・
0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%