Ist dd if = / dev / urandom von = / dev / mem sicher?

9

Was genau macht das? Ich verstehe nicht, wie Sie damit auf den Basisspeicher zugreifen können ... scheint irgendwie komisch. Ist es sicher?

dd if=/dev/urandom of=/dev/mem
Coder14
quelle
Was ist das "sicher", von dem du sprichst? Sicher in Bezug auf was?
Waltinator
Was möchten Sie mit diesem Befehl erreichen?
Jochen

Antworten:

22

Versuchen Sie das nicht zu Hause! Es kann Ihr System zum Absturz bringen, und wenn Sie wirklich Pech haben, kann es ein Peripheriegerät beschädigen oder Ihren Computer nicht mehr bootfähig machen.

Auf den meisten Plattformen schlägt dies nur mit einem Fehler fehl, dies hängt jedoch von der Hardwarearchitektur ab. Es gibt definitiv keine Garantie dafür, dass dies harmlos ist, es sei denn, Sie führen den Befehl als nicht privilegierter Benutzer aus. Bei einem nicht privilegierten Benutzer ist der Befehl völlig harmlos, da Sie ihn nicht öffnen können /dev/mem.

Wenn Sie einen Befehl als root ausführen, sollten Sie wissen, was Sie tun. Der Kernel hindert Sie manchmal daran, etwas Gefährliches zu tun, aber nicht immer. /dev/memist eines dieser potenziell gefährlichen Dinge, bei denen Sie wirklich wissen sollten, was Sie tun.

Ich werde durchgehen, wie ein Schreiben /dev/memunter Linux funktioniert. Das allgemeine Prinzip wäre bei anderen Unices dasselbe, aber Dinge wie Kerneloptionen sind völlig anders.

Was passiert, wenn ein Prozess eine Gerätedatei liest oder in diese schreibt, hängt vom Kernel ab. Beim Zugriff auf eine Gerätedatei wird Code im Treiber ausgeführt, der diese Gerätedatei verarbeitet. Wenn Sie beispielsweise schreiben, um /dev/memdie Funktion write_memindrivers/char/mem.c aufzurufen . Diese Funktion benötigt 4 Argumente: eine Datenstruktur, die die geöffnete Datei darstellt, einen Zeiger auf die zu schreibenden Daten, die Anzahl der zu schreibenden Bytes und die aktuelle Position in der Datei.

Beachten Sie, dass Sie nur so weit kommen, wenn der Anrufer die Berechtigung hatte, die Datei überhaupt zu öffnen. Gerätedateien entsprechen normalerweise den Dateiberechtigungen. Die normalen Berechtigungen von /dev/memsind crw-r-----Eigentum von root:kmem. Wenn Sie also versuchen, es zum Schreiben zu öffnen, ohne root zu sein, erhalten Sie nur die Berechtigung "verweigert" (EACCESS). Wenn Sie jedoch root sind (oder wenn root die Berechtigungen dieser Datei geändert hat), wird die Öffnung durchlaufen und Sie können versuchen, sie zu schreiben.

Der Code in der write_memFunktion führt einige Überprüfungen durch, aber diese Überprüfungen reichen nicht aus, um vor allem Schlechten zu schützen. Als erstes wird die aktuelle Dateiposition *pposin eine physikalische Adresse konvertiert . Wenn dies fehlschlägt (in der Praxis, weil Sie sich auf einer Plattform mit physischen 32-Bit-Adressen, aber 64-Bit-Datei-Offsets befinden und der Datei-Offset größer als 2 ^ 32 ist), schlägt der Schreibvorgang mit EFBIG (Datei zu groß) fehl. Die nächste Überprüfung besteht darin, ob der Bereich der zu schreibenden physischen Adressen für diese bestimmte Prozessorarchitektur gültig ist und ein Fehler zu EFAULT (fehlerhafte Adresse) führt.

Als nächstes wird auf Sparc und m68k jeder Teil des Schreibvorgangs auf der ersten physischen Seite stillschweigend übersprungen.

