Jest to dość trudne, a nawet złożone pytanie, w tym sensie, że można z tym pogłębić. Ale żeby trochę uprościć:
Biorąc pod uwagę twój przykład „ czytania timera w grze w kopalniach ”:
Pierwszym krokiem jest znalezienie adresu pamięci . Zwykle odbywa się to za pomocą narzędzia o nazwie edytor pamięci (w niektórych przypadkach zrobiłby to także debugger), który może korzystać z różnych metod, aby znaleźć lokalizację zmiennej w pamięci procesu . Częstym sposobem jest poszukiwanie określonej wartości (na przykład wartości timera) w przestrzeni pamięci procesu docelowego, a następnie zmiana wartości docelowej (np. Przesunięcie timera) i ponowne wyszukiwanie dopasowań. Ten proces przyporządkowuje kandydatów przy każdej iteracji, dopóki nie pozostanie tylko dokładna zmienna. Podanie adresu tej zmiennej w przestrzeni pamięci procesu to tylko kwestia kliknięcia myszą w edytorze pamięci.
Drugim krokiem jest modyfikacja danych pod tym konkretnym adresem . Sposób wykonania tej operacji zależy od systemu operacyjnego. W systemie Windows istnieje wywołanie WinAPI o nazwie, WriteProcessMemory
którego można użyć do zapisania predefiniowanych danych na dany adres w obszarze pamięci procesu docelowego. W naszym przykładzie użyłbyś tej funkcji do zastąpienia zmiennej timera w procesie docelowym własną pożądaną wartością, skutecznie zmieniając timer w grze.
W praktyce trzeba by znaleźć procesu docelowego procesu identyfikator , a następnie podłączyć proces fałszywego do procesu docelowego, aby uzyskać zdolność do zmiany swojego miejsca w pamięci. Jest to dość trywialne zadanie, ale nie przyczynia się do odpowiedzi na pytanie, dlatego pominąłem je jako ćwiczenie dla czytelnika. ;)
To jest zupełnie inny system operacyjny. Niektóre nie pozwalają na to w ogóle i musisz mieć jakieś środki, aby wiedzieć, gdzie potrzebne dane znajdują się w przestrzeni pamięci celu.
Oto jak to zrobić w systemie Linux: /unix/6301/how-do-i-read-from-proc-pid-mem-under-linux
źródło
Aplikacja otrzymuje zakres pamięci od systemu operacyjnego. Zasadniczo aplikacja musi żądać pamięci, ale ta funkcjonalność może być ukryta dla programisty z powodu języka.
Języki takie jak C pozwalają na blokowanie żądań dla określonych rozmiarów, podczas gdy inne języki, takie jak C ++, C # i Java, pozwalają na żądania za pomocą słów kluczowych, takich jak
new
. Każdy język ma kilka sposobów przydzielania pamięci, więc jest to tylko krótki przegląd. Zwolnienie pamięci z powrotem do systemu operacyjnego może być wykonane jawnie lub przez moduł wyrzucania elementów bezużytecznych.Dostęp do pamięci w aplikacji zależy od sposobu jej przydzielenia. C i C ++ są najlepiej znane z używania koncepcji wskaźników do wskazywania / śledzenia miejsca, w którym znajduje się pamięć. W przeciwnym razie dostęp do pamięci jest obsługiwany przez utworzoną klasę lub zmienną.
Przez większość czasu nie musisz się martwić o określony dostęp do pamięci w swoim programie. Konstrukcje językowe i system operacyjny skutecznie przesłaniają tę troskę.
Twój przykład timera w grze jest doskonałym przykładem tego, gdzie nie musisz się martwić o przydział pamięci. Będziesz mieć zmienną reprezentującą licznik czasu i po prostu będziesz czytać ze zmiennej.
Moja odpowiedź jest ważna podczas pisania aplikacji, podczas gdy odpowiedź zxcdw dotyczy dostępu do pamięci, która należy do innej aplikacji. Twoje warunki LMGTFY to „debugowanie” i „inżynieria wsteczna”, aby zagłębić się w ten temat.
Kilka dodatkowych lektur:
źródło