2009-08-03 1 views
0

実行時にWin32実行可能ファイルのテキストセグメント内のオフセットをポインタに変換するにはどうすればよいですか?実行時にWin32実行可能ファイルのテキストセグメント内のオフセットをポインタに変換するにはどうすればよいですか?

逆アセンブラを使用すると、相対アドレスがわかります。しかし、どうすればそれらを実行時に絶対アドレスに変換できますか?例えば

:それは、実行時にあるアドレス

.text:402BE620 

?その番号をポインタに変換するにはどうすればよいですか?

一部の背景:私は寿命末期のDLLのバグを修正する必要があり、ソースコードにアクセスすることはできません。そのためには、特定の関数をフックして実行時にオーバーライドする必要があります。

(それはMsgWaitForMultipleObjectsを使用する必要がありましたWaitForSingleObjectへの呼び出しが含まれており、なぜならそれはバイナリエディタで固定することはできません追加パラメータの)

EDIT:をご提案いただきありがとうございます、私は追加あなたにいくつかの文脈を与えるためだけにフックについてのもの。 フックフレームワークは必要ありません!。私は重い吊り上げをし、少なくとも今のところは - それ自体をフックすることについて、これ以上の情報は必要ありません - 良いフックフレームワークを持っています。

フックするフレームワークにフックする機能のアドレスを提供するだけで、その計算方法を知っている必要があり、その決定方法がわかりません。

EDIT 2:私は2つの異なる逆アセンブラを使用していますが、どちらも上記のアドレスを示しています。やや奇妙:両方とも "goto"機能を使用すると "402BE620"をオフセットとして拒否します。

答えて

0

あなたの特定の質問に対する答えはわかりませんが、私が行ったとしても、あなたの計画はうまくいかないと思います。私はそれをあなた自身のコードにコール(またはジャンプ)して関数呼び出しを動的にパッチすることを計画していますか?しかし、パッチを含むページがOSによって破棄され、後で(DLLディスクイメージから)いつか再ロードされるとどうなりますか?どのようにこれを検出し、それを再パッチするつもりですか?

だけの思考....

+2

ない、これは動作します。実行可能ページを変更するとコピーオンライトがトリガーされるので、実行中のプロセスはパッチコードを使用します。 –

+0

データページの仕組みは分かっていますが、コードページでも同じであることはわかりませんでした。しかし、意味があります。 –

0

あなたは通常、それはあなたが実行中のプロセスにスレッドを作成することを可能にし、フック/それに任意の関数を置き換えるdetours
を使用することになり、このような何かを。
通常はシンボルを検索することで機能しますが、オフセットを使用しても機能しない理由はありません。

質問に具体的に答えるには、dllファイルには通常、相対アドレスがあります。ファイルの先頭からの相対パスです。 PE(dll、exe)がメモリにロードされると、相対アドレスのすべてが、PEがロードされるベースアドレスを使用して絶対アドレスに置き換えられます。 GetModuleHandle()
402BE620を使用して、特定のDLLのベースアドレスを確認することは、相対アドレスのようには見えません。本当に絶対アドレスのように見えるので、逆アセンブラがあなたに何を示しているかを確認することをお勧めします。相対アドレスは、DLLファイルのサイズより大きくすることはできません。
便利なヒント - プロセスにデバッガを接続すると、通常、すべてのDLLとそれらのベースアドレスが一覧表示されます。

0

API Interception via DLL Redirection(PDF)にこのmilw0rm紙
はあなたが冒険しているアイデアを与える必要がありますいくつかの方法について説明します。

私たちの目標を達成するために使用できるいくつかの方法がありますが、このチュートリアルではDLLリダイレクトのみを調べます。このアプローチは、いくつかの理由から選択されました。

  1. これは実装が比較的簡単です。
  2. API関数に渡されるパラメータを表示および変更し、その関数の戻り値を変更し、必要な他のコードを実行することができます。
  3. 他のほとんどの方法では、ターゲットプロセスにコードを注入するか、 外部アプリケーションから実行する必要がありますが、DLLリダイレクトでは、ターゲットアプリケーションの 作業ディレクトリへの書き込みアクセスのみが必要です。
  4. ターゲット(ディスクまたはメモリのいずれか)または システムファイルを変更せずにAPI呼び出しをインターセプトできます。

