1

ソースコードに基づいて既知の変数を持つWin32アプリから変数にアクセスしようとしています。

Foo foo; // Class foo
foo.mystring = "All your base are belong to us"; // where this is defined as: 'string mystring'

今、逆アセンブラを使用してPEを逆アセンブルしようとしましたが、これが見つかりました

.rdata:00446074 aAllYourBaseAre db 'all your base are belong to us',0

これで、必要なクラス変数を持つ以前のwin32アプリのイメージベースアドレスを取得する別のwin32プロセスができました。

このコードでプロセスアドレスを取得します:

HMODULE parent = ::GetModuleHandle(NULL);
if (parent) {
   const BYTE* imageBase = reinterpret_cast<const BYTE*> ( parent );
   const char* strMemberValue = *reinterpret_cast<const char**>((unsigned char*)imageBase + 0x00446074); 
            std::cout << "Value=" << strMemberValue;
}

親は、私がアクセスしようとしているプロセスです。また、親が正しいプロセスであることをテストしました。問題は、ベースアドレス+オフセットをキャストして文字列を取得しようとすると、何も取得できないことです。

編集:

私は自分の主張を逃した。すでに本番環境にあるターゲットWin32アプリを再コンパイルする方法はありません。ただし、その実行可能ファイルのいくつかの変数にアクセスする必要があります。ここにあるコードは、単なる概念実証**です。

また、「DLLインジェクション」を行っています

デバッグ:

クラスはメソッドを持つ構造体であるため、IDAProを使用して掘ったこのコードは次のクラス定義であると想定しています。Foo

00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ; (Class Informer)
00000000 type_info       struc ; (sizeof=0x8, variable size)
00000000 vftable         dd ?                    ; offset (00000000)
00000004 _m_data         dd ?
00000008 _m_d_name       db 0 dup(?)             ; string(C)
00000008 type_info       ends
00000008
00000000 ; ---------------------------------------------------------------------------

しかし、私はまだこれについて確信が持てません。

4

2 に答える 2

1

二重の間接化により、間違った方法でプロセス メモリにアクセスしています。.rdata:00446074実際の場所へのポインタではなく、文字列が配置されているアドレスです。次のようにアクセスする必要があります。

HMODULE parent = ::GetModuleHandle(NULL);
if (parent) {
   const BYTE* imageBase = reinterpret_cast<const BYTE*> ( parent );
   const char* strMemberValue = (const char *)imageBase + 0x00446074; 
   std::cout << "Value=" << strMemberValue;
}

0x0また、逆アセンブラがデフォルトの PE ベース アドレス ではなく でイメージをベースとしていると確信していますか。0x00400000この場合、文字列の RVA は であり、 では0x00046074ありません0x00446074。また、これは、変数自体ではなく、メンバー変数の初期化に使用される文字列定数です。

于 2012-06-22T09:20:27.280 に答える
0

わかりました、最初に注意すること: 外部プロセス メモリを扱う場合、他の実行可能ファイルを再コンパイルすると、おそらくデータが見つからなくなります。リンカーは、自由にデータとコードをどこにでも配置し、再配置できます。特定の値または関数を再検索するには、バイナリ パターンを検索する必要があります。

次に注意すること: 実際にはメンバー変数があります。つまり、その内容は実際にはオブジェクトごとに異なる可能性があります。現在、デフォルトで割り当てられている文字列を検索しています(メンバーに直接ではなく、 std::string クラスのどこかに)。

最後になりましたが、外部プロセスのコンテンツにアクセスしようとすると、ReadProcessMemoryを使用する必要があります。ただし、プロセス間通信に共有メモリを使用することを検討してください。名前付きパイプも同様です。

実際の値にアクセスする最も簡単な方法は、Fooオブジェクトのアドレスを&foo読み取りプロセスなどに渡し、Foo両方のプロジェクトからアクセスできる共通のプロジェクト ベースにクラスを配置することです。次に、オブジェクト全体をアドレス空間に読み込み (ReadProcessMemory上記を参照)、他のメンバーにアクセスする場合と同じようにメンバーにアクセスします。ただし、実際のオブジェクトのコピーを実際に扱っていることに注意してください。共有メモリは、単一のオブジェクトを両方のプロセスにアクセス可能にすることができます ( CreateFileMapping )

于 2012-06-22T06:48:01.997 に答える