yyy

CTFつよくなりたい

DEF CON CTF Qualifier 2017 Writeup

f:id:ywkw1717:20170501053356p:plain

開催期間(JST)

04/29 AM9:00 ~ 05/01 AM9:00

結果

・チーム名:wabisabi

・得点:85pt

・順位:得点したチーム中,139/368

解いた問題

・crackme1(Baby’s First)

・magic(Crackme 2000)

・sorcery(Crackme 2000)

取り組んだが解けなかった問題

・smashme(Baby’s First)

・beatmeonthedl(Baby’s First)

・alchemy(Crackme 2000)

はじめに

参加しました.

去年は1問も解けず敗北したのでリベンジ.

最終日は夜しか参加できなくて,朝までやってたら英語とオートマトンの授業を寝過ごして死亡しました.

Writeup

crackme1(Baby’s First)

問題文

crackme1_f92e0ab22352440383d58be8f046bebe.quals.shallweplayaga.me:10001

配布されたバイナリ.

$ bzip2 -dc 8a97fb8c264a3b34dad0a707dbfc92832067a0fa0f2b5a576c73557960b11506.tar.bz2|tar xvf -
$ file 4a2181aaf70b04ec984c233fbe50a1fe600f90062a58d6b69ea15b85531b9652
4a2181aaf70b04ec984c233fbe50a1fe600f90062a58d6b69ea15b85531b9652: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, stripped

ncで繋いでみる.

$ nc crackme1_f92e0ab22352440383d58be8f046bebe.quals.shallweplayaga.me 10001

send your solution as base64, followed by a newline
4a2181aaf70b04ec984c233fbe50a1fe600f90062a58d6b69ea15b85531b9652

base64で送ってくれと言われるので適当に送ってみると

aG9nZQo=
didn't exit happy, sorry

とりあえず,objdumpでバイナリを逆アセンブルして,静的解析する.

objdump -d -M intel 4a2181aaf70b04ec984c233fbe50a1fe600f90062a58d6b69ea15b85531b9652

適当に見ていくと,入力値をチェックしているようなところを見つけた.

cmp    rdi,0x79
je     94f <_init+0x257>
sub    rsp,0x8
mov    edi,0x1
call   758 <_init+0x60>
mov    eax,0xa7
ret

cmp    rdi,0x65
je     969 <_init+0x271>
sub    rsp,0x8
mov    edi,0x2
call   758 <_init+0x60>
mov    rax,0xffffffffffffff9b
ret

cmp    rdi,0x73
je     985 <_init+0x28d>
sub    rsp,0x8
mov    edi,0x3
call   758 <_init+0x60>
mov    eax,0xa0
ret

cmp    rdi,0x20
je     99f <_init+0x2a7>
sub    rsp,0x8
mov    edi,0x4
call   758 <_init+0x60>
mov    eax,0x16
ret

cmp    rdi,0x61
je     9b9 <_init+0x2c1>
sub    rsp,0x8
mov    edi,0x5
call   758 <_init+0x60>
mov    rax,0xfffffffffffffff0
ret

cmp    rdi,0x6e
je     9d5 <_init+0x2dd>
sub    rsp,0x8
mov    edi,0x6
call   758 <_init+0x60>
mov    eax,0x190
ret

cmp    rdi,0x64
je     9ef <_init+0x2f7>
sub    rsp,0x8
mov    edi,0x7
call   758 <_init+0x60>
mov    eax,0x1d
ret

cmp    rdi,0x20
je     a09 <_init+0x311>
sub    rsp,0x8
mov    edi,0x8
call   758 <_init+0x60>
mov    eax,0xc5
ret

cmp    rdi,0x68
je     a23 <_init+0x32b>
sub    rsp,0x8
mov    edi,0x9
call   758 <_init+0x60>
mov    eax,0x4
ret

cmp    rdi,0x69
je     a3d <_init+0x345>
sub    rsp,0x8
mov    edi,0xa
call   758 <_init+0x60>
mov    eax,0xc1
ret

cmp    rdi,0x73
je     a57 <_init+0x35f>
sub    rsp,0x8
mov    edi,0xb
call   758 <_init+0x60>
mov    eax,0x10e
ret

cmp    rdi,0x20
je     a71 <_init+0x379>
sub    rsp,0x8
mov    edi,0xc
call   758 <_init+0x60>
mov    rax,0xffffffffffffff4e
ret

cmp    rdi,0x68
je     a8d <_init+0x395>
sub    rsp,0x8
mov    edi,0xd
call   758 <_init+0x60>
mov    eax,0x23
ret

cmp    rdi,0x61
je     aa7 <_init+0x3af>
sub    rsp,0x8
mov    edi,0xe
call   758 <_init+0x60>
mov    eax,0xae
ret

cmp    rdi,0x6e
je     ac1 <_init+0x3c9>
sub    rsp,0x8
mov    edi,0xf
call   758 <_init+0x60>
mov    eax,0x58
ret

cmp    rdi,0x64
je     adb <_init+0x3e3>
sub    rsp,0x8
mov    edi,0x10
call   758 <_init+0x60>
mov    eax,0xb
ret

cmp    rdi,0x73
je     af5 <_init+0x3fd>
sub    rsp,0x8
mov    edi,0x11
call   758 <_init+0x60>
mov    eax,0x2b
ret

