スタックフレームについて
スタックフレームとはEBPレジスタをスタックに退避した後、スタックポインタアドレスESPをEBPに退避して、スタックポインターを一定値減算し、減算した部分をスタックフレームとして、ローカル変数や一時変数などに利用する方法です。
push ebp mov ebp,esp push esi push edi push ebx sub esp,100h push ax lea eax,[ebp-10h] |
スタックに入れた直後のデータ
まず、基本ですが、スタックにプッシュした直後のデータは *(int*)ESP で取り出せます
利用可能な領域
どこからどこまでが使えるかが見た目でぱっとわかりにくいですが、減算する直前のEBPとESPの差をオフセットに減算した分のメモリが利用できます。
上の例では 差が 0xc ですから EBP-0x0c アドレスから EBP-0x10b アドレスまでが変数として利用可能になります。
上の例では、スタックに退避した レジスタの値を変更しようと思えば
ESI = *(int*)(ebp-4)
EDI = *(int*)(ebp-8)
EBX = *(int*)(ebp-0xc)
を操作すればいいわけです。
もちろん *(int*)(ebp)には古い ebpの値が入っています。
WINAPI(_stdcall) の引数の取り出し方
関数が呼ばれた直後、スタックは次のようになっています
*(int*)(esp) リターンアドレス
*(int*)(esp+4) 第1引数
*(int*)(esp+8) 第2引数
*(int*)(esp+0xc) 第3引数
:
スタックフレームが生成された後は
*(int*)(ebp+4) リターンアドレス
*(int*)(ebp+8) 第1引数
*(int*)(ebp+0xc) 第2引数
*(int*)(ebp+0x10) 第3引数
:
こんな風になります。
というわけで、リバースエンジニアリングの基礎知識でした|。・ω・)
最後に応用問題
SUB_L77F854AC: push ebp mov ebp,esp push FFFFFFFFh push L77F812D8 push L77FB7E74 mov eax,fs:[00000000h] push eax mov fs:[00000000h],esp push ecx push ecx sub esp,00000044h push ebx push esi push edi call SUB_L77F8570A mov ecx,eax |
この例で使える変数領域の範囲は?
答えは 4x6+0x44= 0x5c
0x1c+1=0x1d
[ebp-0x5c]~[ebp-0x1d] でした・ω・
[ebp-0x18][ebp-0x14]がecx
[ebp-0x10]が退避した fs:[00000000h] の値
[ebp-0x0c]がL77FB7E74
[ebp-0x08]がL77F812D8
[ebp-0x04]が0xffffffff
[ebp-0x60]がebx
[ebp-0x64]がesi
[ebp-0x68]がedi の値ということになるよ。
Comments