2011-06-05 15 views
5

Necesito saber todo el espacio de direcciones de memoria utilizado por un proceso. El espacio de la memoria se explorará posteriormente para ubicar los valores dentro del proceso e identificar sus ubicaciones/direcciones. Mi proceso actual para esto es tomar la dirección base de cada módulo a través de su (dirección base + tamaño de la memoria).¿Cómo obtener todo el espacio de direcciones de memoria utilizado por un proceso?

Estoy probando esto en un proceso con un valor conocido en una dirección conocida. Cuando busco esa dirección específica, obtengo el valor que espero. Sin embargo, cuando escaneo (lo que creo que es) todo el espacio de direcciones utilizado por el proceso, no puedo encontrar el valor en ningún lado.

sé que un valor numérico "4143000" existe en 0x0CF8DC38 y 0x0CF8DDDC. Cuando llamo a ReadMemoryBytes (module, module.BaseAddress, 4, (IntPtr) (0x0CF8DC38)) Obtengo bytes (152, 55, 63, 0). Cuando llamo a BitConverter.GetBytes (4143000) obtengo el mismo conjunto de bytes. Cuando uso un escáner de memoria diferente en ese proceso, encuentro ese valor en esas direcciones.

Sin embargo, cuando escaneo las "direcciones conocidas", no encuentro este valor en ninguna parte. No parece que mi código incluso encuentre esas direcciones en uso por el proceso.

Thusly, mi pregunta es doble:

  • ¿Cómo puedo encontrar estas direcciones dentro de este proceso?
  • Me preocupa que pueda estar lidiando con direcciones absolutas en la memoria del sistema contra direcciones relativas dentro de un proceso. ¿Lo estoy haciendo bien?

.

// (in the calling method) 
foreach (ProcessModule module in process.Modules) { 
    ParameterizedThreadStart pst = new ParameterizedThreadStart(p => SearchModule(module, value)); 
    Thread t = new Thread(pst); 
    t.Start(); } 

private unsafe void SearchModule(ProcessModule module, string value) 
{ 
Process process = getProcess; 
int iVal; 
double dVal; 
int.TryParse(value, out iVal); 
double.TryParse(value, out dVal); 
for (Int64 addr = (Int64)module.BaseAddress; addr + value.Length < (Int64)module.BaseAddress + module.ModuleMemorySize; addr++) 
{ 
    // Compare ints 
    if (iVal > 0) 
    { 
     byte[] ExpectedBytes = BitConverter.GetBytes(iVal); 
     byte[] ActualBytes = ReadMemoryBytes(module, (IntPtr)addr, (uint)ExpectedBytes.Length, (IntPtr)addr); 

     bool isMatch = true; 
     for (int i = 0; i < ExpectedBytes.Length; i++) 
      if (ExpectedBytes[i] != ActualBytes[i]) 
       isMatch = false; 
     if (isMatch) 
      PossibleAddresses.Add((IntPtr)addr); 
    } 
} 

private byte[] ReadMemoryBytes(ProcessModule mod, IntPtr memAddress, uint size, IntPtr BaseAddress) 
{ 
    byte[] buffer = new byte[size]; 
    IntPtr bytesRead; 
    unsafe 
    { 
     ReadProcessMemory(processPointer, BaseAddress, buffer, size, out bytesRead); 
     return buffer; 
    } 
} 

[DllImport("kernel32.dll")] 
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId); 
[DllImport("kernel32.dll")] 
public static extern Int32 CloseHandle(IntPtr hObject); 
[DllImport("kernel32.dll")] 
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead); 
+0

Su suposición errónea es que (desde MSDN): "ModuleMemorySize no incluye ninguna asignación de memoria adicional que el módulo hace una vez que se ejecuta, sino que incluye solo el tamaño del código estático y los datos en el archivo del módulo". Entonces su bucle no se ve en todas partes. Lo que necesita es un mapa general de la memoria del proceso, pero no estoy seguro de cómo puede hacerlo en C#. La herramienta sysinternals VMMap puede hacerlo, pero no hay una fuente disponible ... (http://technet.microsoft.com/en-us/sysinternals/dd535533) – Joe

Respuesta

1

Las direcciones que está recibiendo son punteros al montón administrado (CLR). Por lo general, no se asignarán a direcciones de memoria absolutas y pueden moverse de llamada a llamada cuando el GC decida ejecutar.

Si utiliza el código "inseguro", puede obtener punteros relativos y administrar su propio espacio de memoria. Todavía está en el montón, pero al menos está garantizado que el GC no modificará su espacio de direcciones.

No espere poder acceder a cosas en el montón desde código que no sea CLR sin un amplio envoltorio. Hay formas de hacer IPC entre procesos gestionados por CLR, pero tendría que escribir proxies de acceso al "mundo exterior" si desea que un proceso que no sea CLR llegue a su memoria.

Cuestiones relacionadas