macOS GCD - Grand Central Dispatch
Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Informazioni di Base
Grand Central Dispatch (GCD), noto anche come libdispatch (libdispatch.dyld
), è disponibile sia su macOS che su iOS. Si tratta di una tecnologia sviluppata da Apple per ottimizzare il supporto dell'applicazione per l'esecuzione concorrente (multithreaded) sull'hardware multicore.
GCD fornisce e gestisce code FIFO a cui la tua applicazione può inviare attività sotto forma di oggetti block. I blocchi inviati alle code di invio vengono eseguiti su un pool di thread completamente gestito dal sistema. GCD crea automaticamente thread per eseguire le attività nelle code di invio e pianifica l'esecuzione di tali attività sui core disponibili.
In sintesi, per eseguire codice in parallelo, i processi possono inviare blocchi di codice a GCD, che si occuperà della loro esecuzione. Pertanto, i processi non creano nuovi thread; GCD esegue il codice fornito con il proprio pool di thread (che potrebbe aumentare o diminuire secondo necessità).
Questo è molto utile per gestire con successo l'esecuzione parallela, riducendo notevolmente il numero di thread creati dai processi e ottimizzando l'esecuzione parallela. Questo è ideale per attività che richiedono grande parallelismo (forza bruta?) o per attività che non dovrebbero bloccare il thread principale: ad esempio, il thread principale su iOS gestisce le interazioni dell'interfaccia utente, quindi qualsiasi altra funzionalità che potrebbe far bloccare l'applicazione (ricerca, accesso a un sito web, lettura di un file...) è gestita in questo modo.
Blocchi
Un blocco è una sezione di codice autocontenuta (come una funzione con argomenti che restituisce un valore) e può anche specificare variabili vincolate.
Tuttavia, a livello di compilatore i blocchi non esistono, sono os_object
. Ciascuno di questi oggetti è formato da due strutture:
letterale del blocco:
Inizia con il campo
isa
, che punta alla classe del blocco:NSConcreteGlobalBlock
(blocchi da__DATA.__const
)NSConcreteMallocBlock
(blocchi nello heap)NSConcreateStackBlock
(blocchi nello stack)Ha
flags
(che indicano i campi presenti nel descrittore del blocco) e alcuni byte riservatiIl puntatore alla funzione da chiamare
Un puntatore al descrittore del blocco
Variabili importate dal blocco (se presenti)
descrittore del blocco: La sua dimensione dipende dai dati presenti (come indicato nei flag precedenti)
Ha alcuni byte riservati
La sua dimensione
Di solito avrà un puntatore a una firma in stile Objective-C per sapere di quanto spazio è necessario per i parametri (flag
BLOCK_HAS_SIGNATURE
)Se le variabili sono referenziate, questo blocco avrà anche puntatori a un aiutante di copia (che copia il valore all'inizio) e a un aiutante di smaltimento (liberandolo).
Code di Invio
Una coda di invio è un oggetto nominato che fornisce l'ordinamento FIFO dei blocchi per le esecuzioni.
I blocchi vengono impostati nelle code per essere eseguiti e supportano 2 modalità: DISPATCH_QUEUE_SERIAL
e DISPATCH_QUEUE_CONCURRENT
. Naturalmente il seriale non avrà problemi di condizione di gara poiché un blocco non verrà eseguito fino a quando il precedente non sarà terminato. Ma l'altro tipo di coda potrebbe averlo.
Code predefinite:
.main-thread
: Dadispatch_get_main_queue()
.libdispatch-manager
: Gestore delle code di GCD.root.libdispatch-manager
: Gestore delle code di GCD.root.maintenance-qos
: Attività a priorità più bassa.root.maintenance-qos.overcommit
.root.background-qos
: Disponibile comeDISPATCH_QUEUE_PRIORITY_BACKGROUND
.root.background-qos.overcommit
.root.utility-qos
: Disponibile comeDISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE
.root.utility-qos.overcommit
.root.default-qos
: Disponibile comeDISPATCH_QUEUE_PRIORITY_DEFAULT
.root.background-qos.overcommit
.root.user-initiated-qos
: Disponibile comeDISPATCH_QUEUE_PRIORITY_HIGH
.root.background-qos.overcommit
.root.user-interactive-qos
: Priorità più alta.root.background-qos.overcommit
Si noti che sarà il sistema a decidere quali thread gestiscono quali code in ogni momento (più thread potrebbero lavorare nella stessa coda o lo stesso thread potrebbe lavorare in code diverse in un certo momento)
Attributi
Quando si crea una coda con dispatch_queue_create
il terzo argomento è un dispatch_queue_attr_t
, che di solito è o DISPATCH_QUEUE_SERIAL
(che in realtà è NULL) o DISPATCH_QUEUE_CONCURRENT
che è un puntatore a una struttura dispatch_queue_attr_t
che consente di controllare alcuni parametri della coda.
Oggetti di Invio
Ci sono diversi oggetti che libdispatch utilizza e le code e i blocchi sono solo 2 di essi. È possibile creare questi oggetti con dispatch_object_create
:
block
data
: Blocchi di datigroup
: Gruppo di blocchiio
: Richieste di I/O asincronemach
: Porte Machmach_msg
: Messaggi Machpthread_root_queue
: Una coda con un pool di thread pthread e senza code di lavoroqueue
semaphore
source
: Sorgente di eventi
Objective-C
In Objective-C ci sono diverse funzioni per inviare un blocco da eseguire in parallelo:
dispatch_async: Invia un blocco per l'esecuzione asincrona su una coda di invio e restituisce immediatamente.
dispatch_sync: Invia un oggetto blocco per l'esecuzione e restituisce dopo che il blocco ha finito di eseguire.
dispatch_once: Esegue un oggetto blocco solo una volta per tutta la durata di un'applicazione.
dispatch_async_and_wait: Invia un elemento di lavoro per l'esecuzione e restituisce solo dopo che ha finito di eseguire. A differenza di
dispatch_sync
, questa funzione rispetta tutti gli attributi della coda quando esegue il blocco.
Queste funzioni si aspettano questi parametri: dispatch_queue_t
queue,
dispatch_block_t
block
Questa è la struttura di un Blocco:
E questo è un esempio per utilizzare il parallelismo con dispatch_async
:
Swift
libswiftDispatch
è una libreria che fornisce binding Swift al framework Grand Central Dispatch (GCD) originariamente scritto in C.
La libreria libswiftDispatch
incapsula le API C GCD in un'interfaccia più amichevole per Swift, rendendo più semplice e intuitivo per gli sviluppatori Swift lavorare con GCD.
DispatchQueue.global().sync{ ... }
DispatchQueue.global().async{ ... }
let onceToken = DispatchOnce(); onceToken.perform { ... }
async await
var (data, response) = await URLSession.shared.data(from: URL(string: "https://api.example.com/getData"))
Esempio di codice:
Frida
Il seguente script Frida può essere utilizzato per agganciarsi a diverse funzioni dispatch
ed estrarre il nome della coda, la traccia retrospettiva e il blocco: https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js
Ghidra
Attualmente Ghidra non comprende né la struttura dispatch_block_t
di ObjectiveC, né quella di swift_dispatch_block
.
Quindi, se vuoi che le comprenda, puoi semplicemente dichiararle:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-be0bf70c1ce76f3498b587d9a47e30a8d75c64cc%252Fimage%2520%281160%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=40f7e788&sv=1)
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-63e406af6ae79cfec58f9bb2d27a0c92c0d01ff8%252Fimage%2520%281162%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=b546ef94&sv=1)
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-7fa96fc073762801b1f522126bbf96728c9bbbc6%252Fimage%2520%281163%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=144bf8e7&sv=1)
Successivamente, trova un punto nel codice in cui vengono utilizzate:
Nota tutti i riferimenti al "block" per capire come potresti individuare che la struttura viene utilizzata.
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-03f6a138dbab5269ae9e672f9947daa6e7a745a0%252Fimage%2520%281164%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=3152deb3&sv=1)
Fai clic destro sulla variabile -> Ridichiara la variabile e seleziona in questo caso swift_dispatch_block
:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-46e4a0c83feb38559dddc62968780d804e9afc22%252Fimage%2520%281165%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=9361129&sv=1)
Ghidra riscriverà automaticamente tutto:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F197708944-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FE5VfhVAq0qYsgU9deMR8%252Fuploads%252Fgit-blob-883a9665d63968d8d9051a6d4d2013c67aa4f4b2%252Fimage%2520%281166%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=a82bfaf2&sv=1)
References
Impara e pratica l'Hacking su AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking su GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Last updated