ふるつき

v(*'='*)v かに

pwn初心者メモ

pwnわからん、でも簡単なのは解けたほうが良いな、バッファオーバーフローくらいならわかる気がする。いや細かいところがわからんぞ? 解けない、やーめた、pwnわからん。でも簡単なのは解けたほうが良いな……になるのでpwn初心者メモを残しておきたい。

特に断らなければx86(-64)のELFです。というかそれ以外のアーキテクチャは初心者じゃなさそう

バッファオーバーフロー

リターンアドレスの書き換え

f:id:Furutsuki:20200112190845p:plain

図はCSAW CTF 2018のget it? これはgetsを利用しているのでバッファオーバーフローができる。入力はvar_20に書き込まれて、64bitバイナリなのでリターンアドレスを書き換えるときのpayloadは "A"* (0x20 + 8) + p64(addr) みたいな感じになる。

もしこのバイナリが32bitだったら"A" * (0x20 + 4) + p32(addr)

ローカル変数の上書き

f:id:Furutsuki:20200112191519p:plain

図はTUCTF 2017のVuln Chat。ここでは最初のscanfの呼び出しでvar_5を書き換えたい。書き込み先はvar_19なのでペイロード"A" * (0x19 - 0x5) + "%99s" とかになる

payload正しそうなのに落ちる

やっぱりCSAW CTF 2018のget it? なんだけど、ペイロード正しそうに見えるのにSegfaultしてしまうときは、ジャンプ先のアドレスに +1 して push rbp を飛ばす。libc 2.27からはこれまで movups 命令が使われていた部分で movaps 命令が使われるようになっているんだけど、この命令が呼ばれたときにスタックが16byteでalignされていないと落ちる。ちゃんとcallしたときは大丈夫なんだけどリターンアドレスを書き換えたりしてjmp相当の処理を行った場合はpush rbp があるとずれるのでこれをなくしているんだなぁ。勉強になる

メモ

__x86_get_pc_thunk_bx とか

x86ではmov ebx, eip みたいなことが出来ないので、スタックに積まれた戻りアドレスからeipを求めるみたいなことをする。そのためにいるのが __x86_get_pc_thunk_bxとかで、細かい関数名はレジスタ名やアーキテクチャ名によってことなるけど、挙動としては mov ebx, [esp] みたいなことをしているだけ。そもそもこれを使って何をしているのかはよくわからない。