VirtualProtect 関連検証

DEP と mofooter その2 でアドバイスをいただいたのでいろいろ検証してみました。


オリジナルのコード

i=(FARPROC)&_imp__DecodePointer;
VirtualProtect(i, sizeof(FARPROC),PAGE_READWRITE    , &dw);
*(FARPROC*)i=(FARPROC)&DecodePointer_stub;
VirtualProtect(i, sizeof(FARPROC), dw, NULL);

1. VirtualProtect 関数 の第4パラメータがNULLの場合関数が失敗する

確かに関数が失敗して意味がないものになっていましたが、例外には直接関係ないようでした。

修正1

i=(FARPROC)&_imp__DecodePointer;
VirtualProtect(i, sizeof(FARPROC),PAGE_READWRITE    , &dw);
*(FARPROC*)i=(FARPROC)&DecodePointer_stub;
VirtualProtect(i, sizeof(FARPROC), dw, &dw);

2. VirtualProtectは周囲4KB(1ページ全体)の保護属性を書き換えるので、__imp__VirtualProtectの実行属性が巻き添えで二度目のVirtualProtect呼び出しでDEPに引っかかっている。

確認してみたところ、1回目の VirtualProtect でDEPに引っかかっている模様。 PAGE_EXECUTE_READWRITE を指定してみたところ、問題なくなった。1回目の関数から戻ってきた瞬間にお亡くなりになってることが判明。よく考えてみれば当たり前でした。

修正2

i=(FARPROC)&_imp__DecodePointer;
VirtualProtect(i, sizeof(FARPROC),PAGE_EXECUTE_READWRITE , &dw);
*(FARPROC*)i=(FARPROC)&DecodePointer_stub;
VirtualProtect(i, sizeof(FARPROC), dw, &dw);

3. 書き込みはポインタアクセスではなくWriteProcessMemoryで行う必要がある。

WriteProcessMemory は 書き込み不可だった場合、関数が失敗して戻ってくるので、書き込み失敗時すると、飛ばされるアドレスが不定で危険なので、プログラムが動作しないのであれば、ポインタアクセスで直接例外発生で問題ないかなという見解|・ω・)
コードも25バイト→7バイトで済むしね。

というわけで、ありがとうございました。おかげで、コードもすっきりしました。

関連記事:
MS11-025 を入れると 98/Me/NT/2000でソフトが動かなくなる件 その2

おすすめ

コメントを残す

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