3

最初は、私は C++ とデバッグの初心者です。DEBUG_ONLY_THIS_PROCESS パラメータを指定して CreateProcess API を使用し、CREATE_PROCESS_DEBUG_EVENT を待ちます。受信したら、ポイントのアドレスを取得するために Eip レジスタをチェックします。そして、この点がメイン関数のアドレスだと思いました。

このアイデアを検証するために、ollydbg を使用して exe の開始アドレスを確認しました。しかし、それは私のものと同じではありませんでした。デバッグ API で見つけたのは 0x77a364d8 ですが、olly は 0x00401000 だと言っています。その後、停止せずに、olly でアドレス 0x77a364d8 を確認しました。アドレスを見つけて、そこにブレークポイントを設定しました。

次に、olly をリロードすると、olly が最初に 0x77a364d8 アドレスに移動してプロセスをロードし、次に 0x00401000 アドレスに移動してそこで待機することがわかりました。0x77a364d8 アドレスは、いくつかの ntdll 関数をポイントして、プロセスをメモリにロードします。

それが本当なら、コードで 0x00401000 アドレスを取得するにはどうすればよいですか (c++、私は初心者で、t を越えてください :) )、それは Main 関数のアドレスですか?

4

3 に答える 3

4

を受け取ったら、組合CREATE_PROCESS_DEBUG_EVENTのメンバーにアクセスできるはずです。CREATE_PROCESS_DEBUG_INFOというメンバーがいlpStartAddressます。

デバッグ イベント ループは次のようになります。

DWORD dwContinueDebugStatus = DBG_CONTINUE;
while(dwContinueDebugStatus)
{
    DEBUG_EVENT debugEvt;
    WaitForDebugEvent(&debugEvt, INFINITE);
    switch(debugEvt.dwDebugEventCode)
    {
    case CREATE_PROCESS_DEBUG_EVENT:
        // Grab the main thread entry point.
        LPTHREAD_START_ROUTINE exentry = debugEvt.u.CreateProcessInfo.lpStartAddress;
        break;
        /* Handle the rest of your debug events here. */
    }
    ContinueDebugEvent(debugEvt.dwProcessId, debugEvt.dwThreadId, dwContinueDebugStatus);
}

編集: 私が言及するのを忘れたいくつかのこと...

これらの手段のいずれかでエントリ ポイントを取得するのは、おそらく、main(). main()を使用してシンボル検索なしでを取得する信頼できる方法はありませんdbghelp.dll

また、 John Robbins によるDebugging Applicationsという本には、いくつかのサンプル コードを含む小さなデバッガの作成に関する章があります。これはおそらく私が見つけた中で最高のドキュメント/例です (しかし、もっと良いものであってほしいと思います)。かなり安く手に入るので検討してみる価値はありそうです。

于 2012-11-30T19:53:04.740 に答える
1

エントリ ポイントは(少なくとも通常は) と同じではありませんmain。エントリ ポイントの署名はvoid entrypoint(void);. 呼び出しの準備として、コマンドラインを取得し、それを個々の引数に解析する必要があります( GUIプログラムでmain呼び出す前に必要な、かなり異なる「もの」を取得する完全に別のものがあります)。WinMain

の実際のアドレスが必要な場合はmain、少なくともSymFromName名前_mainに および/または_wmain(または、GUI プログラムを扱っている場合はWinMain/ wWinmain) を使用して、実際にはターゲット プログラムの一部であるコードを取得することをお勧めします。ほとんど誰も見たことのないライブラリモジュールの何か。

于 2012-11-30T20:49:26.887 に答える
0

全て記憶ですので、多少の間違いがあるかもしれません。

新しいプロセスで EXE のエントリ ポイント アドレスを見つけるには、このプロセスの PEB フィールドを読み取る必要がありますImageBaseAddress。PEB は常に固定アドレスにありますが、EXE が 32 ビットか 64 ビットかによって異なります。事前に決定する必要があります (WOW64 には 32 ビット PEB がありますが、まだ初期化されていない可能性があると思います)。その時点で)。

ASLR のために再配置される可能性があるため、これを EXE からフェッチすることはできないことに注意してください。これを取得したら、EXE を使用して PE ヘッダーを読み取り、構造体からフィールドReadProcessMemoryを取得できます。これは RVA なので、前に見つけたベース アドレスに追加すると、ほら、エントリ ポイント アドレスが得られます。AddressOfEntryPointIMAGE_OPTIONAL_HEADER

于 2012-11-30T19:52:42.820 に答える