macOS GCD - Grand Central Dispatch

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

Basic Information

Grand Central Dispatch (GCD), λ˜ν•œ libdispatch (libdispatch.dyld)둜 μ•Œλ €μ Έ 있으며, macOS와 iOS λͺ¨λ‘μ—μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” Apple이 닀쀑 μ½”μ–΄ ν•˜λ“œμ›¨μ–΄μ—μ„œ λ™μ‹œ(λ©€ν‹°μŠ€λ ˆλ“œ) 싀행을 μ΅œμ ν™”ν•˜κΈ° μœ„ν•΄ κ°œλ°œν•œ κΈ°μˆ μž…λ‹ˆλ‹€.

GCDλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ 블둝 객체 ν˜•νƒœλ‘œ μž‘μ—…μ„ μ œμΆœν•  수 μžˆλŠ” FIFO 큐λ₯Ό μ œκ³΅ν•˜κ³  κ΄€λ¦¬ν•©λ‹ˆλ‹€. λ””μŠ€νŒ¨μΉ˜ 큐에 제좜된 블둝은 μ‹œμŠ€ν…œμ— μ˜ν•΄ μ™„μ „νžˆ κ΄€λ¦¬λ˜λŠ” μŠ€λ ˆλ“œ ν’€μ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€. GCDλŠ” λ””μŠ€νŒ¨μΉ˜ νμ—μ„œ μž‘μ—…μ„ μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ μŠ€λ ˆλ“œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜κ³ , μ‚¬μš© κ°€λŠ₯ν•œ μ½”μ–΄μ—μ„œ μ‹€ν–‰ν•  μž‘μ—…μ„ μ˜ˆμ•½ν•©λ‹ˆλ‹€.

Tip

μš”μ•½ν•˜μžλ©΄, λ³‘λ ¬λ‘œ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ ν”„λ‘œμ„ΈμŠ€λŠ” GCD에 μ½”λ“œ 블둝을 전솑할 수 있으며, GCDκ°€ 싀행을 μ²˜λ¦¬ν•©λ‹ˆλ‹€. λ”°λΌμ„œ ν”„λ‘œμ„ΈμŠ€λŠ” μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•˜μ§€ μ•ŠμœΌλ©°, GCDλŠ” 자체 μŠ€λ ˆλ“œ 풀을 μ‚¬μš©ν•˜μ—¬ μ£Όμ–΄μ§„ μ½”λ“œλ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€(ν•„μš”μ— 따라 μ¦κ°€ν•˜κ±°λ‚˜ κ°μ†Œν•  수 μžˆμŠ΅λ‹ˆλ‹€).

μ΄λŠ” 병렬 싀행을 μ„±κ³΅μ μœΌλ‘œ κ΄€λ¦¬ν•˜λŠ” 데 맀우 μœ μš©ν•˜λ©°, ν”„λ‘œμ„ΈμŠ€κ°€ μƒμ„±ν•˜λŠ” μŠ€λ ˆλ“œ 수λ₯Ό 크게 쀄이고 병렬 싀행을 μ΅œμ ν™”ν•©λ‹ˆλ‹€. μ΄λŠ” 큰 병렬성(무차별 λŒ€μž…?)이 ν•„μš”ν•œ μž‘μ—…μ΄λ‚˜ 메인 μŠ€λ ˆλ“œλ₯Ό μ°¨λ‹¨ν•΄μ„œλŠ” μ•ˆ λ˜λŠ” μž‘μ—…μ— μ΄μƒμ μž…λ‹ˆλ‹€: 예λ₯Ό λ“€μ–΄, iOS의 메인 μŠ€λ ˆλ“œλŠ” UI μƒν˜Έμž‘μš©μ„ μ²˜λ¦¬ν•˜λ―€λ‘œ, 앱을 λ©ˆμΆ”κ²Œ ν•  수 μžˆλŠ” λ‹€λ₯Έ κΈ°λŠ₯(검색, μ›Ή μ ‘κ·Ό, 파일 읽기 λ“±)은 이 λ°©μ‹μœΌλ‘œ κ΄€λ¦¬λ©λ‹ˆλ‹€.

Blocks

