Windows x64で(別のプロセスで)名前でモジュールベースアドレスを見つける方法は?
ProcessModuleCollection は、ntdll.dll wow64.dll wow64win.dll wow64cpu.dll のみを検出します。
モジュール ベース アドレスを名前で検索するための関数の例はどこにありますか (x32 および x64 Windows バージョンで動作します)。
Windows x64で(別のプロセスで)名前でモジュールベースアドレスを見つける方法は?
ProcessModuleCollection は、ntdll.dll wow64.dll wow64win.dll wow64cpu.dll のみを検出します。
モジュール ベース アドレスを名前で検索するための関数の例はどこにありますか (x32 および x64 Windows バージョンで動作します)。
ProcessModuleCollection
呼び出しによって返されるインスタンスにはProcess.Modules
、必要な情報が含まれています。両方のプロセスのビット数が同じであることが前提です。そのため、ターゲット プロセスが 32 ビット プロセスである場合は、プロセスも 32 ビット プロセスであることを確認してください。また、ターゲット プロセスが 64 ビット プロセスの場合は、プロセスが 64 ビット プロセスであることを確認してください。
質問に含めた出力から、その出力を生成したシナリオは次のとおりであることは明らかです。
これらの少数のモジュールのみを列挙する理由は、(おそらく) WOW64 エミュレーターで実行される 32 ビット プロセスに実行可能モジュールと共に含まれる 64 ビット モジュールであるためです。
Windows API を使用して、異なるビット数のプロセス内のモジュールを列挙できると考えたくなるかもしれません。しかし、あなたはできません。を使用しようとするとCreateToolhelp32Snapshot
、を使用する C# コードと同じ結果が得られます。そして、それはまったく驚くべきことではありません。Win32 に実装されている .net が、このタスク用に設計されたネイティブの Win32 API を呼び出すことは完全に理にかなっています。Module32First
Module32Next
Process.Modules
解決策は、への呼び出しがProcess.Modules
32 ビット プロセスから行われるようにすることです。32 ビット プロセスと 64 ビット プロセスの両方をターゲットにする必要がある場合は、異なるビット数のヘルパー プロセスを使用する必要があります。
アップデート
Ben Voigtは、Debug Help API のEnumerateLoadedModules64を教えてくれました。私はこれに気づいていないことを告白します。ただし、ツール ヘルプ API と同じビット数制限があるようです。
最後に、64 ビット プロセスから 32 ビット モジュールを列挙できるEnumProcessModulesExもあります。合格LIST_MODULES_32BIT
した場合、外部の 32 ビット プロセスにロードされた 32 ビット モジュールを、64 ビットの呼び出しプロセスから実際に抽出できます。
このコードで 32 ビット プロセスのみをターゲットにする場合は、次のようにすると問題なく動作するはずです。
/// <summary>
/// Gets the base address of a process' module with the specified name.
/// </summary>
/// <param name="moduleName">Name of the module.</param>
/// <returns>The module BaseAddress if successful; otherwise, IntPtr.Zero.</returns>
public IntPtr GetModuleBaseAddress(string moduleName)
{
var module = Memory.Process.Modules.Cast<ProcessModule>().FirstOrDefault(m => m.ModuleName == moduleName);
return module != null ? module.BaseAddress : IntPtr.Zero;
}
どこ Memory.Process は単なるSystem.Diagnostics.Process
オブジェクトです。実際の x64 プロセスで動作するかどうかはわかりませんが、32 ビット プロセスをターゲットにしている限り (64 ビット プラットフォームでも)、このコードはプロセス モジュールのベース アドレスを取得します。
覚えておく必要があるのは、列挙するたびProcessModules
に、呼び出し先のアーキテクチャ (x86 または x64) にあるモデルのみを取得できるということです。x86 プロセスを実行していて、Process.Modules
別のプロセスを呼び出している場合、そのプロセスの x86 モジュールのみが表示されます。同じことが x64 にも当てはまります。これを回避する方法を見つけるか、プロジェクトを x86 と x64 の両方でコンパイルして、アプリケーションごとに適切なものを使用する必要があります。
編集: GameDeceptionで次のネイティブ コードを見つけました。
unsigned long ProcessDevice::getModuleAddress(DWORD proc, const char *modname)
{
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc);
if( snapshot == INVALID_HANDLE_VALUE )
{
return 0;
}
MODULEENTRY32 mod;
mod.dwSize = sizeof(MODULEENTRY32);
if( Module32First(snapshot, &mod) )
{
if( strcmp(mod.szModule, modname) == 0 )
return (unsigned long)mod.modBaseAddr;
while( Module32Next(snapshot, &mod) )
{
if( strcmp(mod.szModule, modname) == 0 )
return (unsigned long)mod.modBaseAddr;
}
/* Failed to find the module */
return 0;
}
else
{
/* Failed to read any module info */
return 0;
}
}