cmp    rdi,0x20
je     b0f <_init+0x417>
sub    rsp,0x8
mov    edi,0x12
call   758 <_init+0x60>
mov    rax,0xffffffffffffff6d
ret

cmp    rdi,0x73
je     b2b <_init+0x433>
sub    rsp,0x8
mov    edi,0x13
call   758 <_init+0x60>
mov    eax,0x6b
ret

cmp    rdi,0x68
je     b45 <_init+0x44d>
sub    rsp,0x8
mov    edi,0x14
call   758 <_init+0x60>
mov    eax,0x10
ret

cmp    rdi,0x6f
je     b5f <_init+0x467>
sub    rsp,0x8
mov    edi,0x15
call   758 <_init+0x60>
mov    eax,0x18e
ret

cmp    rdi,0x6f
je     b79 <_init+0x481>
sub    rsp,0x8
mov    edi,0x16
call   758 <_init+0x60>
mov    eax,0x91
ret

cmp    rdi,0x6b
je     b93 <_init+0x49b>
sub    rsp,0x8
mov    edi,0x17
call   758 <_init+0x60>
mov    eax,0xce
ret

cmp    rdi,0x20
je     bad <_init+0x4b5>
sub    rsp,0x8
mov    edi,0x18
call   758 <_init+0x60>
mov    rax,0xffffffffffffff17
ret

cmp    rdi,0x77
je     bc9 <_init+0x4d1>
sub    rsp,0x8
mov    edi,0x19
call   758 <_init+0x60>
mov    eax,0xab
ret

cmp    rdi,0x69
je     be3 <_init+0x4eb>
sub    rsp,0x8
mov    edi,0x1a
call   758 <_init+0x60>
mov    eax,0x166
ret

cmp    rdi,0x74
je     bfd <_init+0x505>
sub    rsp,0x8
mov    edi,0x1b
call   758 <_init+0x60>
mov    rax,0xffffffffffffffe8
ret

cmp    rdi,0x68
je     c19 <_init+0x521>
sub    rsp,0x8
mov    edi,0x1c
call   758 <_init+0x60>
mov    eax,0x53
ret

cmp    rdi,0x20
je     c33 <_init+0x53b>
sub    rsp,0x8
mov    edi,0x1d
call   758 <_init+0x60>
mov    rax,0xffffffffffffffb1
ret

cmp    rdi,0x65
je     c4f <_init+0x557>
sub    rsp,0x8
mov    edi,0x1e
call   758 <_init+0x60>
xor    eax,eax
ret

cmp    rdi,0x78
je     c66 <_init+0x56e>
sub    rsp,0x8
mov    edi,0x1f
call   758 <_init+0x60>
mov    eax,0x9e
ret

見やすいように,cmpで区切っている.

比較している対象を切り出してみる.

0x79
0x65
0x73
0x20
0x61
0x6e
0x64
0x20
0x68
0x69
0x73
0x20
0x68
0x61
0x6e
0x64
0x73
0x20
0x73
0x68
0x6f
0x6f
0x6b
0x20
0x77
0x69
0x74
0x68
0x20
0x65
0x78

これをlistとか適当なファイル名で保存して,pythonで文字列に変換してみる.

#!/usr/bin/env python

import sys

def main():
    f = open('./list')
    for i in f:
        sys.stdout.write(chr(int(i.strip('\n'), 16)))


if __name__ == '__main__':
    main()

すると,以下のような文字列が得られる.

yes and his hands shook with ex

なんかパッとしなかったのだが,とりあえずbase64エンコードしてから投げてみる.

$ nc crackme1_f92e0ab22352440383d58be8f046bebe.quals.shallweplayaga.me 10001

send your solution as base64, followed by a newline
4a2181aaf70b04ec984c233fbe50a1fe600f90062a58d6b69ea15b85531b9652
eWVzIGFuZCBoaXMgaGFuZHMgc2hvb2sgd2l0aCBleAo=
The flag is: important videos best playlist Wigeekuk8

いやいやこんな簡単なわけあるか・・?と思いながらも

important videos best playlist Wigeekuk8

という文字列をsubmitしてみると,通った.

magic(Crackme 2000)

問題文

cm2k-magic_b46299df0752c152a8e0c5f0a9e5b8f0.quals.shallweplayaga.me:12001

配布されるバイナリは,恐らく上のcrackme1で渡されたものの,比較している文字が変わったものを200個

自動化しろということだと思うので,上でやったことをコード一発でできるようにした.

とりあえず,書いたコードを貼る.

#!/usr/bin/env python

import commands
import sys
import base64
import socket

def main():
    dic = dic_generator()
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('cm2k-magic_b46299df0752c152a8e0c5f0a9e5b8f0.quals.shallweplayaga.me', 12001))

    while True:
        res_list = []
        data = s.recv(256)
        if data == "":
            break

        if repr(data).find('send your solution') > -1:
            pass
        elif repr(data).find('flag') > -1:
            print repr(data)
            return
        else:
            index = repr(data)[1:-3]
            print dic[index]
            s.sendall(dic[index] + '\n')
    s.close()


def dic_generator():
    f = open('./list')
    dic = {}

    for i in f:
        result = commands.getoutput('objdump -d -M intel ' + i.strip('\n') + '|grep 48\ 83\ ff')
        res_list = result.split('\n')

        string = ''
        for j in res_list:
            string = string + chr(int(j[-4:], 16))

        str_base64 = base64.b64encode(string)

        dic[i.strip('\n')] = str_base64

    f.close()
    return dic


