Pwntools ハンズオン (環境構築・ローカル実行・リモート接続)

CTF の Pwn, Binary 系問題 (c 言語で書かれたプログラムが動くリモートサーバーにアクセスして, 脆弱性を突くことでコマンド実行・フラグ文字列の獲得を目指す問題) でよく使われるツールである pwntools について, 導入など問題を解く以前の基本的な部分についての覚え書きとサンプルコード
以前の記事 で自分用のチートシート的なものは作ったが, 整理も兼ねてサンプルコードを含めた解説をまとめたものがあった方が便利なので製作

検証環境

環境構築

依存関係のインストール

sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential

pwntools のインストール

pip install pwntools
uv add pwntools

インストールの確認

from pwn import *
pwn version
uvx --from pwntools pwn version

make, Docker の準備 (省略可能)

docker compose up

Hello World!

バイナリの準備

// gcc -g hello.c -o ../build/hello
#include <stdio.h>

int main(void) {
    puts("Hello World!");
}

pwntools を用いたローカルバイナリの実行

from pwn import *

# set binary path
context.binary = "../build/hello"

sh = process()
# get one text line
text = sh.recvline()
print(text.decode())

sh.close()

pwntools を用いたリモートへの接続

host = "localhost"
port = "1337"
sh = remote(host, port)

pwntools を用いた入力

バイナリの準備

// gcc -g in_out.c -o ../build/in_out
#include <stdio.h>

int main(void) {
    printf("Input something: ");

    char buf[0x10];
    fgets(buf,sizeof(buf),stdin);
    printf("Your input: %s", buf);
}

文字列の送信

from pwn import *

# set binary path
context.binary = "../build/in_out"

_, host, port = "nc localhost 1337".split()
sh = remote(host, port)

prompt = sh.recvuntil(b"something:")
print("prompt: ", prompt.decode())
sh.sendline(b"Hello Send!")