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

Wie greife ich unter Linux auf physische Adressen aus dem Benutzerbereich zu?

Sie können eine Gerätedatei mit mmap(2) einem Benutzerprozessspeicher zuordnen Systemaufruf. Normalerweise sind Gerätedateien Abbildungen des physischen Speichers auf das Dateisystem. Andernfalls müssen Sie ein Kernelmodul schreiben, das eine solche Datei erstellt oder eine Möglichkeit bietet, den benötigten Speicher einem Benutzerprozess zuzuordnen.

Eine andere Möglichkeit besteht darin, Teile von /dev/mem einem Benutzerspeicher zuzuordnen.

Bearbeiten:Beispiel für mmaping /dev/mem (dieses Programm muss Zugriff auf /dev/mem haben, z. B. Root-Rechte haben):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    if (argc < 3) {
        printf("Usage: %s <phys_addr> <offset>\n", argv[0]);
        return 0;
    }

    off_t offset = strtoul(argv[1], NULL, 0);
    size_t len = strtoul(argv[2], NULL, 0);

    // Truncate offset to a multiple of the page size, or mmap will fail.
    size_t pagesize = sysconf(_SC_PAGE_SIZE);
    off_t page_base = (offset / pagesize) * pagesize;
    off_t page_offset = offset - page_base;

    int fd = open("/dev/mem", O_SYNC);
    unsigned char *mem = mmap(NULL, page_offset + len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, page_base);
    if (mem == MAP_FAILED) {
        perror("Can't map memory");
        return -1;
    }

    size_t i;
    for (i = 0; i < len; ++i)
        printf("%02x ", (int)mem[page_offset + i]);

    return 0;
}

busybox devmem

busybox devmem ist ein winziges CLI-Dienstprogramm, das /dev/mem mmmaps .

Sie können es in Ubuntu erhalten mit:sudo apt-get install busybox

Verwendung:4 Bytes von der physikalischen Adresse 0x12345678 lesen :

sudo busybox devmem 0x12345678

Schreiben Sie 0x9abcdef0 an diese Adresse:

sudo busybox devmem 0x12345678 w 0x9abcdef0

Quelle:https://github.com/mirror/busybox/blob/1_27_2/miscutils/devmem.c#L85

mmap MAP_SHARED

Beim Mapping /dev/mem , möchten Sie wahrscheinlich verwenden:

open("/dev/mem", O_RDWR | O_SYNC);
mmap(..., PROT_READ | PROT_WRITE, MAP_SHARED, ...)

MAP_SHARED bewirkt, dass Schreibvorgänge sofort in den physischen Speicher gehen, was die Beobachtung erleichtert und für Hardware-Registerschreibvorgänge sinnvoller ist.

CONFIG_STRICT_DEVMEM und nopat

Um /dev/mem zu verwenden Um den regulären RAM auf Kernel v4.9 anzuzeigen und zu ändern, müssen Sie zuerst:

  • deaktiviere CONFIG_STRICT_DEVMEM (standardmäßig auf Ubuntu 17.04 eingestellt)
  • übergeben Sie den nopat Kernel-Befehlszeilenoption für x86

IO-Ports funktionieren auch ohne diese.

Siehe auch:mmap von /dev/mem schlägt mit ungültigem Argument für virt_to_phys-Adresse fehl, aber Adresse ist seitenausgerichtet

Cache leeren

Wenn Sie versuchen, in den RAM statt in ein Register zu schreiben, wird der Speicher möglicherweise von der CPU zwischengespeichert:Wie wird der CPU-Cache für einen Bereich des Adressraums in Linux geleert? und ich sehe keinen sehr tragbaren/einfachen Weg, um es zu leeren oder die Region als nicht zwischenspeicherbar zu markieren:

  • Wie schreibt man Kernel Space Memory (physische Adresse) mit O_DIRECT in eine Datei?
  • Wie wird der CPU-Cache für eine Region des Adressraums in Linux geleert?
  • Ist es möglich, im Benutzerbereich einen nicht zwischenspeicherbaren Speicherblock unter Linux zuzuweisen?

Also vielleicht /dev/mem kann nicht zuverlässig verwendet werden, um Speicherpuffer an Geräte zu übergeben?

Dies ist in QEMU leider nicht zu beobachten, da QEMU keine Caches simuliert.

So testen Sie es

Nun zum lustigen Teil. Hier sind ein paar coole Setups:

  • Userland-Speicher
    • weisen Sie volatile zu Variable in einem Userland-Prozess
    • erhalten Sie die physische Adresse mit /proc/<pid>/maps + /proc/<pid>/pagemap
    • Ändern Sie den Wert an der physikalischen Adresse mit devmem , und beobachten Sie, wie der Userland-Prozess reagiert
  • Kernelland-Speicher
    • Kernelspeicher mit kmalloc zuweisen
    • erhalten Sie die physische Adresse mit virt_to_phys und an Userland zurückgeben
    • ändern Sie die physikalische Adresse mit devmem
    • den Wert vom Kernelmodul abfragen
  • IO mem und virtuelles QEMU-Plattformgerät
    • Erstellen Sie ein Plattformgerät mit bekannten physischen Registeradressen
    • benutze devmem in das Register schreiben
    • schau dir printf an s kommen vom virtuellen Gerät als Antwort

Bonus:Ermitteln Sie die physische Adresse für eine virtuelle Adresse

Gibt es eine API zum Ermitteln der physischen Adresse aus der virtuellen Adresse in Linux?


Linux
  1. So fügen Sie einen Benutzer zu einer Gruppe in Linux hinzu oder entfernen ihn

  2. Linux – Wie melde ich mich von Ssh aus bei Tty an?

  3. So entfernen Sie Benutzer aus der Gruppe in Linux [Kurztipp]

  4. So stellen Sie die IP-Adresse von C in Linux ein

  5. Wie kann man einen Linux-Kernel-Puffer dem Benutzerbereich zuordnen?

So gewähren oder verweigern Sie einem bestimmten Benutzer oder einer bestimmten Gruppe in Linux den SSH-Zugriff

So extrahieren Sie E-Mail-Adressen aus einer Textdatei unter Linux

So beschränken Sie den SSH-Zugriff auf bestimmte Benutzer in Linux

So ändern Sie den Benutzer unter Linux

So ändern Sie die IP-Adresse unter Linux

Linux – Wie wird ein virtueller 64-Bit-Prozess-Adressraum in Linux aufgeteilt?