if __name__ == '__main__':
    main()

listという名前のファイルは,200個のファイル名をコピペして作った,ファイル名が格納されているもの.

どうやったかというと,objdumpで逆アセンブルした結果に対して,機械語grepした.

比較している部分で使われている機械語はユニークなもので,

48 83 ff 比較対象

という組み合わせは,他の部分では存在しなかったので,簡単にできた.

その後dic_generatorという関数で,ファイル名が「キー」で,値が「比較対象をbase64エンコードしたもの」である,辞書を作る.

あとは,ソケット通信を開始してから

send your solution as base64, followed by a newline
65cb596908789372c2d6fbeb0ac3a0e3a1089039138711a016ec3994ad5c7f10

この2行目のファイル名のみを取り出して,それをキーにして値を取り出し,送り返す.

10回連続で正解すると,flagが貰えるっぽい.

$ python script.py

ZGVyLiAiVGhhbmtzLiI=
aW5kIGFzIEkgc3RhZ2dlcmVkIGludG8gdGhlIGtpdGNoZW4sIHdoZXJlIExpbCA=
IEhhdW50ZWQgTWFuc2lvbiwgaWYgeW91IGp1c3QgZ2l2ZSBt
YWxlIG9yIG90aGVyIGxpbWl0YXRpb25zIG9uIHRoZSBleGNsdXNpdmUgcmlnaA==
Y3Jld3Mgc2N1cnJ5aW5nIGk=
b3VzZXMgaW4gdGhlaXIgaG9tZXRvd25zLiBUaGUgTWFuc2lvbidzIGJldHRlciA=
eSBvZiwgb3IgdGhl
YnVybmVkIGFsbCBoaXMgcmVwdXRhdGlvbiBjYXBpdGE=
LCB0dXJuaW5nIG1lIGludA==
IGltbWVkaWF0ZQ==
'The flag is: a color map of the sun sokemsUbif\n'

sorcery(Crackme 2000)

問題文

cm2k-sorcery_13de8e6bf26e435fc43efaf46b488eae.quals.shallweplayaga.me:12002

またmagicと同じように,解凍すると200個のバイナリ.

上で書いたスクリプトがそのまま使えるかなと思って試してみたらだめだったので,逆アセンブルして読んでみる.

magicと同じように機械語grepすると,余分なものまで取ってきてしまう.

↓これは,80 f9(cmp cl) でgrepしたもの.0x80以降のcmp全部がいらない.そう思った根拠は,ASCIIコードがないから.あるものもあるけど,明らか違うので排除.

cmp    cl,0x6e
cmp    cl,0x69
cmp    cl,0x63
cmp    cl,0x20
cmp    cl,0x46
cmp    cl,0x72
cmp    cl,0x6f
cmp    cl,0x6e
cmp    cl,0x74
cmp    cl,0x80
cmp    cl,0xf0
cmp    cl,0xf4
cmp    cl,0x80
cmp    cl,0x80
cmp    cl,0xe0
cmp    cl,0xed
cmp    cl,0xee
cmp    cl,0x80
cmp    cl,0x3
cmp    cl,0xe0
cmp    cl,0xf0
cmp    cl,0x1
cmp    cl,0x3
cmp    cl,0x2
cmp    cl,0x1
cmp    cl,0x3
cmp    cl,0x2
cmp    cl,0x1
cmp    cl,0x3
cmp    cl,0x2
cmp    cl,0x4

これでいけるかと思ったらまだダメ.

もう一度注意深く読んでみると,

.
.
.
.

cmp    cl,0x74
jne    38b6 <pthread_mutex_lock@plt+0xd26>
cmp    rax,0x9
je     37e2 <pthread_mutex_lock@plt+0xc52>
mov    al,BYTE PTR [rdi+0x9]

cmp    al,0x69
jne    38c2 <pthread_mutex_lock@plt+0xd32>
mov    rax,QWORD PTR [rsp+0x8]
test   rax,rax
je     377e <pthread_mutex_lock@plt+0xbee>
.
.
.
.

この,cmp al, 0x69のところ.

最後の1文字だけ,alレジスタを使って比較している.

よって,こいつも取り出してあげる必要がある.コマンドで頑張ったらいけた.

あとは,書いたコード.magicで書いたコードをちょっと変えただけ.

#!/usr/bin/env python

import commands
import sys
import base64
import socket

def main():
    dic = dic_generator()

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('cm2k-sorcery_13de8e6bf26e435fc43efaf46b488eae.quals.shallweplayaga.me', 12002))

    while True:
        res_list = []
        data = s.recv(256)
        if data == "":
            break

        if repr(data).find('didn\'t exit happy, sorry') > -1:
            pass
        elif repr(data).find('send your solution as base64') > -1:
            pass
        elif repr(data).find('flag') > -1:
            print repr(data)
            return
        else:
            index = repr(data)[1:-3]
            print dic[index]
            s.sendall(dic[index] + '\n')
    s.close()


