今回はリモート問題だからリモートでアクセスし、ソースコードを見る

気になるのはscanf("%d",passcode1)とscanf("%d",passcode2)の部分だけど

まず、gdbで分析してみよう

welcome関数での中で、sub esp、0x88で変数とダミーで使用される空間(136バイト)を確保している

そして、nameという配列は[ebp-70]から入力が可能ということが分かる

ソースコードで見えたように、100バイト入力可能なので、100を16進数に変換すると64になるから

0xffbba928+64をすると0xffbba98cになるから、0xffbba928から0xffbba98cまでが

nameで入力可能な空間なのが分かる。

 

次は、login関数を分析する

一番目のscanf()関数を呼び出すところにブレイクポイントを設定して実行

そして、入力可能な空間を調べると

[ebp-10]から入力が可能なことが分かる。(int系だから4バイト)

0xffbba988が[ebp-10]だから+4バイトすると

0xffbba98cになる。

ということは、welcome関数のnameの4バイトとpasscode1の空間が被ることがわかるので、

ここを利用すれば良さそう。

最初に気になったところのscanf("%d",passcode1)の部分で

scanf("%d",passcode1)こういう風に使うと、passcode1の住所を参照して、値が入るのではなく、

passcode1に入っているダミーデータ(passcode1=0みたいに初期化しなかったため)を住所として

値を入れる

つまり、aを100個入れて実行後、ebp-10を見てみると0x61616161が出る

その0x61616161という住所にscanf()で入力された値を入れるということ

mov edx、DWORD PTR[ebp-0x10]で、PTRが[ebp-0x10]の前についているので

[ebp-0x10]の位置にある値を住所として認識する


ということは、nameの最後の4バイトに任意の住所を入れ、次の値でその住所に

入れたい値を入れればOKってこと

私はsystem("/bin/cat flag")を実行したいから

GOTオーバーライトを利用する(PLTとGOTはgoogle先生に聞けば教えてくれる)

scanf("%d",passcode1)の次にfflush(stdin)関数が呼び出されるから

fflush()のGOTをオーバーライトするー

これが、fflush()のPLTだ

PLTはGOTを参照するからjmpについていくと

0x804a004がfflush(stdin)のGOT住所だ

次は、

0x804a004にオーバーライトするsystem("/bin/cat flag")の住所を調べる

espに("/bin/cat flag")を入れるのが見えるから

0x080485e3がsystem("/bin/cat flag")が始まる住所だ

 

では、exploitしてみる。

前にscanf("%d",passcode1)で%d(10進数)の形式で値を入力されるから、

0x080485e3を10進数に変える必要がある

で、exploitすると、flagがみえる!!

 

 

 

 

実行ファイルをダウンロードして、実行してみたらできない

 

ので、readelf命令語でセッションを見たら、セッションもない

 

ヘックスエディターで中身をみた

UPXという文字が見えたのでUPXパッキングされてるから、アンパッキングすれば良いね

アンパッキングツールを実行したら、使用方法が出力される、やろうー

アンパッキングされて、容量が変わるのが見える。

では、実行してみよう!

実行したら、こんなメッセージが出力されて終わりー!これがヒントだな!

gdbで見てみよう

gdbで見たら、#0x6c2070<flag>という文字が見えるからそこだ。

ブレイクポイントをかけて実行する

mov rdx、QWORD PTR[rbp-0x8]を実行して

rdxの値を見ると、flagが見える。

成功!!

でも、ヒントで教えてくれたstrcpyまで実行して、raxを見るとやはり同じflagが見える

(関数の戻り値はraxに入るから)

これで、2回成功!!

 

 

 

まずソースコードを見る

gets(overflowme);を攻略すれば良さそう(smash me!)が書いてあるから

key値と0xcafebabeを比較し同じであれば/bin/shシェールを出してくれるから

overflowmeという配列をオーバフローさせて、keyの値を0xcafebabeに上書きすれば良い!

どのぐらいのデータを入れれば上書きができるか見るためにgdbで開いてみる

これがメイン関数でfunc関数に0xdeadbeefを渡すのが見える

これがfunc関数内だけど一番目のcallから見てみよう

まず、一番目のcallの前にブレイクをかけて実行ー!

0x40078cをespに入れてるから見てみる

overflow me :を渡している。ならば、このcallは

printfなのが分かる

だったら、つぎのcallがgets()関数のはず!

やはりputsで出力させるやつ

次の行をみると、lea eax、[ebp-0x2c]で

ebp-0x2cの住所をeaxに入れてるからoverflowme配列のスタート住所は

ebpから0x2c離れてるところ!

スタックを書いたらこんな感じ。。なはず!

さらに0x2c離れてるから0x2cを10進数で変換すると

44byte!

これで、52バイトを書き込めばfunc()関数のkey(0xdeadbeef)の値を上書きできることが分かる

成功!!!

まず、ls -lでどんなファイルがあるか確認して

ソースコードを見る

hashcodeは0x21DD09EC

argv[1]は20バイトを入力しないとダメみたい

そして、check_password()関数にargv[1]を渡いて、そのポインターをchar系からint系に変換する。

その後、for文で5回繰り返しながら4バイトの整数をresに足している。

その最後の値が0x21DD09ECにならなければいけない。

 

つまり、20文字列が入力されそれをint系ポインターに変換して計算するから

int(文字) X 5 = 0x21DD09EC

 

0x21DD09ECを5で割り算すると0x06C5CEC8になるが4があまるので

最後の値には+4しなければならないので

\xc8\xce\xc5\x06*4+\xcc\xce\xc5\x06にすれば良い

flagが出力される

 

/* argv 補充 */

argv[1]に値を\xaa\xbb\xcc\xddを入力すると

argv[1][0]には\xaa

argv[1][1]には\xbb

argv[1][2]には\xcc

argv[1][3]には\xdd

これをint系で変換して出力してみると

 

まず、ls -lでどんなファイルがあるか確認して

ソースコードを見る

len = read(fd、buf、32); でファイルディスクリプタから32バイトを読んで、bufに書いた後、

strcmpで"LETMEWIN"とbufを比較して、同じであればflagが出力される。

int fd = atoi(argv[1]) - 0x1234; だから、argv[1]をint系に変換し、0x1234を引いた結果の番号をファイルディスクリプタとして

使用する。

特にopen()関数を使用してないからファイルディスクリプタを0か1にすれば良さそうだから

0x1234を10進数で4660だから +1して4661をargv[1]に入れて実行し、LETMEWINを入れると

flagが出力される