2009-04-23 10 views
6

Come è possibile cercare una matrice di byte [] nella memoria di un altro processo e quindi ottenere l'indirizzo nel punto in cui si trova l'array byte []?C#: ricerca un array di byte [] nella memoria di un altro processo

Voglio scrivere un array di byte nella memoria di un altro processo (WriteProcessMemory()). Uno dei parametri di tale chiamata è uint Address.Well Voglio ottenere l'indirizzo cercando un array di byte nel processo.

Per esempio cerco {0xEB, 0x20,0x68,0x21,0x27,0x65, ??, 0x21,0x64,0xA1}

Partiamo dal presupposto che questo array è posto solo in un posto nella memoria di il processo in cui mi piacerebbe scrivere memoria.

Per ottenere quell'indirizzo, devo cercare quell'array di byte.

È possibile eseguire in C#?

MODIFICA:Questo è per le applicazioni native, NOT .NET. Non c'è bisogno di sottovalutare la mia domanda, ci sono componenti per C++ che fanno questo, voglio solo farlo in C#.

Grazie per la comprensione!

+0

Solo per curiosità, perché? – Lazarus

+1

Non voglio usare dll C++ esterno, perché richiede Runtime e mi piacerebbe lavorare con la memoria anche in NET. –

+1

John: non è necessario alcun tempo di esecuzione per un'applicazione nativa che non è inclusa in Windows e si dovrà comunque lavorare con la memoria grezza. – Richard

risposta

0

È possibile eseguire in C#?

Sì. Ma molto difficile. È difficile da un'applicazione nativa in cui non vi è impedenza non corrispondente alla vista non gestita dei processi e alle mappe di memoria che è necessario utilizzare.

