macOS IPC - Inter Process Communication
Last updated
Last updated
Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Lerne & übe GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Mach verwendet Tasks als die kleinste Einheit zum Teilen von Ressourcen, und jeder Task kann mehrere Threads enthalten. Diese Tasks und Threads sind 1:1 auf POSIX-Prozesse und -Threads abgebildet.
Die Kommunikation zwischen Tasks erfolgt über Mach Inter-Process Communication (IPC) und nutzt einseitige Kommunikationskanäle. Nachrichten werden zwischen Ports übertragen, die eine Art Nachrichtenwarteschlangen sind, die vom Kernel verwaltet werden.
Ein Port ist das grundlegende Element von Mach IPC. Er kann verwendet werden, um Nachrichten zu senden und zu empfangen.
Jeder Prozess hat eine IPC-Tabelle, in der die Mach-Ports des Prozesses zu finden sind. Der Name eines Mach-Ports ist tatsächlich eine Nummer (ein Zeiger auf das Kernel-Objekt).
Ein Prozess kann auch einen Portnamen mit bestimmten Rechten an einen anderen Task senden, und der Kernel wird diesen Eintrag in der IPC-Tabelle des anderen Tasks erscheinen lassen.
Portrechte, die definieren, welche Operationen ein Task ausführen kann, sind entscheidend für diese Kommunikation. Die möglichen Portrechte sind (Definitionen hier):
Empfangsrecht, das das Empfangen von Nachrichten, die an den Port gesendet werden, erlaubt. Mach-Ports sind MPSC (multiple-producer, single-consumer) Warteschlangen, was bedeutet, dass es im gesamten System nur ein Empfangsrecht für jeden Port geben kann (im Gegensatz zu Pipes, bei denen mehrere Prozesse alle Dateideskriptoren zum Leseende einer Pipe halten können).
Ein Task mit dem Empfangsrecht kann Nachrichten empfangen und Sende-Rechte erstellen, die es ihm ermöglichen, Nachrichten zu senden. Ursprünglich hat nur der eigene Task das Empfangsrecht über seinen Port.
Wenn der Besitzer des Empfangsrechts stirbt oder es tötet, wird das Sende-Recht nutzlos (toter Name).
Sende-Recht, das das Senden von Nachrichten an den Port erlaubt.
Das Sende-Recht kann kloniert werden, sodass ein Task, der ein Sende-Recht besitzt, das Recht klonen und einem dritten Task gewähren kann.
Beachte, dass Portrechte auch durch Mach-Nachrichten übertragen werden können.
Send-once-Recht, das das Senden einer Nachricht an den Port erlaubt und dann verschwindet.
Dieses Recht kann nicht kloniert werden, aber es kann verschoben werden.
Port-Set-Recht, das ein Port-Set anstelle eines einzelnen Ports bezeichnet. Das Entnehmen einer Nachricht aus einem Port-Set entnimmt eine Nachricht aus einem der enthaltenen Ports. Port-Sets können verwendet werden, um gleichzeitig auf mehreren Ports zu hören, ähnlich wie select
/poll
/epoll
/kqueue
in Unix.
Toter Name, der kein tatsächliches Portrecht ist, sondern lediglich ein Platzhalter. Wenn ein Port zerstört wird, verwandeln sich alle bestehenden Portrechte für den Port in tote Namen.
Tasks können SEND-Rechte an andere übertragen, wodurch sie in der Lage sind, Nachrichten zurückzusenden. SEND-Rechte können auch geklont werden, sodass ein Task das Recht duplizieren und einem dritten Task geben kann. Dies, kombiniert mit einem Zwischenprozess, der als Bootstrap-Server bekannt ist, ermöglicht eine effektive Kommunikation zwischen Tasks.
Datei-Ports ermöglichen es, Dateideskriptoren in Mach-Ports zu kapseln (unter Verwendung von Mach-Port-Rechten). Es ist möglich, einen fileport
aus einem gegebenen FD mit fileport_makeport
zu erstellen und einen FD aus einem fileport mit fileport_makefd
zu erstellen.
Wie bereits erwähnt, ist es möglich, Rechte mit Mach-Nachrichten zu senden, jedoch kannst du kein Recht senden, ohne bereits ein Recht zu haben, um eine Mach-Nachricht zu senden. Wie wird also die erste Kommunikation hergestellt?
Dafür ist der Bootstrap-Server (launchd in macOS) beteiligt, da jeder ein SEND-Recht zum Bootstrap-Server erhalten kann, ist es möglich, ihn um ein Recht zu bitten, um eine Nachricht an einen anderen Prozess zu senden:
Task A erstellt einen neuen Port und erhält das EMPFAHRSRECHT dafür.
Task A, als Inhaber des EMPFAHRSRECHTS, generiert ein SEND-Recht für den Port.
Task A stellt eine Verbindung mit dem Bootstrap-Server her und sendet ihm das SEND-Recht für den Port, den es zu Beginn generiert hat.
Denk daran, dass jeder ein SEND-Recht zum Bootstrap-Server erhalten kann.
Task A sendet eine bootstrap_register
-Nachricht an den Bootstrap-Server, um den gegebenen Port mit einem Namen wie com.apple.taska
zu verknüpfen.
Task B interagiert mit dem Bootstrap-Server, um eine Bootstrap-Suche nach dem Dienstnamen (bootstrap_lookup
) durchzuführen. Damit der Bootstrap-Server antworten kann, sendet Task B ihm ein SEND-Recht zu einem Port, den es zuvor erstellt hat, innerhalb der Suchnachricht. Wenn die Suche erfolgreich ist, dupliziert der Server das SEND-Recht, das von Task A empfangen wurde, und überträgt es an Task B.
Denk daran, dass jeder ein SEND-Recht zum Bootstrap-Server erhalten kann.
Mit diesem SEND-Recht ist Task B in der Lage, eine Nachricht an Task A zu senden.
Für eine bidirektionale Kommunikation generiert normalerweise Task B einen neuen Port mit einem EMPFAHRSRECHT und einem SEND-RECHT und gibt das SEND-Recht an Task A, damit es Nachrichten an TASK B senden kann (bidirektionale Kommunikation).
Der Bootstrap-Server kann den Dienstnamen, der von einem Task beansprucht wird, nicht authentifizieren. Das bedeutet, dass ein Task potenziell jede Systemaufgabe impersonieren könnte, indem er fälschlicherweise einen Autorisierungsdienstnamen beansprucht und dann jede Anfrage genehmigt.
Dann speichert Apple die Namen der systemeigenen Dienste in sicheren Konfigurationsdateien, die sich in SIP-geschützten Verzeichnissen befinden: /System/Library/LaunchDaemons
und /System/Library/LaunchAgents
. Neben jedem Dienstnamen wird auch die assoziierte Binärdatei gespeichert. Der Bootstrap-Server wird ein EMPFAHRSRECHT für jeden dieser Dienstnamen erstellen und halten.
Für diese vordefinierten Dienste unterscheidet sich der Suchprozess leicht. Wenn ein Dienstname gesucht wird, startet launchd den Dienst dynamisch. Der neue Workflow ist wie folgt:
Task B initiiert eine Bootstrap-Suche nach einem Dienstnamen.
launchd überprüft, ob der Task läuft, und wenn nicht, startet er ihn.
Task A (der Dienst) führt eine Bootstrap-Check-in (bootstrap_check_in()
) durch. Hier erstellt der **Bootstrap-**Server ein SEND-Recht, behält es und überträgt das EMPFAHRSRECHT an Task A.
launchd dupliziert das SEND-Recht und sendet es an Task B.
Task B generiert einen neuen Port mit einem EMPFAHRSRECHT und einem SEND-RECHT und gibt das SEND-Recht an Task A (den Dienst) weiter, damit er Nachrichten an TASK B senden kann (bidirektionale Kommunikation).
Dieser Prozess gilt jedoch nur für vordefinierte Systemaufgaben. Nicht-Systemaufgaben funktionieren weiterhin wie ursprünglich beschrieben, was potenziell eine Impersonation ermöglichen könnte.
Daher sollte launchd niemals abstürzen, sonst stürzt das gesamte System ab.
Hier mehr Informationen finden
Die Funktion mach_msg
, die im Wesentlichen ein Systemaufruf ist, wird verwendet, um Mach-Nachrichten zu senden und zu empfangen. Die Funktion erfordert, dass die zu sendende Nachricht als erstes Argument übergeben wird. Diese Nachricht muss mit einer mach_msg_header_t
-Struktur beginnen, gefolgt vom eigentlichen Nachrichteninhalt. Die Struktur ist wie folgt definiert:
Prozesse, die über ein receive right verfügen, können Nachrichten über einen Mach-Port empfangen. Umgekehrt wird den Sendenden ein send oder ein send-once right gewährt. Das send-once right ist ausschließlich zum Senden einer einzelnen Nachricht gedacht, nach der es ungültig wird.
Das anfängliche Feld msgh_bits
ist ein Bitmap:
Das erste Bit (am signifikantesten) wird verwendet, um anzuzeigen, dass eine Nachricht komplex ist (mehr dazu unten)
Das 3. und 4. Bit werden vom Kernel verwendet
Die 5 am wenigsten signifikanten Bits des 2. Bytes können für voucher verwendet werden: ein anderer Typ von Port, um Schlüssel/Wert-Kombinationen zu senden.
Die 5 am wenigsten signifikanten Bits des 3. Bytes können für local port verwendet werden
Die 5 am wenigsten signifikanten Bits des 4. Bytes können für remote port verwendet werden
Die Typen, die im Voucher, lokalen und entfernten Ports angegeben werden können, sind (aus mach/message.h):
For example, MACH_MSG_TYPE_MAKE_SEND_ONCE
kann verwendet werden, um anzuzeigen, dass ein send-once Recht für diesen Port abgeleitet und übertragen werden sollte. Es kann auch MACH_PORT_NULL
angegeben werden, um zu verhindern, dass der Empfänger antworten kann.
Um eine einfache zweiseitige Kommunikation zu erreichen, kann ein Prozess einen mach port im mach Nachrichtenkopf angeben, der als Antwortport (msgh_local_port
) bezeichnet wird, wo der Empfänger der Nachricht eine Antwort auf diese Nachricht senden kann.
Beachten Sie, dass diese Art der zweiseitigen Kommunikation in XPC-Nachrichten verwendet wird, die eine Antwort erwarten (xpc_connection_send_message_with_reply
und xpc_connection_send_message_with_reply_sync
). Aber normalerweise werden unterschiedliche Ports erstellt, wie zuvor erklärt, um die zweiseitige Kommunikation zu schaffen.
Die anderen Felder des Nachrichtenkopfes sind:
msgh_size
: die Größe des gesamten Pakets.
msgh_remote_port
: der Port, über den diese Nachricht gesendet wird.
msgh_voucher_port
: mach Gutscheine.
msgh_id
: die ID dieser Nachricht, die vom Empfänger interpretiert wird.
Beachten Sie, dass mach-Nachrichten über einen mach port
gesendet werden, der ein einzelner Empfänger, mehrere Sender Kommunikationskanal ist, der in den mach-Kernel integriert ist. Mehrere Prozesse können Nachrichten an einen mach-Port senden, aber zu jedem Zeitpunkt kann nur ein einzelner Prozess von ihm lesen.
Nachrichten werden dann durch den mach_msg_header_t
Kopf gebildet, gefolgt vom Inhalt und vom Trailer (falls vorhanden), und es kann die Erlaubnis erteilt werden, darauf zu antworten. In diesen Fällen muss der Kernel die Nachricht nur von einer Aufgabe zur anderen weiterleiten.
Ein Trailer ist Informationen, die vom Kernel zur Nachricht hinzugefügt werden (kann nicht vom Benutzer festgelegt werden), die beim Empfang der Nachricht mit den Flags MACH_RCV_TRAILER_<trailer_opt>
angefordert werden können (es gibt unterschiedliche Informationen, die angefordert werden können).
Es gibt jedoch auch andere, komplexere Nachrichten, wie die, die zusätzliche Portrechte übergeben oder Speicher teilen, bei denen der Kernel auch diese Objekte an den Empfänger senden muss. In diesen Fällen wird das signifikanteste Bit des Kopfes msgh_bits
gesetzt.
Die möglichen Deskriptoren, die übergeben werden können, sind in mach/message.h
definiert:
In 32-Bit sind alle Deskriptoren 12B und der Deskriptor-Typ befindet sich im 11. Deskriptor. In 64-Bit variieren die Größen.
Der Kernel wird die Deskriptoren von einer Aufgabe zur anderen kopieren, aber zuerst eine Kopie im Kernel-Speicher erstellen. Diese Technik, bekannt als "Feng Shui", wurde in mehreren Exploits missbraucht, um den Kernel dazu zu bringen, Daten in seinem Speicher zu kopieren, wodurch ein Prozess Deskriptoren an sich selbst sendet. Dann kann der Prozess die Nachrichten empfangen (der Kernel wird sie freigeben).
Es ist auch möglich, Port-Rechte an einen verwundbaren Prozess zu senden, und die Port-Rechte werden einfach im Prozess erscheinen (auch wenn er sie nicht verwaltet).
Beachten Sie, dass Ports mit dem Aufgabennamespace verbunden sind, sodass zum Erstellen oder Suchen eines Ports auch der Aufgabennamespace abgefragt wird (mehr in mach/mach_port.h
):
mach_port_allocate
| mach_port_construct
: Erstellen Sie einen Port.
mach_port_allocate
kann auch ein Port-Set erstellen: Empfangsrecht über eine Gruppe von Ports. Jedes Mal, wenn eine Nachricht empfangen wird, wird der Port angegeben, von dem sie stammt.
mach_port_allocate_name
: Ändern Sie den Namen des Ports (standardmäßig 32-Bit-Ganzzahl)
mach_port_names
: Holen Sie sich Portnamen von einem Ziel
mach_port_type
: Holen Sie sich die Rechte einer Aufgabe über einen Namen
mach_port_rename
: Benennen Sie einen Port um (wie dup2 für FDs)
mach_port_allocate
: Weisen Sie einen neuen RECEIVE, PORT_SET oder DEAD_NAME zu
mach_port_insert_right
: Erstellen Sie ein neues Recht in einem Port, in dem Sie RECEIVE haben
mach_port_...
mach_msg
| mach_msg_overwrite
: Funktionen, die verwendet werden, um mach-Nachrichten zu senden und zu empfangen. Die Überschreibungsversion ermöglicht es, einen anderen Puffer für den Nachrichteneingang anzugeben (die andere Version wird ihn einfach wiederverwenden).
Da die Funktionen mach_msg
und mach_msg_overwrite
die sind, die verwendet werden, um Nachrichten zu senden und zu empfangen, würde das Setzen eines Haltepunkts auf ihnen ermöglichen, die gesendeten und empfangenen Nachrichten zu inspizieren.
Zum Beispiel starten Sie das Debuggen einer beliebigen Anwendung, die Sie debuggen können, da sie libSystem.B
laden wird, die diese Funktion verwenden wird.
Um die Argumente von mach_msg
zu erhalten, überprüfen Sie die Register. Dies sind die Argumente (aus mach/message.h):
Holen Sie die Werte aus den Registern:
Überprüfen Sie den Nachrichtenkopf und prüfen Sie das erste Argument:
Dieser Typ von mach_msg_bits_t
ist sehr verbreitet, um eine Antwort zu ermöglichen.
Der name ist der Standardname, der dem Port zugewiesen wird (überprüfen Sie, wie er in den ersten 3 Bytes zunimmt). Der ipc-object
ist der obfuskierte eindeutige Identifikator des Ports.
Beachten Sie auch, wie die Ports mit nur send
Rechten den Besitzer identifizieren (Portname + pid).
Beachten Sie auch die Verwendung von +
, um andere Aufgaben, die mit demselben Port verbunden sind, anzuzeigen.
Es ist auch möglich, procesxp zu verwenden, um auch die registrierten Dienstnamen zu sehen (mit deaktiviertem SIP aufgrund der Notwendigkeit von com.apple.system-task-port
):
Sie können dieses Tool auf iOS installieren, indem Sie es von http://newosxbook.com/tools/binpack64-256.tar.gz herunterladen.
Beachten Sie, wie der Sender einen Port zuweist, ein Senderecht für den Namen org.darlinghq.example
erstellt und es an den Bootstrap-Server sendet, während der Sender um das Senderecht dieses Namens bittet und es verwendet, um eine Nachricht zu senden.
Es gibt einige spezielle Ports, die es ermöglichen, bestimmte sensible Aktionen auszuführen oder auf bestimmte sensible Daten zuzugreifen, falls ein Task die SEND-Berechtigungen über sie hat. Dies macht diese Ports aus der Perspektive eines Angreifers sehr interessant, nicht nur wegen der Möglichkeiten, sondern auch weil es möglich ist, SEND-Berechtigungen zwischen Tasks zu teilen.
Diese Ports werden durch eine Nummer dargestellt.
SEND-Rechte können durch den Aufruf von host_get_special_port
und RECEIVE-Rechte durch den Aufruf von host_set_special_port
erlangt werden. Beide Aufrufe erfordern jedoch den host_priv
-Port, auf den nur der Root zugreifen kann. Darüber hinaus konnte Root in der Vergangenheit host_set_special_port
aufrufen und beliebige Ports übernehmen, was es beispielsweise ermöglichte, Codesignaturen zu umgehen, indem HOST_KEXTD_PORT
übernommen wurde (SIP verhindert dies jetzt).
Diese sind in 2 Gruppen unterteilt: Die ersten 7 Ports gehören dem Kernel, wobei der 1 HOST_PORT
, der 2 HOST_PRIV_PORT
, der 3 HOST_IO_MASTER_PORT
und der 7 HOST_MAX_SPECIAL_KERNEL_PORT
ist.
Die Ports, die ab der Nummer 8 beginnen, sind im Besitz von System-Daemons und können in host_special_ports.h
gefunden werden.
Host-Port: Wenn ein Prozess über diesen Port die SEND-Berechtigung hat, kann er Informationen über das System abrufen, indem er seine Routinen aufruft wie:
host_processor_info
: Prozessorinformationen abrufen
host_info
: Hostinformationen abrufen
host_virtual_physical_table_info
: Virtuelle/Physische Seitentabelle (erfordert MACH_VMDEBUG)
host_statistics
: Hoststatistiken abrufen
mach_memory_info
: Kernel-Speicherlayout abrufen
Host Priv-Port: Ein Prozess mit SEND-Recht über diesen Port kann privilegierte Aktionen ausführen, wie z.B. Bootdaten anzeigen oder versuchen, eine Kernel-Erweiterung zu laden. Der Prozess muss Root sein, um diese Berechtigung zu erhalten.
Darüber hinaus ist es erforderlich, um die kext_request
-API aufzurufen, andere Berechtigungen com.apple.private.kext*
zu haben, die nur Apple-Binärdateien gewährt werden.
Andere Routinen, die aufgerufen werden können, sind:
host_get_boot_info
: machine_boot_info()
abrufen
host_priv_statistics
: Privilegierte Statistiken abrufen
vm_allocate_cpm
: Kontinuierlichen physischen Speicher zuweisen
host_processors
: Senderecht an Host-Prozessoren
mach_vm_wire
: Speicher resident machen
Da Root auf diese Berechtigung zugreifen kann, könnte er host_set_[special/exception]_port[s]
aufrufen, um Host-Spezial- oder Ausnahmeports zu übernehmen.
Es ist möglich, alle Host-Spezialports zu sehen, indem man Folgendes ausführt:
Diese Ports sind für bekannte Dienste reserviert. Es ist möglich, sie mit task_[get/set]_special_port
abzurufen/zu setzen. Sie sind in task_special_ports.h
zu finden:
From here:
TASK_KERNEL_PORT[task-self send right]: Der Port, der zur Steuerung dieser Aufgabe verwendet wird. Wird verwendet, um Nachrichten zu senden, die die Aufgabe betreffen. Dies ist der Port, der von mach_task_self (siehe Task Ports unten) zurückgegeben wird.
TASK_BOOTSTRAP_PORT[bootstrap send right]: Der Bootstrap-Port der Aufgabe. Wird verwendet, um Nachrichten zu senden, die die Rückgabe anderer Systemdienstports anfordern.
TASK_HOST_NAME_PORT[host-self send right]: Der Port, der verwendet wird, um Informationen über den enthaltenen Host anzufordern. Dies ist der Port, der von mach_host_self zurückgegeben wird.
TASK_WIRED_LEDGER_PORT[ledger send right]: Der Port, der die Quelle benennt, aus der diese Aufgabe ihren verkabelten Kernel-Speicher bezieht.
TASK_PAGED_LEDGER_PORT[ledger send right]: Der Port, der die Quelle benennt, aus der diese Aufgabe ihren standardmäßig verwalteten Speicher bezieht.
Ursprünglich hatte Mach keine "Prozesse", sondern "Aufgaben", die eher als Container von Threads betrachtet wurden. Als Mach mit BSD zusammengeführt wurde, wurde jede Aufgabe mit einem BSD-Prozess korreliert. Daher hat jeder BSD-Prozess die Details, die er benötigt, um ein Prozess zu sein, und jede Mach-Aufgabe hat auch ihre inneren Abläufe (außer für die nicht existierende pid 0, die die kernel_task
ist).
Es gibt zwei sehr interessante Funktionen, die damit zusammenhängen:
task_for_pid(target_task_port, pid, &task_port_of_pid)
: Erhalte ein SEND-Recht für den Task-Port der Aufgabe, die mit dem durch die pid
angegebenen verbunden ist, und gib es an den angegebenen target_task_port
weiter (der normalerweise die aufrufende Aufgabe ist, die mach_task_self()
verwendet hat, aber auch ein SEND-Port über eine andere Aufgabe sein könnte).
pid_for_task(task, &pid)
: Gegeben ein SEND-Recht für eine Aufgabe, finde heraus, zu welcher PID diese Aufgabe gehört.
Um Aktionen innerhalb der Aufgabe auszuführen, benötigte die Aufgabe ein SEND
-Recht für sich selbst, indem sie mach_task_self()
aufruft (was den task_self_trap
(28) verwendet). Mit dieser Berechtigung kann eine Aufgabe mehrere Aktionen ausführen, wie:
task_threads
: Erhalte SEND-Recht über alle Task-Ports der Threads der Aufgabe
task_info
: Erhalte Informationen über eine Aufgabe
task_suspend/resume
: Unterbreche oder setze eine Aufgabe fort
task_[get/set]_special_port
thread_create
: Erstelle einen Thread
task_[get/set]_state
: Steuere den Zustand der Aufgabe
und mehr kann in mach/task.h gefunden werden
Beachte, dass es mit einem SEND-Recht über einen Task-Port einer anderen Aufgabe möglich ist, solche Aktionen über eine andere Aufgabe auszuführen.
Darüber hinaus ist der task_port auch der vm_map
-Port, der es ermöglicht, Speicher innerhalb einer Aufgabe zu lesen und zu manipulieren mit Funktionen wie vm_read()
und vm_write()
. Das bedeutet im Wesentlichen, dass eine Aufgabe mit SEND-Rechten über den task_port einer anderen Aufgabe in der Lage sein wird, Code in diese Aufgabe zu injizieren.
Denke daran, dass, weil der Kernel auch eine Aufgabe ist, wenn es jemandem gelingt, SEND-Berechtigungen über die kernel_task
zu erhalten, er in der Lage sein wird, den Kernel alles ausführen zu lassen (Jailbreaks).
Rufe mach_task_self()
auf, um den Namen für diesen Port für die aufrufende Aufgabe zu erhalten. Dieser Port wird nur vererbt über exec()
; eine neue Aufgabe, die mit fork()
erstellt wird, erhält einen neuen Task-Port (als Sonderfall erhält eine Aufgabe auch einen neuen Task-Port nach exec()
in einem suid-Binary). Der einzige Weg, eine Aufgabe zu starten und ihren Port zu erhalten, besteht darin, den "Port-Swap-Tanz" während eines fork()
auszuführen.
Dies sind die Einschränkungen für den Zugriff auf den Port (aus macos_task_policy
aus dem Binary AppleMobileFileIntegrity
):
Wenn die App die com.apple.security.get-task-allow
-Berechtigung hat, können Prozesse vom gleichen Benutzer auf den Task-Port zugreifen (häufig von Xcode zum Debuggen hinzugefügt). Der Notarisierungs-Prozess erlaubt dies nicht für Produktionsversionen.
Apps mit der com.apple.system-task-ports
-Berechtigung können den Task-Port für jeden Prozess erhalten, außer für den Kernel. In älteren Versionen wurde es task_for_pid-allow
genannt. Dies wird nur Apple-Anwendungen gewährt.
Root kann auf Task-Ports von Anwendungen nicht zugreifen, die mit einer hardened Runtime (und nicht von Apple) kompiliert wurden.
Der Task-Name-Port: Eine unprivilegierte Version des Task-Ports. Er verweist auf die Aufgabe, erlaubt jedoch keine Kontrolle darüber. Das einzige, was anscheinend darüber verfügbar ist, ist task_info()
.
Threads haben ebenfalls zugeordnete Ports, die von der Aufgabe, die task_threads
aufruft, und vom Prozessor mit processor_set_threads
sichtbar sind. Ein SEND-Recht auf den Thread-Port ermöglicht die Verwendung der Funktionen aus dem thread_act
-Subsystem, wie:
thread_terminate
thread_[get/set]_state
act_[get/set]_state
thread_[suspend/resume]
thread_info
...
Jeder Thread kann diesen Port aufrufen, indem er mach_thread_sef
aufruft.
Du kannst einen Shellcode von:
Introduction to ARM64v8Kompilieren Sie das vorherige Programm und fügen Sie die Berechtigungen hinzu, um Code mit demselben Benutzer injizieren zu können (ansonsten müssen Sie sudo verwenden).