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

This commit is contained in:
Translator 2025-10-01 01:54:54 +00:00
parent b57dcf224b
commit d7c103d377
5 changed files with 401 additions and 172 deletions

View File

@ -61,6 +61,7 @@
- [Deofuscation vbs (cscript.exe)](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md)
- [Discord Cache Forensics](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/discord-cache-forensics.md)
- [Local Cloud Storage](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md)
- [Mach O Entitlements And Ipsw Indexing](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md)
- [Office file analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md)
- [PDF File analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md)
- [PNG tricks](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md)

View File

@ -2,7 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
这里你可以找到针对特定文件类型和/或软件的有趣技巧:
这里你可以找到针对特定文件类型和/或软件的有趣技巧:
{{#ref}}
@ -54,4 +54,9 @@ video-and-audio-file-analysis.md
zips-tricks.md
{{#endref}}
{{#ref}}
mach-o-entitlements-and-ipsw-indexing.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,213 @@
# Mach-O 权限提取与 IPSW 索引
{{#include ../../../banners/hacktricks-training.md}}
## 概述
本页介绍如何通过遍历 LC_CODE_SIGNATURE 并解析 code signing SuperBlob编程式地从 Mach-O 二进制中提取 entitlements以及如何通过挂载并索引 Apple IPSW 固件的内容,以便进行取证搜索/差异比较,从而实现规模化处理。
如果你需要复习 Mach-O 格式和 code signing可以参考macOS code signing 和 SuperBlob 内部结构。
- Check macOS code signing details (SuperBlob, Code Directory, special slots): [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md)
- Check general Mach-O structures/load commands: [Universal binaries & Mach-O Format](../../../macos-hardening/macos-security-and-privilege-escalation/macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md)
## Entitlements in Mach-O: where they live
Entitlements 存储在由 LC_CODE_SIGNATURE 加载命令引用的 code signature 数据中,并放置在 __LINKEDIT 段。该签名是一个 CS_SuperBlob包含多个 blobcode directory、requirements、entitlements、CMS 等。entitlements blob 是一个 CS_GenericBlob其数据是一个 Apple Binary Property List (bplist00),将 entitlement 键映射到值。
关键结构(来自 xnu
```c
/* mach-o/loader.h */
struct mach_header_64 {
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};
struct load_command {
uint32_t cmd;
uint32_t cmdsize;
};
/* Entitlements live behind LC_CODE_SIGNATURE (cmd=0x1d) */
struct linkedit_data_command {
uint32_t cmd; /* LC_CODE_SIGNATURE */
uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
uint32_t dataoff; /* file offset of data in __LINKEDIT */
uint32_t datasize; /* file size of data in __LINKEDIT */
};
/* osfmk/kern/cs_blobs.h */
typedef struct __SC_SuperBlob {
uint32_t magic; /* CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 */
uint32_t length;
uint32_t count;
CS_BlobIndex index[];
} CS_SuperBlob;
typedef struct __BlobIndex {
uint32_t type; /* e.g., CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171 */
uint32_t offset; /* offset of entry */
} CS_BlobIndex;
typedef struct __SC_GenericBlob {
uint32_t magic; /* same as type when standalone */
uint32_t length;
char data[]; /* Apple Binary Plist containing entitlements */
} CS_GenericBlob;
```
重要常量:
- LC_CODE_SIGNATURE cmd = 0x1d
- CS SuperBlob magic = 0xfade0cc0
- Entitlements blob type (CSMAGIC_EMBEDDED_ENTITLEMENTS) = 0xfade7171
- DER entitlements may be present via special slot (e.g., -7), see the macOS Code Signing page for special slots and DER entitlements notes
注意多架构fat二进制包含多个 Mach-O slices。你必须选择要检查的架构对应的 slice然后遍历其 load commands。
## Extraction steps (generic, lossless-enough)
1) Parse Mach-O header; iterate ncmds worth of load_command records.
2) Locate LC_CODE_SIGNATURE; read linkedit_data_command.dataoff/datasize to map the Code Signing SuperBlob placed in __LINKEDIT.
3) Validate CS_SuperBlob.magic == 0xfade0cc0; iterate count entries of CS_BlobIndex.
4) Locate index.type == 0xfade7171 (embedded entitlements). Read the pointed CS_GenericBlob and parse its data as an Apple binary plist (bplist00) to key/value entitlements.
Implementation notes:
- Code signature structures use big-endian fields; swap byte order when parsing on little-endian hosts.
- The entitlements GenericBlob data itself is a binary plist (handled by standard plist libraries).
- Some iOS binaries may carry DER entitlements; also some stores/slots differ across platforms/versions. Cross-check both standard and DER entitlements as needed.
- For fat binaries, use the fat headers (FAT_MAGIC/FAT_MAGIC_64) to locate the correct slice and offset before walking Mach-O load commands.
## Minimal parsing outline (Python)
The following is a compact outline showing the control flow to find and decode entitlements. It intentionally omits robust bounds checks and full fat binary support for brevity.
```python
import plistlib, struct
LC_CODE_SIGNATURE = 0x1d
CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0
CSMAGIC_EMBEDDED_ENTITLEMENTS = 0xfade7171
# all code-signing integers are big-endian per cs_blobs.h
be32 = lambda b, off: struct.unpack_from(">I", b, off)[0]
def parse_entitlements(macho_bytes):
# assume already positioned at a single-arch Mach-O slice
magic, = struct.unpack_from("<I", macho_bytes, 0)
is64 = magic in (0xfeedfacf,)
if is64:
ncmds = struct.unpack_from("<I", macho_bytes, 0x10)[0]
sizeofcmds = struct.unpack_from("<I", macho_bytes, 0x14)[0]
off = 0x20
else:
# 32-bit not shown
return None
code_sig_off = code_sig_size = None
for _ in range(ncmds):
cmd, cmdsize = struct.unpack_from("<II", macho_bytes, off)
if cmd == LC_CODE_SIGNATURE:
# struct linkedit_data_command is little-endian in file
_, _, dataoff, datasize = struct.unpack_from("<IIII", macho_bytes, off)
code_sig_off, code_sig_size = dataoff, datasize
off += cmdsize
if code_sig_off is None:
return None
blob = macho_bytes[code_sig_off: code_sig_off + code_sig_size]
if be32(blob, 0x0) != CSMAGIC_EMBEDDED_SIGNATURE:
return None
count = be32(blob, 0x8)
# iterate BlobIndex entries (8 bytes each after 12-byte header)
for i in range(count):
idx_off = 12 + i*8
btype = be32(blob, idx_off)
boff = be32(blob, idx_off+4)
if btype == CSMAGIC_EMBEDDED_ENTITLEMENTS:
# GenericBlob is big-endian header followed by bplist
glen = be32(blob, boff+4)
data = blob[boff+8: boff+glen]
return plistlib.loads(data)
return None
```
Usage tips:
- 要处理 fat binaries首先读取 struct fat_header/fat_arch选择所需的架构切片然后将子范围传递给 parse_entitlements。
- 在 macOS 上可以使用以下命令验证结果codesign -d --entitlements :- /path/to/binary
## 示例发现
具有特权的平台二进制通常会请求如下敏感 entitlements
- com.apple.security.network.server = true
- com.apple.rootless.storage.early_boot_mount = true
- com.apple.private.kernel.system-override = true
- com.apple.private.pmap.load-trust-cache = ["cryptex1.boot.os", "cryptex1.boot.app", "cryptex1.safari-downlevel"]
在大规模固件镜像中搜索这些条目对于 attack surface mapping 和跨发布/设备的 diffing 非常有价值。
## Scaling across IPSWs (mounting and indexing)
要在不存储完整镜像的情况下,对可执行文件进行枚举并大规模提取 entitlements
- 使用 @blacktop 的 ipsw 工具下载并挂载固件文件系统。挂载使用 apfs-fuse因此可以在不完全提取的情况下遍历 APFS 卷。
```bash
# Download latest IPSW for iPhone11,2 (iPhone XS)
ipsw download ipsw -y --device iPhone11,2 --latest
# Mount IPSW filesystem (uses underlying apfs-fuse)
ipsw mount fs <IPSW_FILE>
```
- 遍历已挂载卷以定位 Mach-O 文件(检查 magic 和/或使用 file/otool然后解析 entitlements 和导入的 frameworks。
- 将标准化视图持久化到关系型数据库,以避免在成千上万个 IPSWs 中线性增长:
- executables, operating_system_versions, entitlements, frameworks
- many-to-many: executable↔OS version, executable↔entitlement, executable↔framework
示例查询:列出包含给定 executable 名称的所有 OS versions
```sql
SELECT osv.version AS "Versions"
FROM device d
LEFT JOIN operating_system_version osv ON osv.device_id = d.id
LEFT JOIN executable_operating_system_version eosv ON eosv.operating_system_version_id = osv.id
LEFT JOIN executable e ON e.id = eosv.executable_id
WHERE e.name = "launchd";
```
数据库可移植性说明(如果你实现自己的索引器):
- 使用 ORM/抽象层(例如 SeaORM以保持代码与数据库无关SQLite/PostgreSQL
- SQLite 仅在 INTEGER PRIMARY KEY 上需要 AUTOINCREMENT如果在 Rust 中希望使用 i64 作为主键,可生成实体为 i32 然后转换类型SQLite 在内部将 INTEGER 以 8 字节有符号整数存储。
## Open-source tooling and references for entitlement hunting
- 固件 挂载/下载: https://github.com/blacktop/ipsw
- Entitlement 数据库与参考:
- Jonathan Levins entitlement DB: https://newosxbook.com/ent.php
- entdb: https://github.com/ChiChou/entdb
- 大规模索引器Rustself-hosted Web UI + OpenAPI: https://github.com/synacktiv/appledb_rs
- Apple 头文件(用于结构体和常量):
- loader.h (Mach-O headers, load commands)
- cs_blobs.h (SuperBlob, GenericBlob, CodeDirectory)
有关代码签名内部机制Code Directory、special slots、DER entitlements的更多信息请参见: [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md)
## References
- [appledb_rs: a research support tool for Apple platforms](https://www.synacktiv.com/publications/appledbrs-un-outil-daide-a-la-recherche-sur-plateformes-apple.html)
- [synacktiv/appledb_rs](https://github.com/synacktiv/appledb_rs)
- [blacktop/ipsw](https://github.com/blacktop/ipsw)
- [Jonathan Levins entitlement DB](https://newosxbook.com/ent.php)
- [ChiChou/entdb](https://github.com/ChiChou/entdb)
- [XNU cs_blobs.h](https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/kern/cs_blobs.h)
- [XNU mach-o/loader.h](https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h)
- [SQLite Datatypes](https://sqlite.org/datatype3.html)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,43 +1,43 @@
# macOS Universal binaries & Mach-O Format
# macOS 通用二进制 & Mach-O 格式
{{#include ../../../banners/hacktricks-training.md}}
## 基本信息
Mac OS 二进制文件通常被编译为 **universal binaries**。一个 **universal binary** 可以 **在同一文件中支持多个架构**。
Mac OS 二进制通常被编译为 **universal binaries**。一个 **universal binary** 可以在同一文件中 **支持多个架构**。
这些二进制文件遵循 **Mach-O 结构**,基本由以下部分组成:
这些二进制遵循 **Mach-O 结构**,基本由以下部分组成:
- 头部
- 加载命令
- 数据
- Header
- Load Commands
- Data
![https://alexdremov.me/content/images/2022/10/6XLCD.gif](<../../../images/image (470).png>)
## Fat Header
使用以下命令搜索文件: `mdfind fat.h | grep -i mach-o | grep -E "fat.h$"`
使用以下命令搜索文件:`mdfind fat.h | grep -i mach-o | grep -E "fat.h$"`
<pre class="language-c"><code class="lang-c"><strong>#define FAT_MAGIC 0xcafebabe
</strong><strong>#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
</strong>
struct fat_header {
<strong> uint32_t magic; /* FAT_MAGIC FAT_MAGIC_64 */
</strong><strong> uint32_t nfat_arch; /* 后续结构的数量 */
<strong> uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
</strong><strong> uint32_t nfat_arch; /* number of structs that follow */
</strong>};
struct fat_arch {
cpu_type_t cputype; /* cpu 说明符 (int) */
cpu_subtype_t cpusubtype; /* 机器说明符 (int) */
uint32_t offset; /* 文件偏移到此目标文件 */
uint32_t size; /* 此目标文件的大小 */
uint32_t align; /* 以 2 的幂为单位的对齐 */
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint32_t offset; /* file offset to this object file */
uint32_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
};
</code></pre>
头部包含 **magic** 字节,后面是文件 **包含****archs****数量** (`nfat_arch`),每个架构将有一个 `fat_arch` 结构。
该 header 包含 **magic** 字节,后跟文件包含的 **架构数量** (`nfat_arch`),每个架构都会有一个 `fat_arch` 结构。
使用以下命令检查:
检查示例
<pre class="language-shell-session"><code class="lang-shell-session">% file /bin/ls
/bin/ls: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
@ -68,11 +68,11 @@ capabilities PTR_AUTH_VERSION USERSPACE 0
<figure><img src="../../../images/image (1094).png" alt=""><figcaption></figcaption></figure>
正如你所想,通常为 2 个架构编译的 universal binary **会使文件大小翻倍**,而为 1 个架构编译的文件则不会
正如你可能想到的,通常为 2 个架构编译的 universal binary 的大小会是只为 1 个架构编译的 **两倍**
## **Mach-O Header**
头部包含有关文件的基本信息,例如用于识别它为 Mach-O 文件的 magic 字节和有关目标架构的信息。你可以在以下路径找到它: `mdfind loader.h | grep -i mach-o | grep -E "loader.h$"`
该 header 包含关于文件的基本信息,例如用于识别为 Mach-O 文件的 magic 字节以及目标架构的信息。你可以在以下位置找到它:`mdfind loader.h | grep -i mach-o | grep -E "loader.h$"`
```c
#define MH_MAGIC 0xfeedface /* the mach magic number */
#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
@ -101,17 +101,17 @@ uint32_t reserved; /* reserved */
```
### Mach-O 文件类型
有不同的文件类型,可以在[**源代码中找到定义,例如这里**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h)。最重要的类型有:
存在不同的文件类型,你可以在 [**source code for example here**](https://opensource.apple.com/source/xnu/xnu-2050.18.24/EXTERNAL_HEADERS/mach-o/loader.h) 中找到它们的定义。最重要的有:
- `MH_OBJECT`: 可重定位目标文件(编译的中间产品,尚未成为可执行文件)。
- `MH_OBJECT`: 可重定位目标文件(编译的中间产物,尚非可执行文件)。
- `MH_EXECUTE`: 可执行文件。
- `MH_FVMLIB`: 固定虚拟机库文件。
- `MH_CORE`: 代码转储
- `MH_PRELOAD`: 预加载的可执行文件(XNU 不再支持)
- `MH_DYLIB`: 动态库
- `MH_DYLINKER`: 动态链接器
- `MH_BUNDLE`: “插件文件”。使用 gcc 的 -bundle 生成,并由 `NSBundle``dlopen` 显式加载。
- `MH_DYSM`: 伴随的 `.dSym` 文件(用于调试的符号文件)。
- `MH_FVMLIB`: 固定 VM 库文件。
- `MH_CORE`: 代码转储
- `MH_PRELOAD`: 预加载的可执行文件XNU 不再支持)
- `MH_DYLIB`: 动态库
- `MH_DYLINKER`: 动态链接器
- `MH_BUNDLE`: "插件文件"。使用 gcc 的 `-bundle` 生成,并由 `NSBundle``dlopen` 显式加载。
- `MH_DYSM`: 配套的 `.dSym` 文件(包含调试符号)。
- `MH_KEXT_BUNDLE`: 内核扩展。
```bash
# Checking the mac header of a binary
@ -120,54 +120,54 @@ Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 ARM64 E USR00 EXECUTE 19 1728 NOUNDEFS DYLDLINK TWOLEVEL PIE
```
或使用 [Mach-O View](https://sourceforge.net/projects/machoview/)
使用 [Mach-O View](https://sourceforge.net/projects/machoview/):
<figure><img src="../../../images/image (1133).png" alt=""><figcaption></figcaption></figure>
## **Mach-O 标志**
源代码还定义了几个用于加载库的标志:
源代码还定义了若干对加载库有用的标志:
- `MH_NOUNDEFS`:没有未定义的引用(完全链接)
- `MH_DYLDLINK`Dyld 链接
- `MH_PREBOUND`:动态引用预绑定。
- `MH_SPLIT_SEGS`:文件分割 r/o 和 r/w 段。
- `MH_WEAK_DEFINES`:二进制文件具有弱定义符号
- `MH_BINDS_TO_WEAK`:二进制文件使用弱符号
- `MH_ALLOW_STACK_EXECUTION`:使堆栈可执行
- `MH_NO_REEXPORTED_DYLIBS`:库没有 LC_REEXPORT 命令
- `MH_PIE`:位置无关可执行文件
- `MH_HAS_TLV_DESCRIPTORS`:有一个包含线程局部变量的部分
- `MH_NO_HEAP_EXECUTION`:堆/数据页面不执行
- `MH_HAS_OBJC`:二进制文件具有 oBject-C 部分
- `MH_SIM_SUPPORT`模拟器支持
- `MH_DYLIB_IN_CACHE`:用于共享库缓存中的 dylibs/frameworks。
- `MH_NOUNDEFS`: 没有未定义引用(完全链接)
- `MH_DYLDLINK`: Dyld 链接
- `MH_PREBOUND`: 动态引用预绑定
- `MH_SPLIT_SEGS`: 文件将只读与读写段分离
- `MH_WEAK_DEFINES`: 二进制包含弱定义符号
- `MH_BINDS_TO_WEAK`: 二进制使用弱符号
- `MH_ALLOW_STACK_EXECUTION`: 使栈可执行
- `MH_NO_REEXPORTED_DYLIBS`: 库不包含 LC_REEXPORT 命令
- `MH_PIE`: 位置无关可执行PIE
- `MH_HAS_TLV_DESCRIPTORS`: 包含线程局部变量TLV
- `MH_NO_HEAP_EXECUTION`: 堆/数据页不可执行
- `MH_HAS_OBJC`: 二进制包含 Objective-C 段
- `MH_SIM_SUPPORT`: 模拟器支持
- `MH_DYLIB_IN_CACHE`: 用于位于共享库缓存中的 dylibs/frameworks
## **Mach-O 加载命令**
**文件在内存中的布局**在这里指定,详细说明了 **符号表的位置**、执行开始时主线程的上下文以及所需的 **共享库**。向动态加载器 **(dyld)** 提供了有关二进制文件加载到内存中的过程的指令
这里指定了文件在内存中的布局说明了符号表的位置、执行开始时主线程的上下文以及所需的共享库。还向动态加载器dyld提供了如何将二进制加载到内存的指示
使用 **load_command** 结构,该结构在提到的 **`loader.h`** 中定义
该文件使用在提到的 `loader.h` 中定义的 **load_command** 结构:
```objectivec
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
```
有大约 **50 种不同类型的加载命令**,系统以不同方式处理它们。最常见的有: `LC_SEGMENT_64``LC_LOAD_DYLINKER``LC_MAIN``LC_LOAD_DYLIB``LC_CODE_SIGNATURE`
有大约 **50 种不同类型的 load commands**,系统会以不同方式处理。最常见的有:`LC_SEGMENT_64``LC_LOAD_DYLINKER``LC_MAIN``LC_LOAD_DYLIB``LC_CODE_SIGNATURE`
### **LC_SEGMENT/LC_SEGMENT_64**
> [!TIP]
> 基本上,这种类型的加载命令定义了 **如何加载 \_\_TEXT**(可执行代码)**和 \_\_DATA**(进程数据)**段**,根据二进制文件执行时在数据部分中指示的 **偏移量**
> 基本上,这种类型的加载命令定义了在二进制被执行时**如何根据 Data 部分中指示的偏移量加载 \_\_TEXT**(可执行代码)**和 \_\_DATA**(进程数据)**段**。
这些命令 **定义了段**,在执行进程时被 **映射****虚拟内存空间** 中。
这些命令**定义了段segments**,在进程执行时会被**映射mapped**到进程的**虚拟内存空间**中。
**不同类型** 的段,例如 **\_\_TEXT** 段,它包含程序的可执行代码,以及 **\_\_DATA** 段,它包含进程使用的数据。这些 **段位于 Mach-O 文件的数据部分** 中。
存在不同类型的段,例如包含程序可执行代码的 **\_\_TEXT** 段,以及包含进程使用数据的 **\_\_DATA** 段。这些**段位于 Mach-O 文件的数据节**中。
**每个段** 可以进一步 **划分** 为多个 **节**。**加载命令结构** 包含关于 **这些节** 在各自段中的 **信息**
**每个段**还可以进一步**划分为多个节sections**。load command 的结构包含关于该段中**这些节**的信息
在头部首先找到 **段头**
在头部首先可以找到**段头segment header**
<pre class="language-c"><code class="lang-c">struct segment_command_64 { /* for 64-bit architectures */
uint32_t cmd; /* LC_SEGMENT_64 */
@ -184,11 +184,11 @@ int32_t initprot; /* initial VM protection */
};
</code></pre>
段头的示例:
Example of segment header:
<figure><img src="../../../images/image (1126).png" alt=""><figcaption></figcaption></figure>
该头部定义了 **其后出现的节头数量**
该头部定义了其后出现的**节头数量**
```c
struct section_64 { /* for 64-bit architectures */
char sectname[16]; /* name of this section */
@ -205,62 +205,62 @@ uint32_t reserved2; /* reserved (for count or sizeof) */
uint32_t reserved3; /* reserved */
};
```
示例 **节标题**
关于 **节标题** 的示例
<figure><img src="../../../images/image (1108).png" alt=""><figcaption></figcaption></figure>
如果你 **添加** **节偏移** (0x37DC) + **架构开始的偏移**,在这种情况下 `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
如果你**section 偏移量** (0x37DC) 与 **arch 起始处的偏移量** 相加,在本例中 `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
<figure><img src="../../../images/image (701).png" alt=""><figcaption></figcaption></figure>
可以通过 **命令行** 获取 **头信息**
可以通过 **命令行** 获取 **头信息**
```bash
otool -lv /bin/ls
```
常见的由此命令加载的段:
Common segments loaded by this cmd:
- **`__PAGEZERO`** 它指示内核**映射** **地址零**,以便**无法读取、写入或执行**。结构中的maxprot和minprot变量设置为零以指示此页面上**没有读写执行权限**。
- 此分配对于**缓解NULL指针解引用漏洞**非常重要。这是因为XNU强制实施一个硬页面零确保内存的第一页仅第一页不可访问在i386中除外。一个二进制文件可以通过制作一个小的\_\_PAGEZERO使用`-pagezero_size`来满足这些要求以覆盖前4k并使其余的32位内存在用户模式和内核模式下可访问
- **`__TEXT`**:包含**可执行** **代码**,具有**读取**和**执行**权限(不可写)。此段的常见部分
- `__text`编译的二进制代码
- `__const`常量数据(只读)
- `__ [c/u/os_log]string`C、Unicode或os日志字符串常量
- `__stubs``__stubs_helper`:在动态库加载过程中涉及
- `__unwind_info`:堆栈展开数据。
- 请注意,所有这些内容都是签名的,但也被标记为可执行(为不一定需要此权限的部分(如专用字符串部分)创建更多的利用选项)。
- **`__DATA`**:包含**可读**和**可写**的数据(不可执行)。
- **`__PAGEZERO`:** 它指示内核 **映射** **地址零**,因此**无法被读取、写入或执行**。结构中的 maxprot 和 minprot 变量被设置为零,以表示该页**没有读写执行权限**。
- 这种分配对于**缓解 NULL 指针解引用 漏洞**非常重要。因为 XNU 强制实施一个硬性的 page zero确保内存的第一页仅第一页不可访问i386 除外)。一个二进制可以通过构造一个小的 \_\_PAGEZERO使用 `-pagezero_size`)以覆盖前 4k并使剩余的 32 位内存在用户态和内核态都可访问,从而满足这一要求
- **`__TEXT`**: 包含具有**读取**和**执行**权限的**可执行****代码**(不可写)。此段的常见节
- `__text`: 已编译的二进制代码
- `__const`: 常量数据(只读)
- `__[c/u/os_log]string`: C、Unicode 或 os 日志字符串常量
- `__stubs` and `__stubs_helper`: 在动态库加载过程中参与
- `__unwind_info`: 栈展开unwind数据
- 注意所有这些内容都已签名且被标记为可执行(这为某些并不一定需要此权限的节(例如专用于字符串的节)提供了更多利用途径)。
- **`__DATA`**: 包含**可读**且**可写**的数据(不可执行)。
- `__got:` 全局偏移表
- `__nl_symbol_ptr`:非惰性(加载时绑定)符号指针
- `__la_symbol_ptr`:惰性(使用时绑定)符号指针
- `__const`:应为只读数据(实际上不是
- `__cfstring`CoreFoundation字符串
- `__data`:全局变量(已初始化)
- `__bss`:静态变量(未初始化)
- `__objc_*`\_\_objc_classlist\_\_objc_protolist等由Objective-C运行时使用的信息
- **`__DATA_CONST`**\_\_DATA.\_\_const不保证是常量写权限其他指针和GOT也是如此。此部分使用`mprotect`使`__const`、一些初始化程序和GOT表解析后**只读**。
- **`__LINKEDIT`**:包含链接dyld所需的信息例如符号、字符串和重定位表条目。它是一个通用容器包含不在`__TEXT``__DATA`中的内容,其内容在其他加载命令中描述。
- dyld信息:重定位、非惰性/惰性/弱绑定操作码和导出信息
- 函数开始:函数的起始地址表
- 代码中的数据:\_\_text中的数据岛
- 符号表:二进制中的符号
- 间接符号表:指针/存根符号
- 字符串表
- 代码签名
- **`__OBJC`**包含由Objective-C运行时使用的信息。尽管这些信息也可能在\_\_DATA段中找到在各种\_\_objc\_\*部分中。
- **`__RESTRICT`**:一个没有内容的段,只有一个名为**`__restrict`**也为空的单一部分确保在运行二进制文件时它将忽略DYLD环境变量。
- `__nl_symbol_ptr`: 非懒(在加载时绑定)符号指针
- `__la_symbol_ptr`: 懒(按需绑定)符号指针
- `__const`: 应为只读数据(但实际上并非如此
- `__cfstring`: CoreFoundation 字符串
- `__data`: 已初始化的全局变量
- `__bss`: 未初始化的静态变量
- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, etc): 由 Objective-C 运行时使用的信息
- **`__DATA_CONST`**: \_\_DATA.\_\_const 并不保证是常量(存在写权限),其他指针和 GOT 也一样。此段使用 `mprotect``__const`、一些初始化器和 GOT 表(解析后)设置为**只读**。
- **`__LINKEDIT`**: 包含链路dyld所需的信息例如符号、字符串和重定位表条目。它是一个通用容器用于存放既不在 `__TEXT` 也不在 `__DATA` 中的内容,其内容在其它加载命令中有描述。
- dyld 信息Rebase、Non-lazy/lazy/weak binding opcodes 和导出信息
- Functions starts函数起始地址表
- Data In Code\_\_text 中的数据岛
- SYmbol Table:二进制中的符号
- Indirect Symbol Table:指针/存根符号
- String Table字符串表
- Code Signature代码签名
- **`__OBJC`**: 包含由 Objective-C 运行时使用的信息。尽管这些信息也可能出现在 \_\_DATA 段内的各种 \_\_objc\_\* 节中。
- **`__RESTRICT`**: 一个没有内容的段,只有一个名为 **`__restrict`**(同样为空)的节,确保在运行二进制时会忽略 DYLD 环境变量。
正如在代码中所看到的,**段也支持标志**(尽管它们并不常用):
As it was possible to see in the code, **segments also support flags** (although they aren't used very much):
- `SG_HIGHVM`:仅核心(未使用)
- `SG_FVMLIB`未使用
- `SG_NORELOC`段没有重定位
- `SG_PROTECTED_VERSION_1`加密。例如Finder用于加密文本`__TEXT`
- `SG_HIGHVM`: 仅限内核(未使用)
- `SG_FVMLIB`: 未使用
- `SG_NORELOC`: 段没有重定位
- `SG_PROTECTED_VERSION_1`: 加密。例如 Finder 使用它来加密 `__TEXT` 段的文本
### **`LC_UNIXTHREAD/LC_MAIN`**
**`LC_MAIN`**包含**entryoff属性**中的入口点。在加载时,**dyld**简单地**将**此值添加到(内存中的)**二进制文件基址**,然后**跳转**到此指令以开始执行二进制代码。
**`LC_MAIN`** 包含入口点于 **entryoff 属性**。在加载时,**dyld** 简单地**将该值添加到**(二进制在内存中的)**基地址**,然后**跳转**到该指令以开始执行二进制的代码。
**`LC_UNIXTHREAD`**包含启动主线程时寄存器必须具有的值。这已经被弃用,但**`dyld`**仍在使用它。可以通过以下方式查看寄存器设置的值:
**`LC_UNIXTHREAD`** 包含启动主线程时寄存器应具有的值。它已被弃用,但 **`dyld`** 仍在使用它。可以通过下面的方法查看由此设置的寄存器值:
```bash
otool -l /usr/lib/dyld
[...]
@ -286,34 +286,39 @@ cpsr 0x00000000
```
### **`LC_CODE_SIGNATURE`**
包含关于 **Macho-O 文件的代码签名** 的信息。它仅包含一个 **偏移量**,指向 **签名 blob**。这通常位于文件的最末尾。\
然而,您可以在 [**这篇博客文章**](https://davedelong.com/blog/2018/01/10/reading-your-own_entitlements/) 和这个 [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4) 中找到一些关于此部分的信息。
{{#ref}}
../../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md
{{#endref}}
包含有关 Mach-O 文件**代码签名**的信息。它仅包含一个**偏移量offset**,指向**签名 blob**。该偏移通常位于文件的末尾。\
你可以在[**this blog post**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) 和 [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4) 中找到关于该段的一些信息。
### **`LC_ENCRYPTION_INFO[_64]`**
支持二进制加密。然而,当然,如果攻击者设法破坏了进程,他将能够以未加密的方式转储内存。
支持二进制加密。不过,如果攻击者成功攻陷进程,当然可以将内存以未加密形式 dump 出来
### **`LC_LOAD_DYLINKER`**
包含 **动态链接器可执行文件的路径**,该文件将共享库映射到进程地址空间。**值始终设置为 `/usr/lib/dyld`**。重要的是要注意,在 macOS 中dylib 映射发生在 **用户模式**,而不是内核模式
包含将共享库映射到进程地址空间的动态链接器可执行文件的路径。该值**始终设置为 `/usr/lib/dyld`**。需要注意的是,在 macOS 中dylib 的映射发生在**user mode**而不是内核态kernel mode
### **`LC_IDENT`**
过时,但当配置为在崩溃时生成转储时,会创建一个 Mach-O 核心转储,并在 `LC_IDENT` 命令中设置内核版本
已废弃,但当配置为在 panic 时生成转储时,会创建 Mach-O core dump并且内核版本会在 `LC_IDENT` 命令中设置
### **`LC_UUID`**
随机 UUID。它对任何直接的事情都很有用,但 XNU 将其与其他进程信息一起缓存。它可以在崩溃报告中使用
随机 UUID。本身直接用途有限,但 XNU 会将其与其他进程信息一起缓存,可用于崩溃报告
### **`LC_DYLD_ENVIRONMENT`**
允许在进程执行之前向 dyld 指示环境变量。这可能非常危险,因为它可能允许在进程内部执行任意代码,因此此加载命令仅在使用 `#define SUPPORT_LC_DYLD_ENVIRONMENT` 构建的 dyld 中使用,并进一步限制处理仅限于形式为 `DYLD_..._PATH` 的变量,指定加载路径
允许在进程执行前向 dyld 指定环境变量。这可能非常危险,因为它可能允许在进程内执行任意代码,因此该 load command 仅在 dyld 使用 `#define SUPPORT_LC_DYLD_ENVIRONMENT` 构建时使用,并且进一步将处理限制为形如 `DYLD_..._PATH` 的变量(用于指定加载路径)
### **`LC_LOAD_DYLIB`**
此加载命令描述了一个 **动态** **库** 依赖关系,**指示** **加载器** (dyld) **加载和链接该库**。每个 Mach-O 二进制文件所需的库都有一个 `LC_LOAD_DYLIB` 加载命令
该 load command 描述了一个**动态库dynamic library**依赖,指示 loaderdyld去加载并链接该库。对于 Mach-O 二进制所需的每个库,都会有一个 `LC_LOAD_DYLIB` load command
- 此加载命令是 **`dylib_command`** 类型的结构(其中包含一个描述实际依赖动态库的 struct dylib
- 该 load command 的结构类型为 **`dylib_command`**(其中包含一个 struct dylib描述实际的依赖动态库
```objectivec
struct dylib_command {
uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */
@ -330,7 +335,7 @@ uint32_t compatibility_version; /* library's compatibility vers number*/
```
![](<../../../images/image (486).png>)
您还可以通过命令行获取此信息:
你也可以通过 cli 使用以下命令获取这些信息:
```bash
otool -L /bin/ls
/bin/ls:
@ -338,53 +343,53 @@ otool -L /bin/ls
/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
```
一些潜在的与恶意软件相关的库包括
一些可能与 malware 相关的库有
- **DiskArbitration**: 监控 USB 驱动器
- **DiskArbitration**监控 USB 驱动器
- **AVFoundation:** 捕获音频和视频
- **CoreWLAN**: Wifi 扫描。
- **CoreWLAN**WiFi 扫描。
> [!NOTE]
> Mach-O 二进制文件可以包含一个或 **多个** **构造函数**,这些构造函数将在 **LC_MAIN** 指定的地址 **之前** **执行**。\
> 任何构造函数的偏移量保存在 **\_\_mod_init_func** 段的 **\_\_DATA_CONST** 部分中
> [!TIP]
> 一个 Mach-O 二进制可以包含一个或多个 **构造函数**,这些函数会在 **LC_MAIN** 指定的地址之前**执行**。\
> 任何构造函数的偏移量保存在 **__mod_init_func** section 的 **__DATA_CONST** segment
## **Mach-O 数据**
文件的核心是数据区域,由加载命令区域中定义的多个段组成。**每个段中可以包含多种数据部分**,每个部分 **保存特定类型的代码或数据**
在文件的核心是数据区域,该区域由 load-commands 区域定义的多个段组成。**每个段中可以包含多种数据节**,每个节都**包含特定类型的代码或数据**
> [!TIP]
> 数据基本上是包含所有由加载命令 **LC_SEGMENTS_64** 加载的 **信息** 的部分。
> 数据基本上是由 load commands **LC_SEGMENTS_64** 加载的包含所有**信息**的部分
![https://www.oreilly.com/api/v2/epubs/9781785883378/files/graphics/B05055_02_38.jpg](<../../../images/image (507) (3).png>)
这包括:
- **函数表:** 包含有关程序函数的信息。
- **符号表**: 包含有关二进制文件使用的外部函数的信息
- 还可能包含内部函数、变量名称等
- **函数表** 保存关于程序函数的信息。
- **符号表** 包含二进制使用的外部函数的信息
- 它还可以包含内部函数、变量名等信息
要检查它,可以使用 [**Mach-O View**](https://sourceforge.net/projects/machoview/) 工具:
要检查它,可以使用 [**Mach-O View**](https://sourceforge.net/projects/machoview/) 工具:
<figure><img src="../../../images/image (1120).png" alt=""><figcaption></figcaption></figure>
者从命令行
在命令行中
```bash
size -m /bin/ls
```
## Objetive-C 常见部分
## Objetive-C 常见
`__TEXT` 段 (r-x):
- `__objc_classname`: 类名 (字符串)
- `__objc_methname`: 方法名 (字符串)
- `__objc_methtype`: 方法类型 (字符串)
- `__objc_classname`: 类名(字符串)
- `__objc_methname`: 方法名(字符串)
- `__objc_methtype`: 方法类型(字符串)
`__DATA` 段 (rw-):
- `__objc_classlist`: 所有 Objective-C 类的指针
- `__objc_nlclslist`: 非懒加载 Objective-C 类的指针
- `__objc_catlist`: 类别的指针
- `__objc_nlcatlist`: 非懒加载类别的指针
- `__objc_classlist`: 指向所有 Objetive-C 类的指针
- `__objc_nlclslist`: 指向非延迟 Objective-C 类的指针
- `__objc_catlist`: 指向类别的指针
- `__objc_nlcatlist`: 指向非延迟类别的指针
- `__objc_protolist`: 协议列表
- `__objc_const`: 常量数据
- `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`...

View File

@ -4,12 +4,17 @@
## 基本信息
Mach-o 二进制文件包含一个称为 **`LC_CODE_SIGNATURE`** 的加载命令,指示二进制文件内部签名的 **偏移量****大小**。实际上,使用 GUI 工具 MachOView可以在二进制文件的末尾找到一个名为 **Code Signature** 的部分,其中包含这些信息:
{{#ref}}
../../../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/mach-o-entitlements-and-ipsw-indexing.md
{{#endref}}
Mach-o 二进制包含一个名为 **`LC_CODE_SIGNATURE`** 的 load command指示二进制中签名的 **offset****size**。事实上,使用 GUI 工具 MachOView可以在二进制末尾找到一个名为 **Code Signature** 的区段,其中包含这些信息:
<figure><img src="../../../images/image (1) (1) (1) (1).png" alt="" width="431"><figcaption></figcaption></figure>
代码签名的魔术头是 **`0xFADE0CC0`**。然后你会得到一些信息,例如 superBlob 的长度和 blob 的数量。\
可以在 [源代码这里](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276) 找到这些信息:
Code Signature 的 magic header 是 **`0xFADE0CC0`**。然后你会看到诸如 length 和 superBlob 中包含它们的 blobs 数量等信息。\
可以在 [source code here](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276) 找到这些信息:
```c
/*
* Structure of an embedded-signature SuperBlob
@ -38,14 +43,14 @@ char data[];
} CS_GenericBlob
__attribute__ ((aligned(1)));
```
常见的 blob 包含代码目录、要求和权限以及加密消息语法 (CMS)。\
此外,请注意 blob 中编码的数据是以 **大端字节序** 编码的。
常见的 blobs 包括 Code Directory、Requirements 和 Entitlements以及 Cryptographic Message Syntax (CMS).\
此外,请注意 blobs 中的数据是以 **Big Endian.** 编码的。
此外,签名可以从二进制文件中分离并存储在 `/var/db/DetachedSignatures`iOS 使用)。
## 代码目录 Blob
## Code Directory Blob
可以在代码中找到 [代码目录 Blob 的声明](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L104)
可以在代码中找到 [Code Directory Blob in the code](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L104):
```c
typedef struct __CodeDirectory {
uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */
@ -101,12 +106,12 @@ char end_withLinkage[0];
} CS_CodeDirectory
__attribute__ ((aligned(1)));
```
注意,这个结构有不同的版本,旧版本可能包含较少的信息。
注意该 struct 有不同版本,旧版本可能包含较少信息。
## 签名代码页
## 签名代码页
对整个二进制文件进行哈希计算效率低下,如果它仅部分加载到内存中甚至是无用的。因此,代码签名实际上是一个哈希的哈希,其中每个二进制页面都是单独哈希的。\
实际上,在之前的 **Code Directory** 代码中,您可以看到 **页面大小在其字段中被指定**。此外,如果二进制文件的大小不是页面大小的倍数,字段 **CodeLimit** 指定了签名的结束位置。
对整个二进制文件进行哈希既低效,在只部分加载到内存时甚至无用。因此,代码签名实际上是哈希的哈希,每个二进制页面分别进行哈希。\
实际上,在前面的 **Code Directory** 代码中,你可以看到 **页面大小在其字段之一中指定**。此外,如果二进制的大小不是页面大小的整数倍,字段 **CodeLimit** 指定了签名的结束位置。
```bash
# Get all hashes of /bin/ps
codesign -d -vvvvvv /bin/ps
@ -142,27 +147,27 @@ dd if=$BINARY of=/tmp/`basename $BINARY`.page.$i bs=$PAGESIZE skip=$i count=1
done
openssl sha256 /tmp/*.page.*
```
## Entitlements Blob
## 权限 blob
请注意,应用程序可能还包含一个**entitlement blob**其中定义了所有的权限。此外一些iOS二进制文件可能在特殊槽-7中具体定义其权限而不是在-5权限特殊槽中)。
注意,应用程序可能还包含一个定义了所有权限的**权限 blob**。此外,一些 iOS 二进制文件可能会把它们的权限放在特殊槽位 -7而不是常见的 -5 entitlements 特殊槽位)。
## Special Slots
## 特殊槽位
MacOS应用程序并不具备执行所需的所有内容,而是还使用**外部资源**(通常在应用程序的**bundle**内)。因此,二进制文件中有一些槽将包含一些有趣的外部资源的哈希,以检查它们是否被修改。
MacOS 应用并非把执行所需的所有内容都包含在二进制内,它们也使用 **external resources**(通常位于应用的 **bundle** 内)。因此,二进制中存在一些槽位,用于存放某些重要外部资源的哈希,以便验证它们未被修改。
实际上,可以在代码目录结构中看到一个名为**`nSpecialSlots`**的参数指示特殊槽的数量。没有特殊槽0最常见的槽从-1到-6
事实上,可以在 Code Directory 结构体中看到一个名为 **`nSpecialSlots`** 的参数,用来指示特殊槽位的数量。注意没有特殊槽位 0最常见的槽位是从 -1 到 -6
- `info.plist`的哈希(或在`__TEXT.__info__plist`中的哈希)。
- 需求的哈希
- 资源目录的哈希(在bundle内的`_CodeSignature/CodeResources`文件的哈希)。
- `info.plist` 的哈希(或位于 `__TEXT.__info__plist` 中的那个)。
- Requirements 的哈希
- 资源目录的哈希(位于 bundle 内的 `_CodeSignature/CodeResources` 文件的哈希)。
- 应用程序特定(未使用)
- 权限的哈希
- 仅DMG代码签名
- DER权限
- 仅针对 DMG代码签名
- DER 权限
## Code Signing Flags
## 代码签名标志
每个进程都有一个相关的位掩码,称为`status`,由内核启动,其中一些可以被**代码签名**覆盖。这些可以包含在代码签名中的标志在[代码中定义](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36)
每个进程都有一个关联的位掩码,称为 `status`,由内核设置,其中一些位可以被**代码签名**覆盖。这些可以包含在代码签名中的标志在代码中定义 [defined in the code](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36):
```c
/* code signing attributes of a process */
#define CS_VALID 0x00000001 /* dynamically valid */
@ -207,15 +212,15 @@ CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV | CS_RUNTIME | CS_LINKER_SIGNED)
#define CS_ENTITLEMENT_FLAGS (CS_GET_TASK_ALLOW | CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_NVRAM_UNRESTRICTED)
```
注意函数 [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) 在启动执行时也可以动态添加 `CS_EXEC_*` 标志。
注意函数 [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) 在启动执行时也可以动态添加 `CS_EXEC_*` 标志。
## 代码签名要求
每个应用程序存储一些 **要求**,必须 **满足** 这些要求才能被执行。如果 **应用程序包含的要求未被应用程序满足**,则不会执行(因为它可能已被更改)。
每个应用会存储一些必须**满足**的**要求**,以便能够被执行。如果应用包含的这些**要求**没有被满足,应用将不会被执行(因为它可能已被篡改)。
二进制文件的要求使用 **特殊语法**,这是一个 **表达式** 的流,并使用 `0xfade0c00` 作为魔法编码为 blobs**哈希存储在特殊代码槽中**
二进制的这些要求使用一种**特殊语法**,是由一系列**表达式**组成,并以 blob 的形式编码,使用 `0xfade0c00` 作为魔数,其**哈希存储在一个特殊的 code slot 中**
可以通过运行来查看二进制文件的要求:
可以通过运行以下命令查看二进制的要求:
```bash
codesign -d -r- /bin/ls
Executable=/bin/ls
@ -225,10 +230,10 @@ codesign -d -r- /Applications/Signal.app/
Executable=/Applications/Signal.app/Contents/MacOS/Signal
designated => identifier "org.whispersystems.signal-desktop" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = U68MSDN6DR
```
> [!NOTE]
> 注意这些签名可以检查诸如认证信息、TeamID、ID、权限以及许多其他数据。
> [!TIP]
> 注意这些签名如何检查诸如证书信息、TeamID、IDs、entitlements 等多种数据。
此外,可以使用 `csreq` 工具生成一些编译的要求
此外,可以使用 `csreq` 工具生成一些已编译的 requirements
```bash
# Generate compiled requirements
csreq -b /tmp/output.csreq -r='identifier "org.whispersystems.signal-desktop" and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = U68MSDN6DR'
@ -240,20 +245,20 @@ od -A x -t x1 /tmp/output.csreq
0000020 00 00 00 21 6f 72 67 2e 77 68 69 73 70 65 72 73
[...]
```
可以通过 `Security.framework` 中的一些 API 访问此信息并创建或修改要求,例如:
可以通过 `Security.framework` 的一些 API 访问这些信息并创建或修改要求,如:
#### **检查有效性**
- **`Sec[Static]CodeCheckValidity`**: 根据要求检查 SecCodeRef 的有效性。
- **`SecRequirementEvaluate`**: 在证书上下文中验证要求。
- **`SecTaskValidateForRequirement`**: 验证正在运行的 SecTask 是否符合 `CFString` 要求
- **`Sec[Static]CodeCheckValidity`**根据要求检查 SecCodeRef 的有效性。
- **`SecRequirementEvaluate`**在证书上下文中验证要求。
- **`SecTaskValidateForRequirement`**:根据 `CFString` 要求验证正在运行的 SecTask
#### **创建和管理代码要求**
- **`SecRequirementCreateWithData`:** 从表示要求的二进制数据创建 `SecRequirementRef`
- **`SecRequirementCreateWithString`:** 从要求的字符串表达式创建 `SecRequirementRef`
- **`SecRequirementCopy[Data/String]`**: 检索 `SecRequirementRef` 的二进制数据表示。
- **`SecRequirementCreateGroup`**: 为应用程序组成员资格创建要求。
- **`SecRequirementCreateGroup`**: 为 app-group 成员资格创建要求
#### **访问代码签名信息**
@ -262,35 +267,35 @@ od -A x -t x1 /tmp/output.csreq
#### **修改代码要求**
- **`SecCodeSignerCreate`**: 创建 `SecCodeSignerRef` 对象以执行代码签名操作
- **`SecCodeSignerSetRequirement`**: 为代码签名者设置在签名期间应用的新要求。
- **`SecCodeSignerAddSignature`**: 将签名添加到使用指定签名者签名的代码中
- **`SecCodeSignerCreate`**: 创建用于执行代码签名操作的 `SecCodeSignerRef` 对象。
- **`SecCodeSignerSetRequirement`**: 为签名器设置在签名期间应用的新要求。
- **`SecCodeSignerAddSignature`**: 使用指定签名器向正在签名的代码添加签名
#### **使用要求验证代码**
- **`SecStaticCodeCheckValidity`**: 根据指定要求验证静态代码对象。
#### **其他有用的 API**
#### **其他有用的 APIs**
- **`SecCodeCopy[Internal/Designated]Requirement`: 从 SecCodeRef 获取 SecRequirementRef**
- **`SecCodeCopyGuestWithAttributes`**: 创建一个基于特定属性的代码对象的 `SecCodeRef`,适用于沙箱
- **`SecCodeCopy[Internal/Designated]Requirement`: Get SecRequirementRef from SecCodeRef**
- **`SecCodeCopyGuestWithAttributes`**: 基于特定属性创建表示代码对象的 `SecCodeRef`,可用于沙箱化
- **`SecCodeCopyPath`**: 检索与 `SecCodeRef` 关联的文件系统路径。
- **`SecCodeCopySigningIdentifier`**: 从 `SecCodeRef` 获取签名标识符(例如,团队 ID
- **`SecCodeCopySigningIdentifier`**: 从 `SecCodeRef` 获取签名标识符(例如 Team ID
- **`SecCodeGetTypeID`**: 返回 `SecCodeRef` 对象的类型标识符。
- **`SecRequirementGetTypeID`**: 获取 `SecRequirementRef` 的 CFTypeID
- **`SecRequirementGetTypeID`**: 获取 `SecRequirementRef` 的 CFTypeID
#### **代码签名标志和常量**
- **`kSecCSDefaultFlags`**: 在许多 Security.framework 函数中用于代码签名操作的默认标志。
- **`kSecCSDefaultFlags`**: 在许多 `Security.framework` 函数中用于代码签名操作的默认标志。
- **`kSecCSSigningInformation`**: 用于指定应检索签名信息的标志。
## 代码签名强制执行
## 代码签名强制
**内核**是在允许应用程序代码执行之前**检查代码签名**的。此外,能够在内存中写入和执行新代码的一种方法是滥用 JIT如果 `mprotect` 被调用时带有 `MAP_JIT` 标志。请注意,应用程序需要特殊的权限才能做到这一点
内核负责在允许应用代码执行之前检查代码签名。此外,如果 `mprotect` 使用 `MAP_JIT` 标志被调用,滥用 JIT 是在内存中写入并执行新代码的一种方式。注意,应用需要特殊的 entitlement 才能这样做
## `cs_blobs` & `cs_blob`
[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) 结构包含有关正在运行的进程的权限信息。 `csb_platform_binary` 还指示应用程序是否为平台二进制文件(操作系统在不同时间检查这一点,以应用安全机制,例如保护这些进程的任务端口的 SEND 权限)。
[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) 结构包含关于运行进程 entitlement 的信息。`csb_platform_binary` 还表明应用是否为 platform binary操作系统在不同阶段检查该标志以应用安全机制,例如保护这些进程的任务端口的 SEND 权限)。
```c
struct cs_blob {
struct cs_blob *csb_next;
@ -349,7 +354,7 @@ bool csb_csm_managed;
#endif
};
```
## 参考文献
## 参考资料
- [**\*OS Internals Volume III**](https://newosxbook.com/home.html)