mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/macos-hardening/macos-security-and-privilege-escalation
This commit is contained in:
parent
f3287bab4b
commit
7d3672d277
@ -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)
|
||||
|
@ -1,8 +1,8 @@
|
||||
# 特定のソフトウェア/ファイルタイプ向けトリック
|
||||
# 特定のソフトウェア/ファイルタイプのトリック
|
||||
|
||||
{{#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}}
|
||||
|
@ -0,0 +1,213 @@
|
||||
# Mach-O Entitlements Extraction & IPSW Indexing
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## 概要
|
||||
|
||||
このページでは、LC_CODE_SIGNATURE を辿ってコード署名の SuperBlob を解析することで Mach-O バイナリからプログラム的に entitlements を抽出する方法と、Apple IPSW ファームウェアをマウントして内容をインデックス化し、フォレンジック検索/差分解析にスケールさせる方法を説明します。
|
||||
|
||||
Mach-O フォーマットや code signing の復習が必要な場合は、次も参照してください: macOS code signing and SuperBlob internals.
|
||||
- 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 ロードコマンドで参照されるコード署名データ内、__LINKEDIT セグメントに格納されています。署名は複数の blob(code directory、requirements、entitlements、CMS など)を含む CS_SuperBlob です。entitlements blob は CS_GenericBlob で、そのデータは entitlements キーと値をマッピングする Apple Binary Property List (bplist00) です。
|
||||
|
||||
Key structures (from 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 スライスを含みます。検査したいアーキテクチャのスライスを選択して、その 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.
|
||||
|
||||
実装ノート:
|
||||
- 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
|
||||
```
|
||||
使用上のヒント:
|
||||
- To handle fat binaries, first read struct fat_header/fat_arch, choose the desired architecture slice, then pass the subrange to parse_entitlements.
|
||||
- On macOS you can validate results with: 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 に非常に有用です。
|
||||
|
||||
|
||||
## IPSWs 全体でのスケーリング(マウントとインデックス化)
|
||||
|
||||
フルイメージを保存せずに大規模に実行ファイルを列挙し、entitlements を抽出するには:
|
||||
|
||||
- Use the ipsw tool by @blacktop to download and mount firmware filesystems. Mounting leverages apfs-fuse, so you can traverse APFS volumes without full extraction.
|
||||
```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 と imported 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";
|
||||
```
|
||||
DB の移植性に関する注意(独自のインデクサを実装する場合):
|
||||
- ORM/抽象化レイヤ(例: SeaORM)を使い、コードを DB 非依存(SQLite/PostgreSQL)に保つ。
|
||||
- SQLite は AUTOINCREMENT を INTEGER PRIMARY KEY にのみ要求する。Rust で i64 の PK を使いたい場合は、エンティティを i32 として生成して型変換すること。SQLite は内部的に INTEGER を 8 バイト符号付きで格納する。
|
||||
|
||||
|
||||
## Open-source tooling and references for entitlement hunting
|
||||
|
||||
- Firmware のマウント/ダウンロード: https://github.com/blacktop/ipsw
|
||||
- Entitlement データベースと参考資料:
|
||||
- Jonathan Levin’s entitlement DB: https://newosxbook.com/ent.php
|
||||
- entdb: https://github.com/ChiChou/entdb
|
||||
- Large-scale indexer (Rust, self-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 signing の内部(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 Levin’s 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}}
|
@ -4,40 +4,40 @@
|
||||
|
||||
## 基本情報
|
||||
|
||||
Mac OSのバイナリは通常、**ユニバーサルバイナリ**としてコンパイルされます。**ユニバーサルバイナリ**は**同じファイル内で複数のアーキテクチャをサポート**できます。
|
||||
Mac OS のバイナリは通常 **universal binaries** としてコンパイルされます。**universal binary** は同一ファイル内で複数のアーキテクチャを**サポートできます**。
|
||||
|
||||
これらのバイナリは**Mach-O構造**に従い、基本的には以下で構成されています:
|
||||
これらのバイナリは **Mach-O structure** に従っており、基本的に以下で構成されています:
|
||||
|
||||
- ヘッダー
|
||||
- ロードコマンド
|
||||
- データ
|
||||
- Header
|
||||
- Load Commands
|
||||
- Data
|
||||
|
||||
.png>)
|
||||
|
||||
## ファットヘッダー
|
||||
## Fat Header
|
||||
|
||||
ファイルを検索するには: `mdfind fat.h | grep -i mach-o | grep -E "fat.h$"`
|
||||
Search for the file with: `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>
|
||||
|
||||
ヘッダーには**マジック**バイトがあり、その後にファイルが**含む**アーキテクチャの**数**(`nfat_arch`)が続き、各アーキテクチャには`fat_arch`構造体があります。
|
||||
ヘッダは **magic** バイトの後にファイルが含む **archs** の**数**(`nfat_arch`)が続き、各 arch は `fat_arch` 構造体を持ちます。
|
||||
|
||||
次のコマンドで確認できます:
|
||||
Check it with:
|
||||
|
||||
<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]
|
||||
@ -64,15 +64,15 @@ capabilities PTR_AUTH_VERSION USERSPACE 0
|
||||
</strong> align 2^14 (16384)
|
||||
</code></pre>
|
||||
|
||||
または、[Mach-O View](https://sourceforge.net/projects/machoview/)ツールを使用して:
|
||||
or using the [Mach-O View](https://sourceforge.net/projects/machoview/) tool:
|
||||
|
||||
<figure><img src="../../../images/image (1094).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
おそらく考えているように、通常、2つのアーキテクチャ用にコンパイルされたユニバーサルバイナリは、1つのアーキテクチャ用にコンパイルされたものの**サイズを倍増**させます。
|
||||
おそらく想像できるように、通常 2 つのアーキテクチャ向けにコンパイルされた universal binary は、1 つのアーキテクチャ向けにコンパイルされたものよりも **サイズが2倍** になります。
|
||||
|
||||
## **Mach-Oヘッダー**
|
||||
## **Mach-O Header**
|
||||
|
||||
ヘッダーには、ファイルをMach-Oファイルとして識別するためのマジックバイトや、ターゲットアーキテクチャに関する情報など、ファイルに関する基本情報が含まれています。これを見つけるには: `mdfind loader.h | grep -i mach-o | grep -E "loader.h$"`
|
||||
ヘッダには、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) */
|
||||
@ -99,19 +99,19 @@ uint32_t flags; /* flags */
|
||||
uint32_t reserved; /* reserved */
|
||||
};
|
||||
```
|
||||
### Mach-Oファイルタイプ
|
||||
### Mach-O File Types
|
||||
|
||||
異なるファイルタイプがあり、[**ソースコードの例はこちら**](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`: 固定VMライブラリファイル。
|
||||
- `MH_CORE`: コードダンプ
|
||||
- `MH_PRELOAD`: プリロードされた実行可能ファイル(XNUではもはやサポートされていない)
|
||||
- `MH_DYLIB`: 動的ライブラリ
|
||||
- `MH_DYLINKER`: 動的リンカー
|
||||
- `MH_BUNDLE`: "プラグインファイル"。gccの-bundleを使用して生成され、`NSBundle`または`dlopen`によって明示的にロードされる。
|
||||
- `MH_DYSM`: 付随する`.dSym`ファイル(デバッグ用のシンボルを含むファイル)。
|
||||
- `MH_CORE`: コアダンプ。
|
||||
- `MH_PRELOAD`: プリロードされた実行ファイル(XNUではもはやサポートされていません)。
|
||||
- `MH_DYLIB`: 動的ライブラリ。
|
||||
- `MH_DYLINKER`: 動的リンカ。
|
||||
- `MH_BUNDLE`: 「プラグインファイル」。-bundle in gcc を使って生成され、`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
|
||||
```
|
||||
Or using [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_NOUNDEFS`: No undefined references (fully linked)
|
||||
- `MH_DYLDLINK`: dyld によるリンク
|
||||
- `MH_PREBOUND`: Dynamic references prebound.
|
||||
- `MH_SPLIT_SEGS`: File splits r/o and r/w segments.
|
||||
- `MH_WEAK_DEFINES`: Binary has weak defined symbols
|
||||
- `MH_BINDS_TO_WEAK`: Binary uses weak symbols
|
||||
- `MH_ALLOW_STACK_EXECUTION`: Make the stack executable
|
||||
- `MH_NO_REEXPORTED_DYLIBS`: ライブラリが LC_REEXPORT コマンドを持たない
|
||||
- `MH_PIE`: Position Independent Executable
|
||||
- `MH_HAS_TLV_DESCRIPTORS`: スレッドローカル変数を含むセクションがある
|
||||
- `MH_NO_HEAP_EXECUTION`: ヒープ/データページの実行を許可しない
|
||||
- `MH_HAS_OBJC`: バイナリが Objective-C セクションを持つ
|
||||
- `MH_SIM_SUPPORT`: シミュレータサポート
|
||||
- `MH_DYLIB_IN_CACHE`: 共有ライブラリキャッシュ内の dylibs/frameworks に使用されます。
|
||||
- `MH_DYLIB_IN_CACHE`: shared library cache 内の dylib/framework に使用される。
|
||||
|
||||
## **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`です。
|
||||
There are about **50 different types of load commands** that the system handles differently. The most common ones are: `LC_SEGMENT_64`, `LC_LOAD_DYLINKER`, `LC_MAIN`, `LC_LOAD_DYLIB`, and `LC_CODE_SIGNATURE`.
|
||||
|
||||
### **LC_SEGMENT/LC_SEGMENT_64**
|
||||
|
||||
> [!TIP]
|
||||
> 基本的に、このタイプのロードコマンドは、バイナリが実行されるときに**データセクションに示されたオフセット**に従って、**\_\_TEXT**(実行可能コード)**と\_\_DATA**(プロセスのデータ)**セグメントをどのようにロードするかを定義します**。
|
||||
> 基本的に、このタイプの Load Command は、バイナリが実行される際に Data セクションで示されたオフセットに従って **どのように \_\_TEXT をロードするか** (実行可能コード) **および \_\_DATA** (プロセスのデータ) **セグメント** を定義します。
|
||||
|
||||
これらのコマンドは、プロセスが実行されるときに**仮想メモリ空間**に**マッピング**される**セグメント**を**定義**します。
|
||||
These commands **define segments** that are **mapped** into the **virtual memory space** of a process when it is executed.
|
||||
|
||||
**\_\_TEXT**セグメントのように、プログラムの実行可能コードを保持する**異なるタイプ**のセグメントがあり、プロセスによって使用されるデータを含む**\_\_DATA**セグメントがあります。これらの**セグメントはMach-Oファイルのデータセクションに位置しています**。
|
||||
There are **different types** of segments, such as the **\_\_TEXT** segment, which holds the executable code of a program, and the **\_\_DATA** segment, which contains data used by the process. These **segments are located in the data section** of the Mach-O file.
|
||||
|
||||
**各セグメント**はさらに**複数のセクション**に**分割**できます。**ロードコマンド構造**には、各セグメント内の**これらのセクション**に関する**情報**が含まれています。
|
||||
**Each segment** can be further **divided** into multiple **sections**. The **load command structure** contains **information** about **these sections** within the respective segment.
|
||||
|
||||
ヘッダーの最初には**セグメントヘッダー**があります:
|
||||
In the header first you find the **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>
|
||||
|
||||
このヘッダーは、**その後に表示されるヘッダーのセクションの数を定義します**:
|
||||
This header defines the **number of sections whose headers appear after** it:
|
||||
```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 offset** (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を除く)。バイナリは、最初の4kをカバーする小さな\_\_PAGEZEROを作成し、残りの32ビットメモリをユーザーモードとカーネルモードの両方でアクセス可能にすることで、この要件を満たすことができます。
|
||||
- **`__TEXT`**: **実行可能な** **コード**を含み、**読み取り**および**実行**権限(書き込み不可)を持ちます。 このセグメントの一般的なセクション:
|
||||
- `__text`: コンパイルされたバイナリコード
|
||||
- **`__PAGEZERO`:** カーネルに対して **address zero** を **マップしない(読み取り・書き込み・実行ができないようにする)** よう指示します。構造体内の maxprot と minprot はゼロに設定され、このページに対して **読み・書き・実行の権限が一切ない** ことを示します。
|
||||
- この割り当ては **NULL pointer dereference 脆弱性を軽減する** ために重要です。これは XNU がハードな page zero を強制し、最初のページ(最初の1ページのみ)をアクセス不可にするためです(i386 を除く)。バイナリは小さな __PAGEZERO(`-pagezero_size` を使用)を作成して最初の4kを覆い、残りの32bitメモリをユーザ・カーネル両方でアクセス可能にすることでこの要件を満たせます。
|
||||
- **`__TEXT`**: **実行可能なコード** を含み、**読み取り** と **実行** の権限を持ちます(書き込み不可)。このセグメントの一般的なセクション:
|
||||
- `__text`: コンパイル済みバイナリコード
|
||||
- `__const`: 定数データ(読み取り専用)
|
||||
- `__ [c/u/os_log]string`: C、Unicodeまたはosログの文字列定数
|
||||
- `__stubs`および`__stubs_helper`: 動的ライブラリのロードプロセスに関与
|
||||
- `__unwind_info`: スタックアンワインドデータ。
|
||||
- これらのすべてのコンテンツは署名されていますが、実行可能としてもマークされています(文字列専用セクションのように、この特権を必ずしも必要としないセクションの悪用のためのオプションが増えます)。
|
||||
- **`__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環境変数を無視することを保証します。
|
||||
- `__[c/u/os_log]string`: C、Unicode、または os ログの文字列定数
|
||||
- `__stubs` と `__stubs_helper`: 動的ライブラリ読み込みプロセスで関与
|
||||
- `__unwind_info`: スタックアンワインド情報
|
||||
- これらの内容はすべて署名されていますが、同時に実行可能としてマークされている点に注意してください(文字列専用のセクションなど、本来この権限を必要としないセクションの悪用機会を生みます)。
|
||||
- **`__DATA`**: **読み取り** と **書き込み** が可能なデータを含みます(実行不可)。
|
||||
- `__got:` グローバルオフセットテーブル(Global Offset Table)
|
||||
- `__nl_symbol_ptr`: Non-lazy(ロード時にバインドされる)シンボルポインタ
|
||||
- `__la_symbol_ptr`: Lazy(使用時にバインドされる)シンボルポインタ
|
||||
- `__const`: 本来は読み取り専用であるべきデータ(実際にはそうでないことがある)
|
||||
- `__cfstring`: CoreFoundation 文字列
|
||||
- `__data`: 初期化済みのグローバル変数
|
||||
- `__bss`: 初期化されていない静的変数
|
||||
- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, etc): Objective-C runtime が使用する情報
|
||||
- **`__DATA_CONST`**: \_\_DATA.\_\_const は定数である保証がなく(書き込み権限がある)、他のポインタや GOT も同様です。このセクションは `mprotect` を使用して `__const`、いくつかの初期化子、および(解決後の)GOT テーブルを **読み取り専用** にします。
|
||||
- **`__LINKEDIT`**: リンカ(dyld)用の情報を含みます。たとえばシンボル、文字列、リロケーションテーブルのエントリなどです。`__TEXT` や `__DATA` に含まれない内容の汎用コンテナであり、その内容は他の load command で説明されます。
|
||||
- dyld information: Rebase、Non-lazy/lazy/weak binding opcode と export 情報
|
||||
- Functions starts: 関数の開始アドレスのテーブル
|
||||
- Data In Code: `__text` 内のデータ領域(データアイランド)
|
||||
- Symbol Table: バイナリ内のシンボル
|
||||
- Indirect Symbol Table: ポインタ/スタブシンボル
|
||||
- String Table
|
||||
- Code Signature
|
||||
- **`__OBJC`**: Objective-C runtime が使用する情報を含みます。これらの情報は `__DATA` セグメント内の各種 `__objc_*` セクションにも存在する場合があります。
|
||||
- **`__RESTRICT`**: コンテンツを持たないセグメントで、`__restrict` という単一の(こちらも空の)セクションを持ち、バイナリ実行時に DYLD の環境変数を無視することを保証します。
|
||||
|
||||
コードで見ることができたように、**セグメントはフラグもサポートしています**(ただし、あまり使用されていません):
|
||||
コードからも分かるように、**segments はフラグをサポート** しています(あまり多用されませんが):
|
||||
|
||||
- `SG_HIGHVM`: コアのみ(使用されていない)
|
||||
- `SG_FVMLIB`: 使用されていない
|
||||
- `SG_NORELOC`: セグメントに再配置がない
|
||||
- `SG_PROTECTED_VERSION_1`: 暗号化。Finderが`__TEXT`セグメントのテキストを暗号化するために使用する例があります。
|
||||
- `SG_HIGHVM`: Core 専用(未使用)
|
||||
- `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`**
|
||||
|
||||
Mach-Oファイルの**コード署名**に関する情報を含みます。これは通常、**署名ブロブ**を指す**オフセット**のみを含みます。これは通常、ファイルの非常に最後にあります。\
|
||||
ただし、このセクションに関する情報は[**このブログ投稿**](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}}
|
||||
|
||||
|
||||
Contains information about the **code signature of the Macho-O file**. It only contains an **offset** that **points** to the **signature blob**. This is typically at the very end of the file.\
|
||||
However, you can find some information about this section in [**this blog post**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/) and this [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4).
|
||||
|
||||
### **`LC_ENCRYPTION_INFO[_64]`**
|
||||
|
||||
バイナリ暗号化のサポート。ただし、もちろん、攻撃者がプロセスを侵害することに成功した場合、彼はメモリを暗号化されていない状態でダンプすることができます。
|
||||
Support for binary encryption. However, of course, if an attacker manages to compromise the process, he will be able to dump the memory unencrypted.
|
||||
|
||||
### **`LC_LOAD_DYLINKER`**
|
||||
|
||||
プロセスアドレス空間に共有ライブラリをマッピングする**動的リンカ実行可能ファイルへのパス**を含みます。**値は常に`/usr/lib/dyld`に設定されています**。macOSでは、dylibのマッピングは**ユーザーモード**で行われることに注意が必要です。
|
||||
Contains the **path to the dynamic linker executable** that maps shared libraries into the process address space. The **value is always set to `/usr/lib/dyld`**. It’s important to note that in macOS, dylib mapping happens in **user mode**, not in kernel mode.
|
||||
|
||||
### **`LC_IDENT`**
|
||||
|
||||
廃止されていますが、パニック時にダンプを生成するように設定されていると、Mach-Oコアダンプが作成され、カーネルバージョンが`LC_IDENT`コマンドに設定されます。
|
||||
Obsolete but when configured to geenrate dumps on panic, a Mach-O core dump is created and the kernel version is set in the `LC_IDENT` command.
|
||||
|
||||
### **`LC_UUID`**
|
||||
|
||||
ランダムUUID。直接的には何にでも役立ちますが、XNUはそれをプロセス情報の残りとキャッシュします。クラッシュレポートで使用できます。
|
||||
Random UUID. It's useful for anything directly but XNU caches it with the rest of the process info. It can be used in crash reports.
|
||||
|
||||
### **`LC_DYLD_ENVIRONMENT`**
|
||||
|
||||
プロセスが実行される前にdyldに環境変数を示すことを許可します。これは、プロセス内で任意のコードを実行できる可能性があるため、非常に危険です。このロードコマンドは、`#define SUPPORT_LC_DYLD_ENVIRONMENT`でビルドされたdyldでのみ使用され、`DYLD_..._PATH`形式の変数にのみ処理をさらに制限します。
|
||||
Allows to indicate environment variables to the dyld beforenthe process is executed. This can be vary dangerous as it can allow to execute arbitrary code inside the process so this load command is only used in dyld build with `#define SUPPORT_LC_DYLD_ENVIRONMENT` and further restricts processing only to variables of the form `DYLD_..._PATH` specifying load paths.
|
||||
|
||||
### **`LC_LOAD_DYLIB`**
|
||||
|
||||
このロードコマンドは、**ライブラリ**の依存関係を**動的**に記述し、**ローダー**(dyld)に**指定されたライブラリをロードおよびリンクするように指示します**。Mach-Oバイナリが必要とする**各ライブラリ**に対して`LC_LOAD_DYLIB`ロードコマンドがあります。
|
||||
This load command describes a **dynamic** **library** dependency which **instructs** the **loader** (dyld) to **load and link said library**. There is a `LC_LOAD_DYLIB` load command **for each library** that the Mach-O binary requires.
|
||||
|
||||
- このロードコマンドは、実際の依存動的ライブラリを記述する構造体dylibを含む**`dylib_command`**型の構造体です:
|
||||
- This load command is a structure of type **`dylib_command`** (which contains a struct dylib, describing the actual dependent dynamic library):
|
||||
```objectivec
|
||||
struct dylib_command {
|
||||
uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */
|
||||
@ -330,7 +335,7 @@ uint32_t compatibility_version; /* library's compatibility vers number*/
|
||||
```
|
||||
.png>)
|
||||
|
||||
この情報は、CLIを使用して取得することもできます:
|
||||
この情報はcliから次のコマンドでも取得できます:
|
||||
```bash
|
||||
otool -L /bin/ls
|
||||
/bin/ls:
|
||||
@ -338,54 +343,54 @@ 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)
|
||||
```
|
||||
いくつかの潜在的なマルウェア関連ライブラリは次のとおりです:
|
||||
いくつかのマルウェアに関連するライブラリの例:
|
||||
|
||||
- **DiskArbitration**: USBドライブの監視
|
||||
- **AVFoundation:** 音声と映像のキャプチャ
|
||||
- **CoreWLAN**: Wifiスキャン。
|
||||
|
||||
> [!NOTE]
|
||||
> Mach-Oバイナリは、**LC_MAIN**で指定されたアドレスの**前に**実行される**1つ以上の** **コンストラクタ**を含むことができます。\
|
||||
> すべてのコンストラクタのオフセットは、**\_\_DATA_CONST**セグメントの**\_\_mod_init_func**セクションに保持されます。
|
||||
|
||||
## **Mach-Oデータ**
|
||||
|
||||
ファイルの中心にはデータ領域があり、これはロードコマンド領域で定義された複数のセグメントで構成されています。**各セグメント内にはさまざまなデータセクションが格納される可能性があり**、各セクションは**特定のタイプに関連するコードまたはデータ**を保持します。
|
||||
- **AVFoundation:** 音声および映像のキャプチャ
|
||||
- **CoreWLAN**: Wifi スキャン
|
||||
|
||||
> [!TIP]
|
||||
> データは基本的に、ロードコマンド**LC_SEGMENTS_64**によってロードされるすべての**情報**を含む部分です。
|
||||
> Mach-O バイナリは1つまたは**複数の****コンストラクタ**を含むことがあり、これらは**LC_MAIN**で指定されたアドレスより**前に****実行**されます。\
|
||||
> 任意のコンストラクタのオフセットは**\_\_DATA_CONST**セグメントの**\_\_mod_init_func**セクションに格納されます。
|
||||
|
||||
## **Mach-O データ**
|
||||
|
||||
ファイルの中心にはデータ領域があり、これは load-commands 領域で定義された複数のセグメントから構成されます。**各セグメント内にはさまざまなデータセクションを収めることができ**、各セクションはタイプ固有の**コードやデータを保持します**。
|
||||
|
||||
> [!TIP]
|
||||
> このデータは基本的に load commands **LC_SEGMENTS_64** によってロードされるすべての**情報**を含む部分です
|
||||
|
||||
 (3).png>)
