2008-08-14 14 views
16

Ich habe versucht zu verstehen, wie man die Erinnerung an andere Prozesse auf Mac OS X liest, aber ich habe nicht viel Glück. Ich habe viele Beispiele online gesehen unter Verwendung ptrace mit PEEKDATA und so, jedoch hat es diese Option auf BSD [man ptrace] nicht.Lesen anderer Prozess 'Speicher in OS X?

int pid = fork(); 
if (pid > 0) { 
    // mess around with child-process's memory 
} 

Wie ist es möglich, zu lesen und in den Speicher eines anderen Prozesses auf Mac OS X schreiben?

+1

Ich interessiere mich besonders für den Fall, in dem ich den anderen Prozess nicht kontrolliere - d. H. Herumstochern in jemand anderen Programm, um zu sehen, was es macht. (Vermutlich nach [ASLR deaktivieren] (http://stackoverflow.com/questions/6325537/disabling-aslr-in-mac-os-x-snow-leopard).) –

+0

Ich verstehe nicht, welchen Teil des Prozesses Sie möchte lesen. Haben Sie den Adressraum für den Wandprozess wie in den Core-Dump-Dateien? Sie benötigen Code, um Threads und (manchmal) gemeinsam genutzte Bibliotheken zu bearbeiten. Sie brauchen (meistens) diesen Code nicht, wenn er zum Beispiel nur das Programm binary in ram sucht. – user2284570

+0

@ user2284570 Ich interessiere mich dafür, den Arbeitsgedächtnis eines Prozesses zu beobachten oder zu manipulieren, nicht den ausführbaren Code. –

Antwort

9

Matasano Chargen hatte eine gute Zeit zurück, einige Debugging-Codes nach OS X zu portieren, darunter das Erlernen, wie man Speicher in einem anderen Prozess lesen und schreiben kann (unter anderem).

It has to work, otherwise GDB wouldn't:

Es stellt sich heraus, Apfel, in ihrer unendlichen Weisheit, hatte ptrace() entkernt. Die OS X-man-Seite listet den folgenden Request-Codes:

  • PT_ATTACH - ein Verfahren zur Auswahl
  • PT_DENY_ATTACH zu debuggen - so Prozesse selbst von
    ausgetestet stoppen wird [...]

Keine Erwähnung von Lesen oder Schreiben von Speicher oder Registern. Was wäre entmutigend gewesen, wenn die man-Seite nicht auch PT_GETREGS, PT_SETREGS, PT_GETFPREGS und PT_SETFPREGS im Abschnitt Fehlercodes erwähnt hätte. Also, ich habe ptrace.h überprüft. Dort fand ich:

  • PT_READ_I - zu lesen Datenwörter
  • PT_READ_U - - zu lesen U-Bereich Daten, wenn Sie alt genug sind, sich daran zu erinnern, was die U-Bereich ist
    Befehlsworte
  • PT_READ_D zu lesen [...]

Es ist ein Problem gelöst. Ich kann Speicher für Breakpoints lesen und schreiben. Aber ich kann immer noch keinen Zugang zu Registern bekommen, und ich muss in der Lage sein, mich mit EIP zu messen.

0

Das Gedächtnis eines Prozesses hinter seinem Rücken zu manipulieren ist ein schlechtes Ding und ist voller Gefahr. Aus diesem Grund hat Mac OS X (wie jedes andere Unix-System) Speicher geschützt und Prozesse voneinander isoliert.

Natürlich kann es gemacht werden: Es gibt Einrichtungen für den gemeinsamen Speicher zwischen Prozessen, die explizit kooperieren. Es gibt auch Möglichkeiten, die Adressräume anderer Prozesse zu manipulieren, solange der Prozess das explizite Recht dazu hat (wie vom Sicherheitsframework gewährt). Aber das ist es für Leute, die Debugging-Tools schreiben zu verwenden. Es ist nicht etwas, das für die überwiegende Mehrheit der Entwicklung unter Mac OS X ein normales - oder sogar selten - Ereignis sein sollte.

+0

Ich denke, dass Sie eine Menge von 'bitte nehmen Sie Platz .. "Witze schreiben, oder? : P – horseyguy

11

Verwenden Sie task_for_pid() oder andere Methoden, um den Task-Port des Zielprozesses zu erhalten. Danach können Sie den Adressraum des Prozesses direkt bearbeiten, indem Sie vm_read(), vm_write() und andere verwenden.

+0

Es gibt auch 'vm_remap ', mit dem Sie einen fremden Prozessspeicher in Ihre eigene VM mappen können. –

+0

nach dem Erhalten des Prozesses 'Task-Port, wie bekomme ich seinen Adressraum? und wie suche ich weiter im Adressraum nach einer bestimmten Zeichenkette? Kannst du ein Beispiel geben? – snakeninny

5

Wenn Sie in der Lage sind, Speicherbereiche zwischen Prozessen zu teilen, sollten Sie shm_open (2) und mmap (2) ausprobieren. Es ist ziemlich einfach, einen Teil des Speichers in einem Prozess zuzuweisen und den Pfad (für shm_open) an einen anderen zu übergeben, und beide können dann gemeinsam verrückt werden. Dies ist viel sicherer, als im Adressraum eines anderen Prozesses herumzustochern, wie Chris Hanson erwähnt. Natürlich, wenn Sie beide Prozesse nicht kontrollieren können, wird Ihnen das nicht viel nützen.

(Beachten Sie, dass der maximale Weglänge für shm_open erscheint 26 Bytes zu sein, obwohl dies nicht überall dokumentiert zu sein scheint.)

// Create shared memory block 
void* sharedMemory = NULL; 
size_t shmemSize = 123456; 
const char* shmName = "mySharedMemPath";   
int shFD = shm_open(shmName, (O_CREAT | O_EXCL | O_RDWR), 0600); 
if (shFD >= 0) { 
    if (ftruncate(shFD, shmemSize) == 0) { 
     sharedMemory = mmap(NULL, shmemSize, (PROT_READ | PROT_WRITE), MAP_SHARED, shFD, 0); 
     if (sharedMemory != MAP_FAILED) { 
      // Initialize shared memory if needed 
      // Send 'shmemSize' & 'shmemSize' to other process(es) 
     } else handle error 
    } else handle error 
    close(shFD);  // Note: sharedMemory still valid until munmap() called 
} else handle error 

... 
Do stuff with shared memory 
... 

// Tear down shared memory 
if (sharedMemory != NULL) munmap(sharedMemory, shmemSize); 
if (shFD >= 0) shm_unlink(shmName); 





// Get the shared memory block from another process 
void* sharedMemory = NULL; 
size_t shmemSize = 123456;    // Or fetched via some other form of IPC 
const char* shmName = "mySharedMemPath";// Or fetched via some other form of IPC 
int shFD = shm_open(shmName, (O_RDONLY), 0600); // Can be R/W if you want 
if (shFD >= 0) { 
    data = mmap(NULL, shmemSize, PROT_READ, MAP_SHARED, shFD, 0); 
    if (data != MAP_FAILED) { 
     // Check shared memory for validity 
    } else handle error 
    close(shFD);  // Note: sharedMemory still valid until munmap() called 
} else handle error 


... 
Do stuff with shared memory 
... 

// Tear down shared memory 
if (sharedMemory != NULL) munmap(sharedMemory, shmemSize); 
// Only the creator should shm_unlink() 
+3

Es gibt mehrere Einschränkungen für die Verwendung von shm_open; Zusätzlich zu dem erwähnten Problem mit der Pfadlänge wird MacOSX mit einer Kernel-Statuseinstellung ausgeliefert, die die Größe des gemeinsamen Speichers eines Prozesses auf 4 MB beschränkt. Sie können diese Einstellung sehen, indem Sie in der Befehlszeile 'sysctl -A' ausführen und nach 'kern.sysv.shmmax' suchen. – fixermark

+0

nicht genau, scheint, dass die ~ 4MB Grenze nur die System V IPC ftok/shmget/shmat Funktionen betroffen ist, wenn Sie die POSIX shm_open/ftruncate/mmap Lösung verwenden (oben erwähnt) das Limit kann sogar etwa 16 MB sein (!) (abhängig vom Kernel wahrscheinlich) wir verwenden 16MB Blöcke auf OSX 10.5-10.9 (früher sogar auf 10.4) ohne Probleme. – Hofi

1

Im Allgemeinen würde ich empfehlen, dass Sie offen regelmäßig verwenden() um eine temporäre Datei zu öffnen. Sobald es in beiden Prozessen geöffnet ist, können Sie es vom Dateisystem trennen() und Sie werden so eingerichtet, als ob Sie shm_open verwendet hätten. Das Verfahren ist dem von Scott Marcy für shm_open angegebenen sehr ähnlich.

Der Nachteil dieses Ansatzes ist, dass wenn der Prozess, der die unlink() abstürzen wird, Sie mit einer unbenutzten Datei enden und kein Prozess die Aufgabe hat, ihn zu bereinigen. Dieser Nachteil wird mit shm_open geteilt, da, wenn nichts einen Namen mit shm_unlinks verknüpft, der Name im shared memory space verbleibt und von zukünftigen Prozessen geöffnet werden kann.

1

Sie möchten Inter-Process-Kommunikation mit der Shared-Memory-Methode durchführen. siehe Eine Zusammenfassung der anderen commons Methode, here

Es dauerte nicht lange mich zu finden, was Sie in diesen book müssen die alle APIs enthalten, die für alle UNIX-Varianten gemeinsam sind heute (was viel mehr, als ich dachte). Sie sollten es in Zukunft kaufen. Dieses Buch besteht aus mehreren hundert gedruckten Manpages, die selten auf modernen Maschinen installiert werden. Jede Manpage enthält eine C-Funktion.

Es dauerte nicht lange shmat zu finden()shmctl(); shmdt() und shmget() darin. Ich habe nicht lange gesucht, vielleicht gibt es noch mehr.

Es sah ein bisschen veraltet aus, aber: JA, die Base User-Space API von modernen UNIX OS zurück zu den alten 80er.

Update: Die meisten im Buch beschriebenen Funktionen sind Teil der POSIX C-Header, Sie müssen nichts installieren. Es gibt wenige Ausnahmen, wie bei "curses", der ursprünglichen Bibliothek.

+0

@JeremyBanks Ich muss eine andere Antwort mit Ihrem Kommentar schreiben, aber ich habe ein paar Fragen: Wissen Sie, in was bestehen virtuelle Adressierung von der Benutzerprozesspunkt von Vue (Anmerkung: Wikipedia geben keine wirklichen Erklärungen dazu)? Was ist die Prozessisolation und wie geht es mit IPC um? Es ist ein Basisdienst des Betriebssystems, um * Speicherraumisolierung * zu geben: Stellen Sie sich vor, ein laufender Prozess ohne Administratorrechte könnte unverschlüsselte Passwörter in einem anderen Prozess lesen. Einen Treiber in [ring0] starten (https://en.wikipedia.org/ wiki/Ring_ (computer_security) war das Ziel der Piraten, dies zu erreichen. – user2284570

+0

@ JeremyBanks: Es gibt etwas, was ich vergessen habe: Ja, du könntest es/dev/mem und/dev/kmem, aber beginnend mit der x86-Version von Mac OS X entfernt Apple diese Geräte aus vielen Gründen einschließlich der Sicherheit. Linux hat etwas Ähnliches mit einer config Kompilierzeit Option, die meisten Linux-Ditros aktiviert: es deaktiviert den vollen Zugriff von/dev/mem (auch für root) und beschränkt es nur auf die Adressen Programme (wie Xorg) verwendet. – user2284570

+0

Ich weiß nicht genug über virtuellen Speicher, um die Details zu wissen, wie dies in einem modernen Betriebssystem funktioniert, aber ich verstehe, dass dies die Speicherisolierung verletzt und wenn möglich Administratorrechte erfordern würde. Ich zeichnete den einfachsten Fall von, sagen wir, Modifizieren eines 'static int' in einem C-Programm, das (vielleicht?) Würde dem gleichen Speicherort zugeordnet werden, oder die in irgendeiner Weise gefunden werden könnte. Ich stellte mir vor, dass so manche Spiel-Bots, die in den Zustand des Spiels schauen, funktionieren könnten. Ich war mir nicht ganz sicher, ob es möglich war. –

2

Ich habe definitiv eine kurze Implementierung von was Sie brauchen gefunden (nur eine Quelldatei (main.c)). Es ist speziell für XNU entwickelt.

Es ist in der Top-Ten-Ergebnis der Google-Suche mit den folgenden Suchbegriffen «Umspeicherungsprozesses Speicher os x»

Der Quellcode ist here

aber von einem strengen Punkt des virtuellen Adressraums point de vue , sollten Sie mehr interessiert mit dieser Frage: OS X: Generate core dump without bringing down the process? (siehe auch this)

Wenn Sie an gcore Quellcode schauen, ist es ziemlich kompliziert ist, dies zu tun, da Sie mit Stufen und ihren Zustand behandeln müssen ...

Bei den meisten Linux-Distributionen ist das gcore-Programm jetzt Teil des GDB-Pakets. Ich denke, die OSX-Version wird mit xcode/den Entwicklungstools installiert.

UPDATE: wxHexEditor ist ein Editor, der Geräte bearbeiten kann. IT KANN den Prozessspeicher genauso bearbeiten wie für normale Dateien. Es funktioniert auf allen UNIX-Rechnern.

+0

Interesse Zeug, ich guck mal. Vielen Dank. –

4

Ich weiß, dass dieser Thread 100 Jahre alt, aber für die Leute hier von einer Suchmaschine kommen:

xnumem tut genau das, was Sie suchen, manipulieren und Inter-Prozess-Speicher gelesen.

// Create new xnu_proc instance 
xnu_proc *Process = new xnu_proc(); 

// Attach to pid (or process name) 
Process->Attach(getpid()); 

// Manipulate memory 
int i = 1337, i2 = 0; 
i2 = process->memory().Read<int>((uintptr_t)&i); 

// Detach from process 
Process->Detach(); 
+0

Dieser Link ist ein 404. Ich denke, dass es nach https://github.com/gordio/xnumem verschoben wurde –