Die Linux- proc(5)
Manpage sagt mir, dass /proc/$pid/mem
"verwendet werden kann, um auf die Seiten des Speichers eines Prozesses zuzugreifen". Aber ein einfacher Versuch, es zu benutzen, gibt mir nur
$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error
Warum kann cat
der eigene Speicher nicht gedruckt werden ( /proc/self/mem
)? Und was ist dieser seltsame Fehler "no such process", wenn ich versuche, den Speicher der Shell zu drucken ( /proc/$$/mem
offensichtlich ist der Prozess vorhanden)? Wie kann ich dann lesen /proc/$pid/mem
?
Antworten:
/proc/$pid/maps
/proc/$pid/mem
zeigt den Inhalt des Speichers von $ pid, der auf die gleiche Weise wie im Prozess abgebildet wurde, dh das Byte am Offset x in der Pseudodatei ist das gleiche wie das Byte an der Adresse x im Prozess. Wenn eine Adresse dabei nicht zugeordnet wird, wird das Lesen des entsprechenden Offsets in der Datei zurückgegebenEIO
(Eingabe- / Ausgabefehler). Da beispielsweise die erste Seite in einem Prozess niemals zugeordnet wird (so dass die Dereferenzierung einesNULL
Zeigers/proc/$pid/mem
fehlerfrei fehlschlägt, anstatt unbeabsichtigt auf den tatsächlichen Speicher zuzugreifen), führt das Lesen des ersten Bytes von immer zu einem E / A-Fehler.Der Weg, um herauszufinden, welche Teile des Prozessspeichers abgebildet sind, ist zu lesen
/proc/$pid/maps
. Diese Datei enthält eine Zeile pro zugeordnetem Bereich und sieht folgendermaßen aus:Die ersten beiden Zahlen sind die Grenzen der Region (Adressen des ersten Bytes und des Bytes nach dem letzten in Hexa). Die nächste Spalte enthält die Berechtigungen. Wenn es sich um eine Dateizuordnung handelt, werden einige Informationen zur Datei (Offset, Gerät, Inode und Name) angezeigt. Weitere Informationen finden Sie in der
proc(5)
Manpage oder unter Linux / proc / id / maps .Hier ist ein Proof-of-Concept-Skript, das den Inhalt seines eigenen Speichers speichert.
/proc/$pid/mem
Wenn Sie versuchen, aus der
mem
Pseudodatei eines anderen Prozesses zu lesen , funktioniert dies nicht:ESRCH
Es wird ein Fehler (Kein solcher Prozess) angezeigt.Die Berechtigungen für
/proc/$pid/mem
(r--------
) sind liberaler als dies der Fall sein sollte. Beispielsweise sollte es nicht möglich sein, den Speicher eines Setuid-Prozesses zu lesen. Der Versuch, den Arbeitsspeicher eines Prozesses zu lesen, während dieser geändert wird , kann dem Leser eine inkonsistente Sicht auf den Arbeitsspeicher geben. Schlimmer noch, es gab Race-Bedingungen, die ältere Versionen des Linux-Kernels nachvollziehen können (laut diesem lkml-Thread , obwohl ich Ich kenne die Details nicht. Daher sind zusätzliche Überprüfungen erforderlich:/proc/$pid/mem
mussptrace
mit demPTRACE_ATTACH
Flag an den Prozess angehängt werden. Dies tun Debugger, wenn sie mit dem Debuggen eines Prozesses beginnen. Es ist auch das, wasstrace
mit den Systemaufrufen eines Prozesses geschieht. Sobald der Leser das Lesen beendet hat/proc/$pid/mem
, sollte er sich durch Aufrufenptrace
mit derPTRACE_DETACH
Flagge lösen .ptrace(PTRACE_ATTACH, …)
stoppt der Aufruf den Zielprozess (es wird einSTOP
Signal gesendet), aber es liegt eine Race-Bedingung vor (die Signalübermittlung ist asynchron), sodass der Tracer einen Aufruf durchführen solltewait
(wie in dokumentiertptrace(2)
).Ein Prozess, der als root ausgeführt wird, kann den Speicher eines beliebigen Prozesses lesen, ohne dass ein Aufruf erforderlich
ptrace
ist. Der beobachtete Prozess muss jedoch gestoppt werden, oder der Lesevorgang wird weiterhin ausgeführtESRCH
.In den Linux - Kernel - Quellen und bietet der Code pro Prozess Einträge in
/proc
in istfs/proc/base.c
, und die Funktion zum Lesen von/proc/$pid/mem
istmem_read
. Die zusätzliche Prüfung erfolgt durchcheck_mem_permission
.Hier ist ein Beispiel-C-Code, der an einen Prozess angehängt und einen Teil der
mem
Datei gelesen werden kann (Fehlerprüfung weggelassen):Ich habe bereits ein Proof-of-Concept-Skript zum Speichern
/proc/$pid/mem
in einem anderen Thread veröffentlicht .quelle
/proc/$pid/mem
direkt (ob mitcat
oderdd
oder irgendetwas anderes) nicht funktioniert. Lies meine Antwort./proc/self/mem
. Ein Prozess kann seinen eigenen Speicherbereich ganz gut lesen. Er liest den Speicherbereich eines anderen Prozesses, der benötigt wirdPTRACE_ATTACH
.process_vm_readv()
Systemaufruf (Linux 3.2) verbunden.ESRCH
in diesem Szenario keinen Fehler liefern .Dieser Befehl (von gdb) sichert den Speicher zuverlässig:
Speicherauszüge können groß sein. Verwenden
-o outfile
Sie diese Option, wenn in Ihrem aktuellen Verzeichnis nicht genügend Speicherplatz vorhanden ist.quelle
Bei der Ausführung wird
cat /proc/$$/mem
die Variable$$
von bash ausgewertet, wobei eine eigene pid eingefügt wird. Es wird dann ausgeführt,cat
welches eine andere PID hat. Am Ende müssen Siecat
versuchen, den Speicher desbash
übergeordneten Prozesses zu lesen . Da nicht privilegierte Prozesse nur ihren eigenen Speicherbereich lesen können, wird dies vom Kernel abgelehnt.Hier ist ein Beispiel:
Beachten Sie, dass
$$
17823 ausgewertet wird. Mal sehen, welcher Prozess das ist.Es ist meine aktuelle Shell.
Hier nochmal
$$
17823 auswertet, das ist meine Shell.cat
Ich kann den Speicherplatz meiner Shell nicht lesen.quelle
$pid
ist. Wie ich in meiner Antwort erläutere, müssen Sie die Erinnerung an einen anderen Prozess nachvollziehen, um ihn lesen zu können.$$
wann du schreibst (und liest)$pid
?$$
und$pid
am Ende zu setzen. Ich habe es in meinem Kopf transponiert, ohne es zu merken. Meine gesamte Antwort sollte sich beziehen$$
, nicht$pid
.Hier ist ein kleines Programm, das ich in C geschrieben habe:
Verwendungszweck:
Das Programm verwendet / proc / $ pid / maps, um alle zugeordneten Speicherbereiche des Prozesses zu finden, und liest diese Bereiche dann seitenweise aus / proc / $ pid / mem. Diese Seiten werden auf stdout oder die von Ihnen angegebene IP-Adresse und den angegebenen TCP-Port geschrieben.
Code (auf Android getestet, Superuser-Berechtigungen erforderlich):
quelle
write to stdout
direkt darüberfwrite(..., stdout)
. Siehe programmers.stackexchange.com/questions/119600/…