|
||||
|
||||
これには次のものが含まれます:
|
||||
これには以下が含まれます:
|
||||
|
||||
- **関数テーブル:** プログラム関数に関する情報を保持します。
|
||||
- **シンボルテーブル**: バイナリによって使用される外部関数に関する情報を含みます
|
||||
- 内部関数、変数名なども含まれる可能性があります。
|
||||
- **Function table:** プログラムの関数に関する情報を保持します。
|
||||
- **Symbol table**: バイナリで使用される外部関数に関する情報を含みます
|
||||
- また内部関数や変数名なども含まれることがあります。
|
||||
|
||||
これを確認するには、[**Mach-O View**](https://sourceforge.net/projects/machoview/)ツールを使用できます:
|
||||
To check it you could use the [**Mach-O View**](https://sourceforge.net/projects/machoview/) tool:
|
||||
|
||||
<figure><img src="../../../images/image (1120).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
またはCLIから:
|
||||
Or from the cli:
|
||||
```bash
|
||||
size -m /bin/ls
|
||||
```
|
||||
## Objetive-Cの一般的なセクション
|
||||
## Objetive-C の一般的なセクション
|
||||
|
||||
`__TEXT`セグメント (r-x):
|
||||
`__TEXT` セグメント内 (r-x):
|
||||
|
||||
- `__objc_classname`: クラス名 (文字列)
|
||||
- `__objc_methname`: メソッド名 (文字列)
|
||||
- `__objc_methtype`: メソッドタイプ (文字列)
|
||||
- `__objc_classname`: クラス名(文字列)
|
||||
- `__objc_methname`: メソッド名(文字列)
|
||||
- `__objc_methtype`: メソッドの型(文字列)
|
||||
|
||||
`__DATA`セグメント (rw-):
|
||||
`__DATA` セグメント内 (rw-):
|
||||
|
||||
- `__objc_classlist`: すべてのObjective-Cクラスへのポインタ
|
||||
- `__objc_nlclslist`: 非遅延Objective-Cクラスへのポインタ
|
||||
- `__objc_catlist`: カテゴリへのポインタ
|
||||
- `__objc_nlcatlist`: 非遅延カテゴリへのポインタ
|
||||
- `__objc_protolist`: プロトコルリスト
|
||||
- `__objc_classlist`: すべての Objetive-C クラスへのポインタ
|
||||
- `__objc_nlclslist`: Non-Lazy Objective-C クラスへのポインタ
|
||||
- `__objc_catlist`: Categories へのポインタ
|
||||
- `__objc_nlcatlist`: Non-Lazy Categories へのポインタ
|
||||
- `__objc_protolist`: プロトコルのリスト
|
||||
- `__objc_const`: 定数データ
|
||||
- `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`...
|
||||
|
||||
|
@ -1,15 +1,20 @@
|
||||
# macOS コード署名
|
||||
# macOS Code Signing
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## 基本情報
|
||||
|
||||
Mach-o バイナリには、バイナリ内の署名の **オフセット** と **サイズ** を示す **`LC_CODE_SIGNATURE`** というロードコマンドが含まれています。実際、GUIツールの MachOView を使用すると、バイナリの最後にこの情報を含む **コード署名** というセクションを見つけることができます:
|
||||
{{#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`** というロードコマンドが含まれており、バイナリ内部の署名の **offset** と **size** を示します。実際、GUI ツール MachOView を使うと、バイナリの末尾にこの情報を持つ **Code Signature** というセクションを見つけることができます:
|
||||
|
||||
<figure><img src="../../../images/image (1) (1) (1) (1).png" alt="" width="431"><figcaption></figcaption></figure>
|
||||
|
||||
コード署名のマジックヘッダーは **`0xFADE0CC0`** です。その後、長さやそれらを含む superBlob のブロブの数などの情報があります。\
|
||||
この情報は [こちらのソースコード](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276) で見つけることができます:
|
||||
Code Signature のマジックヘッダは **`0xFADE0CC0`** です。続いて、それらを含む superBlob の長さや blob の数といった情報があります。\
|
||||
この情報は [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)));
|
||||
```
|
||||
一般的なブロブには、Code Directory、Requirements、Entitlements、およびCryptographic Message Syntax (CMS)が含まれています。\
|
||||
さらに、ブロブにエンコードされたデータは**ビッグエンディアン**でエンコードされていることに注意してください。
|
||||
一般的に含まれる blob は Code Directory、Requirements、Entitlements、および Cryptographic Message Syntax (CMS) です。\
|
||||
さらに、blob にエンコードされたデータが **ビッグエンディアン** である点に注意してください。
|
||||
|
||||
さらに、署名はバイナリから切り離され、`/var/db/DetachedSignatures`に保存される可能性があります(iOSで使用されます)。
|
||||
また、署名はバイナリから切り離されて `/var/db/DetachedSignatures` に保存されることがあり(iOSで使用される)、
|
||||
|
||||
## Code Directory Blob
|
||||
|
||||
[Code Directory 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,13 @@ char end_withLinkage[0];
|
||||
} CS_CodeDirectory
|
||||
__attribute__ ((aligned(1)));
|
||||
```
|
||||
注意すべきは、この構造体の異なるバージョンがあり、古いものは情報が少ない場合があることです。
|
||||
この struct には異なるバージョンがあり、古いものは含まれる情報が少ない場合があることに注意してください。
|
||||
|
||||
## コード署名ページ
|
||||
## コードページの署名
|
||||
|
||||
完全なバイナリをハッシュ化することは非効率的であり、部分的にメモリにロードされている場合には無意味です。したがって、コード署名は実際にはハッシュのハッシュであり、各バイナリページが個別にハッシュ化されます。\
|
||||
実際、前の**コードディレクトリ**コードでは、**ページサイズが指定されている**のがわかります。さらに、バイナリのサイズがページのサイズの倍数でない場合、フィールド**CodeLimit**は署名の終わりがどこにあるかを指定します。
|
||||
バイナリ全体をハッシュするのは、メモリに部分的にしかロードされない場合には非効率であり、ほとんど無意味です。したがって、コード署名は実際にはハッシュのハッシュであり、各バイナリページが個別にハッシュされます。\
|
||||
|
||||
実際、前述の **Code Directory** コードでは、そのフィールドのひとつに **ページサイズが指定されている** のがわかります。さらに、バイナリのサイズがページサイズの倍数でない場合、フィールド **CodeLimit** が署名の終端を指定します。
|
||||
```bash
|
||||
# Get all hashes of /bin/ps
|
||||
codesign -d -vvvvvv /bin/ps
|
||||
@ -144,25 +150,25 @@ openssl sha256 /tmp/*.page.*
|
||||
```
|
||||
## Entitlements Blob
|
||||
|
||||
アプリケーションにはすべての権限が定義された**entitlement blob**が含まれている場合があります。さらに、一部のiOSバイナリは、特別なスロット-7に権限を特定している場合があります(-5権限の特別なスロットの代わりに)。
|
||||
アプリケーションには、すべての entitlements が定義された **entitlement blob** が含まれている場合があることに注意してください。さらに、一部の iOS バイナリでは、entitlements が特殊スロット -7(-5 entitlements special slot の代わり)に格納されていることがあります。
|
||||
|
||||
## Special Slots
|
||||
|
||||
MacOSアプリケーションは、バイナリ内で実行するために必要なすべてを持っているわけではなく、**external resources**(通常はアプリケーションの**bundle**内)も使用します。したがって、バイナリ内には、変更されていないことを確認するためにいくつかの興味深い外部リソースのハッシュを含むスロットがあります。
|
||||
MacOS のアプリケーションは実行に必要なすべてをバイナリ内に持っているわけではなく、**external resources**(通常はアプリケーションの **bundle** 内)も使用します。したがって、バイナリ内には外部リソースが改変されていないかを確認するためのハッシュを格納するいくつかのスロットがあります。
|
||||
|
||||
実際、Code Directory構造体には、特別なスロットの数を示す**`nSpecialSlots`**というパラメータがあります。特別なスロット0は存在せず、最も一般的なもの(-1から-6まで)は次のとおりです:
|
||||
実際、Code Directory structs には特殊スロットの数を示すパラメータ **`nSpecialSlots`** があり、それを見ることができます。特殊スロット 0 は存在せず、最も一般的なもの(-1 から -6)は次の通りです:
|
||||
|
||||
- `info.plist`のハッシュ(または`__TEXT.__info__plist`内のもの)。
|
||||
- 要件のハッシュ
|
||||
- リソースディレクトリのハッシュ(バンドル内の`_CodeSignature/CodeResources`ファイルのハッシュ)。
|
||||
- `info.plist` のハッシュ(または `__TEXT.__info__plist` 内のもの)。
|
||||
- Requirements のハッシュ
|
||||
- Resource Directory のハッシュ(bundle 内の `_CodeSignature/CodeResources` ファイルのハッシュ)。
|
||||
- アプリケーション固有(未使用)
|
||||
- 権限のハッシュ
|
||||
- DMGコード署名のみ
|
||||
- DER権限
|
||||
- entitlements のハッシュ
|
||||
- DMG code signatures のみ
|
||||
- DER Entitlements
|
||||
|
||||
## Code Signing Flags
|
||||
|
||||
すべてのプロセスには、カーネルによって開始される`status`として知られるビットマスクが関連付けられており、その一部は**code signature**によって上書きされる可能性があります。コード署名に含めることができるこれらのフラグは[コードで定義されています](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36):
|
||||
各プロセスにはカーネルによって設定されるビットマスクである `status` が関連付けられており、その一部は **code signature** によって上書きすることができます。code signing に含めることができるこれらのフラグは [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 +213,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_*` フラグを動的に追加できることです。
|
||||
Note that the function [**exec_mach_imgact**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_exec.c#L1420) can also add the `CS_EXEC_*` flags dynamically when starting the execution.
|
||||
|
||||
## コード署名要件
|
||||
## コード署名の要件
|
||||
|
||||
各アプリケーションは、実行可能であるために満たさなければならない **要件** をいくつか **保持** しています。もし **アプリケーションに満たされていない要件が含まれている場合**、それは実行されません(おそらく変更されているためです)。
|
||||
各アプリケーションは、実行可能になるために満たすべき**要件**(**requirements**)を格納しています。もしアプリケーションに含まれる**要件が満たされていない場合**、実行は拒否されます(おそらく改変されているため)。
|
||||
|
||||
バイナリの要件は **特別な文法** を使用し、**式** のストリームとして表現され、`0xfade0c00` をマジックとして使用してバイナリとしてエンコードされ、その **ハッシュは特別なコードスロットに保存** されます。
|
||||
バイナリの要件は、**式**のストリームである**特殊な文法**を使用しており、マジック値 `0xfade0c00` を用いたblobとしてエンコードされ、その**ハッシュは特別なコードスロットに格納されます**。
|
||||
|
||||
バイナリの要件は、次のコマンドを実行することで確認できます:
|
||||
バイナリの要件は、次のように実行して確認できます:
|
||||
```bash
|
||||
codesign -d -r- /bin/ls
|
||||
Executable=/bin/ls
|
||||
@ -225,10 +231,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`ツールを使ってコンパイル済みの要件を生成することも可能です:
|
||||
```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,55 +246,57 @@ 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
|
||||
[...]
|
||||
```
|
||||
It's possible to access this information and create or modify requirements with some APIs from the `Security.framework` like:
|
||||
|
||||
#### **有効性の確認**
|
||||
|
||||
- **`Sec[Static]CodeCheckValidity`**: 要件ごとのSecCodeRefの有効性を確認します。
|
||||
- **`SecRequirementEvaluate`**: 証明書コンテキスト内の要件を検証します。
|
||||
- **`SecTaskValidateForRequirement`**: 実行中のSecTaskを`CFString`要件に対して検証します。
|
||||
- **`Sec[Static]CodeCheckValidity`**: SecCodeRef が Requirement に沿って有効かどうかをチェックします。
|
||||
- **`SecRequirementEvaluate`**: 証明書のコンテキストで Requirement を検証します。
|
||||
- **`SecTaskValidateForRequirement`**: 実行中の SecTask を `CFString` の Requirement に対して検証します。
|
||||
|
||||
#### **コード要件の作成と管理**
|
||||
|
||||
- **`SecRequirementCreateWithData`:** 要件を表すバイナリデータから`SecRequirementRef`を作成します。
|
||||
- **`SecRequirementCreateWithString`:** 要件の文字列表現から`SecRequirementRef`を作成します。
|
||||
- **`SecRequirementCopy[Data/String]`**: `SecRequirementRef`のバイナリデータ表現を取得します。
|
||||
- **`SecRequirementCreateGroup`**: アプリグループメンバーシップのための要件を作成します。
|
||||
- **`SecRequirementCreateWithData`:** 要件を表すバイナリデータから `SecRequirementRef` を作成します。
|
||||
- **`SecRequirementCreateWithString`:** 要件の文字列表現から `SecRequirementRef` を作成します。
|
||||
- **`SecRequirementCopy[Data/String]`**: `SecRequirementRef` のバイナリデータ表現を取得します。
|
||||
- **`SecRequirementCreateGroup`**: app-group membership の要件を作成します。
|
||||
|
||||
#### **コード署名情報へのアクセス**
|
||||
|
||||
- **`SecStaticCodeCreateWithPath`**: コード署名を検査するためにファイルシステムパスから`SecStaticCodeRef`オブジェクトを初期化します。
|
||||
- **`SecCodeCopySigningInformation`**: `SecCodeRef`または`SecStaticCodeRef`から署名情報を取得します。
|
||||
- **`SecStaticCodeCreateWithPath`**: コード署名を検査するためにファイルシステムパスから `SecStaticCodeRef` オブジェクトを初期化します。
|
||||
- **`SecCodeCopySigningInformation`**: `SecCodeRef` または `SecStaticCodeRef` から署名情報を取得します。
|
||||
|
||||
#### **コード要件の変更**
|
||||
|
||||
- **`SecCodeSignerCreate`**: コード署名操作を実行するための`SecCodeSignerRef`オブジェクトを作成します。
|
||||
- **`SecCodeSignerSetRequirement`**: 署名中に適用するための新しい要件をコードサイナーに設定します。
|
||||
- **`SecCodeSignerAddSignature`**: 指定されたサイナーで署名されるコードに署名を追加します。
|
||||
- **`SecCodeSignerCreate`**: コード署名操作を行うための `SecCodeSignerRef` オブジェクトを作成します。
|
||||
- **`SecCodeSignerSetRequirement`**: 署名時に適用する新しい要件をコードサイナーに設定します。
|
||||
- **`SecCodeSignerAddSignature`**: 指定したサイナーで署名中のコードに署名を追加します。
|
||||
|
||||
#### **要件によるコードの検証**
|
||||
|
||||
- **`SecStaticCodeCheckValidity`**: 指定された要件に対して静的コードオブジェクトを検証します。
|
||||
|
||||
#### **追加の便利なAPI**
|
||||
#### **追加の有用なAPI**
|
||||
|
||||
- **`SecCodeCopy[Internal/Designated]Requirement`: SecCodeRefからSecRequirementRefを取得**
|
||||
- **`SecCodeCopyGuestWithAttributes`**: 特定の属性に基づいてコードオブジェクトを表す`SecCodeRef`を作成し、サンドボックスに便利です。
|
||||
- **`SecCodeCopyPath`**: `SecCodeRef`に関連付けられたファイルシステムパスを取得します。
|
||||
- **`SecCodeCopySigningIdentifier`**: `SecCodeRef`から署名識別子(例:チームID)を取得します。
|
||||
- **`SecCodeGetTypeID`**: `SecCodeRef`オブジェクトのタイプ識別子を返します。
|
||||
- **`SecRequirementGetTypeID`**: `SecRequirementRef`のCFTypeIDを取得します。
|
||||
- **`SecCodeCopy[Internal/Designated]Requirement`: Get SecRequirementRef from SecCodeRef**
|
||||
- **`SecCodeCopyGuestWithAttributes`**: 特定の属性に基づくコードオブジェクトを表す `SecCodeRef` を作成します(サンドボックス用途で有用)。
|
||||
- **`SecCodeCopyPath`**: `SecCodeRef` に関連付けられたファイルシステムパスを取得します。
|
||||
- **`SecCodeCopySigningIdentifier`**: `SecCodeRef` から署名識別子(例: Team ID)を取得します。
|
||||
- **`SecCodeGetTypeID`**: `SecCodeRef` オブジェクトのタイプ識別子を返します。
|
||||
- **`SecRequirementGetTypeID`**: `SecRequirementRef` の CFTypeID を取得します。
|
||||
|
||||
#### **コード署名フラグと定数**
|
||||
|
||||
- **`kSecCSDefaultFlags`**: コード署名操作のための多くのSecurity.framework関数で使用されるデフォルトフラグです。
|
||||
- **`kSecCSSigningInformation`**: 署名情報を取得する必要があることを指定するために使用されるフラグです。
|
||||
- **`kSecCSDefaultFlags`**: コード署名操作で多くの Security.framework 関数で使用されるデフォルトフラグ。
|
||||
- **`kSecCSSigningInformation`**: 署名情報を取得することを指定するために使用されるフラグ。
|
||||
|
||||
## コード署名の強制
|
||||
|
||||
**カーネル**は、アプリのコードが実行される前に**コード署名を確認**します。さらに、新しいコードをメモリに書き込み実行する方法の一つは、`mprotect`が`MAP_JIT`フラグで呼び出される場合に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権限を保護するためのセキュリティメカニズムを適用するためにOSによって異なるタイミングでチェックされます)。
|
||||
[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) 構造体は、実行中のプロセスの entitlement に関する情報を含みます。`csb_platform_binary` はアプリケーションがプラットフォームバイナリかどうかも示します(これは OS がこれらのプロセスの task port への SEND 権利を保護するなどのセキュリティ機構を適用するために様々な場面でチェックします)。
|
||||
```c
|
||||
struct cs_blob {
|
||||
struct cs_blob *csb_next;
|
||||
|
Loading…
x
Reference in New Issue
Block a user