Translated ['src/generic-methodologies-and-resources/basic-forensic-meth

This commit is contained in:
Translator 2025-10-01 01:55:55 +00:00
parent e8d6897c44
commit cadcf88ec7
5 changed files with 393 additions and 162 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) - [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) - [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) - [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) - [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) - [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) - [PNG tricks](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/png-tricks.md)

View File

@ -1,8 +1,8 @@
# 특정 소프트웨어/파일 형식 # 특정 소프트웨어/파일 형식 요령
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
여기에서 특정 파일 형식 및/또는 소프트웨어에 대한 흥미로운 팁을 제공합니다: 여기에서 특정 파일 형식 및/또는 소프트웨어에 대한 흥미로운 요령을 확인할 수 있습니다:
{{#ref}} {{#ref}}
@ -54,4 +54,9 @@ video-and-audio-file-analysis.md
zips-tricks.md zips-tricks.md
{{#endref}} {{#endref}}
{{#ref}}
mach-o-entitlements-and-ipsw-indexing.md
{{#endref}}
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -0,0 +1,213 @@
# Mach-O 권한(Entitlements) 추출 및 IPSW 인덱싱
{{#include ../../../banners/hacktricks-training.md}}
## 개요
이 페이지에서는 LC_CODE_SIGNATURE를 따라 코드 서명 SuperBlob을 파싱하여 Mach-O 바이너리에서 프로그래밍적으로 entitlements를 추출하는 방법과, Apple IPSW 펌웨어의 내용을 마운트하고 인덱싱하여 포렌식 검색/비교에 적용하는 방법을 다룹니다.
Mach-O 형식 및 코드 서명에 대한 복습이 필요하면 다음을 참조하세요:
- 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)
## Mach-O 권한(Entitlements): 저장 위치
Entitlements는 LC_CODE_SIGNATURE load command가 참조하는 코드 서명 데이터 내부에 저장되며 __LINKEDIT 세그먼트에 배치됩니다. 서명은 여러 블롭(code directory, requirements, entitlements, CMS 등)을 포함하는 CS_SuperBlob입니다. entitlements 블롭은 데이터가 Apple Binary Property List(bplist00)인 CS_GenericBlob이며, 이 plist는 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
Note: Multi-arch (fat) binaries contain multiple Mach-O slices. You must pick the slice for the architecture you want to inspect and then walk its 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를 읽고, 원하는 architecture slice를 선택한 다음 subrange를 parse_entitlements에 전달하세요.
- macOS에서 다음 명령으로 결과를 검증할 수 있습니다: codesign -d --entitlements :- /path/to/binary
## Example findings
Privileged platform binaries는 종종 다음과 같은 민감한 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 및 releases/devices 간의 diffing에 매우 유용합니다.
## Scaling across IPSWs (mounting and indexing)
전체 이미지를 저장하지 않고 실행 파일을 열거하고 entitlements를 대규모로 추출하려면:
- @blacktop의 ipsw tool을 사용하여 펌웨어 파일시스템을 다운로드하고 마운트하세요. 마운트는 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와 imported frameworks를 파싱한다.
- 수천 개의 IPSWs에 걸친 선형 성장을 피하기 위해 정규화된 뷰를 관계형 데이터베이스에 저장한다:
- executables, operating_system_versions, entitlements, frameworks
- many-to-many: executable↔OS version, executable↔entitlement, executable↔framework
Example query to list all OS versions containing a given executable name:
```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바이트 부호 있는 정수로 저장합니다.
## 오픈소스 도구 및 entitlement hunting 참고자료
- 펌웨어 마운트/다운로드: https://github.com/blacktop/ipsw
- Entitlement 데이터베이스 및 참조:
- Jonathan Levins entitlement DB: https://newosxbook.com/ent.php
- entdb: https://github.com/ChiChou/entdb
- 대규모 인덱서 (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 Directory, special slots, DER entitlements)에 대한 자세한 내용은 다음을 참조하세요: [macOS Code Signing](../../../macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-code-signing.md)
## 참고자료
- [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

@ -2,42 +2,42 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## 기본 정보
Mac OS 바이너리는 일반적으로 **유니버설 바이너리**로 컴파일됩니다. **유니버설 바이너리**는 **같은 파일에서 여러 아키텍처를 지원할 수 있습니다**. 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>) ![https://alexdremov.me/content/images/2022/10/6XLCD.gif](<../../../images/image (470).png>)
## Fat Header ## 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 <pre class="language-c"><code class="lang-c"><strong>#define FAT_MAGIC 0xcafebabe
</strong><strong>#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */ </strong><strong>#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
</strong> </strong>
struct fat_header { struct fat_header {
<strong> uint32_t magic; /* FAT_MAGIC 또는 FAT_MAGIC_64 */ <strong> uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
</strong><strong> uint32_t nfat_arch; /* 뒤따르는 구조체의 수 */ </strong><strong> uint32_t nfat_arch; /* number of structs that follow */
</strong>}; </strong>};
struct fat_arch { struct fat_arch {
cpu_type_t cputype; /* cpu 지정자 (int) */ cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* 머신 지정자 (int) */ cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint32_t offset; /* 이 객체 파일에 대한 파일 오프셋 */ uint32_t offset; /* file offset to this object file */
uint32_t size; /* 이 객체 파일의 크기 */ uint32_t size; /* size of this object file */
uint32_t align; /* 2의 거듭제곱으로 정렬 */ uint32_t align; /* alignment as a power of 2 */
}; };
</code></pre> </code></pre>
헤더에는 **매직** 바이트가 있으며, 그 뒤에 파일이 **포함하는** **아키텍처**의 **수**(`nfat_arch`)가 있습니다. 각 아키텍처`fat_arch` 구조체를 가집니다. 헤더**magic** 바이트와 뒤따르는 파일이 포함하는 **archs**의 **개수** (`nfat_arch`)를 포함하며, 각 arch`fat_arch` 구조체를 가집니다.
다음 명령어로 확인합니다: 다음으로 확인하세요:
<pre class="language-shell-session"><code class="lang-shell-session">% file /bin/ls <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] /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> <figure><img src="../../../images/image (1094).png" alt=""><figcaption></figcaption></figure>
당신이 생각할 수 있듯이, 일반적으로 2개의 아키텍처를 위해 컴파일된 유니버설 바이너리는 1개의 아키텍처를 위해 컴파일된 것의 **크기를 두 배로 늘립니다**. 아마 생각하셨겠지만, 보통 2개 아키텍처용으로 컴파일된 universal binary는 단일 아키텍처용으로 컴파일된 것보다 크기가 **2배**가 됩니다.
## **Mach-O Header** ## **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 ```c
#define MH_MAGIC 0xfeedface /* the mach magic number */ #define MH_MAGIC 0xfeedface /* the mach magic number */
#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */ #define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
@ -99,19 +99,19 @@ uint32_t flags; /* flags */
uint32_t reserved; /* reserved */ uint32_t reserved; /* reserved */
}; };
``` ```
### Mach-O 파일 ### 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_EXECUTE`: 실행 파일.
- `MH_FVMLIB`: 고정 VM 라이브러리 파일. - `MH_FVMLIB`: 고정 VM 라이브러리 파일.
- `MH_CORE`: 코드 덤프 - `MH_CORE`: 코드 덤프
- `MH_PRELOAD`: 미리 로드된 실행 파일 (XNU에서 더 이상 지원되지 않음) - `MH_PRELOAD`: 사전 로드된 실행 파일 (현재 XNU에서 더 이상 지원되지 않음)
- `MH_DYLIB`: 동적 라이브러리 - `MH_DYLIB`: 동적 라이브러리
- `MH_DYLINKER`: 동적 링커 - `MH_DYLINKER`: 동적 링커
- `MH_BUNDLE`: "플러그인 파일". gcc에서 -bundle을 사용하여 생성되며 `NSBundle` 또는 `dlopen`에 의해 명시적으로 로드됨. - `MH_BUNDLE`: "플러그인 파일". -bundle in gcc로 생성되며 명시적으로 `NSBundle` 또는 `dlopen`으로 로드됩니다.
- `MH_DYSM`: 동반 `.dSym` 파일 (디버깅을 위한 기호가 포함된 파일). - `MH_DYSM`: 동반 `.dSym` 파일 (디버깅을 위한 심볼이 포함된 파일).
- `MH_KEXT_BUNDLE`: 커널 확장. - `MH_KEXT_BUNDLE`: 커널 확장.
```bash ```bash
# Checking the mac header of a binary # Checking the mac header of a binary
@ -120,54 +120,54 @@ Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 ARM64 E USR00 EXECUTE 19 1728 NOUNDEFS DYLDLINK TWOLEVEL PIE 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> <figure><img src="../../../images/image (1133).png" alt=""><figcaption></figcaption></figure>
## **Mach-O 플래그** ## **Mach-O 플래그**
소스 코드는 라이브러리 로딩에 유용한 여러 플래그를 정의합니다: 소스 코드는 라이브러리 로딩에 유용한 여러 플래그도 정의되어 있다:
- `MH_NOUNDEFS`: 정의되지 않은 참조 없음 (완전 링크됨) - `MH_NOUNDEFS`: 정의되지 않은 참조 없음 (완전 링크됨)
- `MH_DYLDLINK`: Dyld 링크 - `MH_DYLDLINK`: Dyld 링크
- `MH_PREBOUND`: 동적 참조가 미리 바인딩됨. - `MH_PREBOUND`: 동적 참조가 사전 바인딩됨
- `MH_SPLIT_SEGS`: 파일이 r/o 및 r/w 세그먼트로 분할됨. - `MH_SPLIT_SEGS`: 파일이 r/o 및 r/w 세그먼트로 분리됨
- `MH_WEAK_DEFINES`: 바이너리에 약한 정의 기호가 있음 - `MH_WEAK_DEFINES`: 바이너리에 weak로 정의된 심볼이 있음
- `MH_BINDS_TO_WEAK`: 바이너리가 약한 기호를 사용함 - `MH_BINDS_TO_WEAK`: 바이너리가 weak 심볼을 사용함
- `MH_ALLOW_STACK_EXECUTION`: 스택을 실행 가능하게 만듦 - `MH_ALLOW_STACK_EXECUTION`: 스택을 실행 가능하게
- `MH_NO_REEXPORTED_DYLIBS`: 라이브러리에 LC_REEXPORT 명령 없음 - `MH_NO_REEXPORTED_DYLIBS`: 라이브러리에 LC_REEXPORT 명령 없음
- `MH_PIE`: 위치 독립 실행 파일 - `MH_PIE`: 위치 독립 실행 파일
- `MH_HAS_TLV_DESCRIPTORS`: 스레드 로컬 변수가 있는 섹션이 있음 - `MH_HAS_TLV_DESCRIPTORS`: 스레드 로컬 변수 섹션이 있음
- `MH_NO_HEAP_EXECUTION`: 힙/데이터 페이지에 대한 실행 없음 - `MH_NO_HEAP_EXECUTION`: 힙/데이터 페이지에서 실행 불가
- `MH_HAS_OBJC`: 바이너리에 oBject-C 섹션이 있음 - `MH_HAS_OBJC`: 바이너리에 Objective-C 섹션이 있음
- `MH_SIM_SUPPORT`: 시뮬레이터 지원 - `MH_SIM_SUPPORT`: 시뮬레이터 지원
- `MH_DYLIB_IN_CACHE`: 공유 라이브러리 캐시의 dylibs/frameworks에서 사용됨. - `MH_DYLIB_IN_CACHE`: shared library cache에 있는 dylib/framework에 사용됨.
## **Mach-O 로드 명령** ## **Mach-O 로드 명령**
**메모리에서의 파일 레이아웃**은 여기에서 지정되며, **기호 테이블의 위치**, 실행 시작 시 메인 스레드의 컨텍스트, 그리고 필요한 **공유 라이브러리**가 자세히 설명됩니다. 동적 로더 **(dyld)**에 바이너리의 메모리 로딩 프로세스에 대한 지침이 제공됩니다. 파일의 메모리 레이아웃이 여기서 지정되며, 심볼 테이블의 위치, 실행 시작 시 메인 스레드의 컨텍스트, 그리고 필요한 공유 라이브러리들이 상세히 기술된다. 바이너리를 메모리에 로드하는 과정에 대해 동적 로더(dyld)에 지침을 제공한다.
**load_command** 구조체를 사용하며, 이는 언급된 **`loader.h`**에 정의되어 있습니다: 여기서는 앞서 언급한 **`loader.h`**에 정의된 **load_command** 구조체를 사용한다:
```objectivec ```objectivec
struct load_command { struct load_command {
uint32_t cmd; /* type of load command */ uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */ 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** ### **LC_SEGMENT/LC_SEGMENT_64**
> [!TIP] > [!TIP]
> 기본적으로 이 유형의 로드 명령은 **이진 파일이 실행될 때 데이터 섹션에 표시된 오프셋에 따라 \_\_TEXT** (실행 코드) **및 \_\_DATA** (프로세스에 대한 데이터) **세그먼트를 로드하는 방법을 정의합니다.** > 기본적으로, 이 유형의 Load Command는 바이너리가 실행될 때 데이터 섹션에 표시된 **오프셋에 따라 \_\_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 */ <pre class="language-c"><code class="lang-c">struct segment_command_64 { /* for 64-bit architectures */
uint32_t cmd; /* LC_SEGMENT_64 */ uint32_t cmd; /* LC_SEGMENT_64 */
@ -184,11 +184,11 @@ int32_t initprot; /* initial VM protection */
}; };
</code></pre> </code></pre>
세그먼트 헤더의 예: Example of segment header:
<figure><img src="../../../images/image (1126).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1126).png" alt=""><figcaption></figcaption></figure>
이 헤더는 **그 뒤에 나타나는 헤더의 섹션 수를 정의합니다:** This header defines the **number of sections whose headers appear after** it:
```c ```c
struct section_64 { /* for 64-bit architectures */ struct section_64 { /* for 64-bit architectures */
char sectname[16]; /* name of this section */ char sectname[16]; /* name of this section */
@ -205,62 +205,62 @@ uint32_t reserved2; /* reserved (for count or sizeof) */
uint32_t reserved3; /* reserved */ uint32_t reserved3; /* reserved */
}; };
``` ```
**섹션 헤더**: : **섹션 헤더**:
<figure><img src="../../../images/image (1108).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1108).png" alt=""><figcaption></figcaption></figure>
**섹션 오프셋** (0x37DC) + **아키텍처 시작 오프셋**을 추가하면, 이 경우 `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC` 만약 **더하면** **섹션 오프셋** (0x37DC) + **arch가 시작하는 오프셋**, 이 경우 `0x18000` --> `0x37DC + 0x18000 = 0x1B7DC`
<figure><img src="../../../images/image (701).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (701).png" alt=""><figcaption></figcaption></figure>
**명령줄**에서 **헤더 정보**를 얻는 것도 가능합니다: 또한 **헤더 정보**를 **command line**에서 얻을 수도 있습니다:
```bash ```bash
otool -lv /bin/ls otool -lv /bin/ls
``` ```
Common segments loaded by this cmd: Common segments loaded by this cmd:
- **`__PAGEZERO`:** 커널에 **주소 0**을 **매핑**하라고 지시하여 **읽거나, 쓸 수 없고, 실행할 수 없도록** 합니다. 구조체의 maxprot 및 minprot 변수는 이 페이지에 **읽기-쓰기-실행 권한이 없음**을 나타내기 위해 0으로 설정됩니다. - **`__PAGEZERO`:** 커널에**주소 0(address zero)**를 **매핑(map)**하도록 지시하여 **읽기/쓰기/실행이 불가능**하도록 합니다. 구조체의 maxprot 및 minprot 변수는 이 페이지에 대한 **읽기-쓰기-실행 권한이 없음을** 나타내기 위해 0으로 설정됩니다.
- 이 할당은 **NULL 포인터 역참조 취약점**을 완화하는 데 중요합니다. 이는 XNU가 첫 번째 페이지(오직 첫 번째) 메모리가 접근할 수 없도록 보장하는 하드 페이지 제로를 시행하기 때문입니다(단, i386 제외). 이 요구 사항을 충족하기 위해 바이너리는 첫 4k를 커버하는 작은 \_\_PAGEZERO를 제작하고 나머지 32비트 메모리를 사용자 및 커널 모드에서 접근 가능하게 할 수 있습니다. - 이 할당은 **NULL pointer dereference vulnerabilities**를 완화하는 데 중요합니다. 이는 XNU가 하드 페이지 제로를 적용하여 메모리의 첫 번째 페이지(첫 페이지만)를 접근 불가로 만들기 때문입니다(i386 제외). 바이너리는 작은 \_\_PAGEZERO( `-pagezero_size` 사용)를 만들어 처음 4K를 덮고 나머지 32비트 메모리는 유저 및 커널 모드에서 접근 가능하도록 하여 이 요구사항을 충족할 수 있습니다.
- **`__TEXT`**: **읽기** 및 **실행** 권한이 있는 **실행 가능한** **코드**를 포함합니다(쓰기 불가)**.** 이 세그먼트의 일반적인 섹션: - **`__TEXT`**: **실행 가능한(executable)** **코드(code)**를 포함하며 **읽기(read)****실행(execute)** 권한을 가집니다(쓰기 권한 없음). 이 세그먼트의 일반 섹션:
- `__text`: 컴파일된 바이너리 코드 - `__text`: 컴파일된 바이너리 코드
- `__const`: 상수 데이터(읽기 전용) - `__const`: 상수 데이터(읽기 전용)
- `__[c/u/os_log]string`: C, 유니코드 또는 os 로그 문자열 상수 - `__[c/u/os_log]string`: C, Unicode 또는 os 로그 문자열 상수
- `__stubs` `__stubs_helper`: 동적 라이브러리 로딩 과정에서 관련됨 - `__stubs` and `__stubs_helper`: 동적 라이브러리 로딩 과정에 관여
- `__unwind_info`: 스택 언와인드 데이터. - `__unwind_info`: 스택 언와인드 데이터
- 이 모든 콘텐츠는 서명되지만 실행 가능하다고도 표시되어 있습니다(문자열 전용 섹션과 같이 이 권한이 반드시 필요하지 않은 섹션의 악용 가능성을 높임). - 이 모든 내용은 서명되어 있되 실행 가능으로 표시되어 있다는 점에 유의하세요(문자열 전용 섹션처럼 반드시 실행 권한을 필요로 하지 않는 섹션을 악용할 수 있는 가능성이 증가합니다).
- **`__DATA`**: **읽기 가능**하고 **쓰기 가능**한 데이터를 포함합니다(실행 불가)**.** - **`__DATA`**: **읽기(readable)** 및 **쓰기(writable)** 가능한 데이터를 포함합니다(실행 불가).
- `__got:` 전역 오프셋 테이블 - `__got`: 전역 오프셋 테이블(Global Offset Table)
- `__nl_symbol_ptr`: 비게으른(로드 시 바인딩) 심볼 포인터 - `__nl_symbol_ptr`: Non-lazy(로딩 시 바인딩) 심볼 포인터
- `__la_symbol_ptr`: 게으른(사용 시 바인딩) 심볼 포인터 - `__la_symbol_ptr`: Lazy(사용 시 바인딩) 심볼 포인터
- `__const`: 읽기 전용 데이터여야 함(실제로는 아님) - `__const`: 원래는 읽기 전용 데이터여야 함(실제론 그렇지 않음)
- `__cfstring`: CoreFoundation 문자열 - `__cfstring`: CoreFoundation 문자열
- `__data`: 초기화된 전역 변수 - `__data`: 초기화된 전역 변수
- `__bss`: 초기화되지 않은 정적 변수 - `__bss`: 초기화되지 않은 정적 변수
- `__objc_*` (\_\_objc_classlist, \_\_objc_protolist 등): Objective-C 런타임에서 사용되는 정보 - `__objc_*` (\_\_objc_classlist, \_\_objc_protolist, 등): Objective-C 런타임에서 사용하는 정보
- **`__DATA_CONST`**: \_\_DATA.\_\_const는 상수(쓰기 권한)가 보장되지 않으며, 다른 포인터와 GOT도 마찬가지입니다. 이 섹션은 `mprotect`를 사용하여 `__const`, 일부 초기화기 및 GOT 테이블(해결된 후)을 **읽기 전용**으로 만듭니다. - **`__DATA_CONST`**: \_\_DATA.\_\_const는 상수(쓰기 금지)라고 보장되지 않으며, 다른 포인터들과 GOT 또한 마찬가지입니다. 이 섹션은 `__const`, 일부 이니셜라이저 및 (해결된 후의) GOT 테이블을 `mprotect`를 사용해 **읽기 전용**으로 만듭니다.
- **`__LINKEDIT`**: 심볼, 문자열 및 재배치 테이블 항목과 같은 링커(dyld)에 대한 정보를 포함합니다. `__TEXT` 또는 `__DATA`에 없는 콘텐츠를 위한 일반 컨테이너이며, 그 내용은 다른 로드 명령에서 설명됩니다. - **`__LINKEDIT`**: 링커(dyld)를 위한 정보(심볼, 문자열, 재배치 테이블 엔트리 등)를 포함합니다. `__TEXT``__DATA`에 속하지 않는 내용을 담는 일반 컨테이너이며 그 내용은 다른 로드 커맨드에서 기술됩니다.
- dyld 정보: 재배치, 비게으른/게으른/약한 바인딩 opcode 및 내보내기 정보 - dyld 정보: Rebase, Non-lazy/lazy/weak binding opcodes 및 export 정보
- 함수 시작: 함수의 시작 주소 테이블 - Functions starts: 함수들의 시작 주소 표
- 코드 내 데이터: \_\_text의 데이터 섬 - Data In Code: 데이터 섬들 in \_\_text
- 심볼 테이블: 바이너리의 심볼 - Symbol Table: 바이너리 내의 심볼
- 간접 심볼 테이블: 포인터/스텁 심볼 - Indirect Symbol Table: 포인터/스텁 심볼
- 문자열 테이블 - String Table
- 코드 서명 - Code Signature
- **`__OBJC`**: Objective-C 런타임에서 사용되는 정보를 포함합니다. 이 정보는 \_\_DATA 세그먼트의 다양한 \_\_objc\_\* 섹션에서도 발견될 수 있습니다. - **`__OBJC`**: Objective-C 런타임에서 사용하는 정보를 포함합니다. 이 정보는 \_\_DATA 세그먼트 내의 다양한 \_\_objc\_\* 섹션에서도 찾을 수 있습니다.
- **`__RESTRICT`**: 내용이 없는 세그먼트로, **`__restrict`**라는 단일 섹션(비어 있음)을 포함하여 바이너리를 실행할 때 DYLD 환경 변수를 무시하도록 보장합니다. - **`__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_HIGHVM`: Core 전용(사용 안 함)
- `SG_FVMLIB`: 사용되지 않음 - `SG_FVMLIB`: 사용되지 않음
- `SG_NORELOC`: 세그먼트에 재배치 없음 - `SG_NORELOC`: 세그먼트에 재배치 없음
- `SG_PROTECTED_VERSION_1`: 암호화. 예를 들어 Finder가 `__TEXT` 세그먼트를 암호화하는 데 사용됩니다. - `SG_PROTECTED_VERSION_1`: 암호화. 예를 들어 Finder가 텍스트 `__TEXT` 세그먼트를 암호화하는 데 사용됩니다.
### **`LC_UNIXTHREAD/LC_MAIN`** ### **`LC_UNIXTHREAD/LC_MAIN`**
**`LC_MAIN`**은 **entryoff 속성**에 있는 진입점을 포함합니다. 로드 시, **dyld**는 이 값을 (메모리 내) **바이너리의 기본 주소**에 **추가**한 다음, 이 명령어로 **점프**하여 바이너리 코드의 실행을 시작합니다. **`LC_MAIN`**은 **entryoff attribute**에 엔트리포인트를 포함합니다. 로드 시, **dyld**는 단순히 이 값을 (메모리 상의) **바이너리의 베이스(base of the binary)**에 더한 후 해당 명령으로 **점프(jumps)**하여 바이너리 코드를 실행합니다.
**`LC_UNIXTHREAD`**는 메인 스레드를 시작할 때 레지스터가 가져야 할 값을 포함합니다. 이는 이미 사용 중단되었지만 **`dyld`**는 여전히 사용합니다. 이로 설정된 레지스터 값을 확인할 수 있습니다: **`LC_UNIXTHREAD`**는 메인 스레드를 시작할 때 레지스터가 가져야 할 값들을 포함합니다. 이는 이미 deprecated 되었지만 **`dyld`**는 여전히 이를 사용합니다. 이로 인해 설정된 레지스터 값들은 다음 통해 확인할 수 있습니다:
```bash ```bash
otool -l /usr/lib/dyld otool -l /usr/lib/dyld
[...] [...]
@ -286,34 +286,39 @@ cpsr 0x00000000
``` ```
### **`LC_CODE_SIGNATURE`** ### **`LC_CODE_SIGNATURE`**
Mach-O 파일의 **코드 서명**에 대한 정보를 포함합니다. 이는 **서명 블롭**을 가리키는 **오프셋**만 포함합니다. 일반적으로 파일의 맨 끝에 위치합니다.\ {{#ref}}
그러나 이 섹션에 대한 일부 정보는 [**이 블로그 게시물**](https://davedelong.com/blog/2018/01/10/reading-your-own-entitlements/)과 이 [**gists**](https://gist.github.com/carlospolop/ef26f8eb9fafd4bc22e69e1a32b81da4)에서 찾을 수 있습니다. ../../../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]`** ### **`LC_ENCRYPTION_INFO[_64]`**
바이너리 암호화에 대한 지원. 그러나 물론, 공격자가 프로세스를 손상시키면 메모리를 암호화되지 않은 상태로 덤프할 수 있습니다. 바이너리 암호화를 지원합니다. 그러나 공격자가 프로세스를 침해하면 메모리를 암호화되지 않은 상태로 덤프할 수 있습니다.
### **`LC_LOAD_DYLINKER`** ### **`LC_LOAD_DYLINKER`**
프로세스 주소 공간에 공유 라이브러리를 매핑하는 **동적 링커 실행 파일**의 **경로**를 포함합니다. **값은 항상 `/usr/lib/dyld`로 설정됩니다**. macOS에서는 dylib 매핑이 **커널 모드**가 아닌 **사용자 모드**에서 발생한다는 점에 유의하는 것이 중요합니다. 공유 라이브러리를 프로세스 주소 공간에 맵핑하는 dynamic linker 실행 파일의 경로를 포함합니다. 값은 항상 `/usr/lib/dyld`로 설정됩니다. macOS에서는 dylib 매핑이 커널 모드가 아니라 사용자 모드에서 발생한다는 점을 유의하세요.
### **`LC_IDENT`** ### **`LC_IDENT`**
구식이지만 패닉 시 덤프를 생성하도록 구성되면 Mach-O 코어 덤프가 생성되고 커널 버전이 `LC_IDENT` 명령에 설정됩니다. 구식이지만, panic 시 덤프를 생성하도록 구성하면 Mach-O 코어 덤프가 생성되고 커널 버전이 `LC_IDENT` 명령에 설정됩니다.
### **`LC_UUID`** ### **`LC_UUID`**
무작위 UUID. XNU가 나머지 프로세스 정보와 함께 캐시하므로 직접적으로 유용합니다. 충돌 보고서에서 사용할 수 있습니다. 무작위 UUID입니다. 자체적으로는 직접적인 용도는 제한적이지만 XNU가 이를 다른 프로세스 정보와 함께 캐시합니다. 크래시 리포트에 사용할 수 있습니다.
### **`LC_DYLD_ENVIRONMENT`** ### **`LC_DYLD_ENVIRONMENT`**
프로세스가 실행되기 전에 dyld에 환경 변수를 지정할 수 있습니다. 이는 프로세스 내에서 임의의 코드를 실행할 수 있게 하므로 매우 위험할 수 있습니다. 따라서 이 로드 명령은 `#define SUPPORT_LC_DYLD_ENVIRONMENT`로 빌드된 dyld에서만 사용되며, 로드 경로를 지정하는 `DYLD_..._PATH`식의 변수로만 처리하도록 추가 제한됩니다. 프로세스가 실행되기 전에 dyld에 환경 변수를 지정할 수 있게 합니다. 이는 프로세스 내부에서 임의의 코드를 실행할 수 있게 하므로 매우 위험할 수 있습니다. 따라서 이 load command는 `#define SUPPORT_LC_DYLD_ENVIRONMENT`로 빌드된 dyld에서만 사용되며, 처리는 로드 경로를 지정하는 `DYLD_..._PATH`태의 변수로만 제한됩니다.
### **`LC_LOAD_DYLIB`** ### **`LC_LOAD_DYLIB`**
로드 명령은 **동적** **라이브러리** 의존성을 설명하며, **로더**(dyld)에게 **해당 라이브러리를 로드하고 링크하라고 지시합니다**. Mach-O 바이너리가 요구하는 **각 라이브러리**에 대해 `LC_LOAD_DYLIB` 로드 명령이 있습니다. load command는 loader(dyld)에게 라이브러리를 로드하고 링크하도록 지시하는 dynamic library 의존성을 설명합니다. Mach-O 바이너리가 필요로 하는 각 라이브러리마다 하나의 `LC_LOAD_DYLIB` load command가 있습니다.
- 이 로드 명령은 **`dylib_command`** 유형의 구조체입니다(실제 의존 동적 라이브러리를 설명하는 struct dylib 포함): - This load command is a structure of type **`dylib_command`** (which contains a struct dylib, describing the actual dependent dynamic library):
```objectivec ```objectivec
struct dylib_command { struct dylib_command {
uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */ uint32_t cmd; /* LC_LOAD_{,WEAK_}DYLIB */
@ -330,7 +335,7 @@ uint32_t compatibility_version; /* library's compatibility vers number*/
``` ```
![](<../../../images/image (486).png>) ![](<../../../images/image (486).png>)
이 정보를 cli를 통해서도 얻을 수 있습니다: 또는 cli에서 다음과 같이 이 정보를 얻을 수 있습니다:
```bash ```bash
otool -L /bin/ls otool -L /bin/ls
/bin/ls: /bin/ls:
@ -338,30 +343,30 @@ otool -L /bin/ls
/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0) /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) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)
``` ```
일부 잠재적인 맬웨어 관련 라이브러리는 다음과 같습니다: 일부 잠재적 악성코드 관련 라이브러리:
- **DiskArbitration**: USB 드라이브 모니터링 - **DiskArbitration**: USB 드라이브 모니터링
- **AVFoundation:** 오디오 및 비디오 캡처 - **AVFoundation:** 오디오 및 비디오 캡처
- **CoreWLAN**: Wifi 스캔. - **CoreWLAN**: Wifi 스캔.
> [!NOTE] > [!TIP]
> Mach-O 바이너리는 **LC_MAIN**에 지정된 주소 **이전**에 **실행**될 **하나 또는 여러 개의** **생성자**를 포함할 수 있습니다.\ > A Mach-O binary can contain one or **more** **constructors**, that will be **executed** **before** the address specified in **LC_MAIN**.\
> 모든 생성자의 오프셋은 **\_\_DATA_CONST** 세그먼트의 **\_\_mod_init_func** 섹션에 저장됩니다. > The offsets of any constructors are held in the **\_\_mod_init_func** section of the **\_\_DATA_CONST** segment.
## **Mach-O 데이터** ## **Mach-O 데이터**
파일의 핵심은 데이터 영역으로, 로드 명령 영역에 정의된 여러 세그먼트로 구성됩니다. **각 세그먼트 내에는 다양한 데이터 섹션이 포함될 수 있으며**, 각 섹션은 특정 유형에 대한 **코드 또는 데이터**를 보유합니다. 파일의 핵심에는 load-commands 영역에 정의된 여러 세그먼트로 구성된 데이터 영역이 있습니다. **각 세그먼트 안에는 다양한 데이터 섹션이 존재할 수 있으며**, 각 섹션은 특정 타입에 대한 **코드 또는 데이터를 보관**합니다.
> [!TIP] > [!TIP]
> 데이터는 기본적으로 로드 명령 **LC_SEGMENTS_64**에 의해 로드되는 모든 **정보**를 포함하는 부분입니다. > 데이터는 기본적으로 **LC_SEGMENTS_64** 로드 커맨드에 의해 로드되는 모든 **정보**를 포함하는 부분입니다.
![https://www.oreilly.com/api/v2/epubs/9781785883378/files/graphics/B05055_02_38.jpg](<../../../images/image (507) (3).png>) ![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/) 도구를 사용할 수 있습니다:
@ -373,18 +378,18 @@ size -m /bin/ls
``` ```
## Objetive-C 공통 섹션 ## Objetive-C 공통 섹션
In `__TEXT` segment (r-x): `__TEXT` 세그먼트 (r-x):
- `__objc_classname`: 클래스 이름 (문자열) - `__objc_classname`: 클래스 이름(문자열)
- `__objc_methname`: 메서드 이름 (문자열) - `__objc_methname`: 메서드 이름(문자열)
- `__objc_methtype`: 메서드 유형 (문자열) - `__objc_methtype`: 메서드 타입(문자열)
In `__DATA` segment (rw-): `__DATA` 세그먼트 (rw-):
- `__objc_classlist`: 모든 Objetive-C 클래스에 대한 포인터 - `__objc_classlist`: 모든 Objetive-C 클래스에 대한 포인터
- `__objc_nlclslist`: 비지연 Objective-C 클래스에 대한 포인터 - `__objc_nlclslist`: Non-Lazy Objective-C 클래스에 대한 포인터
- `__objc_catlist`: 카테고리에 대한 포인터 - `__objc_catlist`: 카테고리에 대한 포인터
- `__objc_nlcatlist`: 비지연 카테고리에 대한 포인터 - `__objc_nlcatlist`: Non-Lazy 카테고리에 대한 포인터
- `__objc_protolist`: 프로토콜 목록 - `__objc_protolist`: 프로토콜 목록
- `__objc_const`: 상수 데이터 - `__objc_const`: 상수 데이터
- `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`... - `__objc_imageinfo`, `__objc_selrefs`, `objc__protorefs`...

View File

@ -4,12 +4,17 @@
## 기본 정보 ## 기본 정보
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`**라는 load command가 포함되어 있으며, 이는 바이너리 내부 서명들의 **offset**과 **size**를 가리킵니다. 실제로 GUI 도구 MachOView를 사용하면 바이너리 끝에서 **Code Signature**라는 섹션에서 이 정보를 찾을 수 있습니다:
<figure><img src="../../../images/image (1) (1) (1) (1).png" alt="" width="431"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1) (1) (1) (1).png" alt="" width="431"><figcaption></figcaption></figure>
코드 서명의 매직 헤더는 **`0xFADE0CC0`**입니다. 그런 다음 이들을 포함하는 superBlob의 길이와 블롭 수와 같은 정보가 있습니다.\ Code Signature의 magic header는 **`0xFADE0CC0`**입니다. 그 다음에는 length와 superBlob가 포함하는 blobs의 개수 등 정보가 있습니다.\
이 정보는 [소스 코드 여기](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276)에서 찾을 수 있습니다: 이 정보는 [source code here](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L276):
```c ```c
/* /*
* Structure of an embedded-signature SuperBlob * Structure of an embedded-signature SuperBlob
@ -38,14 +43,14 @@ char data[];
} CS_GenericBlob } CS_GenericBlob
__attribute__ ((aligned(1))); __attribute__ ((aligned(1)));
``` ```
일반적으로 포함된 블롭은 Code Directory, Requirements 및 Entitlements와 Cryptographic Message Syntax (CMS)입니다.\ 일반적으로 포함된 blobs에는 Code Directory, Requirements and Entitlements, 그리고 Cryptographic Message Syntax (CMS)가 있습니다.\
또한, 블롭에 인코딩된 데이터가 **Big Endian**으로 인코딩되어 있음을 주목하십시오. 또한, blobs에 인코딩된 데이터가 **Big Endian**으로 인코딩되어 있다는 점을 유의하세요.
또한, 서명은 이진 파일에서 분리되어 `/var/db/DetachedSignatures`에 저장될 수 있습니다 (iOS에서 사용). 또한, 서명은 binaries에서 분리되어 `/var/db/DetachedSignatures`에 저장될 수 있습니다 (iOS에서 사용).
## Code Directory Blob ## 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 ```c
typedef struct __CodeDirectory { typedef struct __CodeDirectory {
uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */ uint32_t magic; /* magic number (CSMAGIC_CODEDIRECTORY) */
@ -101,12 +106,12 @@ char end_withLinkage[0];
} CS_CodeDirectory } CS_CodeDirectory
__attribute__ ((aligned(1))); __attribute__ ((aligned(1)));
``` ```
다양한 버전의 이 구조체가 있으며, 이전 버전은 정보가 적을 수 있습니다. Note that there are different versions of this struct where old ones might contain less information.
## 서명 코드 페이지 ## Signing Code Pages
전체 바이너리를 해싱하는 것은 비효율적이며, 메모리에 부분적으로만 로드될 경우에는 심지어 쓸모가 없습니다. 따라서 코드 서명은 실제로 각 바이너리 페이지가 개별적으로 해싱된 해시의 해시입니다.\ 전체 binary를 해싱하는 것은 비효율적이며, 일부만 메모리에 로드되는 경우에는 무의미할 수 있습니다. 따라서 code signature는 각 binary page를 개별적으로 해싱한 hash들의 hash입니다.\
실제로 이전 **Code Directory** 코드에서 **페이지 크기가 지정되어** 있는 것을 볼 수 있습니다. 게다가, 바이너리의 크기가 페이지 크기의 배수가 아닐 경우, 필드 **CodeLimit**는 서명의 끝이 어디인지 지정합니다. 사실, 이전의 **Code Directory** 코드에서는 **page size is specified**가 필드 중 하나에 명시되어 있는 것을 볼 수 있습니다. 또한 binary의 크기가 page의 크기의 배수가 아닌 경우, 필드 **CodeLimit**가 서명의 끝 위치를 지정합니다.
```bash ```bash
# Get all hashes of /bin/ps # Get all hashes of /bin/ps
codesign -d -vvvvvv /bin/ps codesign -d -vvvvvv /bin/ps
@ -144,25 +149,25 @@ openssl sha256 /tmp/*.page.*
``` ```
## Entitlements Blob ## Entitlements Blob
응용 프로그램에는 모든 권한이 정의된 **entitlement blob**이 포함될 수 있습니다. 또한 일부 iOS 바이너리는 특별 슬롯 -7에 권한이 특정되어 있을 수 있습니다(대신 -5 권한 특별 슬롯에). 애플리케이션은 모든 entitlements가 정의된 **entitlement blob**을 포함할 수 있다는 점을 유의하자. 또한 일부 iOS 바이너리는 entitlements가 특수 슬롯 -5 대신 -7에 위치할 수 있다.
## Special Slots ## Special Slots
MacOS 응용 프로그램은 바이너리 내에서 실행하는 데 필요한 모든 것을 갖추고 있지 않지만 **외부 리소스**(일반적으로 응용 프로그램의 **bundle** 내)에 의존합니다. 따라서 바이너리 내에는 수정되지 않았는지 확인하기 위해 일부 흥미로운 외부 리소스의 해시를 포함하는 슬롯이 있습니다. MacOS 애플리케이션은 실행에 필요한 모든 것을 바이너리 내부에 포함하지 않으며 보통 애플리케이션의 **bundle** 안에 있는 **external resources**를 사용한다. 따라서 바이너리 내부에는 일부 외부 리소스가 변경되지 않았는지 확인하기 위해 해당 리소스들의 해시를 담는 특수 슬롯들이 있다.
실제로, Code Directory 구조체에서 **`nSpecialSlots`**라는 매개변수를 볼 수 있으며, 이는 특별 슬롯의 수를 나타냅니다. 특별 슬롯 0은 없으며 가장 일반적인 슬롯( -1에서 -6까지)은 다음과 같습니다: 실제로 Code Directory structs에서 특수 슬롯의 개수를 나타내는 **`nSpecialSlots`**라는 파라미터를 볼 수 있다. 0번 특수 슬롯은 없으며, 가장 흔한 것들(1에서 6까지)은 다음과 같다:
- `info.plist`의 해시(또는 `__TEXT.__info__plist` 의 것). - `info.plist`의 해시(또는 `__TEXT.__info__plist` 의 것).
- 요구 사항의 해시 - Requirements의 해시
- 리소스 디렉토리의 해시(번들 내의 `_CodeSignature/CodeResources` 파일의 해시). - Resource Directory의 해시(`_CodeSignature/CodeResources` 파일(번들 내부)의 해시).
- 응용 프로그램 특정(사용되지 않음) - 애플리케이션 전용(미사용)
- 권한의 해시 - entitlements의 해시
- DMG 코드 서명 전용 - DMG code signatures 전용
- DER 권한 - DER Entitlements
## Code Signing Flags ## Code Signing Flags
모든 프로세스에는 `status`로 알려진 비트마스크가 관련되어 있으며, 이는 커널에 의해 시작되며 일부는 **코드 서명**에 의해 재정의될 수 있습니다. 코드 서명에 포함될 수 있는 이러한 플래그는 [코드에서 정의되어 있습니다](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36): 모든 프로세스는 커널에 의해 설정되는 `status`라는 비트마스크와 관련되며, 이 중 일부는 **code signature**로 재정의될 수 있다. 코드 서명에 포함될 수 있는 이 플래그들은 [코드에 정의되어 있다](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/kern/cs_blobs.h#L36):
```c ```c
/* code signing attributes of a process */ /* code signing attributes of a process */
#define CS_VALID 0x00000001 /* dynamically valid */ #define CS_VALID 0x00000001 /* dynamically valid */
@ -209,13 +214,13 @@ CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV | CS_RUNTIME | CS_LINKER_SIGNED)
``` ```
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. 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.
## 코드 서명 요구 사항 ## 코드 서명 요구사항
각 애플리케이션은 실행될 수 있도록 **충족해야 하는** **요구 사항**을 저장합니다. **애플리케이션이 충족하지 않는 요구 사항을 포함하고 있다면**, 실행되지 않습니다(변경되었을 가능성이 높기 때문입니다). 각 애플리케이션은 실행되기 위해 충족해야 하는 몇 가지 **요구사항**을 저장합니다. 애플리케이션의 **요구사항**이 충족되지 않으면 해당 애플리케이션은 실행되지 않습니다(변조되었을 가능성이 높기 때문입니다).
바이너리의 요구 사항은 **특별한 문법**을 사용하며, 이는 **표현식**의 흐름으로 `0xfade0c00`을 매직으로 사용하여 블롭으로 인코딩됩니다. 이 **해시는 특별한 코드 슬롯에 저장됩니다**. 바이너리의 요구사항은 일련의 **표현식**으로 구성된 **특수 문법**을 사용하며, `0xfade0c00`를 매직으로 하는 blob으로 인코딩되고 그 **해시가 특수 코드 슬롯에 저장됩니다**.
바이너리의 요구 사항은 다음을 실행하여 확인할 수 있습니다: 바이너리의 요구사항은 다음 명령을 실행하면 확인할 수 있습니다:
```bash ```bash
codesign -d -r- /bin/ls codesign -d -r- /bin/ls
Executable=/bin/ls Executable=/bin/ls
@ -225,10 +230,10 @@ codesign -d -r- /Applications/Signal.app/
Executable=/Applications/Signal.app/Contents/MacOS/Signal 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 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] > [!TIP]
> 이 서명이 인증 정보, TeamID, ID, 권한 및 기타 많은 데이터를 확인할 수 있는 방법에 유의하십시오. > 이러한 서명은 인증서 정보, TeamID, IDs, entitlements 및 그 밖의 여러 데이터를 검사할 수 있다는 점에 주목하세요.
또한, `csreq` 도구를 사용하여 일부 컴파일된 요구 사항을 생성할 수 있습니다: 또한 `csreq` 도구를 사용하여 일부 컴파일된 요구사항을 생성할 수 있습니다:
```bash ```bash
# Generate compiled requirements # 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' 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 +245,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 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의 유효성을 검사합니다. - **`Sec[Static]CodeCheckValidity`**: SecCodeRef의 Requirement별 유효성을 확인합니다.
- **`SecRequirementEvaluate`**: 인증서 컨텍스트에서 요구 사항을 검증합니다. - **`SecRequirementEvaluate`**: 인증서 컨텍스트에서 Requirement를 검증합니다.
- **`SecTaskValidateForRequirement`**: `CFString` 요구 사항에 대해 실행 중인 SecTask를 검증합니다. - **`SecTaskValidateForRequirement`**: 실행 중인 SecTask를 `CFString` Requirement에 대해 검증합니다.
#### **코드 요구 사항 생성 및 관리** #### **코드 Requirement 생성 및 관리**
- **`SecRequirementCreateWithData`:** 요구 사항을 나타내는 이진 데이터에서 `SecRequirementRef`를 생성합니다. - **`SecRequirementCreateWithData`:** Requirement를 나타내는 이진 데이터로부터 `SecRequirementRef`를 생성합니다.
- **`SecRequirementCreateWithString`:** 요구 사항의 문자열 표현에서 `SecRequirementRef`를 생성합니다. - **`SecRequirementCreateWithString`:** Requirement의 문자열 표현으로부터 `SecRequirementRef`를 생성합니다.
- **`SecRequirementCopy[Data/String]`**: `SecRequirementRef`의 이진 데이터 표현을 검색합니다. - **`SecRequirementCopy[Data/String]`**: `SecRequirementRef`의 이진 데이터 표현을 가져옵니다.
- **`SecRequirementCreateGroup`**: 앱 그룹 멤버십에 대한 요구 사항을 생성합니다. - **`SecRequirementCreateGroup`**: app-group 멤버십에 대한 Requirement를 생성합니다
#### **코드 서명 정보 접근** #### **코드 서명 정보 접근**
- **`SecStaticCodeCreateWithPath`**: 코드 서명을 검사하기 위해 파일 시스템 경로에서 `SecStaticCodeRef` 객체를 초기화합니다. - **`SecStaticCodeCreateWithPath`**: 코드 서명을 검사하기 위해 파일 시스템 경로로부터 `SecStaticCodeRef` 객체를 초기화합니다.
- **`SecCodeCopySigningInformation`**: `SecCodeRef` 또는 `SecStaticCodeRef`에서 서명 정보를 얻습니다. - **`SecCodeCopySigningInformation`**: `SecCodeRef` 또는 `SecStaticCodeRef`로부터 서명 정보를 얻습니다.
#### **코드 요구 사항 수정** #### **코드 Requirement 수정**
- **`SecCodeSignerCreate`**: 코드 서명 작업을 수행하기 위한 `SecCodeSignerRef` 객체를 생성합니다. - **`SecCodeSignerCreate`**: 코드 서명 작업을 수행하기 위한 `SecCodeSignerRef` 객체를 생성합니다.
- **`SecCodeSignerSetRequirement`**: 서명 중에 적용할 새로운 요구 사항을 설정합니다. - **`SecCodeSignerSetRequirement`**: 서명 시 적용할 새로운 Requirement를 설정합니다.
- **`SecCodeSignerAddSignature`**: 지정된 서명자로 서명되는 코드에 서명을 추가합니다. - **`SecCodeSignerAddSignature`**: 지정된 서명자로 코드에 서명을 추가합니다.
#### **요구 사항으로 코드 검증** #### **Requirement로 코드 검증**
- **`SecStaticCodeCheckValidity`**: 지정된 요구 사항에 대해 정적 코드 객체를 검증합니다. - **`SecStaticCodeCheckValidity`**: 지정된 Requirement들에 대해 static code 객체의 유효성을 검증합니다.
#### **추가 유용한 API** #### **추가 유용한 API**
- **`SecCodeCopy[Internal/Designated]Requirement`: SecCodeRef에서 SecRequirementRef를 가져옵니다.** - **`SecCodeCopy[Internal/Designated]Requirement`: Get SecRequirementRef from SecCodeRef**
- **`SecCodeCopyGuestWithAttributes`**: 특정 속성을 기반으로 하는 코드 객체를 나타내는 `SecCodeRef`를 생성하며, 샌드박싱에 유용합니다. - **`SecCodeCopyGuestWithAttributes`**: 특정 속성에 기반한 코드 객체를 나타내는 `SecCodeRef`를 생성합니다. sandboxing에 유용합니다.
- **`SecCodeCopyPath`**: `SecCodeRef`와 관된 파일 시스템 경로를 검색합니다. - **`SecCodeCopyPath`**: `SecCodeRef`관된 파일 시스템 경로를 검색합니다.
- **`SecCodeCopySigningIdentifier`**: `SecCodeRef`에서 서명 식별자(예: 팀 ID)를 얻습니다. - **`SecCodeCopySigningIdentifier`**: `SecCodeRef`로부터 서명 식별자(예: Team ID)를 얻습니다.
- **`SecCodeGetTypeID`**: `SecCodeRef` 객체의 유형 식별자를 반환합니다. - **`SecCodeGetTypeID`**: `SecCodeRef` 객체들의 타입 식별자를 반환합니다.
- **`SecRequirementGetTypeID`**: `SecRequirementRef`의 CFTypeID를 가져옵니다. - **`SecRequirementGetTypeID`**: `SecRequirementRef`의 CFTypeID를 가져옵니다.
#### **코드 서명 플래그 및 상수** #### **코드 서명 플래그 및 상수**
- **`kSecCSDefaultFlags`**: 코드 서명 작업을 위한 많은 Security.framework 함수에서 사용되는 기본 플래그입니다. - **`kSecCSDefaultFlags`**: 코드 서명 작업을 위한 많은 Security.framework 함수에서 사용되는 기본 플래그입니다.
- **`kSecCSSigningInformation`**: 서명 정보를 검색해야 함을 지정하는 데 사용되는 플래그입니다. - **`kSecCSSigningInformation`**: 서명 정보를 가져와야 함을 지정하는데 사용되는 플래그입니다.
## 코드 서명 강제 적용 ## 코드 서명 강제
**커널**은 앱의 코드가 실행되기 전에 **코드 서명**을 **검사**합니다. 또한, 메모리에 새로운 코드를 작성하고 실행할 수 있는 한 가지 방법은 `mprotect``MAP_JIT` 플래그와 함께 호출될 때 JIT를 악용하는 것입니다. 이 작업을 수행하려면 애플리케이션에 특별한 권한이 필요합니다. 앱 코드가 실행되도록 허용하기 전에 **kernel**이 **코드 서명을 검사합니다**. 또한, 메모리에 새로운 코드를 쓰고 실행할 수 있게 하는 한 가지 방법은 `mprotect``MAP_JIT` 플래그로 호출될 때 JIT을 악용하는 것입니다. 이를 위해서는 애플리케이션에 특별한 entitlement가 필요하다는 점에 유의하세요.
## `cs_blobs` & `cs_blob` ## `cs_blobs` & `cs_blob`
[**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) 구조체는 실행 중인 프로세스의 권한에 대한 정보를 포함합니다. `csb_platform_binary`는 애플리케이션이 플랫폼 이진 파일인지 여부도 알려줍니다(이는 보안 메커니즘을 적용하기 위해 OS에 의해 여러 순간에 확인됩니다. 예를 들어 이러한 프로세스의 작업 포트에 대한 SEND 권한을 보호하는 것입니다). [**cs_blob**](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/sys/ubc_internal.h#L106) struct는 해당 실행 중인 프로세스의 entitlement에 대한 정보를 포함합니다. `csb_platform_binary`는 또한 애플리케이션이 platform binary인지 여부를 알려줍니다(OS가 이러한 프로세스들의 task port에 대한 SEND rights를 보호하는 등 보안 메커니즘을 적용하기 위해 여러 시점에서 확인합니다).
```c ```c
struct cs_blob { struct cs_blob {
struct cs_blob *csb_next; struct cs_blob *csb_next;
@ -347,7 +354,7 @@ bool csb_csm_managed;
#endif #endif
}; };
``` ```
## References ## 참고자료
- [**\*OS Internals Volume III**](https://newosxbook.com/home.html) - [**\*OS Internals Volume III**](https://newosxbook.com/home.html)