Considerazioni:

  • Sarà necessario il permesso di aprire il processo per ottenere una maniglia.
  • Mentre lo spazio di memoria virtuale di un processo a 32 bit è da due a quattro GB (a seconda del sistema operativo host e dell'interruttore/3 GB), gran parte di questo intervallo di indirizzi non verrà assegnato e la lettura causerà un errore di pagina. Hai davvero bisogno di scoprire quali pagine sono allocate e cosa evitare molti accessi di pagina non validi.

Suggerimenti:

  • Avete davvero bisogno di fare questo? Seriamente questo sarà difficile.
  • Considerare l'esecuzione di un'applicazione nativa, questo eviterà di funzionare attraverso la fence nativa/gestita (questo potrebbe includere una libreria nativa con un'applicazione di gestione gestita).
  • Hai davvero bisogno di fare questo?
  • Considera di eseguire il lavoro all'interno del processo di destinazione. Ciò richiederà una certa intelligenza (documentata) per iniettare una discussione, ma dovrebbe essere molto più veloce.
  • Iniziare leggendo su Windows come funziona la memoria di processo (inizia con Windows Internals e (non può ricordare il suo nome nell'ultima edizione) Jeffrey Richter sul libro sullo sviluppo di applicazioni Win32
  • Hai davvero bisogno di fare questo? ci deve essere qualcosa di più semplice ... si potrebbe automatizzato un debugger
+0

Posso ottenere l'indirizzo nel debugger, il problema è che l'applicazione su cui sto facendo questo è commerciale e viene aggiornata una volta alla settimana. Immagino di doverlo fare. –

+0

@John: In questo caso, sia VS che windbg hanno modelli di estensibilità (VS è .NET) che dovrebbero evitare tutto il duro lavoro. – Richard

+0

Potresti darmi maggiori informazioni a riguardo? –

-3

Se è possibile, io non la penso così. E spero davvero non tanto perché sarebbe un serio rischio per la sicurezza.

+0

Ciò può essere fatto in C++, è per applicazioni native, non NET. –

+3

Perché sarebbe un rischio per la sicurezza? Come pensi che funzionino i debugger? :) –

+0

Non è un rischio per la sicurezza, è necessario aprire il processo e questo significa passare attraverso l'ACL dell'altro processo. I non amministratori possono solo aprire i propri processi, gli amministratori (con elevazione, incluso chiunque disponga del privilegio di debug) possono aprire qualsiasi processo. – Richard

6

Immagino che si possa usare la chiamata API di Windows ReadProcessMemory. C'è anche un premade P/Invoke signature per questo, quindi non devi preoccuparti di farlo manualmente. Si pagina attraverso la memoria del processo, la ricerca attraverso il modello e il gioco è fatto.

+0

Devo specificare l'indirizzo in cui devo chiamarlo (uno dei suoi parametri è l'indirizzo). La mia domanda è: come ottenere l'indirizzo cercando nella memoria. Ho pensato di cercare attraverso l'intera immagine, ma ciò richiederà molto tempo. –

+2

Supponendo che lo si stia facendo in un ambiente a 32 bit, è logico utilizzare pagine 4096-byte per la ricerca, ovvero 1048576 totali. ReadProcessMemory restituisce false se l'indirizzo non è accessibile e accelera notevolmente il ciclo. Non penso che ci vorrà molto tempo per finire, specialmente perché è molto improbabile che il tuo pattern sia superiore a 1 GB. E neanche tu hai altra scelta. –

+1

@John: sarà necessario utilizzare le API della memoria per leggere solo la memoria che è leggibile (controllare VMMap.exe con la memoria libera abilitata ... la maggior parte della mappa della memoria virtuale è inutilizzata). – Richard

1

Questo può aiutare a trovare la strada giusta:?

private static int GetMemoryAddressOfString(byte[] searchedBytes, Process p) 
{ 
    //List<int> addrList = new List<int>(); 
    int addr = 0; 
    int speed = 1024*64; 
    for (int j = 0x400000; j < 0x7FFFFFFF; j+= speed) 
    { 
     ManagedWinapi.ProcessMemoryChunk mem = new ProcessMemoryChunk(p, (IntPtr)j, speed + searchedBytes.Length); 

     byte[] bigMem = mem.Read(); 

     for (int k = 0; k < bigMem.Length - searchedBytes.Length; k++) 
     { 
      bool found = true; 
      for (int l = 0; l < searchedBytes.Length; l++) 
      { 
       if(bigMem[k+l] != searchedBytes[l]) 
       { 
        found = false; 
        break; 
       } 
      } 
      if(found) 
      { 
       addr = k+j; 
       break; 
      } 
     } 
     if (addr != 0) 
     { 
      //addrList.Add(addr); 
      //addr = 0; 
      break; 
     } 
    } 
    //return addrList; 
    return addr; 
} 
+0

Mi piace questo metodo meglio della ricerca del pattern usando ReadProcessMemory(). Tuttavia, questo ha un problema durante la ricerca di pattern in un'area di memoria non scrivibile. –

3

ti consigliamo di utilizzare queste API:

[DllImport("Kernel32.Dll")] 
    public static extern uint VirtualQueryEx(IntPtr ProcessHandle, uint Address, ref MEMORY_BASIC_INFORMATION MemInfo, int MemInfoLength); 
    [DllImport("Kernel32.Dll")] 
    public static extern bool ReadProcessMemory(IntPtr ProcessHandle, uint Address, byte[] Buffer, uint Size, ref uint BytesRead); 
    [DllImport("Kernel32.Dll")] 
    public static extern bool WriteProcessMemory(IntPtr ProcessHandle, uint Address, byte[] Buffer, uint Size, ref uint BytesRead); 

pinvoke.net è un'ottima risorsa per le chiamate API di Windows. Ho scritto un trainer per GTA: Vice City che usa queste chiamate se vuoi controllare lo code su sourceforge. Il codice non è bello, è stato tanto tempo fa e l'ho appena lanciato, ma ci sono classi helper per enumerare le regioni di memoria per un processo e cercare determinati byte o stringhe.

17

È possibile eseguire in C#? Everithing è possibile in C# (o qualsiasi altra lingua), è solo necessario trovare il modo in cui;

rigido codifica qui:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     [DllImport("kernel32.dll", SetLastError = true)] 
      static extern bool ReadProcessMemory(
      IntPtr hProcess, 
      IntPtr lpBaseAddress, 
      [Out] byte[] lpBuffer, 
      int dwSize, 
      out int lpNumberOfBytesRead 
     ); 

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

    [DllImport("kernel32.dll", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool CloseHandle(IntPtr hObject); 
    static void Main(string[] args) 
    { 
     Process[] procs = Process.GetProcessesByName("explorer"); 
     if (procs.Length <= 0) //proces not found 
      return; //can replace with exit nag(message)+exit; 
     IntPtr p = OpenProcess(0x10 | 0x20, true, procs[0].Id); //0x10-read 0x20-write 

     uint PTR = 0x0; //begin of memory 
     byte[] bit2search1 = {0xEB ,0x20,0x68,0x21,0x27,0x65}; //your bit array until ?? 
     int k = 1; //numer of missing array (??) 
     byte[] bit2search2 = {0x21,0x64,0xA1};//your bit array after ?? 
     byte[] buff = new byte[bit2search1.Length+1+bit2search2.Length]; //your array lenght; 
     int bytesReaded; 
     bool finded = false; 

     while (PTR != 0xFF000000) //end of memory // u can specify to read less if u know he does not fill it all 
     { 
      ReadProcessMemory(p, (IntPtr)PTR, buff, buff.Length, out bytesReaded); 
      if (SpecialByteCompare(buff, bit2search1,bit2search2,k)) 
      { 
       //do your stuff 
       finded = true; 
       break; 
      } 
      PTR += 0x1; 
     } 
     if (!finded) 
      Console.WriteLine("sry no byte array found"); 
    } 

    private static bool SpecialByteCompare(byte[] b1, byte[] b2, byte[] b3, int k) //readed memory, first byte array, second byte array, number of missing byte's 
    { 
     if (b1.Length != (b2.Length + k + b3.Length)) 
      return false; 
     for (int i = 0; i < b2.Length; i++) 
     { 
      if (b1[i] != b2[i]) 
       return false; 
     } 

     for (int i = 0; i < b3.Length; i++) 
     { 
      if (b1[b2.Length + k + i] != b3[i]) 
       return false; 
     } 
     return true; 
    } 
} 

}

+1

@Danie - L'esempio potrebbe aiutare gli altri - nice – Leons

+2

+1 Per rispondere in realtà alla domanda senza cercare di essere fantasiosi ed essere morali. –

Problemi correlati