macOS Thread Injection via Task port
Last updated
Last updated
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aanvanklik word die task_threads()
funksie aangeroep op die taakpoort om 'n thread lys van die afstandlike taak te verkry. 'n Thread word gekies vir hijacking. Hierdie benadering verskil van konvensionele kode-inspuitingsmetodes aangesien die skep van 'n nuwe afstandlike thread verbied word weens die nuwe mitigering wat thread_create_running()
blokkeer.
Om die thread te beheer, word thread_suspend()
aangeroep, wat die uitvoering stop.
Die enigste operasies wat op die afstandlike thread toegelaat word, behels stop en begin, verkry en wysig sy registerwaardes. Afstandlike funksie-aanroepe word geïnisieer deur registers x0
tot x7
op die argumente in te stel, pc
te konfigureer om die gewenste funksie te teiken, en die thread te aktiveer. Om te verseker dat die thread nie crasht na die terugkeer nie, is dit nodig om die terugkeer te detecteer.
Een strategie behels die registrasie van 'n uitsonderinghandler vir die afstandlike thread deur thread_set_exception_ports()
te gebruik, en die lr
register op 'n ongeldige adres in te stel voor die funksie-aanroep. Dit veroorsaak 'n uitsondering na funksie-uitvoering, wat 'n boodskap na die uitsonderingpoort stuur, wat staatinspeksie van die thread moontlik maak om die terugkeerwaarde te herstel. Alternatiewelik, soos aangeneem van Ian Beer se triple_fetch exploit, word lr
op oneindig gelus. Die thread se registers word dan deurlopend gemonitor totdat pc
na daardie instruksie wys.
Die volgende fase behels die vestiging van Mach-poorte om kommunikasie met die afstandlike thread te fasiliteer. Hierdie poorte is noodsaaklik vir die oordrag van arbitrêre stuur- en ontvangregte tussen take.
Vir bidireksionele kommunikasie word twee Mach ontvangregte geskep: een in die plaaslike en die ander in die afstandlike taak. Daarna word 'n stuurreg vir elke poort na die teenhanger-taak oorgedra, wat boodskapuitruiling moontlik maak.
Fokus op die plaaslike poort, die ontvangreg word deur die plaaslike taak gehou. Die poort word geskep met mach_port_allocate()
. Die uitdaging lê in die oordrag van 'n stuurreg na hierdie poort in die afstandlike taak.
'n Strategie behels die benutting van thread_set_special_port()
om 'n stuurreg na die plaaslike poort in die afstandlike thread se THREAD_KERNEL_PORT
te plaas. Dan word die afstandlike thread aangesê om mach_thread_self()
aan te roep om die stuurreg te verkry.
Vir die afstandlike poort is die proses basies omgekeerd. Die afstandlike thread word aangestuur om 'n Mach-poort te genereer via mach_reply_port()
(aangesien mach_port_allocate()
onvanpas is weens sy terugkeermeganisme). Na poortskepping word mach_port_insert_right()
in die afstandlike thread aangeroep om 'n stuurreg te vestig. Hierdie reg word dan in die kern gestoor met thread_set_special_port()
. Terug in die plaaslike taak, word thread_get_special_port()
op die afstandlike thread gebruik om 'n stuurreg na die nuut toegeken Mach-poort in die afstandlike taak te verkry.
Die voltooiing van hierdie stappe lei tot die vestiging van Mach-poorte, wat die grondslag lê vir bidireksionele kommunikasie.
In hierdie afdeling is die fokus op die benutting van die uitvoerprimitive om basiese geheue lees- en skryfprimitive te vestig. Hierdie aanvanklike stappe is noodsaaklik om meer beheer oor die afstandlike proses te verkry, alhoewel die primitive op hierdie stadium nie veel doeleindes sal dien nie. Binnekort sal hulle opgegradeer word na meer gevorderde weergawes.
Die doel is om geheue te lees en te skryf met behulp van spesifieke funksies. Vir die lees van geheue word funksies wat die volgende struktuur naboots, gebruik:
En vir skryf na geheue, word funksies soortgelyk aan hierdie struktuur gebruik:
Hierdie funksies stem ooreen met die gegewe samestelling instruksies:
'n Skandering van algemene biblioteke het geskikte kandidate vir hierdie operasies onthul:
Reading Memory: Die property_getName()
funksie van die Objective-C runtime library word geïdentifiseer as 'n geskikte funksie om geheue te lees. Die funksie word hieronder uiteengesit:
Om 'n 64-bis skrywe op 'n spesifieke adres uit te voer, is die afstandsoproep gestruktureer as:
Met hierdie primitiewe gevestig, is die verhoog gereed om gedeelde geheue te skep, wat 'n beduidende vordering in die beheer van die afstandsproses aandui.
Die doel is om gedeelde geheue tussen plaaslike en afstands take te vestig, wat dataverskuiwing vereenvoudig en die oproep van funksies met meerdere argumente fasiliteer. Die benadering behels die benutting van libxpc
en sy OS_xpc_shmem
objektipe, wat gebaseer is op Mach geheue-invoere.
Geheue Toewysing:
Toewys die geheue vir deel met behulp van mach_vm_allocate()
.
Gebruik xpc_shmem_create()
om 'n OS_xpc_shmem
objek vir die toegewyde geheuegebied te skep. Hierdie funksie sal die skepping van die Mach geheue-invoer bestuur en die Mach stuurreg aan offset 0x18
van die OS_xpc_shmem
objek stoor.
Gedeelde Geheue in Afstandsproses Skep:
Toewys geheue vir die OS_xpc_shmem
objek in die afstandsproses met 'n afstandsoproep na malloc()
.
Kopieer die inhoud van die plaaslike OS_xpc_shmem
objek na die afstandsproses. Hierdie aanvanklike kopie sal egter onakkurate Mach geheue-invoer name by offset 0x18
hê.
Die Mach Geheue Invoer Regstel:
Gebruik die thread_set_special_port()
metode om 'n stuurreg vir die Mach geheue-invoer in die afstandstaak in te voeg.
Regstel die Mach geheue-invoer veld by offset 0x18
deur dit te oorskryf met die naam van die afstands geheue-invoer.
Finalisering van Gedeelde Geheue Instelling:
Valideer die afstands OS_xpc_shmem
objek.
Vestig die gedeelde geheue kaart met 'n afstandsoproep na xpc_shmem_remote()
.
Deur hierdie stappe te volg, sal gedeelde geheue tussen die plaaslike en afstands take doeltreffend ingestel word, wat vir eenvoudige dataverskuiwings en die uitvoering van funksies wat meerdere argumente vereis, toelaat.
Vir geheue toewysing en gedeelde geheue objek skepping:
Vir die skep en regstelling van die gedeelde geheue objek in die afstandsproses:
Remember to handle the details of Mach ports and memory entry names correctly to ensure that the shared memory setup functions properly.
Upon successfully establishing shared memory and gaining arbitrary execution capabilities, we have essentially gained full control over the target process. The key functionalities enabling this control are:
Arbitraire Geheue Operasies:
Perform arbitrary memory reads by invoking memcpy()
to copy data from the shared region.
Execute arbitrary memory writes by using memcpy()
to transfer data to the shared region.
Hantering van Funksie-oproepe met Meerdere Argumente:
For functions requiring more than 8 arguments, arrange the additional arguments on the stack in compliance with the calling convention.
Mach Port Oordrag:
Transfer Mach ports between tasks through Mach messages via previously established ports.
Lêer Descriptor Oordrag:
Transfer file descriptors between processes using fileports, a technique highlighted by Ian Beer in triple_fetch
.
This comprehensive control is encapsulated within the threadexec library, providing a detailed implementation and a user-friendly API for interaction with the victim process.
Ensure proper use of memcpy()
for memory read/write operations to maintain system stability and data integrity.
When transferring Mach ports or file descriptors, follow proper protocols and handle resources responsibly to prevent leaks or unintended access.
By adhering to these guidelines and utilizing the threadexec
library, one can efficiently manage and interact with processes at a granular level, achieving full control over the target process.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)