问题
How to find module base address by name (in another process), in Windows x64?
ProcessModuleCollection finds only: ntdll.dll wow64.dll wow64win.dll wow64cpu.dll
Where can find an example of functions for search module base addess by name (which works in x32 and x64 Windows version)?
回答1:
The ProcessModuleCollection
instance returned by calling Process.Modules
has the information you need. Provided that both processes have the same bitness. So, if the target process is a 32 bit process, make sure your process is also a 32 bit process. And if the target process is a 64 bit process, then make sure your process is a 64 bit process.
From the output you include in the question it is clear that the scenario that produced that output is:
- A 64 bit OS.
- Your code executes in a 64 bit process.
- The target process is a 32 bit process.
The reason that you only enumerate those handful of modules is (presumably) that they are the 64 bit modules that are included in the 32 bit process running under the WOW64 emulator, together with the executable module.
You might be tempted to think that you can use the Windows API to enumerate modules in a process with a different bitness. But you cannot. Attempts to use CreateToolhelp32Snapshot
, Module32First
and Module32Next
yield the same results as your C# code that uses Process.Modules
. And that's not at all surprising really. It makes perfect sense that .net, which is implemented in Win32, would call the native Win32 API that is designed for this task.
Your solution is to make sure that the call to Process.Modules
is made from a 32 bit process. You will need to use some helper processes of different bitness if you need to be able to target both 32 and 64 bit processes.
Update
Ben Voigt point me to EnumerateLoadedModules64 from the Debug Help API. I confess to being unaware of this. However, it does appear to have the same bitness limitations as the tool help API.
Finally, there is also EnumProcessModulesEx which can enumerate 32 bit modules from a 64 bit process. If you pass LIST_MODULES_32BIT
then you can indeed extract the 32 bit modules loaded into an external 32 bit process, from a calling process that is 64 bit.
回答2:
If you're only going to target 32-bit processes with this code, the following should work just fine for you:
/// <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;
}
Where Memory.Process is just a System.Diagnostics.Process
object. I'm not sure if it'll work on actual x64 processes, but as long as you're targeting 32bit processes (even on a 64bit platform), this code will obtain the base address of a process' module just fine.
What you have to keep in mind is that whenever you enumerate ProcessModules
, you'll only be able to get the models that are in the architecture of the callee (x86 or x64). If you are running an x86 process and you are calling Process.Modules
on another process, you'll only see the x86 modules of that process. The same applies to x64. You'll either need to find a way around this or compile your project for both x86 and x64 and use the proper ones for each application.
Edit: I've found the following native code on GameDeception which may be of use to you:
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;
}
}
来源:https://stackoverflow.com/questions/17412545/find-module-handle-in-windows-x64-from-external-process