# iOS Frida Configuration

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

### [WhiteIntel](https://whiteintel.io)

<figure><img src="/files/YEhfJ0lgKxxdqFKA17yB" alt=""><figcaption></figcaption></figure>

[**WhiteIntel**](https://whiteintel.io)是一个由**暗网**支持的搜索引擎，提供免费功能，用于检查公司或其客户是否受到**窃取恶意软件**的**侵害**。

WhiteIntel的主要目标是打击由信息窃取恶意软件导致的账户劫持和勒索软件攻击。

您可以访问他们的网站并免费尝试他们的引擎：

{% embed url="<https://whiteintel.io>" %}

***

## 安装Frida

**在越狱设备上安装Frida的步骤：**

1. 打开Cydia/Sileo应用。
2. 转到管理 -> 源 -> 编辑 -> 添加。
3. 输入"<https://build.frida.re"作为URL。>
4. 转到新添加的Frida源。
5. 安装Frida软件包。

如果您使用**Corellium**，您需要从<https://github.com/frida/frida/releases>下载Frida版本（`frida-gadget-[yourversion]-ios-universal.dylib.gz`），并解压缩并复制到Frida要求的dylib位置，例如：`/Users/[youruser]/.cache/frida/gadget-ios.dylib`

安装后，您可以在PC上使用命令\*\*`frida-ls-devices`**并检查设备是否显示（您的PC需要能够访问它）。**\
**还可以执行**`frida-ps -Uia`\*\*来检查手机的运行进程。

## 无需越狱设备和无需修补应用程序的Frida

查看这篇关于如何在非越狱设备上使用Frida而无需修补应用程序的博文：<https://mrbypass.medium.com/unlocking-potential-exploring-frida-objection-on-non-jailbroken-devices-without-application-ed0367a84f07>

## 安装Frida客户端

安装**Frida工具**：

```bash
pip install frida-tools
pip install frida
```

安装了Frida服务器并连接设备后，**检查**客户端是否**正常工作**：

```bash
frida-ls-devices  # List devices
frida-ps -Uia     # Get running processes
```

## Frida跟踪

```bash
# 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"
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 '*[* *]'
```

### 获取所有类和方法

* 自动完成：只需执行 `frida -U <program>`

<figure><img src="/files/VYJqRFe0CkGjHwjd1ynI" alt=""><figcaption></figcaption></figure>

* 获取**所有**可用的**类**（按字符串过滤）

{% code title="/tmp/script.js" %}

```javascript
// frida -U <program> -l /tmp/script.js

var filterClass = "filterstring";

if (ObjC.available) {
for (var className in ObjC.classes) {
if (ObjC.classes.hasOwnProperty(className)) {
if (!filterClass || className.includes(filterClass)) {
console.log(className);
}
}
}
} else {
console.log("Objective-C runtime is not available.");
}
```

{% endcode %}

* 获取类的所有方法（按字符串过滤）

{% code title="/tmp/script.js" %}

```javascript
// frida -U <program> -l /tmp/script.js

var specificClass = "YourClassName";
var filterMethod = "filtermethod";

if (ObjC.available) {
if (ObjC.classes.hasOwnProperty(specificClass)) {
var methods = ObjC.classes[specificClass].$ownMethods;
for (var i = 0; i < methods.length; i++) {
if (!filterMethod || methods[i].includes(filterClass)) {
console.log(specificClass + ': ' + methods[i]);
}
}
} else {
console.log("Class not found.");
}
} else {
console.log("Objective-C runtime is not available.");
}
```

{% endcode %}

* **调用函数**

```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模糊测试

### Frida Stalker

[来自文档](https://frida.re/docs/stalker/)：Stalker是Frida的代码**跟踪引擎**。它允许跟踪线程，**捕获**每个函数，**每个代码块**，甚至执行的每条指令。

您可以在<https://github.com/poxyran/misc/blob/master/frida-stalker-example.py>找到一个实现Frida Stalker的示例。

这是另一个示例，每次调用函数时附加Frida Stalker：

```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" %}
这对于调试目的很有趣，但对于模糊测试来说，不断地 **`.follow()`** 和 **`.unfollow()`** 是非常低效的。
{% endhint %}

## [Fpicker](https://github.com/ttdennis/fpicker)

[**fpicker**](https://github.com/ttdennis/fpicker) 是一个基于 **Frida 的模糊测试套件**，提供各种模糊测试模式，如 AFL++ 模式或被动跟踪模式。它应该可以在所有 Frida 支持的平台上运行。

* [**安装 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
```

* **准备文件系统：**

```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脚本** (`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 %}

* **编译** fuzzer:

```bash
# From inside fpicker clone
## Compile from "myfuzzer.js" to "harness.js"
frida-compile examples/wg-log/myfuzzer.js -o harness.js
```

* 使用 **`radamsa`** 调用模糊器 **`fpicker`**：

{% 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" %}
在这种情况下，我们在每个有效负载之后**不重新启动应用程序或恢复状态**。因此，如果 Frida 发现一个**崩溃**，那么在该有效负载之后的**下一个输入**可能也会**导致应用程序崩溃**（因为应用程序处于不稳定状态），即使**输入不应导致**应用程序崩溃。

此外，Frida 将钩入 iOS 的异常信号，因此当**Frida 发现崩溃**时，可能**不会生成 iOS 崩溃报告**。

为了防止这种情况，例如，我们可以在每次 Frida 崩溃后重新启动应用程序。
{% endhint %}

### 日志和崩溃

您可以检查**macOS 控制台**或\*\*`log`\*\* cli 来查看 macOS 日志。\
您还可以使用\*\*`idevicesyslog`**来检查 iOS 的日志。**\
**一些日志会省略添加**`<private>`\*\*的信息。要显示所有信息，您需要安装一些配置文件，从<https://developer.apple.com/bug-reporting/profiles-and-logs/>下载以启用私人信息。

如果您不知道该怎么办：

```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
```

您可以在以下位置检查崩溃情况：

* **iOS**
  * 设置 → 隐私 → 分析与改进 → 分析数据
  * `/private/var/mobile/Library/Logs/CrashReporter/`
* **macOS**:
  * `/Library/Logs/DiagnosticReports/`
  * `~/Library/Logs/DiagnosticReports`

{% hint style="warning" %}
iOS仅存储同一应用的25个崩溃情况，因此您需要清理，否则iOS将停止创建崩溃报告。
{% endhint %}

## Frida Android 教程

{% content-ref url="/pages/IvNEMKEDSLvjR5qftBUM" %}
[Frida Tutorial](/mobile-pentesting/android-app-pentesting/frida-tutorial.md)
{% endcontent-ref %}

## 参考资料

* <https://www.briskinfosec.com/blogs/blogsdetail/Getting-Started-with-Frida>

### [WhiteIntel](https://whiteintel.io)

<figure><img src="/files/YEhfJ0lgKxxdqFKA17yB" alt=""><figcaption></figcaption></figure>

[**WhiteIntel**](https://whiteintel.io) 是一个由**暗网**支持的搜索引擎，提供**免费**功能，用于检查公司或其客户是否受到**窃取恶意软件**的**侵害**。

WhiteIntel的主要目标是打击由信息窃取恶意软件导致的账户劫持和勒索软件攻击。

您可以访问他们的网站并免费尝试他们的引擎：

{% embed url="<https://whiteintel.io>" %}

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**上关注**我们。
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hacktricks.xsx.tw/mobile-pentesting/ios-pentesting/frida-configuration-in-ios.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
