VC++11製バイナリをXPで動かす

2012年4月1日現在、VisualC++11 Betaで作成したバイナリはXPで動作しません。
今回は、それを強引にXPで動くようにしてしまう方法を紹介します。

この記事の目次

なぜXPで動かないのか?

理由は簡単で

  • 動作対象OSがVista以上
  • ランタイムでVista以降のAPIを使用

だから。

動作対象OSをXPに変更

exeファイルには動作対象のOSを指定するサブシステムバージョンというものが存在し、それに満たない環境では動作しないようになっています。
本来ならリンカオプションのsubsystemで変更できるのですが、VC++11からはXP(5.1)以下を選択できません。
なので、強引にexe冒頭で指定されているサブシステムバージョンを5.1に書き換えることで回避します。

具体的には
ここを05 00 01 00と書き換えるとXP以上という意味になります。

書き換えている場所について詳しく知りたい人は、IMAGE_NT_HEADERSのOptionalHeader.MajorSubsystemVersionとOptionalHeader.MinorSubsystemVersionでググってください。

Windowsのバージョン番号はwikipediaの「Windows のタイムライン」を参照

Vista以降のAPI呼び出しを止める

動作対象のOSをXP以上にしたとしても、XPに存在しないAPIを呼んでいては起動すらできません。
これを回避する方法はいくつかあるのですが、ここではダミーのKernel32.dllを作成し、そこに必要なAPIを独自実装することで回避することにします。

exeファイルには当然リンクするべきdll名が記述されています。
そのうちKERNEL32.dllを書き換え、ダミーのDLL名(ここではKernelXP.dllとします)に変更し、そのDLL越しにKERNEL32.dllを呼ぶように細工します。
これは単にexeファイル内からKERNEL32.dllという文字列を探し、書き換えるだけで可能です。

つぎにダミーのDLLの作り方ですが、まず完成品がこちら。
KernelXP.zip

作り方としては、XPのKERNEL32.dllでエクスポートされている関数の一覧を作り
※エクスポート関数一覧の取得方法はDllFuncList.zipなどを参照
それらをすべてKERNEL32.dllへ受け流すだけのDLLを作成。
その後exeファイルをXPで実行してみて、APIが見つからないエラーが出るたびに、そのダミー実装を作るを繰り返すだけ。
詳しくは、DLLインジェクションやダミーDLLなどでググると見つかるかと思います。

終わりに

今回はダミーのDLLを経由させる方法で実現しましたが、一般的にはIATを書き換える方が多いようです。
いつかそちらについても言及してみたいなと思いつつ、今回はここまで。

VC++11製バイナリをXPで動かす” への3件のフィードバック

  1. ないです。
    XPの64bit版自体ほぼ現存していないと思われるので作る予定もありません。

  2. >>中の人様
    本当は自分で何とかしたいところなのですが、
    x64ではインラインアセンブラとnakedが使えないので、
    同じことをするためにはどうしたらと悩んでおりました。

    失礼いたしました。

コメントを残す

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