Witam ! prezentuję artykuł w formie tutoriala… Zajmiemy się odczytem i zapisem pamięci.

O co chodzi dokładnie? Oczywiście chodzi o wykorzystanie w praktyce procedur ReadProcessMemory i WriteProcessMemory, narazie skupimy się na WriteProcessMemory. Zgryzłem na nich ładne dwa tygodnie… Że tak powiem niby są przyjazne dla potencjalnego programisty, aczkolwiek ich wykorzystanie, nie doświadczonym może sprawić wiele kłopotów. Sam ich doświadczyłem nie mało:)

Co będzie naszym zadaniem?

zadanie:

Zadaniem jest zadeklarowanie zwykłej zmiennej tekstowej typu String i zmodyfikowanie jej wartości za pomocą procedury WriteProcessMemory tak żeby zmienna różniła się od pierwotnej wartości i żeby program nie zakończył się komunikatem „Access Volation”.

Zadanie wygląda na bardzo proste… Chociaż są w nim pewne pułapki.

Zaczynamy!

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';

Jak wygląda wygląda nagłówek procedury WriteProcessMemory? Przyjrzyjmy się jej bliżej:

WriteProcessMemory(
hProcess: Cardinal;
const lpBaseAddress: Pointer;
lpBuffer: Pointer;
nSize: Cardinal;
lpNumberOfBytesWritten: Cardinal);

żeby poprawnie wywołać zapis do pamięci za pomocą procedury WriteProcessMemory trzeba podać jej 5 parametrów. Widzimy… same Pointery… brrr;-)

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 – UWAGA! ADRES A NIE BUFOR… czyli to co mamy zamiar zapisać do pamięci
nSize – rozmiar bufora
lpNumberOfBytesWritten – liczba bajtów zapisywanych do pamięci

ok. Wiedząc to wszystko możemy zacząć. Najpierw musimy otworzyć nasz proces i nadać mu odpowiednie uprawnienia. Zrobimy to za pomocą procedury OpenProcess – tak uzyskamy uchwyt do procesu.

A więc:

var
UchwytProcesu: Cardinal;
Bufor: Pointer;
Zmienna: String = 'nowy tekst zmiennej';

UchwytProcesu := OpenProcess(PROCESS_ALL_ACCESS or PROCESS_VM_OPERATION,False,GetCurrentProcessID);

Co to jest? Uzyskujemy uchwyt do procesu który potem musimy podać procedurze WriteProcessMemory za pomocą OpenProcess.

Pierwsze parametry: PROCESS_ALL_ACCESS or PROCESS_VM_OPERATION – oznacza po prostu możliwość odczytu i modyfikacji pamięci procesu.

Drugi parametr nie jest dla nas istotny, nadajemy mu wartość false.

Trzeci parametr GetCurrentProcessID zwraca nam identyfikator procesu.

Ok! Mamy już uchwyt procesu który znajduje się w zmiennej UchwytProcesu; Spróbujmy teraz coś zapisać do zmiennej… Teraz czas na trochę kodu:

Bufor := addr(Zmienna);// tu wyjasnienie funckcja addr zwraca pointer do zmiennej tzn inaczej jej adres w pamięci

ShowMessage(Tekst);

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

Wciskamy [F9] i co? !!! Błąd…

„Types of actual and formal var parameters must be identical”

O co chodzi? Przecież wszystko wpisaliśmy zgodnie z nagłówkiem procedury? Wydawało by się że wszystko dobrze…

Chodzi o ostatni parametr… wpisaliśmy tam wartość 5, a nie może tak być. Musi być w tym miejscu podana zmienna typu Cardinal. Jeżeli zamiast Cardinal podamy zmienną typu integer program też nam wywali błąd. Ok poprawiamy.

var
Dlugosc: Cardinal;
end;

Bufor := addr(Zmienna);

ShowMessage(Tekst);

WriteProcessMemory(UchwytProcesu,addr(Tekst),Bufor,SizeOf(Bufor),Dlugosc);

ShowMessage(tekst);

Zamiast adresu zmiennej można podać po prostu adres w pamięci: np

Adres := ptr($DEAD00);

Kompilujemy program! Program się skompilował. 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, tym co było wpisane w zmienną zmienna za pomocą WriteProcessMemory. A przecież o to nam chodziło. Wszystko udało się ok.

Jeszcze jedna uwaga! Bufor powinien być tego samego typu co zmienna do której zapisujemy inaczej procedura zapisze tam krzaki zamiast właściwego tekstu.

I ujrzymy access volation…

(C)opyright 2012 by Tweety:)