2017-08-26 11 views
-1

J'ai créé une fonction pour me permettre de demander un type générique en retour d'un pointeur en mémoire avec le processus actuellement ouvert.ReadProcessMemory Retourne False après plusieurs appels

public static T ReadValue<T>(this IntPtr ptr, int length = 0) 
    { 
     Type valT = typeof(T); 
     byte[] buffer = length > 0 ? new byte[length] : new byte[Marshal.SizeOf(valT)]; 
     IntPtr retBytes; 
     object result; 

     if (!ReadProcessMemory(CurrentProcessHandle, ptr, buffer, buffer.Length, out retBytes)) 
      return default(T); 

     Console.WriteLine(ptr); 

     if (valT == typeof(byte)) 
      result = buffer[0]; 
     else if (valT == typeof(bool)) 
      result = buffer[0] > 0; 
     else if (valT == typeof(char)) 
      result = BitConverter.ToChar(buffer, 0); 
     else if (valT == typeof(double)) 
      result = BitConverter.ToDouble(buffer, 0); 
     else if (valT == typeof(float)) 
      result = BitConverter.ToSingle(buffer, 0); 
     else if (valT == typeof(int)) 
      result = BitConverter.ToInt32(buffer, 0); 
     else if (valT == typeof(long)) 
      result = BitConverter.ToInt64(buffer, 0); 
     else if (valT == typeof(object)) 
      result = buffer; 
     else if (valT == typeof(short)) 
      result = BitConverter.ToInt16(buffer, 0); 
     else if (valT == typeof(string)) 
      result = Encoding.Default.GetString(buffer); 
     else if (valT == typeof(uint)) 
      result = BitConverter.ToUInt32(buffer, 0); 
     else if (valT == typeof(ulong)) 
      result = BitConverter.ToUInt64(buffer, 0); 
     else if (valT == typeof(ushort)) 
      result = BitConverter.ToUInt16(buffer, 0); 
     else 
     { 
      IntPtr newVal = Marshal.AllocHGlobal(buffer.Length); 
      Marshal.Copy(buffer, 0, newVal, buffer.Length); 
      result = newVal; 
      Marshal.FreeHGlobal(newVal); 
     } 

     return (T) result; 
    } 

Ce qui se passe est que, après ~ 39600 appels, ReadProcessMemory commence à revenir faux dans 100% des appels suivants. Au début, j'ai supposé que c'était IntPtr attribué incorrectement avant d'être copié et libéré; Cependant, après avoir supprimé le paramètre par défaut IntPtr, le problème persiste toujours. Qu'est-ce qui cause que cela retourne faux après avoir été appelé tant de fois?

Informations supplémentaires de codage:

L'objet qui vous appelle le ReadValue.

public GameObject(IntPtr baseAddress) : this() 
{ 
    BaseAddress = baseAddress; 
    Update(); 
} 

public void Update() 
{ 
    Index = (BaseAddress + 0x8).ReadValue<ushort>(); 
} 

public GameObject GetObjectFromIndex(int index) 
{ 
    //GetPointer will return a pointer at the specified address (objectManagerStart + (index * 4)) 
    IntPtr pointer = HelperProcess.GetPointer(objectManagerStart + (index * 4), 4); 
    return pointer == IntPtr.Zero ? new GameObject().Default() : new GameObject(pointer); 
} 

Et le code où je suis déléguant l'IntPtr:

GameObject player = new GameObject().GetObjectFromIndex(1805); 
+0

Utilisez ['GetLastError'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360 (v = vs.85) .aspx) après avoir échoué à trouver plus d'informations sur le problème. – cubrr

+1

Ah. Merci de me recommander cela. Il a jeté le code d'erreur (0x6) qui était Invalid Handle. Apparemment, la poignée du module changeait, mes pointeurs n'étaient plus corrects. J'apprécie la pointe :) – Approved

+0

Nice! Assurez-vous de répondre à votre question. – cubrr

Répondre

-1

La fonction a été lancer le code d'erreur (0x6) qui était descripteur non valide. Apparemment, la poignée du module changeait, mes pointeurs n'étaient plus corrects. J'ai corrigé ceci en enveloppant la fonction dans une boucle while avec un timeout. Si l'itération en cours de la fonction est inférieure à la temporisation, essayez de récupérer le handle avant de continuer à lire depuis la mémoire.