DLLをロードするようにプログラムをリダイレクトしたら、 が探しているすべての機能を持つ必要があります。 Internet Explorerが行うすべての呼び出しを傍受して、 MessageBoxにしたいとしましょう。 MessageBoxはuser32.dllにありますので、MessageBoxという名前のエクスポート可能な関数を含むuser32.dll という名前のDLLを作成し、iexplore.exe.manifestファイルを作成し、新しく作成したuser32.dllとiexploreを に配置する必要があります。 exe.manifestファイルをC:\ Program Files \ Internet エクスプローラディレクトリに保存します。 IEがAPI関数をインポートすると、 user32.dllファイルからMessageBoxが読み込まれます。 IEがMessageBox関数を呼び出すたびに、 MessageBox関数に配置されたコードが実行されます。

catchは、MessageBoxがuser32.dllからインポートされる唯一の機能ではないということです。 IEがuser32.dllで探している機能が何百もあります。これらのいずれかが であれば、IEは読み込まれません。私たちは、USER32のDLL機能のすべてを再書き込みしたくないので、私たちは 単に

0

は私がからのオフセットを知らない元user32.dllのファイルへの関数の残りの部分を転送します.textセグメントは具体的ですが、デバッガでは必要なアドレスを見て、そこからモジュールの負荷オフセットを引きます。ベースアドレスが明示的に設定されていても毎回異なるアドレスにロードされる可能性があります。

ランタイムパッチの代わりに、dll自体を単にパッチするだけでもかまいません。 OllyDbgは、バイナリに簡単にパッチを適用できる優れたアセンブリレベルのデバッガとコード解析ツールです。

編集:

ちょうど楽しみのためにここで私は、バイナリパッチに私はアプリで好きではなかったいくつかの機能拡張を使用するために使用されるいくつかのサンプルコードです - 実行時には。私はいくつかの単純化を行い、再コンパイルとテストはしませんでしたが、あなたはそのアイデアを得るべきです。

(私はバイナリを定期的知らオフセットから小さな範囲内のパターンと一致するように、したがって、追加の作業を更新されたことの合併症を有していた。)

void MyCrazyPatch() 
{ 
    static bool patched = false; 

    if (!patched) 
    { 
     patched = true; 

     DWORD dwPatchOffsetStart = 0x5310; 
     DWORD dwPatchLength = 22; 

     BYTE rgPatchMatch[] = { 0xab, 0x07, 0x37, 0x56, 0x50, 0xe8, 0x92, 0xfb, 0xff, 0xff, 0x83, 
           0xf8, 0x01, 0x89, 0xb5, 0xfc, 0x0f, 0x85, 0xb2, 0xaa, 0x00, 0x00, 0x8b }; 

     HMODULE hmod = GetModuleHandle(L"mybinary.dll"); 
     if (hmod != NULL 
     { 
      MODULEINFO modInfo; 
      if (GetModuleInformation(GetCurrentProcess(), 
            hmod, 
            &modInfo, 
            sizeof(modInfo))) 
      { 
       DWORD dwIncrement = 0; 
       dwPatchOffsetStart += (DWORD)modInfo.lpBaseOfDll; 

       while (dwIncrement < 0x200 && 
         memcmp((void*)(dwPatchOffsetStart + dwIncrement), 
           rgPatchMatch, 
           sizeof(rgPatchMatch)) != 0) 
       { 
        dwIncrement++; 
       } 

       // Sanity check then add nop's to stomp out the offending code. 
       if (dwIncrement < 0x200 && 
        memcmp((void*)(dwPatchOffsetStart + dwIncrement), 
          rgPatchMatch, 
          sizeof(rgPatchMatch)) == 0) 
       { 
        DWORD dwOldProtect = 0; 

        VirtualProtect((void*)(dwPatchOffsetStart + dwIncrement), 
            dwPatchLength, 
            PAGE_EXECUTE_READWRITE, 
            &dwOldProtect); 
        memset((void*)(dwPatchOffsetStart + dwIncrement), 0x90, dwPatchLength); 

        VirtualProtect((void*)(dwPatchOffsetStart + dwIncrement), 
            dwPatchLength, 
            dwOldProtect, 
            NULL); 
       } 
      } 
     } 
    } 
} 
関連する問題