macOS GCD - Grand Central Dispatch
Reading time: 8 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Basic Information
Grand Central Dispatch (GCD), pia inajulikana kama libdispatch (libdispatch.dyld
), inapatikana katika macOS na iOS. Ni teknolojia iliyotengenezwa na Apple kuboresha msaada wa programu kwa utekelezaji wa sambamba (multithreaded) kwenye vifaa vya multicore.
GCD inatoa na kusimamia FIFO queues ambazo programu yako inaweza kuwasilisha kazi katika mfumo wa block objects. Blocks zilizowasilishwa kwa dispatch queues zina tekelezwa kwenye mchanganyiko wa nyuzi zinazodhibitiwa kikamilifu na mfumo. GCD kiotomatiki huunda nyuzi za kutekeleza kazi katika dispatch queues na kupanga kazi hizo zitekelezwe kwenye cores zinazopatikana.
tip
Kwa muhtasari, ili kutekeleza msimbo kwa sambamba, michakato inaweza kutuma blocks za msimbo kwa GCD, ambayo itashughulikia utekelezaji wao. Hivyo, michakato haisababisha nyuzi mpya; GCD inatekeleza msimbo uliotolewa kwa mchanganyiko wake wa nyuzi (ambayo inaweza kuongezeka au kupungua kadri inavyohitajika).
Hii ni muhimu sana kusimamia utekelezaji wa sambamba kwa mafanikio, ikipunguza kwa kiasi kikubwa idadi ya nyuzi ambazo michakato inaunda na kuboresha utekelezaji wa sambamba. Hii ni bora kwa kazi zinazohitaji paralelism mkubwa (brute-forcing?) au kwa kazi ambazo hazipaswi kuzuia nyuzi kuu: Kwa mfano, nyuzi kuu kwenye iOS inashughulikia mwingiliano wa UI, hivyo kazi nyingine yoyote ambayo inaweza kufanya programu ikang'ang'ane (kutafuta, kufikia wavuti, kusoma faili...) inasimamiwa kwa njia hii.
Blocks
Block ni sehemu ya msimbo iliyo na uhuru (kama kazi yenye hoja inayorejesha thamani) na inaweza pia kubainisha mabadiliko yaliyofungwa.
Hata hivyo, katika ngazi ya kompyuta blocks hazipo, ni os_object
s. Kila moja ya vitu hivi inaundwa na muundo miwili:
- block literal:
- Inaanza na
isa
uwanja, ikielekeza kwenye darasa la block: NSConcreteGlobalBlock
(blocks kutoka__DATA.__const
)NSConcreteMallocBlock
(blocks kwenye heap)NSConcreateStackBlock
(blocks kwenye stack)- Ina
flags
(zinazoashiria maeneo yaliyopo katika block descriptor) na baadhi ya bytes zilizohifadhiwa - Pointer ya kazi ya kuita
- Pointer kwa block descriptor
- Mabadiliko yaliyopitishwa kwenye block (ikiwa yapo)
- block descriptor: Ukubwa wake unategemea data iliyopo (kama ilivyoashiriwa katika flags zilizopita)
- Ina baadhi ya bytes zilizohifadhiwa
- Ukubwa wake
- Kwa kawaida itakuwa na pointer kwa saini ya mtindo wa Objective-C ili kujua ni nafasi ngapi inahitajika kwa params (flag
BLOCK_HAS_SIGNATURE
) - Ikiwa mabadiliko yanarejelewa, block hii pia itakuwa na pointers kwa msaada wa nakala (kuhamasisha thamani mwanzoni) na msaada wa kutupa (kuachilia).
Queues
Dispatch queue ni kitu chenye jina kinachotoa mpangilio wa FIFO wa blocks kwa utekelezaji.
Blocks huwekwa katika queues ili kutekelezwa, na hizi zinasaidia njia 2: DISPATCH_QUEUE_SERIAL
na DISPATCH_QUEUE_CONCURRENT
. Bila shaka serial moja haitakuwa na matatizo ya mashindano kwani block haitatekelezwa hadi ile ya awali ikamilike. Lakini aina nyingine ya queue inaweza kuwa nayo.
Queues za kawaida:
.main-thread
: Kutokadispatch_get_main_queue()
.libdispatch-manager
: Meneja wa queue wa GCD.root.libdispatch-manager
: Meneja wa queue wa GCD.root.maintenance-qos
: Kazi za kipaumbele cha chini.root.maintenance-qos.overcommit
.root.background-qos
: Inapatikana kamaDISPATCH_QUEUE_PRIORITY_BACKGROUND
.root.background-qos.overcommit
.root.utility-qos
: Inapatikana kamaDISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE
.root.utility-qos.overcommit
.root.default-qos
: Inapatikana kamaDISPATCH_QUEUE_PRIORITY_DEFAULT
.root.background-qos.overcommit
.root.user-initiated-qos
: Inapatikana kamaDISPATCH_QUEUE_PRIORITY_HIGH
.root.background-qos.overcommit
.root.user-interactive-qos
: Kipaumbele cha juu zaidi.root.background-qos.overcommit
Kumbuka kwamba itakuwa mfumo ambao utaamua ni nyuzi zipi zinashughulikia queues zipi kila wakati (nyuzi nyingi zinaweza kufanya kazi katika queue moja au nyuzi moja inaweza kufanya kazi katika queues tofauti kwa wakati fulani)
Attributtes
Wakati wa kuunda queue na dispatch_queue_create
hoja ya tatu ni dispatch_queue_attr_t
, ambayo kwa kawaida ni DISPATCH_QUEUE_SERIAL
(ambayo kwa kweli ni NULL) au DISPATCH_QUEUE_CONCURRENT
ambayo ni pointer kwa muundo wa dispatch_queue_attr_t
ambao unaruhusu kudhibiti baadhi ya vigezo vya queue.
Dispatch objects
Kuna vitu vingi ambavyo libdispatch inatumia na queues na blocks ni 2 tu kati yao. Inawezekana kuunda vitu hivi kwa dispatch_object_create
:
block
data
: Data blocksgroup
: Kundi la blocksio
: Maombi ya Async I/Omach
: Mach portsmach_msg
: Mach messagespthread_root_queue
: Queue yenye mchanganyiko wa nyuzi za pthread na si workqueuesqueue
semaphore
source
: Chanzo cha tukio
Objective-C
Katika Objetive-C kuna kazi tofauti za kutuma block kutekelezwa kwa sambamba:
- dispatch_async: Inawasilisha block kwa utekelezaji wa asynchronous kwenye dispatch queue na inarudi mara moja.
- dispatch_sync: Inawasilisha block object kwa utekelezaji na inarudi baada ya block hiyo kumaliza kutekelezwa.
- dispatch_once: Inatekeleza block object mara moja tu kwa muda wa programu.
- dispatch_async_and_wait: Inawasilisha kipengele cha kazi kwa utekelezaji na inarudi tu baada ya kumaliza kutekelezwa. Tofauti na
dispatch_sync
, kazi hii inaheshimu vigezo vyote vya queue wakati inatekeleza block.
Kazi hizi zinatarajia vigezo hivi: dispatch_queue_t
queue,
dispatch_block_t
block
Hii ni struct ya Block:
struct Block {
void *isa; // NSConcreteStackBlock,...
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
// captured variables go here
};
Na hii ni mfano wa kutumia parallelism na 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
ni maktaba inayotoa Swift bindings kwa mfumo wa Grand Central Dispatch (GCD) ambao awali umeandikwa kwa C.
Maktaba ya libswiftDispatch
inafunika APIs za C GCD katika kiolesura kinachofaa zaidi kwa Swift, na kufanya iwe rahisi na ya kueleweka zaidi kwa waendelezaji wa Swift kufanya kazi na 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"))
Mfano wa msimbo:
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
The following Frida script can be used to hook into several dispatch
functions and extract the queue name, the backtrace and the block: 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
Kwa sasa Ghidra haiwezi kuelewa ama muundo wa ObjectiveC dispatch_block_t
, wala muundo wa swift_dispatch_block
.
Hivyo kama unataka iweze kuelewa, unaweza tu kuwatangaza:
Kisha, pata mahali katika msimbo ambapo zinatumika kutumika:
tip
Kumbuka rejea zote zilizofanywa kwa "block" ili kuelewa jinsi unavyoweza kugundua kuwa muundo unatumika.
Bonyeza kulia kwenye variable -> Retype Variable na uchague katika kesi hii swift_dispatch_block
:
Ghidra itandika upya kila kitu kiotomatiki:
References
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.