블둝은 자체 ν¬ν•¨λœ μ½”λ“œ μ„Ήμ…˜(값을 λ°˜ν™˜ν•˜λŠ” μΈμˆ˜κ°€ μžˆλŠ” ν•¨μˆ˜μ™€ μœ μ‚¬)이며, λ°”μΈλ“œ λ³€μˆ˜λ₯Ό μ§€μ •ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
κ·ΈλŸ¬λ‚˜ 컴파일러 μˆ˜μ€€μ—μ„œ 블둝은 μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©°, os_objectμž…λ‹ˆλ‹€. μ΄λŸ¬ν•œ 각 κ°μ²΄λŠ” 두 개의 ꡬ쑰체둜 κ΅¬μ„±λ©λ‹ˆλ‹€:

  • 블둝 λ¦¬ν„°λŸ΄:
  • λΈ”λ‘μ˜ ν΄λž˜μŠ€μ— 포인터λ₯Ό κ°€λ¦¬ν‚€λŠ” isa ν•„λ“œλ‘œ μ‹œμž‘ν•©λ‹ˆλ‹€:
  • NSConcreteGlobalBlock ( __DATA.__const의 블둝)
  • NSConcreteMallocBlock (νž™μ˜ 블둝)
  • NSConcreateStackBlock (μŠ€νƒμ˜ 블둝)
  • flags (블둝 μ„€λͺ…μžμ— μ‘΄μž¬ν•˜λŠ” ν•„λ“œλ₯Ό λ‚˜νƒ€λƒ„) 및 일뢀 μ˜ˆμ•½λœ λ°”μ΄νŠΈκ°€ μžˆμŠ΅λ‹ˆλ‹€.
  • ν˜ΈμΆœν•  ν•¨μˆ˜ 포인터
  • 블둝 μ„€λͺ…μžμ— λŒ€ν•œ 포인터
  • κ°€μ Έμ˜¨ 블둝 λ³€μˆ˜(μžˆλŠ” 경우)
  • 블둝 μ„€λͺ…μž: ν¬κΈ°λŠ” μ‘΄μž¬ν•˜λŠ” 데이터에 따라 λ‹€λ¦…λ‹ˆλ‹€(이전 ν”Œλž˜κ·Έμ—μ„œ λ‚˜νƒ€λ‚Έ λŒ€λ‘œ).
  • 일뢀 μ˜ˆμ•½λœ λ°”μ΄νŠΈκ°€ μžˆμŠ΅λ‹ˆλ‹€.
  • 크기
  • 일반적으둜 λ§€κ°œλ³€μˆ˜μ— ν•„μš”ν•œ 곡간을 μ•ŒκΈ° μœ„ν•΄ Objective-C μŠ€νƒ€μΌ μ„œλͺ…에 λŒ€ν•œ 포인터가 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€(ν”Œλž˜κ·Έ BLOCK_HAS_SIGNATURE).
  • λ³€μˆ˜κ°€ μ°Έμ‘°λ˜λŠ” 경우, 이 블둝은 볡사 λ„μš°λ―Έ(μ‹œμž‘ μ‹œ 값을 볡사) 및 ν•΄μ œ λ„μš°λ―Έ(ν•΄μ œ)λ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터도 κ°€μ§‘λ‹ˆλ‹€.

Queues

λ””μŠ€νŒ¨μΉ˜ νλŠ” 싀행을 μœ„ν•œ λΈ”λ‘μ˜ FIFO μˆœμ„œλ₯Ό μ œκ³΅ν•˜λŠ” λͺ…λͺ…λœ κ°μ²΄μž…λ‹ˆλ‹€.

블둝은 싀행을 μœ„ν•΄ 큐에 μ„€μ •λ˜λ©°, 이듀은 DISPATCH_QUEUE_SERIAL 및 DISPATCH_QUEUE_CONCURRENT의 두 κ°€μ§€ λͺ¨λ“œλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€. λ¬Όλ‘  직렬 νλŠ” 경쟁 쑰건 λ¬Έμ œκ°€ μ—†μœΌλ©°, 블둝은 이전 블둝이 μ™„λ£Œλ  λ•ŒκΉŒμ§€ μ‹€ν–‰λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ λ‹€λ₯Έ μœ ν˜•μ˜ νλŠ” 그럴 수 μžˆμŠ΅λ‹ˆλ‹€.

