Comment obtenir tout l’espace d’adressage mémoire utilisé par un processus?

J’ai besoin de connaître tout l’espace d’adressage mémoire utilisé par un processus. L’espace mémoire sera ensuite analysé pour localiser les valeurs dans le processus et identifier leurs emplacements / adresses. Mon processus actuel consiste à prendre l’adresse de base de chaque module par son adresse (adresse de base + taille de la mémoire).

Je teste ceci sur un processus avec une valeur connue à une adresse connue. Lorsque je cherche cette adresse spécifique, j’obtiens la valeur que j’attends. Cependant, lorsque j’parsing (ce que je crois être) tout l’espace d’adressage utilisé par le processus, je ne trouve la valeur nulle part.

Je sais qu’une valeur numérique “4143000” existe à 0x0CF8DC38 et 0x0CF8DDDC . Lorsque j’appelle ReadMemoryBytes (module, module.BaseAddress, 4, (IntPtr) (0x0CF8DC38)), je récupère des octets (152, 55, 63, 0). Lorsque j’appelle BitConverter.GetBytes (4143000), je récupère le même jeu d’octets. Lorsque j’utilise un autre scanner de mémoire sur ce processus, je trouve cette valeur à ces adresses.

Cependant, lorsque je scanne les “adresses connues”, je ne trouve cette valeur nulle part. Il ne semble pas que mon code trouve même ces adresses utilisées par le processus.

Ainsi, ma question est double:

  • Comment puis-je trouver ces adresses dans ce processus?
  • Je crains d’avoir affaire à des adresses absolues dans la mémoire système et à des adresses relatives dans un processus. Est-ce que je le fais 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, ssortingng 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  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); 

Les adresses que vous obtenez sont des pointeurs vers le segment de mémoire géré (CLR). En règle générale, ils ne mappent pas sur des adresses de mémoire absolue et peuvent passer d’un appel à l’autre lorsque le CPG décide de s’exécuter.

Si vous utilisez du code “non sécurisé”, vous pouvez obtenir des pointeurs relatifs ainsi que gérer votre propre espace mémoire. C’est toujours sur le tas, mais au moins vous avez la garantie que le CPG ne modifiera pas votre espace d’adressage.

Ne vous attendez pas à pouvoir accéder au contenu du tas à partir de code non CLR sans un wrapping complet. Il existe des moyens de procéder à l’IPC entre les processus gérés par le CLR, mais vous devez écrire des mandataires d’access au “monde extérieur” si vous souhaitez qu’un processus non-CLR parvienne à votre mémoire.