2018年5月27日日曜日

BeginnersCTFに参加した

2018/5/26(土) ~2018/5/27(日)の間に開催されていたBeginnersCTF(https://score.beginners.seccon.jp/)に参加しましたメモです。常設の物はいくつか触ったことがあったのですが、リアルタイムで参加したのは初めてだったので楽しかったです。

とりあえず細かい解法は様々なところで出ていると思うので、どういう流れでフラグ取ろうとしたかだけ。

Veni,vidi,vici

 catで順に確認して、文字数からrot13系だなと思ったのでその辺のrot13まわりをいい感じに解決してくれるサイトに放り込んで終了。part3の逆さ読みはこんなことできるんだって思いました。

 Greeting

admin入れたら偽管理者と言われてそうかーとなって一旦別の問題見て戻ってきたらフラグが表示されていてビビりました。よくよく見たらCookieとか時間指定とかあってなるほどねという気持ちに。

plain mail

wiresharkで始めに「オブジェクトをエクスポート」を選択して何か出てくるかなと思ったらそんなことはなかったです。「追跡」を利用してメールの中身を確認して、base64系の物があったのでデコードしてfileで確認。zipだったので解凍、パスワードもざっと目で見てたら見つかりました。

Welcome

寝ぼけながらやったので覚えてないです。IRCチャンネルにアクセスしてトピックみて終わりみたいな感じでした。

Find the message

imgだったのでまずマウントしようとして「ファイルが壊れています」を食らいました。Bzで確認したところ、ファイルの先頭部分が全て0で潰されていたので、それのせいかなと判断。stringsで確認したところ、txt,pdf,pngの3つのファイルが存在することが判明。txtの方は偶然base64っぽいのを見つけたのでデコードして終了でした。
Bzでpdfのマジックナンバーを確認して、このまま切り出せばいいのかなと思いつつ、photorecを使用してpdf回収。なぜかpngだけ出てこないと思って見まわしてたらpngはマジックナンバー周辺が「XXXXXXXX」で上書きされていることが判明。適切に書き換えて再挑戦。結局駄目だったので自力で切り出したら画像の上半分しか表示されず、どうしようと思っていたところFTK Imagerのことを思い出したのでインストールして利用しました。(なぜかpdfが表示されなかったけれど)
そしてBzのビットマップ表示は便利。

Simple_auth

cygwinでELF動かないなとか思っていたらこれを忘れていました。(https://www.cygwin.com/ から引用)

...isn't it?

Cygwin is not:
  • a way to run native Linux apps on Windows. You must rebuild your application from source if you want it to run on Windows.
  • a way to magically make native Windows apps aware of UNIX® functionality like signals, ptys, etc. Again, you need to build your apps from source if you want to take advantage of Cygwin functionality.


 悲しい気持ちになりながらBash on Ubuntu on Windowsの方を起動。Cドライブには/mnt/c/Users/......で入れます。こちらでは起動できたので、解析用にgdbを導入して見て回りました。
 gdbではdisassesmble mainで中身を見ると、authという名前の関数を確認できました。disassemble authで確認すると、movでasciiっぽいものを入れている場所があったので全部拾ってascii変換掛けたらフラグが取れました。
後から確認したところ、ジャンプ条件をきちんと読むともう少しスマートに倒せるようですが分かりませんでした。読んでる本が片付いたらその周りをもう少し勉強したい。


雑感

数年前から見れば解ける問題は増えているのかもしれないけれど、普通に順位見てへこみました。WarmUpすら解けないの悲しすぎるので、勉強します…。というかphp本当に挙動が分からない…。

2018年5月21日月曜日

CentOS6でWordpressやろうとしてた時につまった話

現象
Documentrootとかちゃんとwordpressに繋がるように設定したはずなのにいつまでもApacheの初期画面が出続ける。

原因
phpのインストールしてませんでした。

こういうのはひとつひとつ気を付けないと駄目ですね。反省しました。

2018年5月11日金曜日

Hacking 美しき策謀2

前回は0x200のプログラミング基礎だったので、今回は0x300のバッファオーバーフローを進めていきます。

前章で扱ったプログラムに攻撃を仕掛けに行く展開で面白い。shellcodeはデコードしてもよく分からなかったので次へ。

次はstrcpy()を利用したバッファオーバーフローでした。コマンドラインから文字列を受け取って、特定の文字列と一致していれば認証、みたいなプログラムです。
check_authentication()はauth_flagを戻り値にする関数であり、main関数からは、
if(check_authentication(argv[1])){printf("ok");}
という形で呼び出されて利用されます。
この時、ifは「0でなければ」を判断しているため、何らかの方法で戻り値になる初期値0のauth_flagが、0以外に書き変わっていれば通ってしまう形になります。

check_authentication()内部ではstrcpy()を利用して文字列をバッファ用の配列にコピーし、strcmp()を使って比較します。

実行結果ですが、入力文字列が29文字以上の場合どのような文字列を入力しても認証成功となり、40文字以上だとif-else文それぞれに入っていたprintfが実行されなくなりました。


29文字以上で認証成功については、authentication()内で宣言したint型変数auth_flagとchar型配列password_buffer[16]のメモリの位置が関係しているようです。

int auth_flag=0;
char password_buffer[16];

の順で宣言した結果、ポインタはそれぞれ

&auth_flag 0xffffcb5c
&password_buffer 0xffffcb40;

となり、メモリの状態は

 (gdb) x/20wx 0xffffcb40
0xffffcb40:     0x8021bf56      0x00000001      0x8018949a      0x00000001
0xffffcb50:     0x0003a1a0      0x00000006      0xffffcbe0      0x00000000
(省略)

でした。

(gdb) x/20wx 0xffffcb40
0xffffcb40:     0x30303030      0x30303030      0x30303030      0x30303030
0xffffcb50:     0x30303030      0x30303030      0x30303030      0x30303030

0x30はアスキーコードで0であることを踏まえると、auth_flagは29文字の0に埋め立てられてしまい、0以外になってしまっているようです。想定よりも長い文字列でのstrcpyによって、書き換えられた模様。
(宣言した順とは逆にメモリに配置されているようです)

29文字以上で書き換えという点については、二つの変数の差を確認すると

(gdb) print 0xffffcb5c-0xffffcb40
&1=28

という結果になるようなので、きちんと理由があることが確認できました。



今度は40文字以上の"0"を実行すると何も出なくなる現象について確認。

実行するとreturn auth_flagでアクセス違反が発生していました。指定アドレスが0x3030303030303040という謎の値に。
このタイミングで他の変数も確認しましたが、

(gdb) p &auth_flag
$2 = (int *) 0x303030303030302c
(gdb) p &password_buffer
$3 = (char (*)[16]) 0x3030303030303010

とポインタそのものが書き変わっている感じになっていました。

Segmentation fault前後のレジスタ状況とメモリを確認するとベースポインタが書き換えられていることを確認。

Segmentation fault前
 (gdb) i r
rax            0x17     23
rbx            0xffffcbe0       4294953952
rcx            0x600018040      25769902144
rdx            0x0      0
rsi            0x60003a140      25770041664
rdi            0x8000   32768
rbp            0xffffcb60       0xffffcb60
rsp            0xffffcb20       0xffffcb20
r8             0xffffc85c       4294953052
(gdb) x/20wx 0xffffcb20
0xffffcb20:     0xffffcc65      0x00000000      0xffffcb40      0x00000000
0xffffcb30:     0xffffc85c      0x00000000      0x8013e970      0x00000001
0xffffcb40:     0x8021bf56      0x00000001      0x8018949a      0x00000001
0xffffcb50:     0x0003a1a0      0x00000006      0xffffcbe0      0x00000000
0xffffcb60:     0xffffcb90      0x00000000      0x004011e1      0x00000001

Segmentation fault後
(gdb) i r
rax            0x303030b0       808464560
rbx            0xffffcbe0       4294953952
rcx            0x600018040      25769902144
rdx            0x0      0
rsi            0x60003a140      25770041664
rdi            0x8000   32768
rbp            0x3030303030303030       0x3030303030303030
rsp            0xffffcb70       0xffffcb70
r8             0xffffc85c       4294953052

(gdb) x/20wx 0xffffcb20
0xffffcb20:     0xffffcc65      0x00000000      0xffffcb40      0x00000000
0xffffcb30:     0xffffc85c      0x00000000      0x8013e970      0x00000001
0xffffcb40:     0x30303030      0x30303030      0x30303030      0x30303030
0xffffcb50:     0x30303030      0x30303030      0x30303030      0x30303030
0xffffcb60:     0x30303030      0x30303030      0x00401100      0x00000001

スタック周りにダメージが来ているようでした。rbpはbreak mainして確認した時から本来変わらない値であるはずなのに、変化してしまっていることがプログラムが落ちる原因だったようです。
(p $rbp-$rspはmain関数時点では32,check_authentication関数に入ると64でした)

 なお、auth_flagとpassword_bufferの位置を逆にしたところ、auth_flag上書きによるif分強制trueはありませんでした(password_bufferよりauth_flagの方が先にあるので上書きが発生しない)。
ただし、 24文字以上でrbpが上書きされ、アクセス違反になりました。
書き換えが発生しない代わりに、スタックまでが近いので微妙…。

 とりあえずこんな感じかなと予想は立てたので、引き続き進めながらエラーの詳細を追っていこうと思います。