Linux proc(5)
strona człowiek mówi mi, że /proc/$pid/mem
„może być używany do uzyskania dostępu do stron pamięci procesu”. Ale prosta próba użycia go daje mi tylko
$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error
Dlaczego nie jest w cat
stanie wydrukować własnej pamięci ( /proc/self/mem
)? A jaki jest ten dziwny błąd „brak takiego procesu”, gdy próbuję wydrukować pamięć powłoki ( /proc/$$/mem
oczywiście proces istnieje)? Jak zatem mogę czytać /proc/$pid/mem
?
Odpowiedzi:
/proc/$pid/maps
/proc/$pid/mem
pokazuje zawartość pamięci $ pid zmapowanej w taki sam sposób jak w procesie, tzn. bajt o przesunięciu x w pseudopliku jest taki sam jak bajt o adresie x w procesie. Jeśli adres nie jest odwzorowywany w procesie, odczyt z odpowiedniego przesunięcia w pliku zwracaEIO
(błąd wejścia / wyjścia). Na przykład, ponieważ pierwsza strona w procesie nigdy nie jest odwzorowywana (tak, że wyłuskowanieNULL
wskaźnika kończy się niepowodzeniem, zamiast niezamierzonego dostępu do rzeczywistej pamięci), odczytanie pierwszego bajtu/proc/$pid/mem
zawsze powoduje błąd we / wy.Aby dowiedzieć się, które części pamięci procesu są mapowane, należy przeczytać
/proc/$pid/maps
. Ten plik zawiera jedną linię na region odwzorowany, wygląda następująco:Pierwsze dwie liczby to granice regionu (adresy pierwszego bajtu i bajtu po ostatnim, w heksie). Następna kolumna zawiera uprawnienia, a następnie informacje o pliku (przesunięcie, urządzenie, i-węzeł i nazwa), jeśli jest to mapowanie pliku. Aby uzyskać więcej informacji, zobacz
proc(5)
stronę podręcznika man lub Understanding Linux / proc / id / maps .Oto skrypt sprawdzający koncepcję, który zrzuca zawartość własnej pamięci.
/proc/$pid/mem
Jeśli spróbujesz odczytać z
mem
pseudopliku innego procesu, to nie działa: pojawia sięESRCH
błąd (Brak takiego procesu).Uprawnienia do
/proc/$pid/mem
(r--------
) są bardziej liberalne niż powinno być. Na przykład nie powinieneś być w stanie odczytać pamięci procesu setuid. Co więcej, próba odczytania pamięci procesu, gdy proces się modyfikuje, może dać czytelnikowi niespójny obraz pamięci, a co gorsza, istnieją warunki wyścigu, które mogą śledzić starsze wersje jądra Linuxa (zgodnie z tym wątkiem lkml , chociaż ja nie znam szczegółów). Potrzebne są więc dodatkowe kontrole:/proc/$pid/mem
musi dołączyć do procesu z wykorzystaniemptrace
zPTRACE_ATTACH
flagą. To właśnie robią debuggery, gdy zaczynają debugować proces; dotyczy to równieżstrace
wywołań systemowych procesu. Gdy czytnik zakończy czytanie/proc/$pid/mem
, powinien się odłączyć, dzwoniącptrace
zPTRACE_DETACH
flagą.ptrace(PTRACE_ATTACH, …)
zatrzyma proces docelowy (wysyłaSTOP
sygnał), ale występuje warunek wyścigu (dostarczanie sygnału jest asynchroniczne), więc znacznik powinien wywołaćwait
(zgodnie z dokumentacjąptrace(2)
).Proces działający jako root może odczytywać pamięć dowolnego procesu, bez konieczności wywoływania
ptrace
, ale obserwowany proces musi zostać zatrzymany, inaczej odczyt będzie nadal zwracanyESRCH
.W źródle jądra Linux, kod zapewniając wpisy na procesie w
/proc
jestfs/proc/base.c
, a funkcja odczytu z/proc/$pid/mem
jestmem_read
. Dodatkowa kontrola jest wykonywana przezcheck_mem_permission
.Oto przykładowy kod C do dołączenia do procesu i odczytania fragmentu jego
mem
pliku (pominięto sprawdzanie błędów):Opublikowałem już skrypt sprawdzający koncepcję, który pozwala zrzucić
/proc/$pid/mem
inny wątek .źródło
/proc/$pid/mem
bezpośrednio (bez względu na to,cat
czy jest todd
czy coś innego) nie działa. Przeczytaj moją odpowiedź./proc/self/mem
. Proces może dobrze odczytać swoje własne miejsce w pamięci, to wymaga miejsca w pamięci innego procesuPTRACE_ATTACH
.process_vm_readv()
wywołania systemowego (Linux 3.2).ESRCH
błędu w tym scenariuszu.To polecenie (z gdb) niezawodnie zrzuca pamięć:
Zrzuty mogą być duże, użyj,
-o outfile
jeśli w bieżącym katalogu nie ma wystarczającej ilości miejsca.źródło
Po uruchomieniu
cat /proc/$$/mem
zmienna$$
jest oceniana przez bash, który wstawia własny pid. Następnie wykonuje się,cat
który ma inny pid. Kończyszcat
próbą odczytania pamięcibash
, jej procesu nadrzędnego. Ponieważ procesy nieuprzywilejowane mogą odczytywać tylko własną pamięć, jądro odmawia jej.Oto przykład:
Zauważ, że
$$
wartość wynosi 17823. Zobaczmy, który to proces.To moja obecna skorupa.
Tutaj ponownie
$$
przyjmuje wartość 17823, która jest moją powłoką.cat
nie mogę odczytać pamięci mojej powłoki.źródło
$pid
jest. Jak wyjaśniam w mojej odpowiedzi, czytanie pamięci innego procesu wymaga od ciebie śledzenia.$$
kiedy piszesz (i czytasz)$pid
?$$
i$pid
koniec. Transponowałem to w mojej głowie, nie zdając sobie z tego sprawy. Cała moja odpowiedź powinna dotyczyć$$
, a nie$pid
.Oto mały program, który napisałem w C:
Stosowanie:
Program używa / proc / $ pid / maps, aby znaleźć wszystkie zmapowane regiony pamięci procesu, a następnie odczytać te regiony z / proc / $ pid / mem, po jednej stronie na raz. strony te są zapisywane na standardowe wyjście lub podany adres IP i port TCP.
Kod (testowany na Androidzie, wymaga uprawnień administratora):
źródło
write to stdout
bezpośrednio powyżejfwrite(..., stdout)
. Zobacz programmers.stackexchange.com/questions/119600/…