Wir haben jetzt die Hauptschleife erreicht, die die Daten in Blöcken durchläuft, die in eine MMU- Seite passen . /dev/memDer Zugriff auf den physischen Speicher, nicht auf den virtuellen Speicher, aber die Prozessoranweisungen zum Laden und Speichern von Daten im Speicher verwenden virtuelle Adressen. Daher muss der Code so angeordnet werden, dass der physische Speicher an einer virtuellen Adresse zugeordnet wird. Unter Linux ist diese Zuordnung abhängig von der Prozessorarchitektur und der Kernelkonfiguration entweder permanent vorhanden oder muss im laufenden Betrieb vorgenommen werden. das ist die Aufgabe von xlate_dev_mem_ptr(und unxlate_dev_mem_ptrmacht alles rückgängig, was xlate_dev_mem_ptrauch immer tut). Dann copy_from_userliest die Funktion aus dem Puffer, der an den übergeben wurdewriteSystemaufruf und schreibt nur an die virtuelle Adresse, an der der physische Speicher derzeit zugeordnet ist. Der Code gibt normale Speicheranweisungen aus, und was dies bedeutet, hängt von der Hardware ab.

Bevor ich bespreche, dass ein Schreiben an eine physikalische Adresse funktioniert, werde ich eine Überprüfung besprechen, die vor diesem Schreiben erfolgt. Innerhalb der Schleife page_is_allowedblockiert die Funktion den Zugriff auf bestimmte Adressen, wenn die Kernel-Konfigurationsoption CONFIG_STRICT_DEVMEMaktiviert ist (was standardmäßig der Fall ist): Nur die von erlaubten Adressen devmem_is_allowedkönnen erreicht werden /dev/mem, bei anderen schlägt der Schreibvorgang mit EPERM fehl (Vorgang nicht zulässig). In der Beschreibung dieser Option heißt es:

Wenn diese Option aktiviert ist und IO_STRICT_DEVMEM = n, ermöglicht die Datei / dev / mem nur dem Benutzerbereich den Zugriff auf den PCI-Bereich sowie den BIOS-Code und die Datenbereiche. Dies ist ausreichend für Dosemu und X und alle gängigen Benutzer von / dev / mem.

Dies ist eine sehr x86-zentrierte Beschreibung. Generell wird der CONFIG_STRICT_DEVMEMZugriff auf physische Speicheradressen blockiert, die dem RAM zugeordnet sind, der Zugriff auf Adressen, die nicht dem RAM zugeordnet sind, wird jedoch ermöglicht. Die Details, welche Bereiche der physischen Adresse zulässig sind, hängen von der Prozessorarchitektur ab, aber alle schließen den RAM aus, in dem Daten des Kernels und der Benutzerlandprozesse gespeichert sind. Die zusätzliche Option CONFIG_IO_STRICT_DEVMEM(deaktiviert ab Ubuntu 18.04) blockiert den Zugriff auf physische Adressen, die von einem Treiber beansprucht werden.

Physische Speicheradressen, die dem RAM zugeordnet sind . Es gibt also physische Speicheradressen, die nicht dem RAM zugeordnet sind? Ja. Das ist die Diskussion, die ich oben versprochen habe, was es bedeutet, an eine Adresse zu schreiben.

Ein Speicherspeicherbefehl schreibt nicht unbedingt in den RAM. Der Prozessor zerlegt die Adresse und entscheidet, an welches Peripheriegerät der Speicher gesendet werden soll. (Wenn ich "der Prozessor" sage, umfasse ich Peripheriecontroller, die möglicherweise nicht vom selben Hersteller stammen.) RAM ist nur eine dieser Peripheriegeräte. Wie der Versand erfolgt, hängt stark von der Prozessorarchitektur ab, aber die Grundlagen sind auf allen Architekturen mehr oder weniger gleich. Der Prozessor zerlegt im Grunde genommen die höheren Bits der Adresse und schlägt sie in einigen Tabellen nach, die basierend auf fest codierten Informationen, Informationen, die durch Prüfen einiger Busse erhalten werden, und von der Software konfigurierten Informationen gefüllt werden. Es kann viel Caching und Pufferung erforderlich sein, aber kurz gesagt, nach dieser ZerlegungBus und dann ist es an der Peripherie, damit umzugehen. (Oder das Ergebnis der Tabellensuche könnte sein, dass sich an dieser Adresse kein Peripheriegerät befindet. In diesem Fall wechselt der Prozessor in einen Trap-Status, in dem er Code im Kernel ausführt, der normalerweise zu einem SIGBUS für den aufrufenden Prozess führt.)

