DEP と mofooter その2
SPDEP=GetProcAddress(hDll,"SetProcessDEPPolicy"); 00401A6A 8B F4 mov esi,esp 00401A6C 68 F0 59 4A 00 push offset "SetProcessDEPPolicy" 00401A71 8B 45 C8 mov eax,dword ptr [hDll] 00401A74 50 push eax 00401A75 FF 15 40 EC 4B 00 call dword ptr [GetProcAddress] 00401A7B 3B F4 cmp esi,esp 00401A7D E8 4E 07 05 00 call _RTC_CheckEsp 00401A82 89 45 EC mov dword ptr [SPDEP],eax if(SPDEP){ 00401A85 83 7D EC 00 cmp dword ptr [SPDEP],0 00401A89 74 05 je initialize_findacx+0A0h _asm{ push 0 00401A8B 6A 00 push 0 call SPDEP 00401A8D FF 55 EC call dword ptr [SPDEP] } |
以前 書いた記事で DEP回避用に、 SetProcessDEPPolicy を使うという話がありました
DEP と mofooter
ところが、Windows 7 でこの関数呼ぶと、落とされるという事が判明!
正しくは、
・SetProcessDEPPolicyを呼ぶのは問題ない。
・GetSystemDEPPolicyで呼び出して得た値を、SetProcessDEPPolicy に書き戻したらダメってことでした。
素直にDEPリストに追加した方がよさそうですね。
Windows 7のデータ実行防止リストのGUIいじってたら、定義が消せなくなって、正常に動作しなくなってしまった(汗)これはひどいバグ。
HKEY_LOCAL_MACHINE の SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers に定義が保存されているので、おかしくなったら 手動で削除してみましょう。
VirtualProtect使いましょうよ。Win95でも実装されていないだけでエントリポイントは存在するので、関数の存在チェックは不要です。
いあ、そのVirtualProtect を使うとDEPが有効になってる場合例外で落っこちるんですよ。
i=(FARPROC)&_imp__IsDebuggerPresent;
VirtualProtect(i, sizeof(FARPROC), PAGE_READWRITE, &dw);
*(FARPROC*)i=(FARPROC)&IsDebuggerPresent_stub;
VirtualProtect(i, sizeof(FARPROC), dw, NULL);
↑DEP有効時はこのコードでBEX例外
2つ目のVirtualProtectが失敗して、__imp__IsDebuggerPresentに実行属性が戻されないまま呼び出されてDEPに落とされているのではないでしょうか。
http://msdn.microsoft.com/ja-jp/library/cc430214.aspx
> lpflOldProtect
> 指定されたページ領域の最初のページの以前のアクセス保護値が書き込まれる変数へのポインタを指定します。このパラメータが NULL の場合や、有効な変数を指していない場合、関数は失敗します。
VirtualProtectは周囲4KB(1ページ全体)の保護属性を書き換えるので、__imp__VirtualProtectの実行属性が巻き添えで落とされている可能性が高いです。その場合、当然二度目のVirtualProtect呼び出しでDEPに引っかかります。
一度目のVirtualProtect呼び出しでは保護属性の指定をPAGE_READWRITE_EXECUTEにする必要がありそうです。
あと書き込みはポインタアクセスではなくWriteProcessMemory(GetCurrentProcess(),…)で行う必要があるかと。
ありがとうございます。
検証を新しい記事にまとめました。