読者です 読者をやめる 読者になる 読者になる

Twitterに書ききれないこと

イベントや技術的なことを記したい・・・

Python For Hackers!

6/28に大和セキュリティ勉強会の6月のテーマはPython For Hackers! a.k.a. Python入門に参加してきました。 pythonは、この業界で必須といえるぐらいよく見るので、書けるようにならなとなーとか思いつつ触った程度でした。

問題と資料はhttp://www.yamatosecurity.com/でそのうち公開されると思います。

内容はCTFで使えそうなPythonのコードを問題を解きながら書いてみようという感じでした。私自身Pythonは入門書の内容を理解しているレベルだったので、不安でしたがコーディング力を鍛えたいと思い参加しました。

問題の一部紹介

Q1 /imagefiles以下に10万個のjpgがあり,その中からある一枚を探すという問題

とりあえず/imagefilesでlsをしてみると

pyuser@PythonChallenge:/imgfiles$ ls
1  2  3  4  5  6  7  8  9
pyuser@PythonChallenge:/imgfiles$ cd 1/
pyuser@PythonChallenge:/imgfiles/1$ ls
1  2  3  4  5  6  7  8  pych.jpg

どうやらこの構造のディレクトリが再帰的に用意されてるみたい

pythonでディレクトリを探索しファイルのmd5 hashを出力するコードq1.pyを書いた

import os
import hashlib

rootdir = '/imgfiles'

for (root, dirs, files) in os.walk(rootdir):
    for f in files:
        fd = open(os.path.join(root,f),'rb')
        data = fd.read()
        fd.close()

        md5 = hashlib.md5()
        md5.update(data)

        print 'md5    hash = ' + md5.hexdigest()

出力結果は

md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
md5    hash = c8b9232218b82be10300ad129ab3af1f
...

この中に一つだけ違う出力があるということなので、それを求めるためにコードを書こうと思ったがpythonのコーディング力のなさを感じ断念・・・

結局linuxコマンドを使って行った。

python q1.py > q1hash.txt
cat q1hash.txt | grep -v c8b9232218b82be10300ad129ab3af1f
md5    hash = c96fef6770ec348b84d459dd80cbbb40

これがflagになっていた。

pythonでコードを書くのはすごく楽しいけれど、まだまだわかってないので苦労しました。 はやく一人前の蛇使いになれるようもっとコードを書きたいと思います。

あと7月のSECCON オンライン予選に参加することになりそうなのでそちらに向けて、勉強もしたいと思います。

おまけ

この問題では解答が正しいかどうか判断するのにQ1-Answer.pycというファイルが与えられている。 まず思ったことはこれをリバースエンジニアリングしたら解答がでるんじゃね?

書いたコード

import dis, marshal
code = open("Q1-Answer.pyc", "rb").read()[8:]
code = marshal.loads(code)
dis.dis(code)