Ein Speicher für eine Adresse, die dem RAM zugeordnet ist, "überschreibt" nichts anderes als den Wert, der zuvor an dieser Adresse gespeichert wurde, mit dem Versprechen, dass ein späteres Laden an derselben Adresse den zuletzt gespeicherten Wert zurückgibt. Aber selbst RAM hat einige Adressen, die sich nicht so verhalten: Es gibt einige Register , die Dinge wie Bildwiederholfrequenz und Spannung steuern können.

Im Allgemeinen bewirkt ein Lesen oder Schreiben in ein Hardwareregister, wofür die Hardware programmiert ist. Die meisten Zugriffe auf Hardware funktionieren folgendermaßen: Die Software (normalerweise Kernel-Code) greift auf eine bestimmte physikalische Adresse zu, erreicht den Bus, der den Prozessor mit dem Peripheriegerät verbindet, und das Peripheriegerät erledigt seine Aufgabe. Einige Prozessoren (insbesondere x86) verfügen auch über separate CPU-Anweisungen, die Lese- / Schreibvorgänge an Peripheriegeräten verursachen, die sich vom Laden und Speichern des Speichers unterscheiden. Selbst auf x86 werden viele Peripheriegeräte durch Laden / Speichern erreicht.

Der Befehl dd if=/dev/urandom of=/dev/memschreibt zufällige Daten an jedes Peripheriegerät, das an Adresse 0 zugeordnet ist (und an nachfolgende Adressen, solange die Schreibvorgänge erfolgreich sind). In der Praxis erwarte ich, dass auf vielen Architekturen der physischen Adresse 0 kein Peripheriegerät zugeordnet ist oder RAM vorhanden ist und daher der allererste Schreibversuch fehlschlägt. Wenn jedoch ein Peripheriegerät an Adresse 0 zugeordnet ist oder wenn Sie den Befehl so ändern, dass an eine andere Adresse geschrieben wird, wird im Peripheriegerät etwas Unvorhersehbares ausgelöst. Bei zufälligen Daten mit zunehmenden Adressen ist es unwahrscheinlich, dass etwas Interessantes getan wird, aber im Prinzip könnte dies den Computer ausschalten (es gibt wahrscheinlich eine Adresse, die dies tatsächlich tut), einige BIOS-Einstellungen überschreiben, die das Booten unmöglich machen oder sogar einige treffen Buggy-Peripheriegerät in einer Weise, die es beschädigt.

alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'
Gilles 'SO - hör auf böse zu sein'
quelle
Danke! Das habe ich gesucht! Ich war nur verwirrt, ob / dev / mem Speicherzugriff auf Dinge wie Peripheriegeräte und hardwarebezogene Dinge erlaubt!
Coder14
Ein Peripheriegerät kann nicht an der physischen Adresse 0 auf einem x86-PC zugeordnet werden. Diese Konfiguration würde niemals booten.
Joshua
Dies ist nicht wahr
Yvain
1
Natürlich können Sie den Kernel beschädigen, aber nicht das BIOS
Yvain
1
@Yvain Was ist nicht wahr? Und tatsächlich können Sie den Kernel nicht beschädigen, wenn er CONFIG_STRICT_DEVMEMaktiviert ist.
Gilles 'SO - hör auf böse zu sein'
12

Es ist sicher, wenn Sie den Kernel richtig konfiguriert haben (sicher, weil es nicht funktioniert)

Pro Handbuchseite mem (4) :

/ dev / mem ist eine Zeichengerätedatei, die ein Image des Hauptspeichers des Computers darstellt. Es kann zum Beispiel verwendet werden, um das System zu untersuchen (und sogar zu patchen).

Theoretisch dd if=/dev/urandom of=/dev/memsollte also der gesamte Adressraum des von Ihnen installierten physischen Speichers überschrieben werden. Da der Kernel und andere Programme aus dem Speicher ausgeführt werden, sollte das System effektiv abstürzen. In der Praxis gibt es Grenzen. Aus derselben Manpage:

Seit Linux 2.6.26 und abhängig von der Architektur begrenzt die Kernelkonfigurationsoption CONFIG_STRICT_DEVMEM die Bereiche, auf die über diese Datei zugegriffen werden kann.

