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

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

Der Linux-proc(5) Manpage sagt mir, dass /proc/$pid/mem „kann verwendet werden, um auf die Seiten des Speichers eines Prozesses zuzugreifen“. Aber ein direkter Versuch, es zu verwenden, gibt mir nur

$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error

Warum ist nicht cat kann seinen eigenen Speicher drucken (/proc/self/mem )? Und was ist dieser seltsame „No such process“-Fehler, wenn ich versuche, den Speicher der Shell zu drucken (/proc/$$/mem , offensichtlich existiert der Prozess)? Wie kann ich aus /proc/$pid/mem lesen , dann?

Akzeptierte Antwort:

/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 abgebildet wird, liefert das Lesen aus dem entsprechenden Offset in der Datei EIO zurück (Ein-/Ausgabefehler). Da zum Beispiel die erste Seite in einem Prozess nie abgebildet wird (so dass die Dereferenzierung eines NULL Pointer schlägt sauber fehl, anstatt unbeabsichtigt auf den tatsächlichen Speicher zuzugreifen), indem das erste Byte von /proc/$pid/mem gelesen wird ergibt immer einen E/A-Fehler.

Um herauszufinden, welche Teile des Prozessspeichers gemappt 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 (die gleichen 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 für /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 Reader das Lesen von /proc/$pid/mem beendet hat , sollte es durch Aufrufen von ptrace getrennt werden mit dem PTRACE_DETACH Flagge.
  • Der beobachtete Prozess darf nicht laufen. Normalerweise Aufruf von ptrace(PTRACE_ATTACH, …) stoppt den Zielprozess (es sendet ein STOP Signal), aber es gibt eine Race-Condition (Signalübermittlung ist asynchron), also sollte der Tracer wait aufrufen (wie in ptrace(2) dokumentiert ).
Verwandte:NumLock immer aktiviert lassen?

Ein als root ausgeführter Prozess kann den Speicher eines beliebigen 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 Einträge pro Prozess in /proc bereitstellt befindet sich 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 seines 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 zum Sichern von /proc/$pid/mem gepostet in einem anderen Thread.


Linux
  1. Wie behandelt Linux mehrere aufeinanderfolgende Pfadtrennzeichen (/home////username///file)?

  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 finde ich den Namensraum eines bestimmten Prozesses heraus?

So beenden Sie einen Prozess in Linux

Eine Anleitung zum Dateisystem „/proc“ unter Linux

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

Wie erhalte ich den Pfad eines Prozesses in Unix / Linux

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

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