기본 큐:

  • .main-thread: dispatch_get_main_queue()μ—μ„œ
  • .libdispatch-manager: GCD의 큐 κ΄€λ¦¬μž
  • .root.libdispatch-manager: GCD의 큐 κ΄€λ¦¬μž
  • .root.maintenance-qos: μ΅œμ € μš°μ„  μˆœμœ„ μž‘μ—…
  • .root.maintenance-qos.overcommit
  • .root.background-qos: DISPATCH_QUEUE_PRIORITY_BACKGROUND둜 μ‚¬μš© κ°€λŠ₯
  • .root.background-qos.overcommit
  • .root.utility-qos: DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE둜 μ‚¬μš© κ°€λŠ₯
  • .root.utility-qos.overcommit
  • .root.default-qos: DISPATCH_QUEUE_PRIORITY_DEFAULT둜 μ‚¬μš© κ°€λŠ₯
  • .root.background-qos.overcommit
  • .root.user-initiated-qos: DISPATCH_QUEUE_PRIORITY_HIGH둜 μ‚¬μš© κ°€λŠ₯
  • .root.background-qos.overcommit
  • .root.user-interactive-qos: κ°€μž₯ 높은 μš°μ„  μˆœμœ„
  • .root.background-qos.overcommit

각 μ‹œμ μ—μ„œ μ–΄λ–€ μŠ€λ ˆλ“œκ°€ μ–΄λ–€ 큐λ₯Ό μ²˜λ¦¬ν• μ§€ κ²°μ •ν•˜λŠ” 것은 μ‹œμŠ€ν…œμ΄λ―€λ‘œ μ£Όμ˜ν•˜μ„Έμš”(μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ λ™μΌν•œ νμ—μ„œ μž‘μ—…ν•  수 μžˆκ±°λ‚˜ λ™μΌν•œ μŠ€λ ˆλ“œκ°€ μ—¬λŸ¬ νμ—μ„œ μž‘μ—…ν•  수 μžˆμŠ΅λ‹ˆλ‹€).

Attributtes

**dispatch_queue_create**둜 큐λ₯Ό 생성할 λ•Œ μ„Έ 번째 μΈμˆ˜λŠ” dispatch_queue_attr_t둜, 일반적으둜 DISPATCH_QUEUE_SERIAL(μ‹€μ œλ‘œλŠ” NULL) λ˜λŠ” DISPATCH_QUEUE_CONCURRENT둜, 큐의 일뢀 λ§€κ°œλ³€μˆ˜λ₯Ό μ œμ–΄ν•  수 μžˆλŠ” dispatch_queue_attr_t ꡬ쑰체에 λŒ€ν•œ ν¬μΈν„°μž…λ‹ˆλ‹€.

Dispatch objects

libdispatchκ°€ μ‚¬μš©ν•˜λŠ” μ—¬λŸ¬ 객체가 있으며, 큐와 블둝은 κ·Έ 쀑 두 가지에 λΆˆκ³Όν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ κ°μ²΄λŠ” dispatch_object_create둜 생성할 수 μžˆμŠ΅λ‹ˆλ‹€:

  • block
  • data: 데이터 블둝
  • group: 블둝 κ·Έλ£Ή
  • io: 비동기 I/O μš”μ²­
  • mach: Mach 포트
  • mach_msg: Mach λ©”μ‹œμ§€
  • pthread_root_queue: pthread μŠ€λ ˆλ“œ 풀을 κ°€μ§„ 큐 및 μž‘μ—… 큐가 μ•„λ‹˜
  • queue
  • semaphore
  • source: 이벀트 μ†ŒμŠ€

Objective-C

