他のバージョンの Windows のファイルを差し替えてもソフトが動かない3つの理由
よく、『プロシージャ エントリ ポイント MOFMOF がダイナミック リンク ライブラリ KERNEL32.dll から見つかりませんでした』 などのエラーが出た時に、 Windows XP や 7から 同名のファイルを持ってきて上書きすればいいんじゃないか?などの安直な考えを実行してしまってPCが起動しなくなってしまったというトラブルがありますがなぜだめなのかを分かり易く説明してみます ・ω・
1. 関数間のリンクの問題
DLLやEXE 形式の プログラムは、後から使うかもしれない関数と 必ず使う関数のテーブルをファイルの中に持っています。使うかもしれない関数はプログラム起動時に発見できなくてもエラーにはなりませんが、必ず使う関数が目的のDLLに存在しないと
『プロシージャ エントリ ポイント ~ がダイナミック リンク ライブラリ ~ から見つかりませんでした』 のエラーになります。
Windows 2000のKERNEL32.DLLは約 800、Windows VistaのKERNEL32.DLLは約 1200の関数があります。
ところが、NTDLLの必要な関数が 2000 とVistaでは違います
Windows 2000にVista のkenrel32.dllを読み込ませてみた所です。
NTDLLの機能不足によって、読み出しに失敗しています
逆に、2000に存在したのに、Windows Vista のKernel32.dllでは削られてしまった関数もあります。
ほぼすべてのDLLやEXEは KERNEL32.DLL にリンクしているのですが、上位バージョンの Windows のDLLを使うためには、NTDLLを含む、KERNEL32.DLL を置き換えなくてはいけないわけです。
WindowsのNTDLL.DLL は関数の外部参照がないため、入れ替えてしまえば動作するように見えます。
2. 一部のDLLは カーネル機能を使う問題
実は、NTDLLやGDI32や KERNEL32 や USER32 や WIN32K は カーネル関数という、関数名ではなく、機能番号を用いた関数を利用しています。
NtFsControlFile: mov eax,00000048h lea edx,[esp+04h] int 2Eh retn 0028h ;------------------------------------------------------------------------------ NtGetContextThread: mov eax,00000049h lea edx,[esp+04h] int 2Eh retn 0008h |
Windows 2000
NtFsControlFile: mov eax,00000086h mov edx,7FFE0300h call [edx] retn 0028h ;------------------------------------------------------------------------------ Align 4 NtGetContextThread: mov eax,00000087h mov edx,7FFE0300h call [edx] retn 0008h |
Windows 7
eax に代入されているのが機能番号です。
一目見て分かるように、 Windows 番号が変わると、機能番号が、変わってしまうのです。
2000とXPですら、番号が違うのです。
さぁたいへん、 NTDLLや WIN32K.SYSや GDI32.DLLや USER32.DLLを入れ替えてしまうと、外部関数参照の問題が解決できても、カーネルの関数番号がずれてしまうので、全く別の処理が行われてしまいます!
3. Teb / Peb 等の システム構造体の配置が違うよ!
そして一番大きいのが、 Process / Thread Environment Block と呼ばれる 変数領域の使い方がOSによって若干異なるということです。
PEB Evolution
Peb に関してはそれほどおおきなちがいはないのですが、スレッド情報などを参照すると、オフセットがずれていたりするので、「情報が入ってるアドレスを参照したら、使用中のメモリブロックの数が返ってきた!」なんてこともあり、クラッシュの原因になります。
Windows XPから 2000に関数を移植するときに、めんどくさいのもこれだったりします
なので、安直に、システム DLLを別のOSから持ってきて動かすというのは無謀なのです・ω・
Comments