Die Isolierung von Prozessadressräumen ist ein bemerkenswertes Merkmal moderner Betriebssysteme. Auch dies ist eine Besonderheit, die es von „alten“ Betriebssystemen unterscheidet. Die Isolierung des Prozessadressraums bedeutet, dass Prozess P1 nicht beliebig auf den Speicher von Prozess P2 zugreifen kann, sofern der Speicher nicht als gemeinsam genutzt deklariert ist. Das ist ganz einfach zu verstehen. Ich gebe Ihnen ein Beispiel. Wir wissen, dass es in der Gesellschaft primitiver Wilder kein Familienkonzept gibt. Alle Ressourcen werden innerhalb des Stammes geteilt, und jeder Wilde kann jederzeit und auf jede Art mit jedem anderen Wilden interagieren. Dies ist bei Betriebssystemen wie DOS der Fall, bei denen der Speicheradressraum nicht isoliert ist. Prozesse können frei auf den Speicher anderer Prozesse zugreifen. Später, mit der Entstehung des Familienkonzepts, wurden die Familienressourcen isoliert und die Menschen konnten nicht mehr in die Häuser anderer Leute einbrechen. Man konnte nicht mehr in die Häuser anderer Leute eindringen und deren Sachen auf einfache Art und Weise mitnehmen, es sei denn, der Eigentümer erlaubte es. Nachdem das Betriebssystem in den modernen Modus gewechselt war, verfügte der Prozess auch über ein familienähnliches Konzept. Doch das Konzept der Familie ist virtuell; die Menschen halten sich lediglich an die Vereinbarungen und zerstören nicht die Familien anderer Leute. Das Haus fungiert als physische Infrastruktur, die die Familie schützt. In einem Betriebssystem entspricht das Home dem virtuellen Adressraum und das Haus der Seitentabelle. Nachbarn können nicht in Ihr Haus einbrechen, die Polizei hingegen schon. Aus triftigen Gründen können dies auch Regierungsbeamte tun. Die sogenannten privilegierten Verwaltungsbehörden können die Häuser gewöhnlicher Menschen betreten und den Besitz der Familie anrühren, sofern sie dafür ausreichende Gründe haben. Bei einem Betriebssystem ist dies die Aufgabe des Kernels, und der Kernel kann auf den Adressraum jedes Prozesses zugreifen. Natürlich wird der Kernel nicht ohne Grund in die Häuser anderer Leute einbrechen, genauso wie die Polizei nicht ohne Grund in die Häuser anderer Leute einbrechen wird. Sie können den Kernel jedoch dazu veranlassen, dies absichtlich zu tun, um etwas Unrechtes zu tun. Probieren wir es aus und schauen uns zunächst ein Programm an: //test.c // gcc test.c -o test #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/mman.h> int main() { char* Adresse = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); strcpy(Adresse, "Zhejiang Wenzhou Pixie Shi"); printf("Adresse: %lu pid:%d\n", Adresse, getpid()); printf("vorher:%s \n", Adresse); getchar(); printf("nach:%s\n", Adresse); gebe 0 zurück; } Die Ausgabe dieses Programms ist sehr einfach. Sowohl davor als auch danach wird „Zhejiang wenzhou pixie shi“ ausgegeben. Aber wir möchten diesen Satz ändern. Was sollen wir tun? Wenn der Testprozess die Änderungen nicht selbst vornimmt, können wir natürlich nichts tun. Aber wir können den Kernel zwingen, Änderungen vorzunehmen, als würden wir in ein Privathaus einbrechen. Als nächstes schreibe ich ein Kernelmodul: //test.c // make -C /lib/modules/`uname -r`/build SUBDIRS=`pwd` Module #include <linux/mm.h> #include <linux/sched.h> #include <linux/module.h> statische int pid = 1; module_param(pid, int, 0644); statische vorzeichenlose lange Adresse = 0; module_param(Adresse, lang, 0644); // Das Finden der Seitentabelle eines Prozesses basierend auf seiner virtuellen Adresse ist gleichbedeutend damit, die Adresse des Hauses der Familie zu finden und dann einzubrechen! statisches pte_t* get_pte(Struktur task_struct *task, vorzeichenlose lange Adresse) { pgd_t* pgd; pud_t* pud; pmd_t* pmd; pte_t* pte; Struktur mm_Struktur *mm = Aufgabe->mm; pgd = pgd_offset(mm, Adresse); wenn(pgd_none(*pgd) || pgd_bad(*pgd)) gibt NULL zurück; pud = pud_offset(pgd, Adresse); wenn(pud_none(*pud) || pud_bad(*pud)) gibt NULL zurück; pmd = pmd_offset(pud, Adresse); wenn(pmd_none(*pmd) || pmd_bad(*pmd)) gibt NULL zurück; pte = pte_offset_kernel(pmd, Adresse); wenn (pte_none(*pte)) gibt NULL zurück; Rückkehr pte; } statische int test_init(void) { Struktur task_struct *task; pte_t* pte; Strukturseite*Seite; // Diese Familie suchen task = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID); // Finden Sie heraus, wo diese Familie lebt, wenn (! (pte = get_pte (task, addr))) Rückgabe -1; Seite = pte_Seite(*pte); // Mit Gewalt einbrechen addr = page_address(page); //sdajgdoiewhgikwnsviwgvwgvw strcpy(addr, (char *)"Regenflutungswasser wird nicht dick!"); // Nachdem die Arbeit erledigt ist, gehen Sie und verbergen Sie Ihre Erfolge und Ihren Ruhm. return 0; } statischer void test_exit(void) { } modul_init(test_init); modul_exit(test_exit); MODULE_LICENSE("GPL"); Komm, lass es uns versuchen: [root@10 Seitenersetzung]# ./test Adresse: 140338535763968 PID: 9912 vorher:Zhejiang Wenzhou Pixie Shi An dieser Stelle laden wir das Kernelmodul test.ko [root@10 test]# insmod test.ko pid=9912 addr=140338535763968 [root@10-Test] Drücken Sie im Testvorgang die Eingabetaste: [root@10 Seitenersetzung]# ./test Adresse: 140338535763968 PID: 9912 vorher:Zhejiang Wenzhou Pixie Shi nachher: Regen, Hochwasser wird nicht fett! [root@10 Seite_ersetzen] Offenbar wurde die Aussage „In Wenzhou, Zhejiang werden Ihre Lederschuhe nass“ in „Wenn es regnet und Sie durchnässt werden, werden Sie nicht dick“ geändert. Schauen Sie sich die Funktion get_pte des obigen Kernelmoduls genau an. Um diese Funktion richtig schreiben zu können, müssen Sie ein gewisses Verständnis der MMU der Maschine haben, auf der sich der Prozess befindet, den Sie zerstören möchten, z. B. ob es sich um ein 32-Bit-System oder ein 64-Bit-System handelt und ob es sich um eine 3-stufige, 4-stufige oder 5-stufige Seitentabelle handelt. Das… Der Spaß an Linux liegt darin, dass Sie es selbst erledigen oder es von jemand anderem erledigen lassen können. Beispielsweise kann die durch den Seitentabelleneintrag der virtuellen Adresse eines Prozesses angegebene physische Seite direkt abgerufen werden. Gibt es eine solche API? Ja, vergessen Sie nicht, dass alles eine Datei ist. Im Proc-Dateisystem gibt es eine solche Datei: Wenn wir diese Datei lesen, erhalten wir den Seitentabelleneintrag der virtuellen Adresse des Prozesses. Die folgende Abbildung stammt aus dem Kernel-Dokument: Der virtuelle Adressraum gilt pro Prozess, während der physische Adressraum von allen Prozessen gemeinsam genutzt wird. Mit anderen Worten: Physische Adressen sind global. Schreiben Sie nun gemäß der Erklärung in Documentation/vm/pagemap.txt ein Programm, um die globale physikalische Adresse einer beliebigen virtuellen Adresse eines beliebigen Prozesses abzurufen: // getphys.c // gcc getphys -o getphys #include <fcntl.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { int fd; int pid; unsignierter langer Pte; vorzeichenlose lange Adresse; vorzeichenlose lange phy_addr; char procbuf[64] = {0}; pid = atoi(argv[1]); Adresse = atol(argv[2]); sprintf(procbuf, "/proc/%d/pagemap", pid); fd = öffnen(procbuf, O_RDONLY); size_t Offset = (Adresse/4096) * Größe von (unsigned long); lseek(fd, Offset, SEEK_SET); lesen(fd, &pte, sizeof(unsigned long)); phy_addr = (pte & ((((unsigned long)1) << 55) - 1))*4096 + addr%4096; printf("phy Adresse:%lu\n", phy_addr); gebe 0 zurück; } Dann ändern wir das Kernelmodul: #include <linux/module.h> statische vorzeichenlose lange Adresse = 0; module_param(Adresse, lang, 0644); statische int test_init(void) { strcpy(phys_to_virt(addr), (char *)"Regenflutwasser wird nicht dick!"); gebe 0 zurück; } statischer void test_exit(void) { } modul_init(test_init); modul_exit(test_exit); MODULE_LICENSE("GPL"); Führen Sie zuerst „test“ aus, verwenden Sie dann die Ausgabe von „test“ als Eingabe für „getphys“ und anschließend die Ausgabe von „getphys“ als Eingabe für das Kernelmodul „test.ko“. Fertig. Erinnerst du dich? Ist das nicht der Stil der Weiterleitung mehrerer Programme? Geben Sie eine physische Adresse ein und ändern Sie diese, das ist alles. Der Vorgang des Abrufens der Seitentabelle über die virtuelle Adresse wurde durch das Lesen und Analysieren der Pagemap-Datei im Benutzermodus ersetzt. Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird. Das könnte Sie auch interessieren:
|
<<: Vue implementiert eine Online-Vorschau von PDF-Dateien (mithilfe von pdf.js/iframe/embed)
>>: Tutorial zur MySQL-Datensicherungsmethode mit Multi-Master und One-Slave
BinLog BinLog ist ein Binärprotokoll, das alle Än...
Im Folgenden habe ich einige grundlegende SQL-Ken...
Konzept MMM (Master-Master-Replikationsmanager fü...
Inhaltsverzeichnis 1. Ist setState synchron? asyn...
Einfügen von Daten in Tabellennamen (Spaltenname ...
Methode 1: Verwenden Sie den Befehl SET PASSWORD ...
Ich bin heute auf ein seltsames Netzwerkproblem g...
Pseudo-Arrays und Arrays In JavaScript sind mit A...
Vorwort Die bei der persönlichen tatsächlichen En...
Inhaltsverzeichnis Vorwort Warum Wie viel kostet ...
Inhaltsverzeichnis Hintergrund LIMIT-Optimierung ...
Im vorherigen Artikel haben wir erklärt, wie ngin...
1. HBase-Übersicht 1.1 Was ist HBase? HBase ist e...
Docker-Download-Adresse: http://get.daocloud.io/#...
1.MySQL-Version [root@clq-System]# mysql -v Willk...