def dic_generator():
    f = open('./list')
    dic = {}

    for i in f:
        result = commands.getoutput('objdump -d -M intel ' + i.strip('\n') + '|grep 80\ f9 |head -n -22')
        result = result + '\n' + commands.getoutput('objdump -d -M intel ' + i.strip('\n') + '|grep cmp |grep al |head -2 |tail -1')
        res_list = result.split('\n')

        string = ''
        for j in res_list:
            string = string + chr(int(j[-4:], 16))

        str_base64 = base64.b64encode(string)

        dic[i.strip('\n')] = str_base64

    f.close()
    return dic


if __name__ == '__main__':
    main()

実行結果.

$ python script.py

IEkgc2FpZC4gIkp1c3QgZ29pbmcgc29tZXdoZXJlIGVsc2UsIHN0YXJ0aW4=
b2QgcG9pbnQsIExpc2EuIFRoZSBvZmZlciB3ZSdyZSBtYWtpbmcgdG8g
IHRoYXQgaGFwcGVucywgdGhlcmUncyBub3RoaW5n
IGJyb3VnaHQgb3Zlcg==
IG9mIGdldHRpbmcgaW50byBjaGFyYWN0ZXIuIFNv
aG9tZSwgYXM=
cyBhIHNpbmdsZSBjYXN0bWVtYg==
ZyBhIGxpdHQ=
bWluZyB0byB0aGUgcG9pbnQuICJXZSByZWFkIHlvdQ==
aWNjZWQgbmVydm91c2x5IGFzIEkgd2F0Y2hlZCBteSBwcm9ncmVzcw==
"The flag is: don't forget me when you're famous Klousovnec\n"

取り組んだが解けなかった問題

beatmeonthedl(Baby’s First)

問題文

I really like to be beaten but keep it on the dl.

Connect to:

beatmeonthedl_498e7cad3320af23962c78c7ebe47e16.quals.shallweplayaga.me 6969

配布されたバイナリ.

$ file beatmeonthedl
beatmeonthedl: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, not stripped

