3

私のプログラムは、Windows Vista Ultimate と Windows 7 では問題なく動作しますが、Windows XP では失敗します。

まず、私のアプリケーションはシステム ファイルのプロセスを作成し、GetThreadContext(remote_thread) を呼び出して LPVOID 値を値 context->Eip に設定し、VirtualQueryEx から設定された MEMORY_BASIC_INFORMATION 構造体の値をチェックします。

VirtualQueryEx が呼び出されたときに返される値は次のとおりです。

WindowsXP

  • 0 - 配賦基準
  • 0 - 割り当て保護
  • 2088828928 - ベースアドレス
  • 1 - 保護する
  • 983040 - 領域サイズ
  • 65536 - 状態
  • 0 - タイプ

ウィンドウズ7

  • 2003959808 - 割り当てベース
  • 128 - 割り当て保護
  • 2004025344 - ベースアドレス
  • 32 - 守る
  • 876544 - 領域サイズ
  • 4096 - 状態
  • 16777216 - タイプ

Windows ビスタ

  • 2006122496 - 割り当てベース
  • 128 - 割り当て保護
  • 2006536192 - ベースアドレス
  • 32 - 守る
  • 389120 - 領域サイズ
  • 4096 - 状態
  • 16777216 - タイプ

Windows XP でアプリケーションを実行すると、アロケーション ベースとアロケーション プロテクトがなく、Windows 7 や Windows Vista とは値がまったく異なるのはなぜですか。

アドレス (コンテキスト-> Eip) で VirtualProtectEx を使用する予定なので、それらが XP の値である場合、アクセスできないメモリにアクセスするため、VirtualProtectEx は必然的に失敗します。

プロセスを作成する方法は次のとおりです。

    if ( CreateProcessW(m_pwszContainerPath, NULL, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED, NULL, NULL, &m_stStartInfo, &m_stProcessHandles) == TRUE )
    {
    // Get context of thread
    m_stContext.ContextFlags = CONTEXT_FULL;
    if ( GetThreadContext(m_stProcessHandles.hThread, &m_stContext) == FALSE )
        goto _CLEANUP;
    // Grab, Eip
    m_pvLdrInitEip = (LPVOID)m_stContext.Eip;
        }

実際のところ、これは Windows 7 と Windows Vista の両方で問題なく動作します。

私がここに欠けているものはありますか?助けてくれてありがとう。

編集 - ここに写真があります:

ウィンドウズ7 WindowsXP メモリ内の EIP の場所を表示している Windows XP.. アドレスがntdllにあることを示すWindows 7 これは、実行可能ファイルを実行している olly の 2 つのインスタンスの図です。1 つは XP 仮想マシン内で、もう 1 つは外部です。私が気づいたことから、XP の画像 (一番下) では EIP が ModuleEntryPoint に設定されていますが、Windows 7 インスタンスでは ntdll に設定されています。

さらに調査したところ、EIP は実際には、本来あるべき ntdll.dll ではなく、kernel32.dll イメージ (Windows XP の場合) にあることがわかりました..

4

2 に答える 2

5

でプロセスを作成するとCREATE_SUSPENDED、コードを実行する前にメイン プロセスの初期化が完了しません。ローダーの実装方法により、XP と Vista/7 の間で異なる効果が生じます。CREATE_SUSPENDEDドキュメントではプロセスの初期化が許可されていないため、その方法を実際に当てにすることはできません。CREATE_SUSPENDEDフラグは、メインスレッドが中断された状態でプロセスが作成されたことを示しているだけです 。
OPが何を達成したいのかは明確ではありませんが、同様の目標を達成するためのいくつかの方法が思い浮かびます:

  1. 別のプロセスをリモートで操作する代わりに、デバッガーを作成します。簡単なチュートリアルとコード例は、ここにあります。デバッガーは、生成されたスレッドごとにイベントを取得します。おそらくそれを使用できます。

  2. コードの新しいセクションを作成し、PE に TLS エントリを配置して、プロセスのメモリ空間内でコードを実行することにより、PE を変更して他のどのコードよりも先にコードを実行します。コードは、プロセスの EntryPoint の前に実行されますが、初期化された後に実行されます。

  3. PE を変更EntryPointし、PE ヘッダー内の を独自のコードに置き換えます。元のエントリ ポイントを自分で実行するようにしてください。一部の初期化が失われますが、すべての PE コード セクションが読み込まれます。

  4. 中断されたプロセスを作成して別のスレッドから DLL をロードするか、またはその他の方法で、プロセスのメモリ アドレスに DLL を挿入します。この記事ではいくつかをリストしますが、Google でさらに多くの情報を入手できます。同様の問題のためにプロセスを初期化したい場合、すべての場合に機能するかどうかはわかりませんが、LoadLibrary を呼び出すと目的の効果が得られると思います。これは、デバッガーを使用するよりもステルスでありながら、別のプロセスにコードを取得して操作するためのクリーンな方法でもあります。

  5. プロセスが中断されている間に操作したいコードチャンクを探すためにメモリ全体をスキャンすることもできます。これは XP でも機能する可能性があります。

  6. 中断されていないプロセスを作成して、スレッドを中断する前に短時間実行することができます。タイミングといくつかのテストの後、初期化にかかる時間について妥当な感覚が得られます。それは少し危険ですが、うまくいくかもしれません。

デバッガーを作成することは、最も簡単で最も堅牢で一般的な方法ですが、簡単に検出されるという欠点があります (ただし、アンチアンチデバッグのトリックを使用することはできます)。操作されたプロセスによって検出されないようにしたい場合 (アンチデバッグのトリックがある場合)、DLL をロードすることが最善の方法です。あなたの質問からは明らかではないので、達成してください。プログラムに関するもう少し詳細 (ネイティブか、.net かなど) も役立ちます。

EDIT:友人が提案した別の推測は、システムコールが返されてVirtualQueryEx. 彼は、プロセスが完全に初期化されるとプロセスのハンドルを呼び出すWaitForSingleObjectと戻り、すべての情報にアクセスして後で実行を再開できると述べました。

于 2013-06-20T14:43:43.283 に答える
3

CreateProcess(CREATE_SUSPENDED)部分的な初期化のみを行います。VirtualAllocEx()EIP リージョンにアクセスして、明示的に COMMIT することもできますVirtualProtectEx。もちろん、これは簡単なハックです。テストを行うことができます。これで問題が解決するかどうかはわかりません。ところで、そうするあなたの本当の目的は何ですか? プロセス実行の初期段階でフックする場合は、PE ヘッダーのエントリ ポイントにパッチを適用することをお勧めします。これは、命令制御フローがエントリ ポイントに到達したときに、プロセスが初期化を完了している必要があるためです。ただし、これには TLS コールバックなどの欠点もあります。エントリ ポイントが実行される前に呼び出されます。

于 2013-06-02T19:12:21.297 に答える