Objective-Cμ—μ„œλŠ” 블둝을 λ³‘λ ¬λ‘œ μ‹€ν–‰ν•˜κΈ° μœ„ν•΄ μ „μ†‘ν•˜λŠ” λ‹€μ–‘ν•œ ν•¨μˆ˜κ°€ μžˆμŠ΅λ‹ˆλ‹€:

  • dispatch_async: λ””μŠ€νŒ¨μΉ˜ νμ—μ„œ 비동기 싀행을 μœ„ν•΄ 블둝을 μ œμΆœν•˜κ³  μ¦‰μ‹œ λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • dispatch_sync: 싀행을 μœ„ν•΄ 블둝 객체λ₯Ό μ œμΆœν•˜κ³  ν•΄λ‹Ή 블둝이 싀행을 마친 ν›„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • dispatch_once: μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 생애 λ™μ•ˆ 블둝 객체λ₯Ό ν•œ 번만 μ‹€ν–‰ν•©λ‹ˆλ‹€.
  • dispatch_async_and_wait: 싀행을 μœ„ν•΄ μž‘μ—… ν•­λͺ©μ„ μ œμΆœν•˜κ³  싀행이 μ™„λ£Œλœ ν›„μ—λ§Œ λ°˜ν™˜ν•©λ‹ˆλ‹€. dispatch_sync와 달리, 이 ν•¨μˆ˜λŠ” 블둝을 μ‹€ν–‰ν•  λ•Œ 큐의 λͺ¨λ“  속성을 μ‘΄μ€‘ν•©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ ν•¨μˆ˜λŠ” λ‹€μŒ λ§€κ°œλ³€μˆ˜λ₯Ό κΈ°λŒ€ν•©λ‹ˆλ‹€: dispatch_queue_t queue, dispatch_block_t block

이것은 λΈ”λ‘μ˜ κ΅¬μ‘°μ²΄μž…λ‹ˆλ‹€:

struct Block {
void *isa; // NSConcreteStackBlock,...
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
// captured variables go here
};

그리고 이것은 **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**λŠ” μ›λž˜ C둜 μž‘μ„±λœ Grand Central Dispatch (GCD) ν”„λ ˆμž„μ›Œν¬μ— λŒ€ν•œ Swift 바인딩을 μ œκ³΅ν•˜λŠ” λΌμ΄λΈŒλŸ¬λ¦¬μž…λ‹ˆλ‹€.
libswiftDispatch λΌμ΄λΈŒλŸ¬λ¦¬λŠ” C GCD APIλ₯Ό 더 Swift μΉœν™”μ μΈ μΈν„°νŽ˜μ΄μŠ€λ‘œ 감싸, Swift κ°œλ°œμžκ°€ 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"))

Code example:

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

λ‹€μŒ Frida μŠ€ν¬λ¦½νŠΈλŠ” μ—¬λŸ¬ dispatch ν•¨μˆ˜μ— ν›„ν‚Ήν•˜κ³  큐 이름, 백트레이슀 및 블둝을 μΆ”μΆœν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€: 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

ν˜„μž¬ GhidraλŠ” ObjectiveC dispatch_block_t ꡬ쑰체와 swift_dispatch_block ꡬ쑰체λ₯Ό μ΄ν•΄ν•˜μ§€ λͺ»ν•©λ‹ˆλ‹€.

κ·Έλž˜μ„œ 이듀을 μ΄ν•΄ν•˜λ„λ‘ ν•˜λ €λ©΄, μ„ μ–Έν•˜λ©΄ λ©λ‹ˆλ‹€:

그런 λ‹€μŒ, μ½”λ“œμ—μ„œ 이듀이 μ‚¬μš©λ˜λŠ” μœ„μΉ˜λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€:

Tip

β€œblockβ€œμ— λŒ€ν•œ λͺ¨λ“  μ°Έμ‘°λ₯Ό κΈ°λ‘ν•˜μ—¬ ꡬ쑰체가 μ‚¬μš©λ˜κ³  μžˆμŒμ„ νŒŒμ•…ν•˜λŠ” 방법을 μ΄ν•΄ν•˜μ„Έμš”.

λ³€μˆ˜μ—μ„œ 였λ₯Έμͺ½ 클릭 -> λ³€μˆ˜ μž¬μž…λ ₯ 및 이 경우 **swift_dispatch_block**을 μ„ νƒν•©λ‹ˆλ‹€:

GhidraλŠ” λͺ¨λ“  것을 μžλ™μœΌλ‘œ λ‹€μ‹œ μž‘μ„±ν•©λ‹ˆλ‹€:

References

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°