GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wie lese ich unter Linux aus /proc/$pid/mem?

/proc/$pid/maps

/proc/$pid/mem zeigt den Inhalt des Speichers von $pid, der auf die gleiche Weise abgebildet wird wie im Prozess, d.h. das Byte am Offset x in der Pseudodatei ist dasselbe wie das Byte an der Adresse x dabei. Wenn eine Adresse dabei nicht zugeordnet wird, liefert das Lesen aus dem entsprechenden Offset in der Datei EIO (Ein-/Ausgabefehler). Da beispielsweise die erste Seite in einem Prozess nie gemappt wird (so dass die Dereferenzierung eines NULL Pointer schlägt sauber fehl, anstatt unbeabsichtigt auf den tatsächlichen Speicher zuzugreifen), und liest das erste Byte von /proc/$pid/mem ergibt immer einen E/A-Fehler.

Um herauszufinden, welche Teile des Prozessspeichers zugeordnet sind, lesen Sie /proc/$pid/maps . Diese Datei enthält eine Zeile pro zugeordneter Region und sieht so aus:

08048000-08054000 r-xp 00000000 08:01 828061     /bin/cat
08c9b000-08cbc000 rw-p 00000000 00:00 0          [heap]

Die ersten beiden Zahlen sind die Grenzen der Region (Adressen des ersten Bytes und des überletzten Bytes in Hexa). Die nächste Spalte enthält die Berechtigungen, dann gibt es einige Informationen über die Datei (Offset, Gerät, Inode und Name), wenn es sich um eine Dateizuordnung handelt. Siehe proc(5) Manpage oder Linux verstehen /proc/id/maps für weitere Informationen.

Hier ist ein Proof-of-Concept-Skript, das den Inhalt seines eigenen Speichers ausgibt.

#! /usr/bin/env python
import re
maps_file = open("/proc/self/maps", 'r')
mem_file = open("/proc/self/mem", 'rb', 0)
output_file = open("self.dump", 'wb')
for line in maps_file.readlines():  # for each mapped region
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    if m.group(3) == 'r':  # if this is a readable region
        start = int(m.group(1), 16)
        end = int(m.group(2), 16)
        mem_file.seek(start)  # seek to region start
        chunk = mem_file.read(end - start)  # read region contents
        output_file.write(chunk)  # dump contents to standard output
maps_file.close()
mem_file.close()
output_file.close()

/proc/$pid/mem

[Das Folgende dient dem historischen Interesse. Es gilt nicht für aktuelle Kernel.]

Seit Version 3.3 des Kernels können Sie auf /proc/$pid/mem zugreifen Normalerweise, solange Sie darauf zugreifen, greifen Sie nur auf gemappte Offsets zu und Sie haben die Berechtigung, es zu verfolgen (gleiche Berechtigungen wie ptrace für Nur-Lese-Zugriff). Aber in älteren Kerneln gab es einige zusätzliche Komplikationen.

Wenn Sie versuchen, aus dem mem zu lesen Pseudo-Datei eines anderen Prozesses, es funktioniert nicht:Sie erhalten einen ESRCH (Kein solcher Prozess) Fehler.

Die Berechtigungen auf /proc/$pid/mem (r-------- ) liberaler sind, als es der Fall sein sollte. Beispielsweise sollten Sie nicht in der Lage sein, den Speicher eines setuid-Prozesses zu lesen. Darüber hinaus könnte der Versuch, den Speicher eines Prozesses zu lesen, während der Prozess ihn ändert, dem Leser eine inkonsistente Ansicht des Speichers geben, und schlimmer noch, es gab Race-Conditions, die ältere Versionen des Linux-Kernels verfolgen könnten (laut diesem lkml-Thread, obwohl ich kenne die Details nicht). Daher sind zusätzliche Überprüfungen erforderlich:

  • Der Prozess, der von /proc/$pid/mem lesen möchte muss mit ptrace an den Prozess angehängt werden mit dem PTRACE_ATTACH Flagge. Dies ist, was Debugger tun, wenn sie mit dem Debuggen eines Prozesses beginnen; es ist auch was strace macht mit den Systemaufrufen eines Prozesses. Sobald der Leser ab /proc/$pid/mem fertig gelesen hat , sollte es durch Aufrufen von ptrace getrennt werden mit dem PTRACE_DETACH Flagge.
  • Der beobachtete Prozess darf nicht laufen. Ruft normalerweise ptrace(PTRACE_ATTACH, …) an stoppt den Zielprozess (es sendet einen STOP Signal), aber es gibt eine Wettlaufbedingung (Signalübermittlung ist asynchron), also sollte der Tracer wait aufrufen (wie in ptrace(2) dokumentiert ).

Ein Prozess, der als Root läuft, kann den Speicher jedes Prozesses lesen, ohne ptrace aufrufen zu müssen , aber der beobachtete Prozess muss gestoppt werden, oder der Lesevorgang gibt immer noch ESRCH zurück .

In der Linux-Kernel-Quelle der Code, der prozessbezogene Einträge in /proc bereitstellt ist in fs/proc/base.c , und die Funktion zum Lesen von /proc/$pid/mem ist mem_read . Die zusätzliche Prüfung erfolgt durch check_mem_permission .

Hier ist ein Beispiel-C-Code, den Sie an einen Prozess anhängen und einen Teil von mem lesen können Datei (Fehlerprüfung entfällt):

sprintf(mem_file_name, "/proc/%d/mem", pid);
mem_fd = open(mem_file_name, O_RDONLY);
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid(pid, NULL, 0);
lseek(mem_fd, offset, SEEK_SET);
read(mem_fd, buf, _SC_PAGE_SIZE);
ptrace(PTRACE_DETACH, pid, NULL, NULL);

Ich habe bereits ein Proof-of-Concept-Skript für das Dumping von /proc/$pid/mem gepostet in einem anderen Thread.


Dieser Befehl (von gdb) sichert den Speicher zuverlässig:

gcore pid

Dumps können groß sein, verwenden Sie -o outfile wenn Ihr aktuelles Verzeichnis nicht genug Platz hat.


Wenn Sie cat /proc/$$/mem ausführen die Variable $$ wird von bash ausgewertet, die ihre eigene PID einfügt. Es führt dann cat aus die eine andere PID hat. Am Ende erhalten Sie cat versucht, den Speicher von bash zu lesen , seinen übergeordneten Prozess. Da nicht-privilegierte Prozesse nur ihren eigenen Speicherplatz lesen können, wird dies vom Kernel verweigert.

Hier ist ein Beispiel:

$ echo $$
17823

Beachten Sie, dass $$ ergibt 17823. Mal sehen, welcher Prozess das ist.

$ ps -ef | awk '{if ($2 == "17823") print}'
bahamat  17823 17822  0 13:51 pts/0    00:00:00 -bash

Es ist meine aktuelle Shell.

$ cat /proc/$$/mem
cat: /proc/17823/mem: No such process

Auch hier wieder $$ ergibt 17823, was meine Shell ist. cat kann den Speicherplatz meiner Shell nicht lesen.


Linux
  1. Linux – Wie liest man unter Linux aus /proc/$pid/mem?

  2. Linux – Wie unterscheidet sich der /proc//exe Symlink von gewöhnlichen Symlinks?

  3. Linux – Wie bekomme ich die IPv4-Adresse für eine Schnittstelle von /proc?

  4. Linux – /proc/mnt mit /proc/mounts verknüpfen?

  5. Linux – Wie testet man, ob ein Blockgerät von /sys oder /proc aus schreibgeschützt ist?

So beenden Sie einen Prozess in Linux

Eine Anleitung zum Dateisystem „/proc“ unter Linux

/proc/cpuinfo- und /proc/meminfo-Dateien unter Linux

/proc/[pid]/pagemaps und /proc/[pid]/maps | Linux

Wie erhalte ich die Anzahl der CPUs/Kerne in Linux über die Befehlszeile?

Wie entschlüsselt man /proc/pid/pagemap Einträge unter Linux?