hacktricks/mobile-pentesting/ios-pentesting/frida-configuration-in-ios.md

417 lines
17 KiB
Markdown
Raw Normal View History

# iOS Frida配置
2022-04-28 16:01:33 +00:00
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks云 ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 推特 🐦</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>
* 你在一个**网络安全公司**工作吗你想在HackTricks中看到你的**公司广告**吗?或者你想要**获取PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f) 或者 [**telegram群组**](https://t.me/peass) 或者 **关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
</details>
## 安装Frida
在越狱设备的**Cydia/Sileo**应用中,通过进入**Manage -> Sources -> Edit -> Add**并输入[**https://build.frida.re** ](https://build.frida.re)来添加Frida的存储库。这将在源列表中添加一个新的源。进入F**rida** **源**,现在你应该**安装** **Frida**软件包。
2021-11-30 16:46:07 +00:00
![](https://miro.medium.com/max/614/0\*qSD26kBtgt\_UIZk1.png)
如果你使用的是**Corellium**,你需要从[https://github.com/frida/frida/releases](https://github.com/frida/frida/releases)下载Frida的发布版本`frida-gadget-[yourversion]-ios-universal.dylib.gz`并解压缩并复制到Frida要求的dylib位置例如`/Users/[youruser]/.cache/frida/gadget-ios.dylib`
安装完成后,你可以在你的电脑上使用命令**`frida-ls-devices`**并检查设备是否出现(你的电脑需要能够访问它)。\
还可以执行**`frida-ps -Uia`**来检查手机上正在运行的进程。
## 无需越狱设备和无需修补应用程序的Frida
查看这篇关于如何在非越狱设备上使用Frida而无需修补应用程序的博客文章[https://mrbypass.medium.com/unlocking-potential-exploring-frida-objection-on-non-jailbroken-devices-without-application-ed0367a84f07](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跟踪
Frida is a dynamic instrumentation toolkit that allows you to inject JavaScript code into running processes. It is commonly used for reverse engineering, debugging, and dynamic analysis of mobile applications. In this section, we will discuss how to configure Frida for iOS pentesting.
Frida是一个动态插桩工具包允许您将JavaScript代码注入到正在运行的进程中。它通常用于移动应用程序的逆向工程、调试和动态分析。在本节中我们将讨论如何配置Frida用于iOS渗透测试。
### Setting up Frida Server on iOS
To use Frida on iOS, you need to set up Frida Server on the target device. Follow the steps below to configure Frida Server:
1. Jailbreak the iOS device or use a jailbroken device.
2. Install the Frida package from the Cydia repository.
3. Open a terminal and run the following command to start Frida Server:
```bash
frida-server -l 0.0.0.0
```
This will start Frida Server and listen on all available network interfaces.
4. Make sure the device and the machine running Frida have network connectivity.
### Connecting to Frida Server from the Host Machine
Once Frida Server is running on the iOS device, you can connect to it from your host machine using the Frida command-line tools or the Frida Python bindings. Follow the steps below to connect to Frida Server:
1. Install the Frida command-line tools or the Frida Python bindings on your host machine.
2. Open a terminal and run the following command to connect to Frida Server:
```bash
frida-ps -H <device_ip_address>
```
Replace `<device_ip_address>` with the IP address of the iOS device running Frida Server.
3. If the connection is successful, you will see a list of running processes on the iOS device.
### Injecting JavaScript Code into a Process
Once you are connected to Frida Server, you can inject JavaScript code into a running process on the iOS device. Follow the steps below to inject JavaScript code:
1. Identify the process ID (PID) of the target process using the `frida-ps` command.
2. Open a terminal and run the following command to inject JavaScript code into the target process:
```bash
frida -H <device_ip_address> -p <pid> -l <script.js>
```
Replace `<device_ip_address>` with the IP address of the iOS device running Frida Server, `<pid>` with the process ID of the target process, and `<script.js>` with the path to the JavaScript code file.
3. If the injection is successful, the JavaScript code will be executed in the target process.
### Conclusion
Configuring Frida for iOS pentesting involves setting up Frida Server on the target device and connecting to it from the host machine. Once connected, you can inject JavaScript code into running processes on the iOS device for reverse engineering, debugging, and dynamic analysis. Frida is a powerful tool that can greatly enhance your iOS pentesting capabilities.
```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="../../.gitbook/assets/image (687).png" 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
Stalker是Frida的代码**追踪引擎**。它允许跟踪线程,**捕获**每个函数,**每个块**,甚至每个执行的指令。
你可以在[https://github.com/poxyran/misc/blob/master/frida-stalker-example.py](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
```
* **模糊测试脚本** (`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 %}
* **编译**模糊测试器:
```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/](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="../android-app-pentesting/frida-tutorial/" %}
[frida-tutorial](../android-app-pentesting/frida-tutorial/)
{% endcontent-ref %}
<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>
* 您在**网络安全公司**工作吗您想在HackTricks中看到您的**公司广告**吗?或者您想要访问**PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或在**Twitter**上**关注**我[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享您的黑客技巧。**
</details>