実行してみるとこんな感じ.

      __      __       .__                                  __           
        /  \    /  \ ____ |  |   ____  ____   _____   ____   _/  |_  ____   
        \   \/\/   // __ \|  | _/ ___\/  _ \ /     \_/ __ \  \   __\/  _ \  
         \        /\  ___/|  |_\  \__(  <_> )  Y Y  \  ___/   |  | (  <_> ) 
          \__/\  /  \___  >____/\___  >____/|__|_|  /\___  >  |__|  \____/  
               \/       \/          \/            \/     \/                 
      __  .__             .__         .__                 _____    __  .__            
    _/  |_|  |__   ____   |  | _____  |__|______    _____/ ____\ _/  |_|  |__   ____  
    \   __\  |  \_/ __ \  |  | \__  \ |  \_  __ \  /  _ \   __\  \   __\  |  \_/ __ \ 
     |  | |   Y  \  ___/  |  |__/ __ \|  ||  | \/ (  <_> )  |     |  | |   Y  \  ___/ 
     |__| |___|  /\___  > |____(____  /__||__|     \____/|__|     |__| |___|  /\___  >
               \/     \/            \/                                      \/     \/ 
  _________.__                .___              __________                __
 /   _____/|  |__ _____     __| _/______  _  __ \______   \_______  ____ |  | __ ___________  ______
 \_____  \ |  |  \\__  \   / __ |/  _ \ \/ \/ /  |    |  _/\_  __ \/  _ \|  |/ \// __ \_  __ \/  ___/
 /        \|   Y  \/ __ \_/ /_/ (  <_> )     /   |    |   \ |  | \(  <_> )    <\  ___/|  |  \/\___ \ 
/_______  /|___|  (____  /\____ |\____/ \/\_/    |______  / |__|   \____/|__|_ \\___  >__|    /____ >
        \/      \/     \/      \/                       \/                    \/    \/             \/ 
Enter username: 

PCで見ないと表示が崩れてそう.

Enter username: hoge
Invalid user: hoge

Enter username: 

適当なusernameだと入れない.

gdbで,正当なusernameを探す.

$ gdb beatmeonthedl
[-------------------------------------code-------------------------------------]
   0x40125a <main+30>:   call   0x400cf6 <header>
   0x40125f <main+35>:   nop
   0x401260 <main+36>:   mov    eax,0x0
=> 0x401265 <main+41>:    call   0x400ec8 <login>
   0x40126a <main+46>:   test   eax,eax
   0x40126c <main+48>:   je     0x401260 <main+36>
   0x40126e <main+50>:   mov    eax,0x0
   0x401273 <main+55>:   call   0x400f52 <printmenu>

loginという関数があるので,ステップインして追いかける.

loginではさらに,checkuserとcheckpassという関数があり,usernameとpasswordをチェックしている.

checkuserにおいて,

0x400d9e <checkuser+86>:  mov    rax,QWORD PTR [rip+0x208c53]        # 0x6099f8 <user>

ここが実行された後にRAXを見ると,usernameがわかった.

RAX: 0x4085d8 --> 0x776100796c66636d ('mcfly')

さらに今度はpasswordを探す.

checkpassにおいて,

0x400e77 <checkpass+135>: mov    rax,QWORD PTR [rip+0x208b82]        # 0x609a00 <pass>

ここが実行された後にRAXを見ると,passwordがわかった.

RAX: 0x4085de --> 0x70616e73657761 ('awesnap')

この2つでログインすると,

Enter username: mcfly
Enter Pass: awesnap
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 

ここから,pwnのようなことをやってシェルを奪うのかなと思ったが,全くわからなかった.

alchemy(Crackme 2000)

magicやsorceryと同じように自動化する問題?

自動化できないようにさらに工夫がされてて厳しかった.

感想

意外に結構解けたので嬉しかった.

smashmeとbeatmeonthedlは解いている人が多かったけど自分はサッパリだったのでこういうのも解けるようになりたい・・・

PlaidCTF 2017 Writeup

開催期間(JST)

04/22 AM6:00 ~ 04/24 AM6:00

結果

・チーム名:wabisabi

・得点:51pt

・順位:332/1150

解いた問題

・sanity check(Misc 1)

・zipper(Misc 50)

取り組んだが解けなかった問題

・Pykemon(Web 151)

・no_mo_flo(Reversing 125)

はじめに

参加しました.

また1問しか解けてないやんけ!!!ってことで,とりあえずやったことまとめ.

Writeup

sanity check(Misc 1)

PCTF{poop}

zipper(Misc 50)

問題文

Something doesn't seem quite right with this zip file. 

Can you fix it and get the flag?

zipファイルが渡される.

解凍しようとすると,

Archive:  zipper_50d3dc76dcdfa047178f5a1c19a52118.zip
warning:  filename too long--truncating.
:  bad extra field length (central)

バイナリを読む.

f:id:ywkw1717:20170424095413p:plain

ファイル名のサイズを格納しているところが2923となっていることから,めちゃくちゃな長さになっていることがわかる.(0x2329 → 9001文字?)

ここを正しい値にしないといけないが,正しい値がわからないので他の情報を元に修正する.

まず,zipファイルは大体,Local file header,File data,Central directory header,End of central directory recordの4つのフィールドから構成されている.

ZIP書庫ファイル フォーマット - 略して仮。

ここが詳しい.

読んでいくと,格納データがASCIIであることや,デフレート形式で圧縮されていることなどがわかる.

Central directory headerのファイル名が格納されている場所と,End of centralのシグネチャに注目した.

この間に格納されているデータは,

-----------
relative offset
of local header
-----------
file name
------------
extra field
------------
file comment
------------
End of central
dir signature
(0x50,0x4b,0x05,0x06)
------------

のようになっており,Central directory headerを読むとfile commentは0であることから,End of central directoryのシグネチャがある部分からextra fieldのサイズ分手前に戻し,求まった場所とrelative offset of local headerの間にあるのがファイル名であり,ファイルサイズも求めることができる.

extra fieldのサイズは,0x18(24bytes)

求まったファイル名は,

0000 0000 0000 0000

サイズは,0x8であることがわかる.

よって,Local file headerとCentral directory headerにあるfile name lengthという2byteの領域に書いてある,

2923

を,以下のように変更する.

0800

これで,いけると思ったがファイル名が指定されていないので適当に

666c6167

flagとかいうファイル名で書き換える.

これで解凍すると,

Huzzah, you have captured the flag:
PCTF{f0rens1cs_yay}

このようなテキストファイルが抽出できて,おしまい.

取り組んだが解けなかった問題

Pykemon(Web 151)

問題文

Gotta catch them FLAGs! 

Take this with you.

flaskで書かれたWebアプリケーションが与えられる.

Pykemonという名前の,ポケモンの丸パクリのゲーム.Pykemonを捕まえて,その記録とかを見れる.FLAGを捕まえてFLAGを読みだす.

こんな感じ.

f:id:ywkw1717:20170424125010p:plain

ソースコードも与えられる.

コードを読んでいくと,それぞれのPykemonにrarityという捕まえられる確率的なものが設定されていて,結論から言うとFLAGを捕まえることは不可能.

どうにかして,捕まえる必要がある.

やったこととしては,Burpを使ってセッションを書き換えたり,Pykemonをrenameするところに以下のようなstored XSSを見つけたりした.

f:id:ywkw1717:20170424125326p:plain

XSS使って何かするんだろうなぁと思ってたんだけど,結局はセッションをローカルでデコードするだけで良かったっぽい.

詳しくは他の方のwriteupへ.

no_mo_flo(Reversing 125)

問題文

Can you go with the flow?

file

no_flo_f51e2f24345e094cd2080b7b690f69fb: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b9de9235c1a8c49096daba03ce36e334cf150c1c, stripped

入力を受け取り,32文字より小さければ

Short input

32文字与えると,

You aint goin with the flow....

正しい入力値を与えて,

Good flow!!

と出力する値を探す.

中で,チェッカーみたいな関数が2つありなにかやって,その戻り値で分岐していることはわかって,objdump, gdb, radare2を使ってこんな感じで↓頑張っていた.

f:id:ywkw1717:20170424145358p:plain

分岐を書き換えてGood flow!!にすることはできたけど,それでは意味なくて,結局タイムアップ.

感想

rev問に関しては,解けなかったけど1日中向き合ってたこともあって,アセンブリを読むことに抵抗がなくなって少しは読めるようになってきたので収穫はあった.

Web担当のid:ktr_0731,忙しくて参加できてないのかなぁと思っていたら忘れていたらしく,今度からremindしまくってやるからなという気持ち.

ASIS CTF Quals 2017 Writeup

開催期間(JST)

04/07 PM21:30 ~ 04/09 PM21:30

結果

・チーム名:wabisabi

・得点:169pt

・順位:132/451

解いた問題

・Welcome!(Trivia 1)

・Piper TV(Misc & Forensics 159)

・CTF Survey(Trivia 9)

(「Welcome!」と「CTF Servey」の2問はボーナス問題)

途中まで解いた問題

・Flour(Reversing 114)

はじめに

SECCON予選以来CTFに出ていなかったので,みんなで出ようとなって参加した.

自分にとってはレベルが高い問題ばかりでほぼ解けなくて惨敗.

全く解けてないぞお前!と未来の自分に残すために解いた問題などをまとめておく.

Writeup

Welcome!(Trivia 1)

ボーナス問題.

問題文

What is the smallest valid flag for ASIS CTF?

よって答えは,ASIS{}

Piper TV(Misc & Forensics 159)

問題文

Recently, a very interesting program has been broadcasted on Piper TV, have you watched it?

$ file PiperTV_e65d6f13bae89c187d2d719ee8bf35cfd9e96387     
$ PiperTV_e65d6f13bae89c187d2d719ee8bf35cfd9e96387: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144)

pcapファイルだとわかるので,Wiresharkで見てみる.

f:id:ywkw1717:20170409233653p:plain

後半のほうにある緑色に色付けされたパケットを見ていく.

これをHTTPストリームして,Raw形式で保存する.

f:id:ywkw1717:20170409234013p:plain

$ file target
$ target: MPEG transport stream data

MPEGだとわかるので拡張子を.mpegに変えて再生してみる.

すると,可愛らしい動物の動画が・・・

f:id:ywkw1717:20170409234519p:plain

19秒ほどの動画だが,よく見ていると14秒くらいで上のほうにフラグらしき文字列が一瞬現れるようになっている.

動体視力がくそで何回やってもそこで止まらないのでフレームを抽出することに.

ffmpegを使うといい感じに切り出せるので,フレームレート等を適当に設定して使う.

$ ffmpeg -i target.mpeg -f image2 -vf fps=100 frame%05d.png

約1800枚の画像ができる.少しやりすぎた感があった.

で,フラグが表示されている辺りを見ていくと

f:id:ywkw1717:20170409235638p:plain

CTF Survey(Trivia 9)

ボーナス問題.

どうでしたか~みたいなのをGoogleフォームに記入していくと貰える.

途中まで解いた問題

Flour(Reversing 114)

問題文

Flour is a basic ingredient in all bread making, what about this bread?

テキストファイルが与えられて,中身はよくわからない文字列.

:100000000C9436000C945E000C945E000C945E0020
:100010000C945E000C945E000C945E000C945E00E8
:100020000C945E000C945E000C945E000C945E00D8
:100030000C945E000C945E000C945E000C945E00C8
:100040000C9481020C945E000C944F020C942902D3
:100050000C945E000C945E000C945E000C945E00A8

こんなのが200行以上に渡って書かれている.

調べてみると,Intel Hexフォーマットというやつらしい.

バイナリをテキスト形式で運ぶため?に作られたものらしく,だったらデコードもできるだろってことでツールを探す.

sourceforge.net

このHex2Binというやつを使ってバイナリに戻す.

出てきたバイナリに対してstringsしてみると

Hey! Good job.
This is not real flag: ASIS{is_th1s_f4k3_flag?!!}
Enter real flag: 

という文章は見つけたものの,fake以外は見つからない.

だいぶ時間が経っても誰一人解いている人がいなくて諦めた.

感想

他にはpwn問のStartを友人とやってたけど解けなかった.

rev力とpwn力が無さすぎる.

とても厳しかった.

実家に帰ってきたと思ったら、ノートPC(Win7)をクラックすることになった話

はじめに

帰ってきたばかりで疲れてる時に朝4時まで作業していたからくそ眠い.

無駄に消耗した気がするので,その記録.

経緯

実家のノートPCがネットに接続できない云々で頼まれたから,とりあえずPC開いてみたら管理者のパスワードがわからない

少し酔ってそうな親父に聞いてもわからんと言われたので,クラックするしか無いやん!っていう.

アカウントはもう一個あって,そっち使ってたのかな・・?(そもそもPCを使うことがほぼ無いと言ってた)

やったこと

Ophcrackっていう便利ツールがあるのは知ってて,簡単に言うとWindowsのパスワードを簡単にクラックできるぜっていうツール.

使ってみたこと無いなって思って,ちょうど良い機会だしやってみることにした.

OphcrackはUSBやCDなどからブートできるので,手元にあったUSBに入れてやってみたけど・・・・

SYSLINUX 3.80 2009-05-04 CBIOS Copyright © 1994-2009 H.Peter Anvin et al で止まる

嘘やん・・・って思いつついろいろ調べると,こういうことらしい↓

springpaduser.blogspot.jp

USBブート無理な感じなのか・・・?とか思いつつ,ココらへんで消耗するのも嫌だなぁと思って,自分のPCのWindows(Ubuntuとのデュアルブートにしてある)側に,exeを落としてきて(iso以外にもexeがあった)そこで解析しようと考えた.

そこで必要になるのは,

  1. C:\Windows\System32\config\SYSTEM
  2. C:\Windows\System32\config\SAM

の2つのファイル.

特にSAMファイルには,ユーザがログオンするときに使うパスワードのハッシュが格納されている.

パスワードハッシュにも LM Hash(LAN Manager Hash)NT Hash(Windows NT Hash)があるらしく,文字数や暗号化手法にも違いがある. 詳しくは↓

Windowsのパスワードハッシュについてsec401mentor.wordpress.com

まずは,2つのファイルを取ってくることから始める.

パスワードハッシュファイルの取得

手元にあったKali Linux 64bit LightをUSBブートさせて,ファイルの取得を試みた.

パーティションテーブルを確認

sudo fdisk -l

Windowsパーティションを選択して,ntfsで/mntにマウント

mount -t ntfs /dev/sda3 /mnt

SAMデータベースがある場所へ移動

cd /mnt/Windows/System32/config

syskeyとbootkeyをダンプするツール(コマンド?)であるbkhiveがない・・・

入れるぞ!

curlがない -> apt-get

curl http://http.us.debian.org/debian/pool/main/s/samdump2/samdump2_1.1.1-1.1_amd64.deb > samdump2_1.1.1-1.1_amd64.deb

dpkg -i samdump2_1.1.1-1.1_amd64.deb

libssl1.0.0がない

他のパッケージがない

Kali「おいおいこのパッケージもねえよ」

「」

みたいな感じで,全く入る気配がないので諦めた

Light版だからか,Liveモードだからか?よくわからない.

なので,Ubuntubkhiveともう一つ,パスワードハッシュをダンプするのに必要なツールsamdump2を入れることにした.

さ〜てやるぞ〜と思っていた1時半頃・・・

親父が起きてきて一言.

親父「パスワードがわからんのか?」

自分「おう」

親父「あ〜これだよこれ」(受話器の横に置いてあったメモを取り出す)

親父「〜のパスワードは◯◯◯◯◯で〜のパスワードは◯◯◯◯◯だな」

自分「」

(わからんって言ったやんけ!!!!!!!!!!!!!!!)

パスワードを聞いてしまったのだが,ここまで来て辞めるなんてことは絶対にしたくなかったので続ける・・・

Ubuntu(15.04)へbkhiveとsamdump2を入れる

  1. curl http://http.us.debian.org/debian/pool/main/s/samdump2/samdump2_1.1.1-1.1_i386.deb > samdump2_1.1.1-1.1_i386.deb

  2. dpkg -i samdump2_1.1.1-1.1_i386.deb

  3. curl http://http.us.debian.org/debian/pool/main/b/bkhive/bkhive_1.1.1-1_i386.deb > bkhive_1.1.1-1_i386.deb

  4. dpkg -i bkhive_1.1.1-1_i386.deb

bkhivesamdump2が入った.これらのコマンドを使って,

bkhive(tmp/hoge.txtは出力するファイル)

bkhive SYSTEM tmp/hoge.txt

samdump2(bkhiveで作ったファイルとSAMファイルを渡して,tmp/hash.txtは出力するファイル)

samdump2 SAM tmp/hoge.txt > tmp/hash.txt

すると,

Administrator:xxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:::

このような形式のものが何行かにわたって記載されたhashファイルが完成する.

あとはOphcrackの出番!!

解析結果

f:id:ywkw1717:20170313054027j:plain

AdministratorとGuestはempty(解析可能ではないということ)になり,$というユーザ(なんだこのユーザ・・?)はパスワードが見つからない,つまりある程度は堅牢なパスワードだということ.

逆に,数字のみのものに関しては全て破られている.(数字4桁なので当たり前だろうと思うけど,数字10桁とかでも危なそう)

OphcrackはRainbow Tableを使って解析するため,他のテーブルをダウンロードしてきて使うこともできる.デフォルトで入っている以外のもので,数字のみに特化したものを使うことなども可能.

まとめ

消耗した記録として残すものなので,やってみたい人は他の人の使ってみた系のブログを参考にすることを強くオススメ致します・・・

脆弱なパスワード,ダメ.

おまけ

親父から聞いたパスワードのうち,管理者のほうは間違っていたので,

解析した甲斐があった!!!!!!!!

(聞いたのは昔のもので,親が全く覚える気配がなくてわかりやすいようにしてくれと頼まれて変更したことを忘れてた)



おわり

参考

Ubuntuにログインできなくなった日

はじめに

題名の通り.今日ふとPCを付けてログインしようとしたら,正しいパスワードを入れて認証されているはずなのに,またログイン画面に戻される.(Xが再起動している?)

環境

Distributor ID:  Ubuntu
Description:    Ubuntu 15.04
Release:    15.04
Codename:   vivid

心当たりが全くなかったので,ググる

原因

.profileに書いていた,exec /bin/zshが問題だったっぽい.

今はログインシェルをzshにしているんだけど,確かログインシェルをbashにして,子プロセスとしてzshを起動するみたいなことをやっていた時の名残・・・

やったこと

最初は,

poppycompass.hatenablog.jp

を見て,ICEauthorityXauthorityを削除して再起動していたんだけど,解決しなかった.

別の問題だろうと思い,また探していたら全く同じような状態の人を見つけた.

qiita.com

これを参考に,

  1. Ctrl + Alt + F1CUIに入る.

  2. 今はもうログインシェルがzshなので.profileに書いてあるexec /bin/zshを消す

  3. Alt + F7GUI

としたら治った.

でもなんで今さらログインがループするようになったかが謎すぎる.

そもそも.profile自体が

wa3.i-3-i.info

とかにも書かれている通り,ログインシェルがbashの時のみ読み込まれると思っていた.

.profileに関して

謎が深まるばかりなので,試しに.profileにecho $SHELL > /home/yyy/testなどとして,何が書き込まれるのか見てみた.

rebootして,testの中身を見てみると

/usr/bin/zsh

zshから読み込まれてるやんけ!

ログインシェルをfishとかに変えてもう一度試してみる.

/usr/bin/fish

.profileの先頭にも

# ~/.profile: executed by the command interpreter for login shells.

と書かれている通り,bashと限定されてはいなかった.

よって,ログインシェルがbashじゃない場合も読み込まれる時はある?

いつの間にか.profileの話になってしまった.




ThinkPadが早く届いて欲しい・・・

ノートPCのメモリを増設した

はじめに

メモリ増設した.

理由は,自分が普段ブラウザのタブめっちゃ開く人間だったり,その他にもいろいろあって,時々PCの動作が重くなる時があって,使用量とか見てみると”枯渇してるやんけ!!”なんてことがよくあったから.

あとは,VAIO Zを買おうと思っていたんだけど,少しはお金出してやるとか言っていた親父が,「彼女を家に連れてきたら買ってやるよ」とか言い出して,そんなの無理なのでもうしばらく今のPCで頑張らなきゃならなくなったため.

で,スロットの空きあんのかなとか思って裏側をパカッと開けてみてみたら,4GBx1しかなくて残り1スロット空いてて,いけるやんってことで.

買ったもの

当初は,4GBを買って合計8GBにするつもりだったんだけど,値段見てみると4GBと8GBとそんなに変わらんなと思ったので,8GBを購入.楽天カード作った時のポイントとか,元々のAmazonのポイントとか使って2千円いかないぐらいで買えたので最高.

取り付け

画像を垂れ流す.

f:id:ywkw1717:20170127001929j:plain

開封

f:id:ywkw1717:20170127001949j:plain

メモリがある部分をパカッと開ける

f:id:ywkw1717:20170127002037j:plain

カチッといい感じにハマればOK

f:id:ywkw1717:20170127002118j:plain

BIOS(増設前)

f:id:ywkw1717:20170127002158j:plain

BIOS(増設後)

f:id:ywkw1717:20170127002217j:plain

まとめ

取り付けなんて1分もかからずに終わるし,素人でも絶対できると思う.

合計12GB(正直こんなにいらなそう)になって快適.

メモリ自体が対応していない場合もあるので,元々搭載しているメモリの型番とかを参考に同じものを買うのが良いと思う.

キーボード買った

はじめに

あけましておめでとうございます.

初日の出が見れなかった2017年です.

きっかけ

大晦日, とりあえず家にはいたくないなぁと思っていて, 最初は図書館で本読むつもりだった.

しかし図書館がやっていないことがわかり, どうするかと散々悩んだ結果, 秋葉原にキーボードを買いに行くことにした.

キーボード自体はずっと前から欲しいやつがあって, 某大学バイトの給料が入り次第買うつもりでいた.

けど今年度のバイト代はだいぶ遅くなるらしいし, 今買っちゃえ!!って感じで.

買ったもの

秋葉原

こんなに外国人の割合多かったっけ…?ってぐらい外国人が多かった. (大晦日だったからかな)

どこ行くかなぁと思って, そんな希少なキーボードじゃないし東京ならどこでもあるやろって思い, とりあえずソフマップ



置いてない


メカニカルキーボードもそうじゃないのもそこそこあるって感じだったんだけど, 置いてなかった.

東京はなんでもあるやろってイメージだったので, これはちゃんと調べないとって思い, ここで調べ始める.

参考にしたサイト.

店頭展示キーボード数まとめ(秋葉原編) | K4750.net

ヨドバシ Akibaに置いてある数が圧倒的だったので行くことに.



置いてない


まず探してたFILCO自体が少なかったし, ゲーミングキーボードは多かったけど, んーイマイチって感じだった.

次!ってことでツクモ eX. パソコン館へ.



ここが天国だった


メカニカルじゃないキーボードとか置かねぇよぐらいの勢いで, 数はそこまで多くないんだけどいろんな種類があった. マニアックな人?向けな印象を受けた.

探してたキーボードも見つけたので即購入.

実を言うと直前で黒軸茶軸で迷っていた.

黒軸, 反発力強いから高速タイピング向けってのはわかるんだけど, どうも反発が強くて疲れそうで自分には合わないなと思って茶軸を購入. (宗教戦争起こす気はない)

帰り際に東プレのRealforceのこれ↓触ったけど, めっちゃ良かった…

価格.com - 東プレ Realforce87UB-55 SE18T0 [黒] 価格比較

感想

今までLogicoolメンブレンのやつ使ってて, メカニカルキーボード, 言うほど良いのか?とか思ってたけど, 世界が変わった.

打ち心地最高だし, 打鍵音も気持ちが良い.

ずっと打っていたい, そんな感じ.

注意点

自分の環境(Ubuntu15.04)だと以下のちょっとした設定が必要だった. (最初, JIS配列としか認識されなかった)

  1. 右上の設定アイコンから, システム設定
  2. キーボード
  3. 左下にある"テキスト入力"
  4. 使用する入力ソースに"英語(US)“を追加


ノートpcで使う場合, 元々搭載してるのはJIS配列なので切り替えとか面倒っぽくて, うーんという感じ.

悩ましい.