実行結果

  3           0 LOAD_CONST               0 (-1) 
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (sys)
              9 STORE_NAME               0 (sys)

  4          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              1 (re)
             21 STORE_NAME               1 (re)

  6          24 LOAD_NAME                0 (sys)
             27 LOAD_ATTR                2 (argv)
             30 STORE_NAME               3 (argvs)

  7          33 LOAD_NAME                4 (len)
             36 LOAD_NAME                3 (argvs)
             39 CALL_FUNCTION            1
             42 STORE_NAME               5 (argc)

 10          45 LOAD_CONST               2 (7937348281823435352881793132367836328032333780803628797878783228L)
             48 STORE_NAME               6 (integer)

 11          51 LOAD_CONST               3 ('')
             54 STORE_NAME               7 (ht)

 12          57 BUILD_LIST               0
             60 LOAD_NAME                8 (range)
             63 LOAD_CONST               4 (0)
             66 LOAD_NAME                4 (len)
             69 LOAD_NAME                9 (str)
             72 LOAD_NAME                6 (integer)
             75 CALL_FUNCTION            1
             78 CALL_FUNCTION            1
             81 LOAD_CONST               5 (2)
             84 CALL_FUNCTION            3
             87 GET_ITER            
        >>   88 FOR_ITER                29 (to 120)
             91 STORE_NAME              10 (i)
             94 LOAD_NAME                9 (str)
             97 LOAD_NAME                6 (integer)
            100 CALL_FUNCTION            1
            103 LOAD_NAME               10 (i)
            106 LOAD_NAME               10 (i)
            109 LOAD_CONST               5 (2)
            112 BINARY_ADD          
            113 SLICE+3             
            114 LIST_APPEND              2
            117 JUMP_ABSOLUTE           88
        >>  120 STORE_NAME              11 (ll)

 13         123 SETUP_LOOP              40 (to 166)
            126 LOAD_NAME               11 (ll)
            129 GET_ITER            
        >>  130 FOR_ITER                32 (to 165)
            133 STORE_NAME              12 (el)

 14         136 LOAD_NAME                7 (ht)
            139 LOAD_NAME               13 (chr)
            142 LOAD_NAME               14 (int)
            145 LOAD_NAME               12 (el)
            148 CALL_FUNCTION            1
            151 LOAD_CONST               6 (20)
            154 BINARY_ADD          
            155 CALL_FUNCTION            1
            158 INPLACE_ADD         
            159 STORE_NAME               7 (ht)
            162 JUMP_ABSOLUTE          130
        >>  165 POP_BLOCK           

 16     >>  166 LOAD_CONST               7 (61957777799393111110592710808675811083931012589994828988839312L)
            169 STORE_NAME               6 (integer)

 17         172 LOAD_CONST               3 ('')
            175 STORE_NAME              15 (at)

 18         178 BUILD_LIST               0
            181 LOAD_NAME                8 (range)
            184 LOAD_CONST               4 (0)
            187 LOAD_NAME                4 (len)
            190 LOAD_NAME                9 (str)
            193 LOAD_NAME                6 (integer)
            196 CALL_FUNCTION            1
            199 CALL_FUNCTION            1
            202 LOAD_CONST               5 (2)
            205 CALL_FUNCTION            3
            208 GET_ITER            
        >>  209 FOR_ITER                29 (to 241)
            212 STORE_NAME              10 (i)
            215 LOAD_NAME                9 (str)
            218 LOAD_NAME                6 (integer)
            221 CALL_FUNCTION            1
            224 LOAD_NAME               10 (i)
            227 LOAD_NAME               10 (i)
            230 LOAD_CONST               5 (2)
            233 BINARY_ADD          
            234 SLICE+3             
            235 LIST_APPEND              2
            238 JUMP_ABSOLUTE          209
        >>  241 STORE_NAME              11 (ll)

 19         244 SETUP_LOOP              40 (to 287)
            247 LOAD_NAME               11 (ll)
            250 GET_ITER            
        >>  251 FOR_ITER                32 (to 286)
            254 STORE_NAME              12 (el)

 20         257 LOAD_NAME               15 (at)
            260 LOAD_NAME               13 (chr)
            263 LOAD_NAME               14 (int)
            266 LOAD_NAME               12 (el)
            269 CALL_FUNCTION            1
            272 LOAD_CONST               8 (22)
            275 BINARY_ADD          
            276 CALL_FUNCTION            1
            279 INPLACE_ADD         
            280 STORE_NAME              15 (at)
            283 JUMP_ABSOLUTE          251
        >>  286 POP_BLOCK           

 22     >>  287 LOAD_NAME                5 (argc)
            290 LOAD_CONST               5 (2)
            293 COMPARE_OP               4 (>)
            296 POP_JUMP_IF_FALSE      309

 23         299 LOAD_NAME               16 (quit)
            302 CALL_FUNCTION            0
            305 POP_TOP             
            306 JUMP_FORWARD             0 (to 309)

 25     >>  309 LOAD_NAME                5 (argc)
            312 LOAD_CONST               5 (2)
            315 COMPARE_OP               2 (==)
            318 POP_JUMP_IF_FALSE      373

 26         321 LOAD_NAME                3 (argvs)
            324 LOAD_CONST               9 (1)
            327 BINARY_SUBSCR       
            328 STORE_NAME              10 (i)

 27         331 LOAD_NAME               10 (i)
            334 LOAD_NAME                7 (ht)
            337 COMPARE_OP               2 (==)
            340 POP_JUMP_IF_FALSE      351

 28         343 LOAD_NAME               15 (at)
            346 PRINT_ITEM          
            347 PRINT_NEWLINE       
            348 JUMP_ABSOLUTE          373

 30     >>  351 LOAD_CONST              10 ('Failed!! your code is "')
            354 LOAD_NAME                9 (str)
            357 LOAD_NAME               10 (i)
            360 CALL_FUNCTION            1
            363 BINARY_ADD          
            364 LOAD_CONST              11 ('"')
            367 BINARY_ADD          
            368 PRINT_ITEM          
            369 PRINT_NEWLINE       
            370 JUMP_FORWARD             0 (to 373)

 32     >>  373 LOAD_NAME                5 (argc)
            376 LOAD_CONST               9 (1)
            379 COMPARE_OP               2 (==)
            382 POP_JUMP_IF_FALSE      393

 34         385 LOAD_CONST              12 ('Input argument')
            388 PRINT_ITEM          
            389 PRINT_NEWLINE       
            390 JUMP_FORWARD             0 (to 393)
        >>  393 LOAD_CONST               1 (None)
            396 RETURN_VALUE 

んーハッシュっぽいものはない・・・ 7937348281823435352881793132367836328032333780803628797878783228L 61957777799393111110592710808675811083931012589994828988839312L

けどこのへんをいじったら答えがでそうだなという感じ。 今回は本題ではなかったのでここまでで諦めた。

主催者のザックさんはEasy Python Decompilerを使ったらしいのだが、完全にコードを復元できたらしい。 比較に使ってる変数をprintすることでflagをゲット・・・ なるほどそういう手があったのか。