初めてのPWN作り
10月27日はSECCON CTFオンライン予選!
手作りのPWN問題を職場の同僚や友達に送って,日ごろの感謝の気持ちを伝えてみませんか?
材料
- ★Docker 1つ
- xinetd 1つ
- ★git 適量
- ★gcc 1つ
- ★Python2 1つ
- ★pwntools 1つ
- ★vim 3つ
- ★お好みのテキストエディタ 少々
- お好みのLinuxディストリビューション(ArchLinuxを使用) 1つ
下準備
Linuxにアップデートを入れてパッケージマネージャで馴染ませせてから,★を入れて混ぜ合わせる.:
ディストリビューションを確認して,その都度正しいパッケージマネージャでしっかり入れる.
# Arch sudo pacman -Syu && sudo pacman -S docker git gcc-multilib python2 vim python2-pip && sudo pip2 install pwntools
# Ubuntu sudo apt update && sudo apt upgrade && sudo apt install docker-ce git gcc python2 vim python2-pip && sudo pip2 install pwntools
問題作り
1. 生地を用意する
Buffer Over FlowやFormat String Attackなどどんな生地にするかを決める.
2.方法を考える
シェルコードやROPなどどんな方法でやるかを考えて適切なセキュリティ機構を選択する.
3.作る
作る.
【ここでおいしく作るためのワンポイントアドバイス!】
1. ユーザーに何かを入力してもらう前にfflush(stdout);を呼び出そう!バッファされているputs()やprintf()の出力が全部出力されて,解いてくれる人からの好感度もアップ!
2. 攻撃対象の関数はmain()以外の関数にしよう!インストラクションポインタより前にスタックポインタがエラーを吐いてしまうから,main()のretではeipは振り向いてくれないぞ!
#include <stdio.h> void print_flag(void) { // 略 } int in_name(void) { char name[16]; printf("Type Your Name : "); fflush(stdout); scanf("%32s", name); return 0; } int main(void) { in_name(); return 0; }
4.コンパイル
コンパイルをする.
【注意!!】普段のプログラミングでは何気なく使っているこのコンパイラ,PWNを作るときには注意深く気持ちを込めてオプションを決定しよう!
mkdir bin gcc pwn.c -o bin/pwn -m32 -O0 -fno-stack-protector -no-pie -fno-pie
5.完成
問題は完成!
実際に攻撃できるかどうかpwntoolsを使って味見をしてみよう!
動作環境作り
ここまでで問題は完成したけど,ラッピングをして実際に動作するようにしてあげよう!
なんかめんどくさくなってきたけど頑張って!
【なんで環境作るん?】
pwnでルート取らせる問題で実際のルート取られたら大変やろ?
だからDockerでルート取られてもいい環境作るんやで(まる)
別に自分で試すだけなら
socat TCP-LISTEN:8080,reuseaddr,fork EXEC:./pwn
でおk
1.サービス起動
Archだったらこれやる.
sudo systemctl start docker.service
2.設定ファイルの用意
設定ファイル落としてくる
git clone https://github.com/Eadom/ctf_xinetd
ctf.xinetdのserver_args = --userspec=1000:1000 /home/ctf ./helloworld部分をhelloworldから自分の実行ファイル名に書き換える
3.ビルド
ビルドする.
sudo docker build -t "pwn"
4.実行
sudo docker run --rm -d -p "9999:9999" -h "pwn" --name="pwn" pwn
5.接続確認
わーいできたー!
接続確認.
nc localhost 9999
さっき作ったpwntoolsを今度はネットワーク越しに実行
Oh, YEAH !