7.9 KiB
macOS GCD - Grand Central Dispatch
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite svoju kompaniju reklamiranu na HackTricks-u ili da preuzmete HackTricks u PDF formatu proverite PLANOVE ZA PRIJAVU!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte Porodicu PEASS, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitteru 🐦 @carlospolopm.
- Podelite svoje hakovanje trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
Grand Central Dispatch (GCD), takođe poznat kao libdispatch, dostupan je i na macOS-u i iOS-u. To je tehnologija razvijena od strane Apple-a za optimizaciju podrške aplikacija za konkurentno (višenitno) izvršavanje na višejezgarnom hardveru.
GCD obezbeđuje i upravlja FIFO redovima u koje vaša aplikacija može podneti zadatke u obliku blok objekata. Blokovi podneti redovima za raspoređivanje se izvršavaju na poolu niti potpuno upravljanim od strane sistema. GCD automatski kreira niti za izvršavanje zadataka u redovima za raspoređivanje i raspoređuje te zadatke da se izvrše na dostupnim jezgrima.
{% hint style="success" %} U suštini, da bi se izvršio kod paralelno, procesi mogu poslati blokove koda GCD-u, koji će se pobrinuti za njihovo izvršavanje. Dakle, procesi ne stvaraju nove niti; GCD izvršava dati kod sa svojim poolom niti. {% endhint %}
Ovo je veoma korisno za uspešno upravljanje paralelnim izvršavanjem, značajno smanjujući broj niti koje procesi kreiraju i optimizujući paralelno izvršavanje. Ovo je idealno za zadatke koji zahtevaju veliku paralelnost (bruteforcing?) ili za zadatke koji ne bi trebali blokirati glavnu nit: Na primer, glavna nit na iOS-u upravlja interakcijama sa korisničkim interfejsom, pa se na ovaj način upravlja svaka druga funkcionalnost koja bi mogla da zamrzne aplikaciju (pretraga, pristup vebu, čitanje fajla...).
Objective-C
U Objective-C-u postoje različite funkcije za slanje bloka radi izvršavanja paralelno:
- dispatch_async: Podnosi blok za asinhrono izvršavanje na red za raspoređivanje i odmah se vraća.
- dispatch_sync: Podnosi blok objekat za izvršavanje i vraća se nakon što se taj blok završi sa izvršavanjem.
- dispatch_once: Izvršava blok objekat samo jednom za vreme trajanja aplikacije.
- dispatch_async_and_wait: Podnosi radnu stavku za izvršavanje i vraća se tek nakon što se završi sa izvršavanjem. Za razliku od
dispatch_sync
, ova funkcija poštuje sve atribute reda kada izvršava blok.
Ove funkcije očekuju ove parametre: dispatch_queue_t
queue,
dispatch_block_t
block
Ovo je struktura Bloka:
struct Block {
void *isa; // NSConcreteStackBlock,...
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
// captured variables go here
};
I ovo je primer korišćenja paralelizma sa dispatch_async
:
#import <Foundation/Foundation.h>
// Define a block
void (^backgroundTask)(void) = ^{
// Code to be executed in the background
for (int i = 0; i < 10; i++) {
NSLog(@"Background task %d", i);
sleep(1); // Simulate a long-running task
}
};
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Create a dispatch queue
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.example.backgroundQueue", NULL);
// Submit the block to the queue for asynchronous execution
dispatch_async(backgroundQueue, backgroundTask);
// Continue with other work on the main queue or thread
for (int i = 0; i < 10; i++) {
NSLog(@"Main task %d", i);
sleep(1); // Simulate a long-running task
}
}
return 0;
}
Swift
libswiftDispatch
je biblioteka koja pruža Swift veze sa Grand Central Dispatch (GCD) okvirom koji je originalno napisan u C-u.
Biblioteka libswiftDispatch
omotava C GCD API-je u interfejs koji je prijateljskiji za Swift, čineći ga lakšim i intuitivnijim za Swift programere da rade sa GCD-om.
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"))
Primer koda:
import Foundation
// Define a closure (the Swift equivalent of a block)
let backgroundTask: () -> Void = {
for i in 0..<10 {
print("Background task \(i)")
sleep(1) // Simulate a long-running task
}
}
// Entry point
autoreleasepool {
// Create a dispatch queue
let backgroundQueue = DispatchQueue(label: "com.example.backgroundQueue")
// Submit the closure to the queue for asynchronous execution
backgroundQueue.async(execute: backgroundTask)
// Continue with other work on the main queue
for i in 0..<10 {
print("Main task \(i)")
sleep(1) // Simulate a long-running task
}
}
Frida
Sledeći Frida skript može se koristiti za povezivanje sa nekoliko dispatch
funkcija i izvlačenje imena reda, steka poziva i bloka: https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js
frida -U <prog_name> -l libdispatch.js
dispatch_sync
Calling queue: com.apple.UIKit._UIReusePool.reuseSetAccess
Callback function: 0x19e3a6488 UIKitCore!__26-[_UIReusePool addObject:]_block_invoke
Backtrace:
0x19e3a6460 UIKitCore!-[_UIReusePool addObject:]
0x19e3a5db8 UIKitCore!-[UIGraphicsRenderer _enqueueContextForReuse:]
0x19e3a57fc UIKitCore!+[UIGraphicsRenderer _destroyCGContext:withRenderer:]
[...]
Ghidra
Trenutno Ghidra ne razume ni strukturu ObjectiveC dispatch_block_t
, ni swift_dispatch_block
.
Dakle, ako želite da ih razume, jednostavno ih možete deklarisati:
Zatim pronađite mesto u kodu gde se oni koriste:
{% hint style="success" %} Zabeležite sve reference na "block" kako biste razumeli kako možete utvrditi da se struktura koristi. {% endhint %}
Desni klik na promenljivu -> Promeni tip promenljive i izaberite u ovom slučaju swift_dispatch_block
:
Ghidra će automatski prepraviti sve: