hacktricks/macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md

10 KiB
Raw Blame History

macOS GCD - Grand Central Dispatch

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

HackTricksをサポートする他の方法:

基本情報

Grand Central Dispatch (GCD)、またはlibdispatchは、macOSとiOSの両方で利用可能です。これはAppleが開発した技術で、マルチコアハードウェア上でのアプリケーションの並行マルチスレッド実行を最適化するためのものです。

GCDは、アプリケーションがブロックオブジェクトの形でタスクを送信できるFIFOキューを提供し、管理します。ディスパッチキューに送信されたブロックは、システムによって完全に管理されるスレッドプール上で実行されます。GCDは自動的にディスパッチキューでタスクを実行するためのスレッドを作成し、利用可能なコア上でそれらのタスクを実行するようにスケジュールします。

{% hint style="success" %} 要約すると、コードを並行して実行するために、プロセスはコードのブロックをGCDに送信でき、GCDがその実行を管理します。したがって、プロセスは新しいスレッドを作成せず、GCDは自身のスレッドプールで与えられたコードを実行します。 {% endhint %}

これは、並行実行を成功させるために非常に役立ち、プロセスが作成するスレッドの数を大幅に減らし、並行実行を最適化します。これは、大きな並列性ブルートフォースが必要なタスクや、メインスレッドをブロックすべきでないタスクに理想的です。例えば、iOSのメインスレッドはUIのインタラクションを処理するため、アプリをハングさせる可能性のある他の機能検索、ウェブへのアクセス、ファイルの読み取りなどはこの方法で管理されます。

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"))

コード例:

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**構造体も理解していません。

それらを理解させたい場合は、単に宣言することができます:

次に、コード内でそれらが使用されている場所を見つけます:

{% hint style="success" %} "block"へのすべての参照に注意して、構造体が使用されていることをどのように判断できるかを理解してください。 {% endhint %}

変数を右クリック -> Retype Variableを選択し、この場合は**swift_dispatch_block**を選択します:

Ghidraは自動的にすべてを書き換えます

htARTE (HackTricks AWS Red Team Expert)でゼロからヒーローまでAWSハッキングを学ぶ

HackTricksをサポートする他の方法