Der Versuch , diese auf virtuelle Maschine Ubuntu 18.04, es gibt einen Fehler dd: writing to '/dev/mem': Operation not permittedauch mit sudound trotz Berechtigungen für root crw-r-----. Aus dem Ubuntu-Wiki :

/ dev / mem Schutz

Einige Anwendungen (Xorg) benötigen direkten Zugriff auf den physischen Speicher aus dem Benutzerbereich. Die spezielle Datei / dev / mem ist vorhanden, um diesen Zugriff bereitzustellen. In der Vergangenheit war es möglich, den Kernelspeicher dieser Datei anzuzeigen und zu ändern, wenn ein Angreifer Root-Zugriff hatte. Die Kerneloption CONFIG_STRICT_DEVMEM wurde eingeführt, um den Speicherzugriff ohne Gerät zu blockieren (ursprünglich CONFIG_NONPROMISC_DEVMEM genannt).

Technisch gesehen ist es nicht sicher (da es das System zum Absturz bringen würde) und wenn die Kerneloption CONFIG_STRICT_DEVMEMdeaktiviert ist, ist dies eine Sicherheitslücke, aber nach dem, was ich bisher gesehen habe, würde der Befehl nicht ausgeführt, wenn diese Option aktiviert ist. Laut standortübergreifendem Duplikat werden durch einen Neustart alle Probleme behoben, aber natürlich würden die Daten im RAM zu diesem Zeitpunkt verloren gehen und nicht auf die Festplatte übertragen (falls vorhanden).

Es gibt eine empfohlene Methode für das zuvor verknüpfte Duplikat. busybox devmemWenn Sie also entschlossen sind, mit dem RAM herumzuspielen, gibt es möglicherweise doch einen Weg.

Sergiy Kolodyazhnyy
quelle
6
"Es ist sicher" Nein, das ist es mit Sicherheit nicht. Selbst mit CONFIG_STRICT_DEVMEMkönnen Sie auf Speicherbereiche zugreifen, in denen ein Peripheriegerät zugeordnet ist /dev/mem. Wenn Sie zufällige Inhalte an Peripheriegeräte schreiben, kann alles passieren. Sie erhalten die Meldung "Operation nicht zulässig", wenn Sie versuchen, auf eine nicht zugeordnete Adresse zuzugreifen, und der Befehl bei Adresse 0 beginnt. Ob Adresse 0 auf etwas Schlechtes abgebildet wird, hängt von der Hardwarearchitektur ab. Soweit ich weiß, wird es möglicherweise nie auf einem PC zugeordnet, aber im Allgemeinen ist es nicht sicher.
Gilles 'SO - hör auf böse zu sein'
1
@ Gilles Auf x86 (nicht sicher über x86-64) enthält die erste 1 KB RAM (Adressen 0x0 bis 0x3ff) die Interruptvektoren; Adresse im Wert von vier Bytes pro Vektor. Wenn es Ihnen gelingt, solche mit zufälligem Müll zu überschreiben, werden wahrscheinlich alle möglichen interessanten Dinge sehr bald passieren. Höchstwahrscheinlich werden Sie einen doppelten oder dreifachen Fehler haben und das System wird abstürzen, aber es gibt keine Garantien ...
ein CVn
@aCVn Es ist sicherlich etwas zugeordnet ( head -c 1024 </dev/mem | od -tx1), aber ich weiß nicht, ob diese verwendet werden, wenn sich der Prozessor nicht im Real-Modus befindet (8088-Modus). Ich glaube nicht, dass sie im 64-Bit-Modus verwendet werden können: Immerhin haben die 8088-Interrupt-Vektoren nur 32 Bit für die Adresse. Übrigens ist dies mit CONFIG_STRICT_DEVMEMset zugänglich , also denke ich, dass Linux es nicht benutzt.
Gilles 'SO - hör auf böse zu sein'
@ Gilles: Die 0-Seite auf x86 ist für v86, Bootloader usw. reserviert. Das ist die Real-Mode-Interrupt-Vektortabelle dort. Im geschützten Modus befindet sich das IVT an einer anderen Stelle (ein Maschinenregister gibt an, wo).
Joshua