Translated ['macos-hardening/macos-security-and-privilege-escalation/mac

This commit is contained in:
Translator 2024-04-29 10:23:47 +00:00
parent b73102126b
commit 820d37d8bd
5 changed files with 601 additions and 254 deletions

View file

@ -175,6 +175,7 @@
* [macOS Java Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-java-apps-injection.md)
* [macOS Library Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/README.md)
* [macOS Dyld Hijacking & DYLD\_INSERT\_LIBRARIES](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/macos-dyld-hijacking-and-dyld\_insert\_libraries.md)
* [macOS Dyld Process](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-library-injection/macos-dyld-process.md)
* [macOS Perl Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-perl-applications-injection.md)
* [macOS Python Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-python-applications-injection.md)
* [macOS Ruby Applications Injection](macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-ruby-applications-injection.md)

View file

@ -1,4 +1,4 @@
# macOS文件夹、文件和二进制文件内存
# macOS文件夹、文件和二进制文件 & 内存
<details>
@ -6,46 +6,46 @@
支持HackTricks的其他方式
- 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
- 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
- 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
- **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
- 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>
## 文件层次结构
- **/Applications**:已安装的应用程序应位于此处。所有用户都可以访问它们。
- **/bin**:命令行二进制文件
- **/cores**:如果存在,用于存储核心转储
- **/dev**:一切都被视为文件,因此您可能会在此处看到存储的硬件设备。
- **/etc**:配置文件
- **/Library**可以在此处找到许多与首选项、缓存和日志相关的子目录和文件。根目录和每个用户目录中都存在一个Library文件夹。
- **/private**:未记录,但许多提到的文件夹是符号链接到私有目录
- **/sbin**:基本系统二进制文件(与管理相关)
- **/System**使OS X运行的文件。您应该在这里主要找到Apple特定的文件而不是第三方文件
- **/tmp**文件将在3天后被删除这是指向/private/tmp的软链接
- **/Users**:用户的主目录。
- **/usr**:配置和系统二进制文件
- **/var**:日志文件
- **/Volumes**:挂载的驱动器将出现在这里。
- **/.vol**:运行`stat a.txt`,您将获得类似`16777223 7545753 -rw-r--r-- 1 username wheel ...`的内容其中第一个数字是文件所在卷的ID号第二个数字是索引节点号。您可以通过/.vol/访问具有信息的文件的内容,运行`cat /.vol/16777223/7545753`
* **/Applications**:已安装的应用程序应位于此处。所有用户都可以访问它们。
* **/bin**:命令行二进制文件
* **/cores**:如果存在,用于存储核心转储
* **/dev**:一切都被视为文件,因此您可能会在此处看到存储的硬件设备。
* **/etc**:配置文件
* **/Library**可以在此处找到许多与首选项、缓存和日志相关的子目录和文件。根目录和每个用户目录中都存在一个Library文件夹。
* **/private**:未记录,但许多提到的文件夹是符号链接到私有目录。
* **/sbin**:基本系统二进制文件(与管理相关)
* **/System**使OS X运行的文件。您应该在这里主要找到Apple特定的文件而不是第三方文件
* **/tmp**文件将在3天后被删除这是指向/private/tmp的软链接
* **/Users**:用户的主目录。
* **/usr**:配置和系统二进制文件
* **/var**:日志文件
* **/Volumes**:挂载的驱动器将出现在这里。
* **/.vol**:运行`stat a.txt`,您将获得类似`16777223 7545753 -rw-r--r-- 1 username wheel ...`的内容其中第一个数字是文件所在卷的ID号第二个数字是索引节点号。您可以通过/.vol/访问该文件的内容,使用该信息运行`cat /.vol/16777223/7545753`
### 应用程序文件夹
- **系统应用程序**位于`/System/Applications`
- **已安装的**应用程序通常安装在`/Applications`或`~/Applications`
- **应用程序数据**可以在`/Library/Application Support`中找到用于以root身份运行的应用程序以及在`~/Library/Application Support`中找到,用于以用户身份运行的应用程序。
- **需要以root身份运行**的第三方应用程序**守护程序**通常位于`/Library/PrivilegedHelperTools/`
- **沙箱**应用程序映射到`~/Library/Containers`文件夹。每个应用程序都有一个根据应用程序的捆绑ID`com.apple.Safari`)命名的文件夹。
- **内核**位于`/System/Library/Kernels/kernel`
- **Apple的内核扩展**位于`/System/Library/Extensions`
- **第三方内核扩展**存储在`/Library/Extensions`
* **系统应用程序**位于`/System/Applications`
* **已安装的**应用程序通常安装在`/Applications`或`~/Applications`
* **应用程序数据**可以在`/Library/Application Support`中找到用于以root身份运行的应用程序以及在`~/Library/Application Support`中找到,用于以用户身份运行的应用程序。
* **需要以root身份运行**的第三方应用程序**守护程序**通常位于`/Library/PrivilegedHelperTools/`
* **沙箱**应用程序映射到`~/Library/Containers`文件夹。每个应用程序都有一个根据应用程序的捆绑ID`com.apple.Safari`)命名的文件夹。
* **内核**位于`/System/Library/Kernels/kernel`
* **Apple的内核扩展**位于`/System/Library/Extensions`
* **第三方内核扩展**存储在`/Library/Extensions`
### 包含敏感信息的文件
macOS在几个位置存储诸如密码之类的信息
MacOS在几个位置存储诸如密码之类的信息
{% content-ref url="macos-sensitive-locations.md" %}
[macos-sensitive-locations.md](macos-sensitive-locations.md)
@ -59,23 +59,23 @@ macOS在几个位置存储诸如密码之类的信息
## OS X特定扩展
- **`.dmg`**:苹果磁盘映像文件在安装程序中非常常见。
- **`.kext`**它必须遵循特定结构是驱动程序的OS X版本它是一个捆绑包
- **`.plist`**也称为属性列表以XML或二进制格式存储信息。
- 可以是XML或二进制。可以使用以下命令读取二进制文件
- `defaults read config.plist`
- `/usr/libexec/PlistBuddy -c print config.plsit`
- `plutil -p ~/Library/Preferences/com.apple.screensaver.plist`
- `plutil -convert xml1 ~/Library/Preferences/com.apple.screensaver.plist -o -`
- `plutil -convert json ~/Library/Preferences/com.apple.screensaver.plist -o -`
- **`.app`**:遵循目录结构的苹果应用程序(它是一个捆绑包)。
- **`.dylib`**动态库类似于Windows的DLL文件
- **`.pkg`**与xar可扩展存档格式相同。可以使用installer命令安装这些文件的内容。
- **`.DS_Store`**:每个目录中都有此文件,它保存目录的属性和自定义。
- **`.Spotlight-V100`**:此文件夹出现在系统上每个卷的根目录上
- **`.metadata_never_index`**如果此文件位于卷的根目录中Spotlight将不会索引该卷。
- **`.noindex`**具有此扩展名的文件和文件夹不会被Spotlight索引。
- **`.sdef`**捆绑包中的文件指定如何从AppleScript与应用程序进行交互。
* **`.dmg`**:苹果磁盘映像文件在安装程序中非常常见。
* **`.kext`**它必须遵循特定结构是驱动程序的OS X版本它是一个捆绑包
* **`.plist`**也称为属性列表以XML或二进制格式存储信息。
* 可以是XML或二进制。可以使用以下命令读取二进制文件
* `defaults read config.plist`
* `/usr/libexec/PlistBuddy -c print config.plsit`
* `plutil -p ~/Library/Preferences/com.apple.screensaver.plist`
* `plutil -convert xml1 ~/Library/Preferences/com.apple.screensaver.plist -o -`
* `plutil -convert json ~/Library/Preferences/com.apple.screensaver.plist -o -`
* **`.app`**:遵循目录结构的苹果应用程序(它是一个捆绑包)。
* **`.dylib`**动态库类似于Windows的DLL文件
* **`.pkg`**与xar可扩展存档格式相同。可以使用安装程序命令安装这些文件的内容。
* **`.DS_Store`**:每个目录中都有此文件,它保存目录的属性和自定义。
* **`.Spotlight-V100`**:此文件夹出现在系统上每个卷的根目录中
* **`.metadata_never_index`**如果此文件位于卷的根目录中Spotlight将不会索引该卷。
* **`.noindex`**具有此扩展名的文件和文件夹不会被Spotlight索引。
* **`.sdef`**捆绑包中的文件指定如何从AppleScript与应用程序进行交互。
### macOS捆绑包
@ -85,11 +85,14 @@ macOS在几个位置存储诸如密码之类的信息
[macos-bundles.md](macos-bundles.md)
{% endcontent-ref %}
## Dyld共享缓存
## Dyld共享缓存SLC
在macOS和iOS所有系统共享库如框架和dylibs都**合并到一个单个文件**中,称为**dyld共享缓存**。这提高了性能,因为代码可以更快地加载。
在macOS和iOS所有系统共享库如框架和dylibs都**合并到一个文件**中,称为**dyld共享缓存**。这提高了性能,因为代码可以更快地加载。
与dyld共享缓存类似内核和内核扩展也编译到内核缓存中在引导时加载。
在macOS中它位于`/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/`,在旧版本中,您可能会在**`/System/Library/dyld/`**中找到**共享缓存**。\
在iOS中您可以在**`/System/Library/Caches/com.apple.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)
```bash
@ -103,36 +106,53 @@ dyldex_all [dyld_shared_cache_path] # Extract all
```
{% endcode %}
在旧版本中,您可能会在 **`/System/Library/dyld/`** 中找到 **共享缓存**
在 iOS 中,您可以在 **`/System/Library/Caches/com.apple.dyld/`** 中找到它们。
{% hint style="success" %}
请注意,即使 `dyld_shared_cache_util` 工具无法工作,您也可以将 **共享 dyld 二进制文件传递给 Hopper**Hopper 将能够识别所有库并让您 **选择要调查的库**
请注意,即使 `dyld_shared_cache_util` 工具无法工作,您也可以将**共享的 dyld 二进制文件传递给 Hopper**Hopper 将能够识别所有库并让您**选择要调查的库**
{% endhint %}
<figure><img src="../../../.gitbook/assets/image (1149).png" alt="" width="563"><figcaption></figcaption></figure>
一些提取器可能无法工作,因为 dylibs 预链接到硬编码地址,因此它们可能会跳转到未知地址
{% hint style="success" %}
还可以通过在 Xcode 中使用模拟器来下载 macOS 中其他 \*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`
{% endhint %}
### 映射 SLC
**`dyld`** 使用系统调用 **`shared_region_check_np`** 来检查 SLC 是否已映射(返回地址),并使用 **`shared_region_map_and_slide_np`** 来映射 SLC。
请注意,即使 SLC 在第一次使用时被滑动,所有**进程**都使用**相同的副本**,如果攻击者能够在系统中运行进程,则**消除了 ASLR** 保护。 这实际上在过去被利用过,并通过共享区域分页器进行了修复。
分支池是创建图像映射之间的小空间的小 Mach-O dylibs使得不可能插入函数。
### 覆盖 SLCs
使用环境变量:
* **`DYLD_DHARED_REGION=private DYLD_SHARED_CACHE_DIR=</path/dir> DYLD_SHARED_CACHE_DONT_VALIDATE=1`** -> 这将允许加载新的共享库缓存
* **`DYLD_SHARED_CACHE_DIR=avoid`** 并手动用符号链接替换共享缓存中的库与真实库(您需要提取它们)
## 特殊文件权限
### 文件夹权限
在一个 **文件夹** 中,**读取** 允许 **列出它****写入** 允许 **删除****写入** 文件,**执行** 允许 **遍历** 目录。因此,例如,一个用户对目录中的 **文件具有读取权限**,但他 **没有执行权限**,则 **无法读取** 该文件。
**文件夹**中,**读取**允许**列出**它,**写入**允许**删除**和**写入**文件,**执行**允许**遍历**目录。因此,例如,用户对**没有执行权限**的目录中的文件具有**读取权限**,则**无法读取**该文件。
### 标志修饰符
有一些标志可以设置在文件中,使文件的行为不同。您可以使用 `ls -lO /path/directory` 命令 **检查目录中文件的标志**
有一些标志可以设置在文件中,使文件的行为不同。您可以使用 `ls -lO /path/directory` 检查目录中文件的标志
* **`uchg`**:被称为 **uchange** 标志,将 **阻止任何更改或删除** **文件** 的操作。要设置它,请执行:`chflags uchg file.txt`
* root 用户可以 **移除该标志** 并修改文件
* **`uchg`**:称为**uchange**标志,将**阻止任何更改或删除**文件的操作。要设置它,请执行:`chflags uchg file.txt`
* root 用户可以**移除该标志**并修改文件
* **`restricted`**:此标志使文件受到 SIP 的保护(无法将此标志添加到文件)。
* **`Sticky bit`**:如果一个目录具有粘性位,**只有** 目录的 **所有者或 root 可以重命名或删除** 文件。通常在 /tmp 目录上设置此标志,以防止普通用户删除或移动其他用户的文件。
* **`粘性位`**:如果一个目录具有粘性位,**只有**目录的**所有者或 root 可以重命名或删除**文件。通常在 /tmp 目录上设置此标志,以防止普通用户删除或移动其他用户的文件。
所有标志都可以在文件 `sys/stat.h` 中找到(使用 `mdfind stat.h | grep stat.h` 查找),包括:
所有标志都可以在文件 `sys/stat.h` 中找到(使用 `mdfind stat.h | grep stat.h` 查找),它们是
* `UF_SETTABLE` 0x0000ffff可更改所有者标志的掩码。
* `UF_NODUMP` 0x00000001不要转储文件。
* `UF_IMMUTABLE` 0x00000002文件不得更改。
* `UF_SETTABLE` 0x0000ffff所有者可更改标志的掩码。
* `UF_NODUMP` 0x00000001不转储文件。
* `UF_IMMUTABLE` 0x00000002文件不更改。
* `UF_APPEND` 0x00000004只能追加写入文件。
* `UF_OPAQUE` 0x00000008目录对于联合是不透明的。
* `UF_COMPRESSED` 0x00000020文件已压缩某些文件系统
@ -143,21 +163,21 @@ dyldex_all [dyld_shared_cache_path] # Extract all
* `SF_SETTABLE` 0x3fff0000超级用户可更改的标志掩码。
* `SF_SYNTHETIC` 0xc0000000系统只读合成标志的掩码。
* `SF_ARCHIVED` 0x00010000文件已存档。
* `SF_IMMUTABLE` 0x00020000文件不更改。
* `SF_IMMUTABLE` 0x00020000文件不更改。
* `SF_APPEND` 0x00040000只能追加写入文件。
* `SF_RESTRICTED` 0x00080000需要写入的授权。
* `SF_NOUNLINK` 0x00100000项目不被移除、重命名或挂载。
* `SF_NOUNLINK` 0x00100000项目不被移除、重命名或挂载。
* `SF_FIRMLINK` 0x00800000文件是一个 firmlink。
* `SF_DATALESS` 0x40000000文件是无数据对象。
### **文件 ACLs**
文件 **ACLs** 包含 **ACE**(访问控制条目),可以为不同用户分配更**细粒度权限**
文件**ACLs** 包含**ACE**(访问控制条目),可以为不同用户分配更**精细的权限**
可以授予一个 **目录** 这些权限:`list`、`search`、`add_file`、`add_subdirectory`、`delete_child`、`delete_child`。\
对于一个 **文件**`read`、`write`、`append`、`execute`。
可以授予**目录**这些权限:`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
@ -174,7 +194,7 @@ ls -RAle / 2>/dev/null | grep -E -B1 "\d: "
```
### 扩展属性
扩展属性具有名称和任何所需值,可以使用 `ls -@` 查看,并使用 `xattr` 命令进行操作。一些常见的扩展属性包括:
扩展属性具有名称和任何所需值,可以使用 `ls -@` 查看,并使用 `xattr` 命令进行操作。一些常见的扩展属性包括:
- `com.apple.resourceFork`: 资源叉兼容性。也可在 `filename/..namedfork/rsrc` 中看到
- `com.apple.quarantine`: MacOS: Gatekeeper 隔离机制 (III/6)
@ -182,9 +202,9 @@ ls -RAle / 2>/dev/null | grep -E -B1 "\d: "
- `com.apple.lastuseddate` (#PS): 最后使用日期
- `com.apple.FinderInfo`: MacOS: Finder 信息(例如,颜色标签)
- `com.apple.TextEncoding`: 指定 ASCII 文本文件的文本编码
- `com.apple.logd.metadata`: 由 `/var/db/diagnostics` 中的 logd 在文件上使用
- `com.apple.logd.metadata`: 由位于 `/var/db/diagnostics` 中的 logd 使用的文件
- `com.apple.genstore.*`: 生成存储 (`/.DocumentRevisions-V100` 在文件系统根目录中)
- `com.apple.rootless`: MacOS: 由系统完整性保护使用以标记文件 (III/10)
- `com.apple.rootless`: MacOS: 由系统完整性保护用于标记文件 (III/10)
- `com.apple.uuidb.boot-uuid`: 具有唯一 UUID 的引导时期的 logd 标记
- `com.apple.decmpfs`: MacOS: 透明文件压缩 (II/7)
- `com.apple.cprotect`: \*OS: 每个文件的加密数据 (III/11)
@ -192,7 +212,7 @@ ls -RAle / 2>/dev/null | grep -E -B1 "\d: "
### 资源叉 | macOS ADS
这是在 MacOS 机器中获取**备用数据流**的一种方法。您可以通过将内容保存在名为 **com.apple.ResourceFork** 的扩展属性中的文件中保存在 **file/..namedfork/rsrc** 中。
这是在 MacOS 机器中获取**备用数据流**的一种方法。您可以通过将内容保存在名为 **com.apple.ResourceFork** 的扩展属性中的文件中,将其保存在 **file/..namedfork/rsrc** 中。
```bash
echo "Hello" > a.txt
echo "Hello Mac ADS" > a.txt/..namedfork/rsrc
@ -209,19 +229,17 @@ ls -l a.txt #The file length is still q
```bash
find / -type f -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; printf "\n"}' | xargs -I {} xattr -lv {} | grep "com.apple.ResourceFork"
```
{% endcode %}
## decmpfs
### decmpfs
扩展属性`com.apple.decmpfs`表示文件已加密存储,`ls -l`将报告**大小为0**,压缩数据位于此属性内。每当访问文件时,它将在内存中解密。
扩展属性 `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可用于强制解压缩文件
工具 afscexpand 可用于强制解压缩文件。
## **通用二进制文件和** Mach-o 格式
## **通用二进制文件 &** Mach-o 格式
Mac OS 二进制文件通常编译为**通用二进制文件**。**通用二进制文件** 可以**在同一文件中支持多个架构**。
Mac OS 二进制文件通常编译为**通用二进制文件**。**通用二进制文件**可以在同一文件中**支持多个架构**。
{% content-ref url="universal-binaries-and-mach-o-format.md" %}
[universal-binaries-and-mach-o-format.md](universal-binaries-and-mach-o-format.md)
@ -235,20 +253,20 @@ Mac OS 二进制文件通常编译为**通用二进制文件**。**通用二进
## Mac OS 风险类别文件
目录 `/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/System` 存储有关不同文件扩展名的**风险级别信息**。目录将文件分类为不同的风险级别,影响 Safari 在下载后如何处理这些文件。分类如下:
目录`/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/System`存储有关不同文件扩展名的**风险级别信息**。目录将文件分类为不同的风险级别,影响 Safari 在下载后如何处理这些文件。各类别如下:
* **LSRiskCategorySafe**:此类文件被认为**完全安全**。Safari 将在下载后自动打开这些文件。
* **LSRiskCategoryNeutral**这些文件没有警告Safari **不会自动打开**它们。
* **LSRiskCategoryUnsafeExecutable**:此类文件会**触发警告**,指示文件是一个应用程序。这是一项安全措施,用于提醒用户。
* **LSRiskCategoryMayContainUnsafeExecutable**:此类文件,如存档文件,可能包含可执行文件。除非 Safari 可以验证所有内容是安全或中立,否则 Safari 将**触发警告**。
- **LSRiskCategorySafe**:此类别中的文件被认为是**完全安全**的。Safari 将在下载后自动打开这些文件。
- **LSRiskCategoryNeutral**:这些文件没有警告,并且**Safari 不会自动打开**它们。
- **LSRiskCategoryUnsafeExecutable**:此类别下的文件会**触发警告**,指示文件是一个应用程序。这是一项安全措施,用于提醒用户。
- **LSRiskCategoryMayContainUnsafeExecutable**:此类别适用于可能包含可执行文件的文件,例如存档文件。除非 Safari 可以验证所有内容是安全或中立,否则将**触发警告**。
## 日志文件
* **`$HOME/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**:包含有关下载文件的信息,如下载文件的 URL。
* **`/var/log/system.log`**OSX 系统的主要日志。com.apple.syslogd.plist 负责执行系统日志记录(您可以通过在 `launchctl list` 中查找 "com.apple.syslogd" 来检查是否已禁用)。
* **`/private/var/log/asl/*.asl`**:这些是可能包含有趣信息的 Apple 系统日志。
* **`$HOME/Library/Preferences/com.apple.recentitems.plist`**存储通过“Finder”最近访问的文件和应用程序。
* **`$HOME/Library/Preferences/com.apple.loginitems.plsit`**:存储系统启动时要启动的项目。
* **`$HOME/Library/Logs/DiskUtility.log`**DiskUtility 应用程序的日志文件(包含有关驱动器的信息,包括 USB 设备)。
* **`/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist`**:关于无线访问点的数据。
* **`/private/var/db/launchd.db/com.apple.launchd/overrides.plist`**:已停用的守护进程列表。
- **`$HOME/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2`**:包含有关下载文件的信息,如下载文件的 URL。
- **`/var/log/system.log`**OSX 系统的主要日志。com.apple.syslogd.plist 负责执行系统日志记录(您可以通过在`launchctl list`中查找"com.apple.syslogd"来检查是否已禁用)。
- **`/private/var/log/asl/*.asl`**:这些是可能包含有趣信息的 Apple 系统日志。
- **`$HOME/Library/Preferences/com.apple.recentitems.plist`**存储通过“Finder”最近访问的文件和应用程序。
- **`$HOME/Library/Preferences/com.apple.loginitems.plsit`**:存储系统启动时要启动的项目。
- **`$HOME/Library/Logs/DiskUtility.log`**DiskUtility 应用程序的日志文件(包含有关驱动器的信息,包括 USB 设备)。
- **`/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist`**:关于无线访问点的数据。
- **`/private/var/db/launchd.db/com.apple.launchd/overrides.plist`**:已停用的守护进程列表。

View file

@ -1,28 +1,30 @@
# macOS Function Hooking
# macOS函数挂钩
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS Red Team Expert</strong></a><strong></strong></summary>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS红队专家</strong></a><strong></strong></summary>
支持HackTricks的其他方式
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
- 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
- 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
- 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
- **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
- 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>
## 函数插入
创建一个包含指向**原始**和**替换**函数的**函数指针**元组的**dylib**,其中包含一个\*\*`__interpose`**部分(或标记为**`S_INTERPOSING`\*\*的部分)。
创建一个包含指向**原始**和**替换**函数的**函数指针**元组的**dylib**,其中包含一个**`__interpose` (`__DATA___interpose`)**部分(或一个标记为**`S_INTERPOSING`**的部分)。
然后,使用\*\*`DYLD_INSERT_LIBRARIES`**注入dylib插入操作需要在主应用程序加载之前发生。显然这里也适用于对**`DYLD_INSERT_LIBRARIES`\*\*的[**限制**](macos-library-injection/#check-restrictions)。
然后,使用**`DYLD_INSERT_LIBRARIES`**注入dylib插入操作需要在主应用程序加载之前发生。显然这里也适用于对**`DYLD_INSERT_LIBRARIES`**的[**限制**](macos-library-injection/#check-restrictions)。
### 插入printf
{% code title="interpose.c" %}
{% tabs %}
{% tab title="interpose.c" %}
{% code title="interpose.c" overflow="wrap" %}
```c
// gcc -dynamiclib interpose.c -o interpose.dylib
#include <stdio.h>
@ -42,7 +44,9 @@ __attribute__((used)) static struct { const void *replacement; const void *repla
__attribute__ ((section ("__DATA,__interpose"))) = { (const void *)(unsigned long)&my_printf, (const void *)(unsigned long)&printf };
```
{% endcode %}
{% endtab %}
{% tab title="hello.c" %}
```c
//gcc hello.c -o hello
#include <stdio.h>
@ -52,33 +56,10 @@ printf("Hello World!\n");
return 0;
}
```
{% endtab %}
#### macOS功能挂钩
macOS提供了一种称为`DYLD_INSERT_LIBRARIES`的环境变量,允许我们在程序加载时注入动态链接库。这为我们提供了一种功能挂钩的方法,可以用来劫持程序的函数调用。
我们可以创建一个动态链接库,重写目标函数的实现,然后将其注入到目标程序中。这样,当目标程序调用该函数时,实际上会执行我们注入的代码。
以下是一个示例,展示了如何使用`DYLD_INSERT_LIBRARIES`环境变量来劫持`open`函数的调用:
```c
#include <stdio.h>
#include <dlfcn.h>
int open(const char *path, int oflag, ...) {
int (*original_open)(const char *, int, ...);
original_open = dlsym(RTLD_NEXT, "open");
printf("Intercepted open call: %s\n", path);
return original_open(path, oflag);
}
```
在这个示例中,我们重写了`open`函数,添加了一行打印语句,然后调用原始的`open`函数。
通过这种方式,我们可以在不修改目标程序源代码的情况下,劫持其函数调用,实现各种有趣的功能。
{% tab title="interpose2.c" %}
{% code overflow="wrap" %}
```c
// Just another way to define an interpose
// gcc -dynamiclib interpose2.c -o interpose2.dylib
@ -102,7 +83,9 @@ return ret;
DYLD_INTERPOSE(my_printf,printf);
```
{% endcode %}
{% endtab %}
{% endtabs %}
```bash
DYLD_INSERT_LIBRARIES=./interpose.dylib ./hello
Hello from interpose
@ -110,25 +93,44 @@ Hello from interpose
DYLD_INSERT_LIBRARIES=./interpose2.dylib ./hello
Hello from interpose
```
{% hint style="warning" %}
**`DYLD_PRINT_INTERPOSTING`** 环境变量可用于调试 interposing并将打印 interpose 过程。
{% endhint %}
还要注意,**interposing 发生在进程和加载的库之间**,它不适用于共享库缓存。
### 动态 Interposing
现在也可以使用函数 **`dyld_dynamic_interpose`** 动态地 interpose 一个函数。这允许在运行时以编程方式 interpose 一个函数,而不仅仅是从一开始就这样做。
只需要指示**要替换的函数和替换函数的元组**。
```c
struct dyld_interpose_tuple {
const void* replacement;
const void* replacee;
};
extern void dyld_dynamic_interpose(const struct mach_header* mh,
const struct dyld_interpose_tuple array[], size_t count);
```
## 方法交换
在 ObjectiveC 中,方法的调用方式如下:**`[myClassInstance nameOfTheMethodFirstParam:param1 secondParam:param2]`**
需要**对象**、**方法**和**参数**。当调用方法时,会使用函数\*\*`objc_msgSend`**发送**消息\*\*`int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);`
需要**对象**、**方法**和**参数**。当调用方法时,会使用函数**`objc_msgSend`**发送**消息**`int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);`
对象是\*\*`someObject`**,方法是**`@selector(method1p1:p2:)`**,参数是**value1\*\*、**value2**。
对象是**`someObject`**,方法是**`@selector(method1p1:p2:)`**,参数是**value1**、**value2**。
根据对象结构,可以访问一个包含方法**名称**和**指向方法代码的指针**的**方法数组**。
{% hint style="danger" %}
请注意,由于方法和类是根据它们的名称访问的,这些信息存储在二进制文件中,因此可以使用 `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) 检索它
{% endhint %}
### 访问原始方法
可以访问方法的信息,如名称、参数数量或地址,如下例所示:
{% code overflow="wrap" %}
```objectivec
// gcc -framework Foundation test.m -o test
@ -194,15 +196,15 @@ NSLog(@"Uppercase string: %@", uppercaseString3);
return 0;
}
```
### 使用`method_exchangeImplementations`进行方法交换
函数\*\*`method_exchangeImplementations`**允许**更改**一个函数的**实现地址为另一个函数\*\*。
函数**`method_exchangeImplementations`**允许**更改**一个函数的**实现地址为另一个函数**的地址
{% hint style="danger" %}
因此,当调用一个函数时,**执行的是另一个函数**。
{% endhint %}
{% code overflow="wrap" %}
```objectivec
//gcc -framework Foundation swizzle_str.m -o swizzle_str
@ -246,6 +248,7 @@ NSLog(@"Substring: %@", subString);
return 0;
}
```
{% endcode %}
{% hint style="warning" %}
在这种情况下,如果**合法方法的实现代码**验证**方法名称**,它可以**检测**到这种方法交换并阻止其运行。
@ -255,10 +258,11 @@ return 0;
### 使用method\_setImplementation进行方法交换
之前的格式很奇怪,因为你正在改变其中一个方法的实现。使用函数\*\*`method_setImplementation`**,您可以将一个方法的**实现更改为另一个方法\*\*。
之前的格式很奇怪,因为你正在改变其中一个方法的实现。使用函数**`method_setImplementation`**,你可以将一个方法的实现**更改为另一个方法**。
只需记住,如果打算从新实现中调用原始实现的地址,**存储原始实现的地址**,因为稍后要定位该地址将变得更加复杂。
只需记住,如果打算从新实现中调用原始实现的地址,**存储原始实现的地址**,因为稍后要定位该地址将变得更加复杂。
{% code overflow="wrap" %}
```objectivec
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@ -310,19 +314,19 @@ return 0;
}
}
```
{% endcode %}
## Hooking Attack Methodology
在这一页中,讨论了不同的挂钩函数的方法。然而,它们涉及**在进程内运行代码进行攻击**。
在这一页中,讨论了钩函数的不同方法。然而,它们涉及**在进程内运行代码进行攻击**。
为了做到这一点,最简单的技术是通过环境变量或劫持注入[Dyld](macos-library-injection/macos-dyld-hijacking-and-dyld\_insert\_libraries.md)。然而,我认为这也可以通过[通过任务端口进行的Dylib进程注入](macos-ipc-inter-process-communication/#dylib-process-injection-via-task-port)来实现。
为了做到这一点,最简单的技术是通过注入[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。
因此攻击者的向量将是要么找到漏洞要么剥离应用程序的签名通过应用程序的Info.plist注入\*\*`DYLD_INSERT_LIBRARIES`\*\*环境变量,添加类似以下内容:
然而,函数钩取攻击非常具体,攻击者会这样做是为了**从进程内部窃取敏感信息**如果不是的话你只会进行进程注入攻击。而这些敏感信息可能位于用户下载的应用程序中比如MacPass。
因此攻击者的向量将是要么找到一个漏洞要么剥离应用程序的签名通过应用程序的Info.plist注入**`DYLD_INSERT_LIBRARIES`**环境变量,添加类似以下内容:
```xml
<key>LSEnvironment</key>
<dict>
@ -330,7 +334,6 @@ return 0;
<string>/Applications/Application.app/Contents/malicious.dylib</string>
</dict>
```
然后**重新注册**应用程序:
{% code overflow="wrap" %}
@ -342,11 +345,12 @@ return 0;
在该库中添加挂钩代码以外泄信息:密码,消息...
{% hint style="danger" %}
请注意,在较新版本的 macOS 中,如果您**剥离应用程序二进制文件的签名**并且该应用程序之前已被执行macOS将**不再执行该应用程序**。
请注意,在 macOS 的新版本中,如果您**剥离应用程序二进制文件的签名**,并且该应用程序之前已被执行macOS将**不再执行该应用程序**。
{% endhint %}
#### 库示例
{% code overflow="wrap" %}
```objectivec
// gcc -dynamiclib -framework Foundation sniff.m -o sniff.dylib
@ -382,6 +386,7 @@ IMP fake_IMP = (IMP)custom_setPassword;
real_setPassword = method_setImplementation(real_Method, fake_IMP);
}
```
{% endcode %}
## 参考
@ -389,14 +394,14 @@ real_setPassword = method_setImplementation(real_Method, fake_IMP);
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
<summary><strong>从零开始学习 AWS 黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS 红队专家)</strong></a><strong></strong></summary>
支持HackTricks的其他方式
支持 HackTricks 的其他方式:
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
* 如果您想看到您的**公司在 HackTricks 中做广告**或**下载 PDF 版本的 HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
* 发现[**PEASS 家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或**关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)****
* 通过向 [**HackTricks**](https://github.com/carlospolop/hacktricks) [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来分享您的黑客技巧。
</details>

View file

@ -1,4 +1,4 @@
# macOS Library Injection
# macOS库注入
<details>
@ -6,55 +6,63 @@
支持HackTricks的其他方式
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
- 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
- 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
- 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[NFTs](https://opensea.io/collection/the-peass-family)收藏品
- **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
- 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>
{% hint style="danger" %}
**dyld的代码是开源的**,可以在[https://opensource.apple.com/source/dyld/](https://opensource.apple.com/source/dyld/)找到,并且可以使用类似[https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)的URL下载tar文件。
**dyld的代码是开源的**,可以在[https://opensource.apple.com/source/dyld/](https://opensource.apple.com/source/dyld/)找到,可以使用类似[https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)的URL下载tar文件。
{% endhint %}
## **Dyld进程**
查看Dyld如何在二进制文件中加载库
{% content-ref url="macos-dyld-process.md" %}
[macos-dyld-process.md](macos-dyld-process.md)
{% endcontent-ref %}
## **DYLD\_INSERT\_LIBRARIES**
这类似于[**Linux上的LD\_PRELOAD**](../../../../linux-hardening/privilege-escalation/#ld\_preload)。它允许指示一个进程将要运行以从路径加载特定库的库(如果启用了环境变量)
这类似于[**Linux上的LD\_PRELOAD**](../../../../linux-hardening/privilege-escalation/#ld\_preload)。它允许指示一个进程将从路径加载特定库(如果启用了环境变量)
这种技术也可以**用作ASEP技术**,因为每个安装的应用程序都有一个名为"Info.plist"的plist允许使用名为`LSEnvironmental`的键**分配环境变量**。
这种技术也可以**用作ASEP技术**,因为每个安装的应用程序都有一个名为"Info.plist"的属性列表,允许使用名为`LSEnvironmental`的键**分配环境变量**。
{% hint style="info" %}
自2012年以来**苹果大大降低了** **`DYLD_INSERT_LIBRARIES`** 的权限。
自2012年以来**苹果大大减少了** **`DYLD_INSERT_LIBRARIES`** 的权限。
转到代码并**检查`src/dyld.cpp`**。在函数\*\*`pruneEnvironmentVariables`**中,您可以看到**`DYLD_*`\*\*变量被移除
转到代码并**检查`src/dyld.cpp`**。在函数**`pruneEnvironmentVariables`**中,您可以看到**删除了`DYLD_*`**变量。
在函数\*\*`processRestricted`\*\*中设置了限制的原因。检查该代码,您会看到限制的原因是:
在函数**`processRestricted`**中设置了限制的原因。检查该代码,您会看到限制的原因是:
* 二进制文件是`setuid/setgid`
* 在macho二进制文件中存在`__RESTRICT/__restrict`部分。
* 软件具有没有[`com.apple.security.cs.allow-dyld-environment-variables`](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_allow-dyld-environment-variables)授权的强化运行时
* 使用以下命令检查二进制文件的**授权**`codesign -dv --entitlements :- </path/to/bin>`
- 二进制文件是`setuid/setgid`
- 在macho二进制文件中存在`__RESTRICT/__restrict`部分。
- 软件具有没有[`com.apple.security.cs.allow-dyld-environment-variables`](https://developer.apple.com/documentation/bundleresources/entitlements/com\_apple\_security\_cs\_allow-dyld-environment-variables)授权的强化运行时
- 使用以下命令检查二进制文件的**授权**`codesign -dv --entitlements :- </path/to/bin>`
在更新的版本中,您可以在函数\*\*`configureProcessRestrictions`**的第二部分找到这种逻辑。然而,在较新版本中执行的是函数的**开始检查\*\*您可以删除与iOS或模拟相关的if因为这些在macOS中不会使用
在更新的版本中,您可以在函数**`configureProcessRestrictions`**的第二部分找到此逻辑。但是,在较新版本中执行的是函数的**开始检查**您可以删除与iOS或模拟相关的if因为这些在macOS中不会使用
{% endhint %}
### 库验证
即使二进制文件允许使用\*\*`DYLD_INSERT_LIBRARIES`\*\*环境变量,如果二进制文件检查要加载的库的签名,不会加载自定义内容。
即使二进制文件允许使用**`DYLD_INSERT_LIBRARIES`**环境变量,如果二进制文件检查要加载的库的签名,它将不会加载自定义内容。
为了加载自定义库,二进制文件需要具有以下授权之一:
* [`com.apple.security.cs.disable-library-validation`](../../macos-security-protections/macos-dangerous-entitlements.md#com.apple.security.cs.disable-library-validation)
* [`com.apple.private.security.clear-library-validation`](../../macos-security-protections/macos-dangerous-entitlements.md#com.apple.private.security.clear-library-validation)
- [`com.apple.security.cs.disable-library-validation`](../../macos-security-protections/macos-dangerous-entitlements.md#com.apple.security.cs.disable-library-validation)
- [`com.apple.private.security.clear-library-validation`](../../macos-security-protections/macos-dangerous-entitlements.md#com.apple.private.security.clear-library-validation)
或者二进制文件**不应该**具有**强化运行时标志**或**库验证标志**。
您可以使用`codesign --display --verbose <bin>`检查二进制文件是否具有**强化运行时**,检查\*\*`CodeDirectory`**中的标志运行时,例如:**`CodeDirectory v=20500 size=767 flags=0x10000(runtime) hashes=13+7 location=embedded`\*\*
您可以使用`codesign --display --verbose <bin>`检查二进制文件是否具有**强化运行时**,检查**`CodeDirectory`**中的标志运行时,例如:**`CodeDirectory v=20500 size=767 flags=0x10000(runtime) hashes=13+7 location=embedded`**
如果**与二进制文件相同证书签名**,也可以加载库。
如果**使用与二进制文件相同证书签名**,也可以加载库。
找到一个关于如何(滥用)使用此功能并检查限制的示例:
找到一个关于如何(滥用)用此功能并检查限制的示例:
{% content-ref url="macos-dyld-hijacking-and-dyld_insert_libraries.md" %}
[macos-dyld-hijacking-and-dyld\_insert\_libraries.md](macos-dyld-hijacking-and-dyld\_insert\_libraries.md)
@ -63,28 +71,29 @@
## Dylib劫持
{% hint style="danger" %}
请记住**以前的库验证限制也适用**执行Dylib劫持攻击。
请记住**以前的库验证限制也适用**执行Dylib劫持攻击。
{% endhint %}
与Windows一样在MacOS中您也可以**劫持dylibs**以使**应用程序**执行**任意**代码实际上从普通用户这样做可能不可能因为您可能需要TCC权限才能写入`.app`包并劫持库)。 然而,**MacOS**应用程序**加载**库的方式**比Windows更受限制**。这意味着**恶意软件**开发人员仍然可以使用此技术进行**隐蔽**,但是**滥用此技术以提升权限的可能性要低得多**。
与Windows一样在MacOS中您也可以**劫持dylibs**以使**应用程序**执行**任意** **代码**实际上从普通用户这样做可能不可能因为您可能需要TCC权限才能写入`.app`包并劫持库)。\
然而,**MacOS**应用程序**加载**库的方式**比Windows更受限制**。这意味着**恶意软件**开发人员仍然可以使用此技术进行**隐蔽**,但是**滥用此技术以提升权限的可能性要低得多**。
首先,**更常见**的是发现**MacOS二进制文件指示要加载的库的完整路径**。其次,**MacOS从不在** **$PATH** **文件夹中搜索**库。
首先,**更常见**的是发现**MacOS二进制文件指示库的完整路径**。其次,**MacOS从不在** **$PATH** **文件夹中搜索**库。
与此功能相关的**主要**代码部分位于`ImageLoader.cpp`中的\*\*`ImageLoader::recursiveLoadLibraries`\*\*中。
与此功能相关的**主要**代码部分位于`ImageLoader.cpp`中的**`ImageLoader::recursiveLoadLibraries`**中。
Macho二进制文件可以使用**4个不同的头部命令**来加载库:
* \*\*`LC_LOAD_DYLIB`\*\*命令是加载dylib的常见命令。
* \*\*`LC_LOAD_WEAK_DYLIB`\*\*命令与前一个命令类似但如果未找到dylib则继续执行而不会出现任何错误。
* \*\*`LC_REEXPORT_DYLIB`\*\*命令代理(或重新导出)来自不同库的符号。
* \*\*`LC_LOAD_UPWARD_DYLIB`\*\*命令在两个库彼此依赖时使用(这称为\_向上依赖\_
- **`LC_LOAD_DYLIB`**命令是加载dylib的常见命令。
- **`LC_LOAD_WEAK_DYLIB`**命令与前一个命令类似但如果未找到dylib则继续执行而不会出现任何错误。
- **`LC_REEXPORT_DYLIB`**命令代理(或重新导出)来自不同库的符号。
- **`LC_LOAD_UPWARD_DYLIB`**命令在两个库彼此依赖时使用这称为_向上依赖_
然而,有**2种dylib劫持**
* **缺失的弱链接库**:这意味着应用程序将尝试加载一个使用**LC\_LOAD\_WEAK\_DYLIB**配置的不存在的库。然后,**如果攻击者将dylib放在预期的位置它将被加载**。
* 与此相关的**代码**在`ImageLoaderMachO.cpp`的`ImageLoaderMachO::doGetDependentLibraries`函数中,其中`lib->required`仅在`LC_LOAD_WEAK_DYLIB`为true时为`false`
* 在二进制文件中查找**弱链接库**(稍后您将看到如何创建劫持库的示例):
- **缺失的弱链接库**:这意味着应用程序将尝试加载一个使用**LC\_LOAD\_WEAK\_DYLIB**配置的不存在的库。然后,**如果攻击者将dylib放在预期的位置它将被加载**。
- 链接是“弱”的意思是即使未找到库,应用程序也将继续运行
- 与此相关的**代码**位于`ImageLoaderMachO.cpp`的`ImageLoaderMachO::doGetDependentLibraries`函数中,其中`lib->required`仅在`LC_LOAD_WEAK_DYLIB`为true时为`false`。
- 在二进制文件中查找**弱链接库**(稍后您将看到如何创建劫持库的示例):
```bash
otool -l </path/to/bin> | grep LC_LOAD_WEAK_DYLIB -A 5 cmd LC_LOAD_WEAK_DYLIB
cmdsize 56
@ -93,24 +102,25 @@ Macho二进制文件可以使用**4个不同的头部命令**来加载库:
current version 1.0.0
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`\*\*中路径的顺序
* 使用以下命令在二进制文件中查找rpath路径和库`otool -l </path/to/binary> | grep -E "LC_RPATH|LC_LOAD_DYLIB" -A 5`
- **配置为@rpath**Mach-O二进制文件可以具有**`LC_RPATH`**和**`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`
{% hint style="info" %}
**`@executable_path`**:是包含**主可执行文件**的目录的**路径**
**`@executable_path`**:是包含 **主可执行文件****目录路径**
**`@loader_path`**:是包含**包含加载命令的Mach-O二进制文件**的**目录**的**路径**。
**`@loader_path`**:是包含包含加载命令的 **Mach-O 二进制文件** **目录路径**
* 在可执行文件中使用时,\*\*`@loader_path`**实际上与**`@executable_path`\*\*相同
* 在**dylib**中使用时,**`@loader_path`给出dylib**的**路径**。
* 当在可执行文件中使用时,**`@loader_path`** 实际上与 **`@executable_path`** **相同**
* **dylib** 中使用时,**`@loader_path`** 给出**dylib** **路径**
{% endhint %}
滥用此功能升级权限的方式是在**以root身份执行的应用程序**中查找**攻击者具有写权限的某个文件夹**中的某个库的情况下
利用这种功能进行 **权限提升** 的方式是在罕见情况下,由 **root** 执行的 **应用程序** 正在 **查找** 一些 **库**,而攻击者具有写权限的某个文件夹中存在该库
{% hint style="success" %}
一个很好的**扫描工具**,用于查找应用程序中的**缺失库**是[**Dylib Hijack Scanner**](https://objective-see.com/products/dhs.html)或[**CLI版本**](https://github.com/pandazheng/DylibHijack)。 关于此技术的技术细节的**报告**可以在[**这里**](https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x)找到。
一个很好的 **扫描工具**,用于查找应用程序中的 **缺失库** 是 [**Dylib Hijack Scanner**](https://objective-see.com/products/dhs.html) 或 [**CLI 版本**](https://github.com/pandazheng/DylibHijack)。
关于这种技术的一个带有技术细节的不错的 **报告** 可以在 [**这里**](https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x) 找到。
{% endhint %}
**示例**
@ -119,16 +129,15 @@ Macho二进制文件可以使用**4个不同的头部命令**来加载库:
[macos-dyld-hijacking-and-dyld\_insert\_libraries.md](macos-dyld-hijacking-and-dyld\_insert\_libraries.md)
{% endcontent-ref %}
## Dlopen劫持
## Dlopen 劫持
{% hint style="danger" %}
请记住,**以前的库验证限制也适用于**执行Dlopen劫持攻击。
请记住,执行 Dlopen 劫持攻击时也适用 **先前的库验证限制**
{% endhint %}
从\*\*`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`\*\*)。
来自 **`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`(如果不受限制)
@ -137,44 +146,51 @@ Macho二进制文件可以使用**4个不同的头部命令**来加载库:
6. `/usr/lib/`
{% hint style="danger" %}
如果名称中没有斜杠,有两种方法可以进行劫持:
如果名称中没有斜杠,有两种方法可以进行劫持:
* 如果任何\*\*`LC_RPATH`**是**可写的\*\*(但会检查签名,因此对于此,您还需要二进制文件是不受限制的)
* 如果二进制文件是**不受限制的**那么可以从CWD加载内容或滥用其中提到的环境变量之一
* 如果任何 **`LC_RPATH`** 是 **可写的**(但会检查签名,因此您还需要二进制文件是不受限制的)
* 如果二进制文件是 **不受限制的**,那么可以从 CWD加载内容(或滥用其中提到的环境变量之一)
{% endhint %}
* 当路径**看起来像一个框架路径**(例如`/stuff/foo.framework/foo`)时,如果在启动时设置了\*\*`$DYLD_FRAMEWORK_PATH`**dyld将首先在该目录中查找**框架部分路径\*\*(例如`foo.framework/foo`。接下来dyld将尝试**使用提供的路径**对于相对路径使用当前工作目录。最后对于旧二进制文件dyld将尝试一些回退。如果在启动时设置了\*\*`$DYLD_FALLBACK_FRAMEWORK_PATH`**dyld将搜索这些目录。否则它将搜索**`/Library/Frameworks`**在macOS上如果进程不受限制然后在**`/System/Library/Frameworks`\*\*中搜索。
* 当路径 **看起来像一个框架** 路径(例如 `/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`
2. 提供的路径(对于相对路径,如果不受限制,使用当前工作目录)
2. 提供的路径(对于相对路径,如果不受限制,使用当前工作目录)
3. `$DYLD_FALLBACK_FRAMEWORK_PATH`
4. `/Library/Frameworks`(如果不受限制)
5. `/System/Library/Frameworks`
{% hint style="danger" %}
如果是框架路径,劫持的方式是:
如果是框架路径,劫持的方式是:
* 如果进程是**不受限制的**,滥用**相对路径从CWD**和提到的环境变量(即使在文档中没有说过如果进程受限制DYLD\_\*环境变量将被移除)
* 如果进程是 **不受限制的**可以滥用从 CWD 开始的 **相对路径** 和提到的环境变量(即使在文档中没有提到进程是否受限制DYLD\_\* 环境变量会被移除)
{% endhint %}
* 当路径**包含斜杠但不是框架路径**即完整路径或指向dylib的部分路径dlopen()首先在(如果设置了)**`$DYLD_LIBRARY_PATH`中查找使用路径的叶部分。接下来dyld尝试提供的路径**对于相对路径仅对于不受限制的进程使用当前工作目录。最后对于旧二进制文件dyld将尝试回退。如果在启动时设置了\*\*`$DYLD_FALLBACK_LIBRARY_PATH`**dyld将在这些目录中搜索否则dyld将在**`/usr/local/lib/`**中查找(如果进程不受限制),然后在**`/usr/lib/`\*\*中查找。
* 当路径 **包含斜杠但不是框架路径**(即完整路径或指向 dylib 的部分路径dlopen() 首先在(如果设置了) **`$DYLD_LIBRARY_PATH`** 中查找使用路径的叶子部分。接下来dyld 将尝试使用 **提供的路径**对于相对路径仅对于不受限制的进程使用当前工作目录。最后对于旧的二进制文件dyld 将尝试一些回退。如果在启动时设置了 **`$DYLD_FALLBACK_LIBRARY_PATH`**dyld 将在这些目录中搜索否则dyld 将在 **`/usr/local/lib/`** 中查找(如果进程是不受限制的),然后在 **`/usr/lib/`** 中查找。
1. `$DYLD_LIBRARY_PATH`
2. 提供的路径(对于相对路径,如果不受限制,使用当前工作目录)
2. 提供的路径(对于相对路径,如果不受限制,使用当前工作目录)
3. `$DYLD_FALLBACK_LIBRARY_PATH`
4. `/usr/local/lib/`(如果不受限制)
5. `/usr/lib/`
{% hint style="danger" %}
如果名称中有斜杠而不是框架,劫持的方式是:
如果名称中有斜杠而不是框架,劫持的方式是:
* 如果二进制文件是**不受限制的**那么可以从CWD或`/usr/local/lib`加载内容(或滥用其中提到的环境变量)
* 如果二进制文件是 **不受限制的**,那么可以从 CWD `/usr/local/lib`加载内容(或滥用其中提到的环境变量之一
{% endhint %}
注意:没有**控制dlopen搜索**的配置文件。
{% hint style="info" %}
注意:没有配置文件来 **控制 dlopen 搜索**
注意:如果主可执行文件是\*\*set\[ug]id二进制文件或具有授权的
注意:如果主可执行文件是 **set\[ug]id 二进制文件或使用授权签名**,则会 **忽略所有环境变量**,只能使用完整路径([查看 DYLD\_INSERT\_LIBRARIES 限制](macos-dyld-hijacking-and-dyld\_insert\_libraries.md#check-dyld\_insert\_librery-restrictions) 获取更详细信息)
注意Apple 平台使用 "universal" 文件来组合 32 位和 64 位库。这意味着没有 **单独的 32 位和 64 位搜索路径**
注意:在 Apple 平台上,大多数 OS dylibs 都 **合并到 dyld 缓存** 中,不存在于磁盘上。因此,调用 **`stat()`** 来预先检查 OS dylib 是否存在 **不起作用**。但是,**`dlopen_preflight()`** 使用与 **`dlopen()`** 相同的步骤来查找兼容的 mach-o 文件。
{% endhint %}
**检查路径**
让我们使用以下代码检查所有选项:
```c
// gcc dlopentest.c -o dlopentest -Wl,-rpath,/tmp/test
#include <dlfcn.h>
@ -217,33 +233,27 @@ fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
return 0;
}
```
如果您编译并执行它,您可以看到**每个库未成功搜索到的位置**。此外,您可以**过滤FS日志**
如果您编译并执行它,您可以看到**每个库未成功搜索的位置**。此外,您可以**过滤FS日志**
```bash
sudo fs_usage | grep "dlopentest"
```
## 相对路径劫持
如果一个**特权二进制应用**比如一个SUID或一些拥有强大权限的二进制应用)正在**加载一个相对路径**库(例如使用`@executable_path`或`@loader_path`),并且**禁用了库验证**,那么可能会将二进制应用移动到攻击者可以**修改相对路径加载的库**的位置,并利用它来在进程中注入代码。
如果一个**特权二进制应用程序**比如一个SUID或一些拥有强大权限的二进制文件)正在**加载一个相对路径**库(例如使用`@executable_path`或`@loader_path`),并且**禁用了库验证**,那么可能会将二进制文件移动到攻击者可以**修改相对路径加载的库**的位置,并滥用它来向进程注入代码。
## 清理 `DYLD_*``LD_LIBRARY_PATH` 环境变量
## 修剪 `DYLD_*``LD_LIBRARY_PATH` 环境变量
在文件 `dyld-dyld-832.7.1/src/dyld2.cpp` 中,可以找到函数\*\*`pruneEnvironmentVariables`\*\*,它将删除任何以`DYLD_`开头和`LD_LIBRARY_PATH=`的环境变量。
在文件 `dyld-dyld-832.7.1/src/dyld2.cpp` 中,可以找到函数**`pruneEnvironmentVariables`**,它将删除任何以`DYLD_`开头和`LD_LIBRARY_PATH=`的环境变量。
它还会将\*\*`DYLD_FALLBACK_FRAMEWORK_PATH`**和**`DYLD_FALLBACK_LIBRARY_PATH`**这两个环境变量特别设置为**null\*\*,用于**suid**和**sgid**二进制应用。
如果针对类似OSX的目标该函数将从同一文件的\*\*`_main`\*\*函数中调用:
它还会将**`DYLD_FALLBACK_FRAMEWORK_PATH`**和**`DYLD_FALLBACK_LIBRARY_PATH`**这两个环境变量对于**suid**和**sgid**二进制文件设置为**null**。
如果针对OSX可以从同一文件的**`_main`**函数中调用此函数:
```cpp
#if TARGET_OS_OSX
if ( !gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache ) {
pruneEnvironmentVariables(envp, &apple);
```
并且这些布尔标志在代码中的同一文件中设置:
```cpp
#if TARGET_OS_OSX
// support chrooting from old kernel
@ -274,15 +284,13 @@ gLinkContext.allowClassicFallbackPaths = !isRestricted;
gLinkContext.allowInsertFailures = false;
gLinkContext.allowInterposing = true;
```
这基本上意味着,如果二进制文件是**suid**或**sgid**,或者在标头中有一个**RESTRICT**段,或者使用**CS\_RESTRICT**标志签名,那么\*\*`!gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache`\*\*为真,环境变量将被修剪。
这基本上意味着,如果二进制文件是**suid**或**sgid**,或者在标头中有一个**RESTRICT**段,或者使用**CS\_RESTRICT**标志进行签名,那么**`!gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache`**为真,环境变量将被修剪。
请注意如果CS\_REQUIRE\_LV为真则变量不会被修剪但库验证将检查它们是否使用与原始二进制文件相同的证书。
## 检查限制
### SUID & SGID
```bash
# Make it owned by root and suid
sudo chown root hello
@ -293,14 +301,11 @@ DYLD_INSERT_LIBRARIES=inject.dylib ./hello
# Remove suid
sudo chmod -s hello
```
### 区块 `__RESTRICT` 与段 `__restrict`
```bash
gcc -sectcreate __RESTRICT __restrict /dev/null hello.c -o hello-restrict
DYLD_INSERT_LIBRARIES=inject.dylib ./hello-restrict
```
### 强化运行时
在钥匙串中创建一个新证书,并使用它来签署二进制文件:
@ -328,31 +333,27 @@ DYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed # Won't work
{% endcode %}
{% hint style="danger" %}
请注意,即使有用标志\*\*`0x0(none)`**签名的二进制文件,当执行时也可以动态地获得**`CS_RESTRICT`\*\*标志,因此这种技术在其中不起作用。
您可以使用以下命令检查进程是否具有此标志(获取[**csops here**](https://github.com/axelexic/CSOps)
请注意,即使有用标志**`0x0(none)`**签名的二进制文件,当执行时也可以动态地获得**`CS_RESTRICT`**标志,因此这种技术在其中不起作用。
您可以使用以下命令检查进程是否具有此标志(获取[**csops here**](https://github.com/axelexic/CSOps):
```bash
csops -status <pid>
```
然后检查标志0x800是否已启用。
{% endhint %}
## 参考资料
* [https://theevilbit.github.io/posts/dyld\_insert\_libraries\_dylib\_injection\_in\_macos\_osx\_deep\_dive/](https://theevilbit.github.io/posts/dyld\_insert\_libraries\_dylib\_injection\_in\_macos\_osx\_deep\_dive/)
* [**\*OS Internals, Volume I: User Mode. By Jonathan Levin**](https://www.amazon.com/MacOS-iOS-Internals-User-Mode/dp/099105556X)
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS Red Team Expert</strong></a><strong></strong></summary>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
支持HackTricks的其他方式
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASSHackTricks周边产品**](https://peass.creator-spring.com)
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 发现[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>

View file

@ -0,0 +1,322 @@
# macOS Dyld 进程
<details>
<summary><strong>从零开始学习 AWS 黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS 红队专家)</strong></a><strong></strong></summary>
支持 HackTricks 的其他方式:
- 如果您想看到您的**公司在 HackTricks 中做广告**或**下载 PDF 版的 HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
- 获取[**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
- 探索[**PEASS 家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
- **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或在 **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)** 上关注我们**。
- 通过向 [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来分享您的黑客技巧。
</details>
## 基本信息
Mach-o 二进制文件的真正**入口点**是动态链接器,在 `LC_LOAD_DYLINKER` 中定义,通常为 `/usr/lib/dyld`
这个链接器需要定位所有可执行库,在内存中映射它们,并链接所有非懒加载库。只有在此过程完成后,二进制文件的入口点才会被执行。
当然,**`dyld`** 没有任何依赖(它使用系统调用和 libSystem 片段)。
{% hint style="danger" %}
如果此链接器包含任何漏洞,因为它在执行任何二进制文件(甚至是高度特权的二进制文件)之前被执行,将有可能**提升权限**。
{% endhint %}
### 流程
Dyld 将由 **`dyldboostrap::start`** 加载,它还会加载诸如**栈保护**之类的东西。这是因为此函数将在其**`apple`**参数向量中接收此类**敏感**的**值**。
**`dyls::_main()`** 是 dyld 的入口点,它的第一个任务是运行 `configureProcessRestrictions()`,通常会限制**`DYLD_*`**环境变量,详细说明在:
{% content-ref url="./" %}
[.](./)
{% endcontent-ref %}
然后,它映射 dyld 共享缓存,其中预链接了所有重要的系统库,然后映射二进制文件依赖的库,并递归继续,直到加载所有需要的库。因此:
1. 它开始加载插入的库,使用 `DYLD_INSERT_LIBRARIES`(如果允许)
2. 然后是共享缓存中的库
3. 然后是导入的库
4. 然后继续递归导入库
一旦所有库都加载完毕,这些库的**初始化程序**将被运行。这些程序使用**`__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`**)。
### 存根
macOS 中的所有二进制文件都是动态链接的。因此,它们包含一些存根部分,帮助二进制文件在不同的机器和上下文中跳转到正确的代码。在执行二进制文件时,需要 dyld 来解析这些地址(至少是非懒加载的地址)。
二进制文件中的一些存根部分:
- **`__TEXT.__[auth_]stubs`**:来自 `__DATA` 部分的指针
- **`__TEXT.__stub_helper`**:调用带有要调用函数信息的动态链接的小代码
- **`__DATA.__[auth_]got`**:全局偏移表(指向导入函数的地址,在解析后绑定(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`
- **`__DATA.__nl_symbol_ptr`**:非懒加载符号指针(在加载时绑定,因为它标记为 `S_NON_LAZY_SYMBOL_POINTERS`
- **`__DATA.__la_symbol_ptr`**:惰性符号指针(首次访问时绑定)
{% hint style="warning" %}
请注意,带有前缀 "auth\_" 的指针使用一个进程内加密密钥进行保护PAC。此外可以使用 arm64 指令 `BLRA[A/B]` 在跟随指针之前验证指针。而 RETA\[A/B\] 可以用于替代 RET 地址。\
实际上,**`__TEXT.__auth_stubs`** 中的代码将使用 **`braa`** 而不是 **`bl`** 来调用请求的函数以验证指针。
还要注意,当前的 dyld 版本将**所有内容加载为非懒加载**。
{% endhint %}
### 查找惰性符号
```c
//gcc load.c -o load
#include <stdio.h>
int main (int argc, char **argv, char **envp, char **apple)
{
printf("Hi\n");
}
```
有趣的反汇编部分:
```armasm
; objdump -d ./load
100003f7c: 90000000 adrp x0, 0x100003000 <_main+0x1c>
100003f80: 913e9000 add x0, x0, #4004
100003f84: 94000005 bl 0x100003f98 <_printf+0x100003f98>
```
可以看到跳转到调用 printf 的位置是在 **`__TEXT.__stubs`**
```bash
objdump --section-headers ./load
./load: file format mach-o arm64
Sections:
Idx Name Size VMA Type
0 __text 00000038 0000000100003f60 TEXT
1 __stubs 0000000c 0000000100003f98 TEXT
2 __cstring 00000004 0000000100003fa4 DATA
3 __unwind_info 00000058 0000000100003fa8 DATA
4 __got 00000008 0000000100004000 DATA
```
在**`__stubs`**部分的反汇编中:
```bash
objdump -d --section=__stubs ./load
./load: file format mach-o arm64
Disassembly of section __TEXT,__stubs:
0000000100003f98 <__stubs>:
100003f98: b0000010 adrp x16, 0x100004000 <__stubs+0x4>
100003f9c: f9400210 ldr x16, [x16]
100003fa0: d61f0200 br x16
```
你可以看到我们正在**跳转到GOT的地址**在这种情况下它是通过非延迟解析的将包含printf函数的地址。
在其他情况下而不是直接跳转到GOT它可以跳转到**`__DATA.__la_symbol_ptr`**,它将加载一个代表它正在尝试加载的函数的值,然后跳转到**`__TEXT.__stub_helper`**,它跳转到包含**`dyld_stub_binder`**地址的**`__DATA.__nl_symbol_ptr`**,该函数接受函数编号和地址作为参数。\
在找到搜索的函数地址后,该最后一个函数将其写入**`__TEXT.__stub_helper`**中的相应位置,以避免将来进行查找。
{% hint style="success" %}
但请注意当前dyld版本将所有内容都作为非延迟加载。
{% endhint %}
#### Dyld操作码
最后,**`dyld_stub_binder`**需要找到指定的函数并将其写入正确的地址以免再次搜索。为此它在dyld内部使用操作码有限状态机
## apple\[]参数向量
在macOS中主函数实际上接收4个参数而不是3个。第四个称为apple每个条目的形式为`key=value`。例如:
```c
// gcc apple.c -o apple
#include <stdio.h>
int main (int argc, char **argv, char **envp, char **apple)
{
for (int i=0; apple[i]; i++)
printf("%d: %s\n", i, apple[i])
}
```
结果:
```
0: executable_path=./a
1:
2:
3:
4: ptr_munge=
5: main_stack=
6: executable_file=0x1a01000012,0x5105b6a
7: dyld_file=0x1a01000012,0xfffffff0009834a
8: executable_cdhash=757a1b08ab1a79c50a66610f3adbca86dfd3199b
9: executable_boothash=f32448504e788a2c5935e372d22b7b18372aa5aa
10: arm64e_abi=os
11: th_port=
```
{% hint style="success" %}
当这些值到达主函数时,敏感信息已经被删除,否则可能会导致数据泄漏。
{% endhint %}
在进入主函数之前,可以通过调试查看所有这些有趣的值:
<pre><code>lldb ./apple
<strong>(lldb) target create "./a"
</strong>当前可执行文件设置为'/tmp/a' (arm64)。
(lldb) process launch -s
[..]
<strong>(lldb) mem read $sp
</strong>0x16fdff510: 00 00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 ................
0x16fdff520: d8 f6 df 6f 01 00 00 00 00 00 00 00 00 00 00 00 ...o............
<strong>(lldb) x/55s 0x016fdff6d8
</strong>[...]
0x16fdffd6a: "TERM_PROGRAM=WarpTerminal"
0x16fdffd84: "WARP_USE_SSH_WRAPPER=1"
0x16fdffd9b: "WARP_IS_LOCAL_SHELL_SESSION=1"
0x16fdffdb9: "SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk"
0x16fdffe24: "NVM_DIR=/Users/carlospolop/.nvm"
0x16fdffe44: "CONDA_CHANGEPS1=false"
0x16fdffe5a: ""
0x16fdffe5b: ""
0x16fdffe5c: ""
0x16fdffe5d: ""
0x16fdffe5e: ""
0x16fdffe5f: ""
0x16fdffe60: "pfz=0xffeaf0000"
0x16fdffe70: "stack_guard=0x8af2b510e6b800b5"
0x16fdffe8f: "malloc_entropy=0xf2349fbdea53f1e4,0x3fd85d7dcf817101"
0x16fdffec4: "ptr_munge=0x983e2eebd2f3e746"
0x16fdffee1: "main_stack=0x16fe00000,0x7fc000,0x16be00000,0x4000000"
0x16fdfff17: "executable_file=0x1a01000012,0x5105b6a"
0x16fdfff3e: "dyld_file=0x1a01000012,0xfffffff0009834a"
0x16fdfff67: "executable_cdhash=757a1b08ab1a79c50a66610f3adbca86dfd3199b"
0x16fdfffa2: "executable_boothash=f32448504e788a2c5935e372d22b7b18372aa5aa"
0x16fdfffdf: "arm64e_abi=os"
0x16fdfffed: "th_port=0x103"
0x16fdffffb: ""
</code></pre>
## dyld\_all\_image\_infos
这是由dyld导出的一个结构包含有关dyld状态的信息可以在[**源代码**](https://opensource.apple.com/source/dyld/dyld-852.2/include/mach-o/dyld\_images.h.auto.html)中找到包括版本、指向dyld\_image\_info数组的指针、指向dyld\_image\_notifier的指针、如果进程与共享缓存分离、是否调用了libSystem初始化程序、指向dyld自身Mach头文件的指针、指向dyld版本字符串的指针...
## dyld环境变量
### 调试dyld
有助于了解dyld操作的有趣环境变量
* **DYLD\_PRINT\_LIBRARIES**
检查加载的每个库:
```
DYLD_PRINT_LIBRARIES=1 ./apple
dyld[19948]: <9F848759-9AB8-3BD2-96A1-C069DC1FFD43> /private/tmp/a
dyld[19948]: <F0A54B2D-8751-35F1-A3CF-F1A02F842211> /usr/lib/libSystem.B.dylib
dyld[19948]: <C683623C-1FF6-3133-9E28-28672FDBA4D3> /usr/lib/system/libcache.dylib
dyld[19948]: <BFDF8F55-D3DC-3A92-B8A1-8EF165A56F1B> /usr/lib/system/libcommonCrypto.dylib
dyld[19948]: <B29A99B2-7ADE-3371-A774-B690BEC3C406> /usr/lib/system/libcompiler_rt.dylib
dyld[19948]: <65612C42-C5E4-3821-B71D-DDE620FB014C> /usr/lib/system/libcopyfile.dylib
dyld[19948]: <B3AC12C0-8ED6-35A2-86C6-0BFA55BFF333> /usr/lib/system/libcorecrypto.dylib
dyld[19948]: <8790BA20-19EC-3A36-8975-E34382D9747C> /usr/lib/system/libdispatch.dylib
dyld[19948]: <4BB77515-DBA8-3EDF-9AF7-3C9EAE959EA6> /usr/lib/system/libdyld.dylib
dyld[19948]: <F7CE9486-FFF5-3CB8-B26F-75811EF4283A> /usr/lib/system/libkeymgr.dylib
dyld[19948]: <1A7038EC-EE49-35AE-8A3C-C311083795FB> /usr/lib/system/libmacho.dylib
[...]
```
* **DYLD\_PRINT\_SEGMENTS**
检查每个库是如何加载的:
```
DYLD_PRINT_SEGMENTS=1 ./apple
dyld[21147]: re-using existing shared cache (/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e):
dyld[21147]: 0x181944000->0x1D5D4BFFF init=5, max=5 __TEXT
dyld[21147]: 0x1D5D4C000->0x1D5EC3FFF init=1, max=3 __DATA_CONST
dyld[21147]: 0x1D7EC4000->0x1D8E23FFF init=3, max=3 __DATA
dyld[21147]: 0x1D8E24000->0x1DCEBFFFF init=3, max=3 __AUTH
dyld[21147]: 0x1DCEC0000->0x1E22BFFFF init=1, max=3 __AUTH_CONST
dyld[21147]: 0x1E42C0000->0x1E5457FFF init=1, max=1 __LINKEDIT
dyld[21147]: 0x1E5458000->0x22D173FFF init=5, max=5 __TEXT
dyld[21147]: 0x22D174000->0x22D9E3FFF init=1, max=3 __DATA_CONST
dyld[21147]: 0x22F9E4000->0x230F87FFF init=3, max=3 __DATA
dyld[21147]: 0x230F88000->0x234EC3FFF init=3, max=3 __AUTH
dyld[21147]: 0x234EC4000->0x237573FFF init=1, max=3 __AUTH_CONST
dyld[21147]: 0x239574000->0x270BE3FFF init=1, max=1 __LINKEDIT
dyld[21147]: Kernel mapped /private/tmp/a
dyld[21147]: __PAGEZERO (...) 0x000000904000->0x000101208000
dyld[21147]: __TEXT (r.x) 0x000100904000->0x000100908000
dyld[21147]: __DATA_CONST (rw.) 0x000100908000->0x00010090C000
dyld[21147]: __LINKEDIT (r..) 0x00010090C000->0x000100910000
dyld[21147]: Using mapping in dyld cache for /usr/lib/libSystem.B.dylib
dyld[21147]: __TEXT (r.x) 0x00018E59D000->0x00018E59F000
dyld[21147]: __DATA_CONST (rw.) 0x0001D5DFDB98->0x0001D5DFDBA8
dyld[21147]: __AUTH_CONST (rw.) 0x0001DDE015A8->0x0001DDE01878
dyld[21147]: __AUTH (rw.) 0x0001D9688650->0x0001D9688658
dyld[21147]: __DATA (rw.) 0x0001D808AD60->0x0001D808AD68
dyld[21147]: __LINKEDIT (r..) 0x000239574000->0x000270BE4000
dyld[21147]: Using mapping in dyld cache for /usr/lib/system/libcache.dylib
dyld[21147]: __TEXT (r.x) 0x00018E597000->0x00018E59D000
dyld[21147]: __DATA_CONST (rw.) 0x0001D5DFDAF0->0x0001D5DFDB98
dyld[21147]: __AUTH_CONST (rw.) 0x0001DDE014D0->0x0001DDE015A8
dyld[21147]: __LINKEDIT (r..) 0x000239574000->0x000270BE4000
[...]
```
* **DYLD\_PRINT\_INITIALIZERS**
打印每个库初始化程序运行时的信息:
```
DYLD_PRINT_INITIALIZERS=1 ./apple
dyld[21623]: running initializer 0x18e59e5c0 in /usr/lib/libSystem.B.dylib
[...]
```
### 其他
* `DYLD_BIND_AT_LAUNCH`: 惰性绑定将使用非惰性绑定解析
* `DYLD_DISABLE_PREFETCH`: 禁用对 \_\_DATA 和 \_\_LINKEDIT 内容的预取
* `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_APIS`: 打印 libdyld API 调用
* `DYLD_PRINT_APIS_APP`: 打印主程序调用的 libdyld API
* `DYLD_PRINT_BINDINGS`: 绑定时打印符号
* `DYLD_WEAK_BINDINGS`: 仅在绑定时打印弱符号
* `DYLD_PRINT_CODE_SIGNATURES`: 打印代码签名注册操作
* `DYLD_PRINT_DOFS`: 打印加载的 D-Trace 对象格式部分
* `DYLD_PRINT_ENV`: 打印 dyld 可见的环境变量
* `DYLD_PRINT_INTERPOSTING`: 打印 interposing 操作
* `DYLD_PRINT_LIBRARIES`: 打印加载的库
* `DYLD_PRINT_OPTS`: 打印加载选项
* `DYLD_REBASING`: 打印符号重新定位操作
* `DYLD_RPATHS`: 打印 @rpath 的扩展
* `DYLD_PRINT_SEGMENTS`: 打印 Mach-O 段的映射
* `DYLD_PRINT_STATISTICS`: 打印时间统计信息
* `DYLD_PRINT_STATISTICS_DETAILS`: 打印详细的时间统计信息
* `DYLD_PRINT_WARNINGS`: 打印警告消息
* `DYLD_SHARED_CACHE_DIR`: 用于共享库缓存的路径
* `DYLD_SHARED_REGION`: "use", "private", "avoid"
* `DYLD_USE_CLOSURES`: 启用闭包
可以通过类似以下方式找到更多内容:
```bash
strings /usr/lib/dyld | grep "^DYLD_" | sort -u
```
或者从[https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)下载dyld项目并在文件夹内运行
```bash
find . -type f | xargs grep strcmp| grep key,\ \" | cut -d'"' -f2 | sort -u
```
## 参考资料
* [**\*OS Internals, Volume I: User Mode. By Jonathan Levin**](https://www.amazon.com/MacOS-iOS-Internals-User-Mode/dp/099105556X)
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong></strong></summary>
支持HackTricks的其他方式
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群组**](https://discord.gg/hRep4RUj7f) 或 [**电报群组**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>