Jak przejść do czytania pamięci z procesu? Czy to inaczej w systemie operacyjnym?

11

Jako doświadczony programista stron internetowych, ale początkujący programista „niskiego poziomu”, te rzeczy są dla mnie nadal voodoo.

Ciekawi mnie, jak można zacząć szukać bloku pamięci, a następnie czytać go (na przykład czytając stoper w grze w kopalniach)? Czy różni się to w zależności od wersji systemu operacyjnego?

Eva
źródło

Odpowiedzi:

14

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, WriteProcessMemoryktó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. ;)

zxcdw
źródło
Czy lokalizacja zmiennej będzie taka sama przy każdym uruchomieniu procesu?
brunoqc,
1
@brunoqc Nie, prawie na pewno nie.
Dan
2

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

pjc50
źródło
jaki system operacyjny na to nie pozwoli? Wygląda na to, że możesz to zrobić przynajmniej pod Linuksem i Windows
Eva
@Evan Każdy system operacyjny musi umożliwiać (ograniczony ze względów bezpieczeństwa) środki do zdalnej modyfikacji pamięci procesu w celu debugowania. Należy jednak pamiętać, że na przykład niedopasowanie uprawnień ze względów bezpieczeństwa może powodować, że nie można odczytać / zapisać pamięci procesu o wyższym stopniu uprzywilejowania. Dobrym przykładem tego byłoby niedopuszczenie, aby proces z uprawnieniami użytkownika-gościa czytał / zapisywał pamięć procesu z uprawnieniami administratora, ponieważ może to potencjalnie zagrozić całemu systemowi i być bezpośrednim sposobem na uzyskanie przez administratora gościa uprawnień do system.
zxcdw
1

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:

  • Artykuł w Wikipedii na temat pamięci komputera daje dobry przegląd rzeczy.
  • Następnie zapoznaj się z artykułem Wikipedii na temat we / wy mapowanym na pamięć, aby lepiej zrozumieć trwające machinacje.
  • Na koniec zapoznaj się z artykułem na temat pamięci wirtualnej, aby uzyskać lepszą odpowiedź na temat tego, jak każdy system operacyjny będzie obsługiwał mapowanie pamięci nieco inaczej niż inne.

źródło
doskonała odpowiedź, chociaż tak, w tym przypadku bardziej martwię się czytaniem pamięci z aplikacji, której sam nie napisałem. Będę głosować, jak tylko będę mieć 15 powtórzeń;)
Eva
@Evan - zdecydowanie przeczytaj artykuł na temat pamięci wirtualnej. To da ci lepsze zrozumienie trwającego mapowania. Musisz zrozumieć mapowanie, aby rozdzielić aplikację. Większość debuggerów pozwoli ci dołączyć się do uruchomionego procesu, który pozwoli ci zobaczyć instrukcje i pamięć aplikacji.