macOS GCD - Grand Central Dispatch
Informations de base
Grand Central Dispatch (GCD), également connu sous le nom de libdispatch, est disponible à la fois sur macOS et iOS. Il s'agit d'une technologie développée par Apple pour optimiser le support des applications pour l'exécution concurrente (multithread) sur un matériel multicœur.
GCD fournit et gère des files d'attente FIFO auxquelles votre application peut soumettre des tâches sous forme d'objets de bloc. Les blocs soumis aux files d'attente de répartition sont exécutés sur un pool de threads entièrement géré par le système. GCD crée automatiquement des threads pour exécuter les tâches dans les files d'attente de répartition et planifie l'exécution de ces tâches sur les cœurs disponibles.
En résumé, pour exécuter du code en parallèle, les processus peuvent envoyer des blocs de code à GCD, qui se chargera de leur exécution. Par conséquent, les processus ne créent pas de nouveaux threads ; GCD exécute le code donné avec son propre pool de threads.
Cela est très utile pour gérer avec succès l'exécution parallèle, réduisant considérablement le nombre de threads que les processus créent et optimisant l'exécution parallèle. Cela est idéal pour les tâches qui nécessitent une grande parallélisme (force brute ?) ou pour les tâches qui ne doivent pas bloquer le thread principal : par exemple, le thread principal sur iOS gère les interactions UI, donc toute autre fonctionnalité qui pourrait faire planter l'application (recherche, accès à un site web, lecture d'un fichier...) est gérée de cette manière.
Objective-C
En Objective-C, il existe différentes fonctions pour envoyer un bloc à exécuter en parallèle :
dispatch_async : Soumet un bloc pour une exécution asynchrone sur une file d'attente de répartition et retourne immédiatement.
dispatch_sync : Soumet un objet de bloc pour exécution et retourne une fois que ce bloc a fini d'exécuter.
dispatch_once : Exécute un objet de bloc une seule fois pendant la durée de vie d'une application.
dispatch_async_and_wait : Soumet un élément de travail pour exécution et ne retourne qu'après son exécution. Contrairement à
dispatch_sync
, cette fonction respecte tous les attributs de la file d'attente lorsqu'elle exécute le bloc.
Ces fonctions attendent ces paramètres : dispatch_queue_t
queue,
dispatch_block_t
block
Voici la structure d'un bloc :
Et voici un exemple d'utilisation de parallélisme avec dispatch_async
:
Swift
libswiftDispatch
est une bibliothèque qui fournit des liaisons Swift au framework Grand Central Dispatch (GCD) qui est initialement écrit en C.
La bibliothèque libswiftDispatch
enveloppe les API C GCD dans une interface plus conviviale pour Swift, facilitant ainsi le travail des développeurs Swift avec 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"))
Exemple de code:
Frida
Le script Frida suivant peut être utilisé pour s'accrocher à plusieurs fonctions dispatch
et extraire le nom de la file d'attente, la trace de la pile et le bloc : https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js
Ghidra
Actuellement, Ghidra ne comprend ni la structure ObjectiveC dispatch_block_t
, ni celle de swift_dispatch_block
.
Donc, si vous voulez qu'il les comprenne, vous pouvez simplement les déclarer :
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-be0bf70c1ce76f3498b587d9a47e30a8d75c64cc%252Fimage%2520%28688%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=c66cd0c&sv=1)
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-63e406af6ae79cfec58f9bb2d27a0c92c0d01ff8%252Fimage%2520%28690%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=1d2371d7&sv=1)
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-7fa96fc073762801b1f522126bbf96728c9bbbc6%252Fimage%2520%28691%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=dda0f664&sv=1)
Ensuite, trouvez un endroit dans le code où ils sont utilisés :
Notez toutes les références à "block" pour comprendre comment vous pourriez déterminer que la structure est utilisée.
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-03f6a138dbab5269ae9e672f9947daa6e7a745a0%252Fimage%2520%28692%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=694c395a&sv=1)
Cliquez avec le bouton droit sur la variable -> Retype Variable et sélectionnez dans ce cas swift_dispatch_block
:
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-46e4a0c83feb38559dddc62968780d804e9afc22%252Fimage%2520%28693%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=920429a2&sv=1)
Ghidra réécrira automatiquement tout :
![](https://book.hacktricks.xyz/~gitbook/image?url=https%3A%2F%2F2088318145-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Frq9WIQinJaxpWMvakjIQ%252Fuploads%252Fgit-blob-883a9665d63968d8d9051a6d4d2013c67aa4f4b2%252Fimage%2520%28694%29.png%3Falt%3Dmedia&width=768&dpr=4&quality=100&sign=424da34d&sv=1)
Last updated