スタックフレームについて

スタックフレームとは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 の値ということになるよ。

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です