2013-08-01 4 views
0

J'ai écrit une classe d'éditeur de mémoire qui peut lire et écrire de la mémoire, mais ce que je dois faire est de scanner la mémoire du programme et de trouver la liste des adresses mémoire contenant la mémoire. Je cherche.C# Recherche efficace de l'adresse mémoire

Ceci est la classe de l'éditeur de mémoire.

class MemoryEditor 
{ 
    public const uint DELETE = 0x00010000; 
    public const uint READ_CONTROL = 0x00020000; 
    public const uint WRITE_DAC = 0x00040000; 
    public const uint WRITE_OWNER = 0x00080000; 
    public const uint SYNCHRONIZE = 0x00100000; 
    public const uint END = 0xFFF; 
    public const uint PROCESS_ALL_ACCESS = (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE | END); 

    public Process targetedProcess; 

    [DllImport("kernel32.dll")] 
    public static extern int OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId); 

    [DllImport("kernel32.dll")] 
    public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesRead); 

    [DllImport("kernel32.dll")] 
    public static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesWritten); 

    public Process targetProcess(string name, int index = 0) 
    { 
     return (targetedProcess = Process.GetProcessesByName(name)[index]); 
    } 

    public int getHandle(Process proc, uint access = PROCESS_ALL_ACCESS) 
    { 
     return OpenProcess(access, false, proc.Id); 
    } 

    public byte[] getBytesFromString(string str) 
    { 
     return Encoding.Unicode.GetBytes(str); 
    } 

    public string getStringFromBytes(byte[] byteArr) 
    { 
     return Encoding.Unicode.GetString(byteArr); 
    } 

    public int makeHex(string str) 
    { 
     return (int.Parse(str, System.Globalization.NumberStyles.HexNumber)); 
    } 

    public byte[] ReadMemory(int address, int processSize) 
    { 
     byte[] buffer = new byte[processSize]; 
     ReadProcessMemory(getHandle(targetedProcess), address, buffer, processSize, 0); 
     return buffer; 
    } 

    public List<int> GetAddress(byte[] memory, int index = 0) 
    { 
     List<int> buf = new List<int>(); 

     for (int i = 0; i < int.MaxValue; i++) 
      if (ReadMemory(makeHex(i.ToString()), 1) == memory) 
       buf.Add(i); 

     return buf; 
    } 

    public void WriteMemory(int address, byte[] processBytes) 
    { 
     WriteProcessMemory(getHandle(targetedProcess), address, processBytes, processBytes.Length, 0); 
    } 

    public int GetObjectSize(object TestObject) 
    { 
     BinaryFormatter bf = new BinaryFormatter(); 
     MemoryStream ms = new MemoryStream(); 
     byte[] Array; 
     bf.Serialize(ms, TestObject); 
     Array = ms.ToArray(); 
     return Array.Length; 
    } 
} 

Et voici la fonction pour essayer de trouver la mémoire adresses

public List<int> GetAddress(byte[] memory, int index = 0) 
    { 
     List<int> buf = new List<int>(); 

     for (int i = 0; i < int.MaxValue; i++) 
      if (ReadMemory(makeHex(i.ToString()), 1) == memory) 
       buf.Add(i); 

     return buf; 
    } 

il accuse un retard très mal, et je ne suis que le ciblage bloc-notes. Lorsque je scanne la mémoire dans Cheat Engine, il la trouve immédiatement, sans aucun décalage. Mon programme scanne de 0, à la valeur maximale d'un int, mais Cheat Engine le fait 0 à la valeur maximale d'un long, donc je ne sais pas ce que je fais mal.

De toute façon je peux le faire efficacement?

+0

Il serait très utile si vous pouviez également supprimer tout code non apparenté. ('GetObjectSize' par exemple) –

Répondre

2

Il y a plusieurs problèmes que je vois tout de suite.

1. Vous lisez seulement un octet à la fois:

ReadMemory(makeHex(i.ToString()), 1) 

Je ne suis pas certain, mais je suppose qu'un appel à ReadProcessMemory a besoin d'un appel système pour exécuter, et le faire pour chaque octet va certainement être une source de ralentissement. Au lieu de cela, vous devriez lire une certaine taille de "bloc" et ensuite parcourir ce bloc dans votre processus. (Faire une page à la fois peut être le plus efficace.)

2. Pourquoi dans le monde faites-vous toutes les conversions de va-et-vient aux chaînes ?!

public int makeHex(string str) 
{ 
    return (int.Parse(str, System.Globalization.NumberStyles.HexNumber)); 
} 

.... 

for (int i = 0; i < int.MaxValue; i++) 
    if (ReadMemory(makeHex(i.ToString()), 1) == memory) 

Chaque itération de cette boucle, vous convertissez i à une chaîne (la valeur par défaut, décimal - pas hex), puis il passe immédiatement à makeHex qui parse (comme hex, toujours) retour à un entier. Quel est le point de cela? Passez juste l'entier! Ces conversions peuvent être très coûteuses.

<pedantic> Par ailleurs, le nom « makeHex » n'a pas de sens - il va de hex et faire un entier. </pedantic>

+0

Très bien, je l'ai édité pour qu'il se lise en morceaux de la taille de la mémoire que j'essaye de balayer. Maintenant, au lieu de lire octet à octet, il va dans les morceaux en utilisant la fonction GetObjectSize –

+0

Etes-vous en train de sérialiser un 'objet', puis recherchez ces octets dans un autre processus? Cela ne marchera jamais, jamais. –

Questions connexes