Praktyczne użycie funkcji WriteProcessMemory

tweety

O co chodzi dokładnie? Oczywiście chodzi o wykorzystanie w praktyce funkcji ReadProcessMemory i WriteProcessMemory, na razie skupimy się na tej pierwszej. Teoretycznie są przyjazne dla potencjalnego programisty, aczkolwiek ich wykorzystanie przez niedoświadczonych może sprawić wiele kłopotów.

Co będzie naszym zadaniem? Zadaniem będzie zadeklarowanie zwykłej zmiennej tekstowej typu String i zmodyfikowanie jej wartości za pomocą funkcji WriteProcessMemory tak, by zmienna różniła się od pierwotnej wartości i żeby program nie zakończył działania komunikatem "Access Volation".

Na początku deklarujemy zmienną tekstową, którą będziemy odczytywać, i do której będziemy zapisywać:

var
  Tekst: String = 'Przykładowa zmienna tekstowa';

Przyjrzyjmy się bliżej nagłówkowi funkcji WriteProcessMemory:

WriteProcessMemory(hProcess: Cardinal; const lpBaseAddress: Pointer; lpBuffer: Pointer;
                   nSize: Cardinal; lpNumberOfBytesWritten: Cardinal);
Argument Opis
hProcess identyfikator procesu, do którego będziemy wykonywali zapis
lpBaseAddress adres w pamięci, do którego będziemy zapisywali np adres jakiejś zmiennej
lpBuffer adres bufora
nSize rozmiar bufora
lpNumberOfBytesWritten liczba bajtów zapisywanych do pamięci
W pierwszej kolejności należy otworzyć proces i nadać mu odpowiednie uprawnienia, za pomocą funkcji OpenProcess. W ten sposób uzyskamy uchwyt do procesu.
var
  UchwytProcesu: Cardinal;
  Bufor: Pointer;
  Zmienna: String = 'nowy tekst zmiennej';
begin
  UchwytProcesu := OpenProcess(PROCESS_ALL_ACCESS or PROCESS_VM_OPERATION, False, GetCurrentProcessID);

Co to jest? Uzyskujemy w ten sposób uchwyt do procesu, który następnie musimy podać funkcji WriteProcessMemory.

Pierwsze parametry: PROCESS_ALL_ACCESS or PROCESS_VM_OPERATION oznaczają możliwość odczytu i modyfikacji pamięci procesu. Drugi parametr nie jest dla nas istotny, nadajemy mu wartość False. Trzeci parametr GetCurrentProcessID zwraca identyfikator procesu.

Mamy już uchwyt procesu, który znajduje się w zmiennej UchwytProcesu. Następnie spróbujmy zapisać dane do zmiennej:

Bufor := addr(Zmienna); //funckcja Addr zwraca pointer do zmiennej
ShowMessage(Tekst);

WriteProcessMemory(UchwytProcesu, Addr(Tekst), Bufor, SizeOf(Bufor), 5);

Niestety powyższy kod nie może zostać skompilowany, przez co w oknie komunikatów kompilacji otrzymamy komunikat: "Types of actual and formal var parameters must be identical". O co chodzi? O ostatni parametr - wpisaliśmy tam wartość 5. Musi być w tym miejscu podana zmienna typu Cardinal. Jeżeli zamiast Cardinal podamy zmienną typu Integer program także nie skompiluje się.

var
  {...}
  Dlugosc: Cardinal;
  {...}
begin
  {...}
  Bufor := Addr(Zmienna);
  ShowMessage(Tekst);

  WriteProcessMemory(UchwytProcesu, Addr(Tekst), Bufor, SizeOf(Bufor), Dlugosc);
  ShowMessage(tekst);

Zamiast adresu zmiennej mozna bezpośrednio podać adres w pamięci, np:

Adres := Ptr($00ADFF);

Najpierw wyświetlił tekst Przykładowa zmienna tekstowa, a potem drugi tekst nowy tekst zmiennej.

Co to oznacza? To znaczy że program pomyślnie nadpisał pierwotną wartość zmiennej Tekst, zawartością zmiennej Zmienna, za pomocą WriteProcessMemory.

Jeszcze jedna uwaga - Bufor powinien być tego samego typu co zmienna, do której zapisujemy - inaczej funkcja zapisze tam nieprawidłowe dane, zamiast właściwego tekstu. Ujżymy zatem komunikat Access Volation.

© Copyright 2012 by Tweety

0 komentarzy