関数先頭にあるMOV EDI,EDIって何だろう?
Windows環境において、多くのAPI関数の先頭に存在するMOV EDI,EDIという命令。たとえばMessageBoxWの先頭2バイトを次のようなプログラムで調べてみる。
// VC++ 2010 Express版 #include <stdio.h> #include <Windows.h> int main() { HMODULE user32 = ::LoadLibrary(L"user32.dll"); auto pMessageBoxW = reinterpret_cast<decltype(MessageBoxW)*> (GetProcAddress(user32, "MessageBoxW")); BYTE bBuff[8]; memcpy(bBuff, (void *)pMessageBoxW, 2); TCHAR szStr[1024]; wsprintf(szStr, L"MessageBoxW first 2byte is '%02x %02x'.", bBuff[0], bBuff[1]); pMessageBoxW(GetForegroundWindow(), szStr, L"MESSAGE", MB_OK); return 0; }
先頭2バイトは8b ff。つまりmov edi, edi。これ自体はなんの意味もない命令な気がするけどなんで各API関数の先頭に常にあるの? みたいな疑問。その答えはこちら。
Why do Windows functions all begin with a pointless MOV EDI, EDI instruction?
It's a hot-patch point.
どうやらパッチ用のようです。
もっと具体的にいうとAPIフック用。先頭2バイトがmov edi, ediなので、まずはここをeb f9:jmp -7に変える。デバッガとかで確認すると、mov edi, ediの上には5バイト連続でnop辺りが埋まってるはず。ここに飛ぶようにして、この5バイトの領域にe9 XX XX XX XX:jmp 0xXXXXXXXXみたいなコードを入れると任意の場所にジャンプできる。つまり手軽にAPIフックが実現できる。便利。なのでmov edi, ediと上の5バイトはセットみたいなもんなのかな。