関数先頭にある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バイトはセットみたいなもんなのかな。