macOS Universal binaries & Mach-O Format

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

๊ธฐ๋ณธ ์ •๋ณด

Mac OS ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ๋ณดํ†ต universal binaries๋กœ ์ปดํŒŒ์ผ๋ฉ๋‹ˆ๋‹ค. universal binary๋Š” ๋‹จ์ผ ํŒŒ์ผ์—์„œ ์—ฌ๋Ÿฌ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ์œผ๋กœ ๊ตฌ์„ฑ๋œ Mach-O ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค:

  • Header
  • Load Commands
  • Data

https://alexdremov.me/content/images/2022/10/6XLCD.gif

Fat Header

๋‹ค์Œ์œผ๋กœ ํŒŒ์ผ์„ ๊ฒ€์ƒ‰ํ•˜์„ธ์š”: mdfind fat.h | grep -i mach-o | grep -E "fat.h$"

#define FAT_MAGIC	0xcafebabe
#define FAT_CIGAM	0xbebafeca	/* NXSwapLong(FAT_MAGIC) */

struct fat_header {
	uint32_t	magic;		/* FAT_MAGIC or FAT_MAGIC_64 */
	uint32_t	nfat_arch;	/* number of structs that follow */
};

struct fat_arch {
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 */
};

ํ—ค๋”๋Š” magic ๋ฐ”์ดํŠธ์™€ ๋’ค๋”ฐ๋ฅด๋Š” ํŒŒ์ผ์ด ํฌํ•จํ•˜๋Š” archs์˜ ๊ฐœ์ˆ˜ (nfat_arch)๋ฅผ ํฌํ•จํ•˜๋ฉฐ, ๊ฐ arch๋Š” fat_arch ๊ตฌ์กฐ์ฒด๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ ํ™•์ธํ•˜์„ธ์š”:

% 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 (for architecture x86_64):	Mach-O 64-bit executable x86_64
/bin/ls (for architecture arm64e):	Mach-O 64-bit executable arm64e

% otool -f -v /bin/ls
Fat headers
fat_magic FAT_MAGIC
nfat_arch 2
architecture x86_64
    cputype CPU_TYPE_X86_64
cpusubtype CPU_SUBTYPE_X86_64_ALL
capabilities 0x0
    offset 16384
    size 72896
    align 2^14 (16384)
architecture arm64e
    cputype CPU_TYPE_ARM64
cpusubtype CPU_SUBTYPE_ARM64E
capabilities PTR_AUTH_VERSION USERSPACE 0
    offset 98304
    size 88816
    align 2^14 (16384)

๋˜๋Š” Mach-O View ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ:

์•„๋งˆ ์ƒ๊ฐํ•˜์…จ๊ฒ ์ง€๋งŒ, ๋ณดํ†ต 2๊ฐœ ์•„ํ‚คํ…์ฒ˜์šฉ์œผ๋กœ ์ปดํŒŒ์ผ๋œ universal binary๋Š” ๋‹จ์ผ ์•„ํ‚คํ…์ฒ˜์šฉ์œผ๋กœ ์ปดํŒŒ์ผ๋œ ๊ฒƒ๋ณด๋‹ค ํฌ๊ธฐ๊ฐ€ 2๋ฐฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

Mach-O Header

ํ—ค๋”์—๋Š” Mach-O ํŒŒ์ผ๋กœ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ magic ๋ฐ”์ดํŠธ์™€ ๋Œ€์ƒ ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•œ ์ •๋ณด ๋“ฑ ํŒŒ์ผ์˜ ๊ธฐ๋ณธ ์ •๋ณด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: mdfind loader.h | grep -i mach-o | grep -E "loader.h$"

#define	MH_MAGIC	0xfeedface	/* the mach magic number */
#define MH_CIGAM	0xcefaedfe	/* NXSwapInt(MH_MAGIC) */
struct mach_header {
uint32_t	magic;		/* mach magic number identifier */
cpu_type_t	cputype;	/* cpu specifier (e.g. I386) */
cpu_subtype_t	cpusubtype;	/* machine specifier */
uint32_t	filetype;	/* type of file (usage and alignment for the file) */
uint32_t	ncmds;		/* number of load commands */
uint32_t	sizeofcmds;	/* the size of all the load commands */
uint32_t	flags;		/* flags */
};

#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
struct mach_header_64 {
uint32_t	magic;		/* mach magic number identifier */
int32_t		cputype;	/* cpu specifier */
int32_t		cpusubtype;	/* machine specifier */
uint32_t	filetype;	/* type of file */
uint32_t	ncmds;		/* number of load commands */
uint32_t	sizeofcmds;	/* the size of all the load commands */
uint32_t	flags;		/* flags */
uint32_t	reserved;	/* reserved */
};

Mach-O ํŒŒ์ผ ํ˜•์‹

์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํŒŒ์ผ ํ˜•์‹์ด ์žˆ์œผ๋ฉฐ, source code for example here์—์„œ ์ •์˜๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  • MH_OBJECT: ์žฌ๋ฐฐ์น˜ ๊ฐ€๋Šฅํ•œ ์˜ค๋ธŒ์ ํŠธ ํŒŒ์ผ (์ปดํŒŒ์ผ์˜ ์ค‘๊ฐ„ ์‚ฐ์ถœ๋ฌผ๋กœ ์•„์ง ์‹คํ–‰ ํŒŒ์ผ์ด ์•„๋‹˜).
  • MH_EXECUTE: ์‹คํ–‰ ํŒŒ์ผ.
  • MH_FVMLIB: ๊ณ ์ • VM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ.
  • MH_CORE: ์ฝ”๋“œ ๋คํ”„
  • MH_PRELOAD: ์‚ฌ์ „ ๋กœ๋“œ๋œ ์‹คํ–‰ ํŒŒ์ผ (ํ˜„์žฌ XNU์—์„œ ๋” ์ด์ƒ ์ง€์›๋˜์ง€ ์•Š์Œ)
  • MH_DYLIB: ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • MH_DYLINKER: ๋™์  ๋ง์ปค
  • MH_BUNDLE: โ€œํ”Œ๋Ÿฌ๊ทธ์ธ ํŒŒ์ผโ€. -bundle in gcc๋กœ ์ƒ์„ฑ๋˜๋ฉฐ ๋ช…์‹œ์ ์œผ๋กœ NSBundle ๋˜๋Š” dlopen์œผ๋กœ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.
  • MH_DYSM: ๋™๋ฐ˜ .dSym ํŒŒ์ผ (๋””๋ฒ„๊น…์„ ์œ„ํ•œ ์‹ฌ๋ณผ์ด ํฌํ•จ๋œ ํŒŒ์ผ).
  • MH_KEXT_BUNDLE: ์ปค๋„ ํ™•์žฅ.
# Checking the mac header of a binary
otool -arch arm64e -hv /bin/ls
Mach header
magic  cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64    ARM64          E USR00     EXECUTE    19       1728   NOUNDEFS DYLDLINK TWOLEVEL PIE

๋˜๋Š” Mach-O View:

Mach-O ํ”Œ๋ž˜๊ทธ

์†Œ์Šค ์ฝ”๋“œ์—๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ์— ์œ ์šฉํ•œ ์—ฌ๋Ÿฌ ํ”Œ๋ž˜๊ทธ๋„ ์ •์˜๋˜์–ด ์žˆ๋‹ค:

  • MH_NOUNDEFS: ์ •์˜๋˜์ง€ ์•Š์€ ์ฐธ์กฐ ์—†์Œ (์™„์ „ ๋งํฌ๋จ)
  • MH_DYLDLINK: Dyld ๋งํฌ
  • MH_PREBOUND: ๋™์  ์ฐธ์กฐ๊ฐ€ ์‚ฌ์ „ ๋ฐ”์ธ๋”ฉ๋จ
  • MH_SPLIT_SEGS: ํŒŒ์ผ์ด r/o ๋ฐ r/w ์„ธ๊ทธ๋จผํŠธ๋กœ ๋ถ„๋ฆฌ๋จ
  • MH_WEAK_DEFINES: ๋ฐ”์ด๋„ˆ๋ฆฌ์— weak๋กœ ์ •์˜๋œ ์‹ฌ๋ณผ์ด ์žˆ์Œ
  • MH_BINDS_TO_WEAK: ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ weak ์‹ฌ๋ณผ์„ ์‚ฌ์šฉํ•จ
  • MH_ALLOW_STACK_EXECUTION: ์Šคํƒ์„ ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ
  • MH_NO_REEXPORTED_DYLIBS: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— LC_REEXPORT ๋ช…๋ น์ด ์—†์Œ
  • MH_PIE: ์œ„์น˜ ๋…๋ฆฝ ์‹คํ–‰ ํŒŒ์ผ
  • MH_HAS_TLV_DESCRIPTORS: ์Šค๋ ˆ๋“œ ๋กœ์ปฌ ๋ณ€์ˆ˜ ์„น์…˜์ด ์žˆ์Œ
  • MH_NO_HEAP_EXECUTION: ํž™/๋ฐ์ดํ„ฐ ํŽ˜์ด์ง€์—์„œ ์‹คํ–‰ ๋ถˆ๊ฐ€
  • MH_HAS_OBJC: ๋ฐ”์ด๋„ˆ๋ฆฌ์— Objective-C ์„น์…˜์ด ์žˆ์Œ
  • MH_SIM_SUPPORT: ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ ์ง€์›
  • MH_DYLIB_IN_CACHE: shared library cache์— ์žˆ๋Š” dylib/framework์— ์‚ฌ์šฉ๋จ.

Mach-O ๋กœ๋“œ ๋ช…๋ น

ํŒŒ์ผ์˜ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์ด ์—ฌ๊ธฐ์„œ ์ง€์ •๋˜๋ฉฐ, ์‹ฌ๋ณผ ํ…Œ์ด๋ธ”์˜ ์œ„์น˜, ์‹คํ–‰ ์‹œ์ž‘ ์‹œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์˜ ์ปจํ…์ŠคํŠธ, ๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•œ ๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์ƒ์„ธํžˆ ๊ธฐ์ˆ ๋œ๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œํ•˜๋Š” ๊ณผ์ •์— ๋Œ€ํ•ด ๋™์  ๋กœ๋”(dyld)์— ์ง€์นจ์„ ์ œ๊ณตํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ๋Š” ์•ž์„œ ์–ธ๊ธ‰ํ•œ **loader.h**์— ์ •์˜๋œ load_command ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค:

struct load_command {
uint32_t cmd;           /* type of load command */
uint32_t cmdsize;       /* total size of command in bytes */
};

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

๊ธฐ๋ณธ์ ์œผ๋กœ, ์ด ์œ ํ˜•์˜ Load Command๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๋ฐ์ดํ„ฐ ์„น์…˜์— ํ‘œ์‹œ๋œ ์˜คํ”„์…‹์— ๋”ฐ๋ผ __TEXT(์‹คํ–‰ ์ฝ”๋“œ) ๋ฐ __DATA(ํ”„๋กœ์„ธ์Šค์˜ ๋ฐ์ดํ„ฐ) ์„ธ๊ทธ๋จผํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ๋กœ๋“œํ•˜๋Š”์ง€ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

These commands define segments that are mapped into the virtual memory space of a process when it is executed.

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:

struct segment_command_64 { /* for 64-bit architectures */
uint32_t	cmd;		/* LC_SEGMENT_64 */
uint32_t	cmdsize;	/* includes sizeof section_64 structs */
char		segname[16];	/* segment name */
uint64_t	vmaddr;		/* memory address of this segment */
uint64_t	vmsize;		/* memory size of this segment */
uint64_t	fileoff;	/* file offset of this segment */
uint64_t	filesize;	/* amount to map from the file */
int32_t		maxprot;	/* maximum VM protection */
int32_t		initprot;	/* initial VM protection */
	uint32_t	nsects;		/* number of sections in segment */
	uint32_t	flags;		/* flags */
};

Example of segment header:

This header defines the number of sections whose headers appear after it:

struct section_64 { /* for 64-bit architectures */
char		sectname[16];	/* name of this section */
char		segname[16];	/* segment this section goes in */
uint64_t	addr;		/* memory address of this section */
uint64_t	size;		/* size in bytes of this section */
uint32_t	offset;		/* file offset of this section */
uint32_t	align;		/* section alignment (power of 2) */
uint32_t	reloff;		/* file offset of relocation entries */
uint32_t	nreloc;		/* number of relocation entries */
uint32_t	flags;		/* flags (section type and attributes)*/
uint32_t	reserved1;	/* reserved (for offset or index) */
uint32_t	reserved2;	/* reserved (for count or sizeof) */
uint32_t	reserved3;	/* reserved */
};

์˜ˆ: ์„น์…˜ ํ—ค๋”:

๋งŒ์•ฝ ๋”ํ•˜๋ฉด ์„น์…˜ ์˜คํ”„์…‹ (0x37DC) + arch๊ฐ€ ์‹œ์ž‘ํ•˜๋Š” ์˜คํ”„์…‹, ์ด ๊ฒฝ์šฐ 0x18000 โ€“> 0x37DC + 0x18000 = 0x1B7DC

๋˜ํ•œ ํ—ค๋” ์ •๋ณด๋ฅผ command line์—์„œ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

otool -lv /bin/ls

Common segments loaded by this cmd:

  • __PAGEZERO: ์ปค๋„์—๊ฒŒ **์ฃผ์†Œ 0(address zero)**๋ฅผ **๋งคํ•‘(map)**ํ•˜๋„๋ก ์ง€์‹œํ•˜์—ฌ ์ฝ๊ธฐ/์“ฐ๊ธฐ/์‹คํ–‰์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด์˜ maxprot ๋ฐ minprot ๋ณ€์ˆ˜๋Š” ์ด ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์ฝ๊ธฐ-์“ฐ๊ธฐ-์‹คํ–‰ ๊ถŒํ•œ์ด ์—†์Œ์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•ด 0์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
  • ์ด ํ• ๋‹น์€ NULL pointer dereference vulnerabilities๋ฅผ ์™„ํ™”ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” XNU๊ฐ€ ํ•˜๋“œ ํŽ˜์ด์ง€ ์ œ๋กœ๋ฅผ ์ ์šฉํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€(์ฒซ ํŽ˜์ด์ง€๋งŒ)๋ฅผ ์ ‘๊ทผ ๋ถˆ๊ฐ€๋กœ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(i386 ์ œ์™ธ). ๋ฐ”์ด๋„ˆ๋ฆฌ๋Š” ์ž‘์€ __PAGEZERO( -pagezero_size ์‚ฌ์šฉ)๋ฅผ ๋งŒ๋“ค์–ด ์ฒ˜์Œ 4K๋ฅผ ๋ฎ๊ณ  ๋‚˜๋จธ์ง€ 32๋น„ํŠธ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์œ ์ € ๋ฐ ์ปค๋„ ๋ชจ๋“œ์—์„œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜์—ฌ ์ด ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • __TEXT: ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ(executable) **์ฝ”๋“œ(code)**๋ฅผ ํฌํ•จํ•˜๋ฉฐ ์ฝ๊ธฐ(read) ๋ฐ ์‹คํ–‰(execute) ๊ถŒํ•œ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค(์“ฐ๊ธฐ ๊ถŒํ•œ ์—†์Œ). ์ด ์„ธ๊ทธ๋จผํŠธ์˜ ์ผ๋ฐ˜ ์„น์…˜:
  • __text: ์ปดํŒŒ์ผ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ฝ”๋“œ
  • __const: ์ƒ์ˆ˜ ๋ฐ์ดํ„ฐ(์ฝ๊ธฐ ์ „์šฉ)
  • __[c/u/os_log]string: C, Unicode ๋˜๋Š” os ๋กœ๊ทธ ๋ฌธ์ž์—ด ์ƒ์ˆ˜
  • __stubs and __stubs_helper: ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋กœ๋”ฉ ๊ณผ์ •์— ๊ด€์—ฌ
  • __unwind_info: ์Šคํƒ ์–ธ์™€์ธ๋“œ ๋ฐ์ดํ„ฐ
  • ์ด ๋ชจ๋“  ๋‚ด์šฉ์€ ์„œ๋ช…๋˜์–ด ์žˆ๋˜ ์‹คํ–‰ ๊ฐ€๋Šฅ์œผ๋กœ ํ‘œ์‹œ๋˜์–ด ์žˆ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”(๋ฌธ์ž์—ด ์ „์šฉ ์„น์…˜์ฒ˜๋Ÿผ ๋ฐ˜๋“œ์‹œ ์‹คํ–‰ ๊ถŒํ•œ์„ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š๋Š” ์„น์…˜์„ ์•…์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค).
  • __DATA: ์ฝ๊ธฐ(readable) ๋ฐ ์“ฐ๊ธฐ(writable) ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค(์‹คํ–‰ ๋ถˆ๊ฐ€).
  • __got: ์ „์—ญ ์˜คํ”„์…‹ ํ…Œ์ด๋ธ”(Global Offset Table)
  • __nl_symbol_ptr: Non-lazy(๋กœ๋”ฉ ์‹œ ๋ฐ”์ธ๋”ฉ) ์‹ฌ๋ณผ ํฌ์ธํ„ฐ
  • __la_symbol_ptr: Lazy(์‚ฌ์šฉ ์‹œ ๋ฐ”์ธ๋”ฉ) ์‹ฌ๋ณผ ํฌ์ธํ„ฐ
  • __const: ์›๋ž˜๋Š” ์ฝ๊ธฐ ์ „์šฉ ๋ฐ์ดํ„ฐ์—ฌ์•ผ ํ•จ(์‹ค์ œ๋ก  ๊ทธ๋ ‡์ง€ ์•Š์Œ)
  • __cfstring: CoreFoundation ๋ฌธ์ž์—ด
  • __data: ์ดˆ๊ธฐํ™”๋œ ์ „์—ญ ๋ณ€์ˆ˜
  • __bss: ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ์ •์  ๋ณ€์ˆ˜
  • __objc_* (__objc_classlist, __objc_protolist, ๋“ฑ): Objective-C ๋Ÿฐํƒ€์ž„์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ •๋ณด
  • __DATA_CONST: __DATA.__const๋Š” ์ƒ์ˆ˜(์“ฐ๊ธฐ ๊ธˆ์ง€)๋ผ๊ณ  ๋ณด์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ, ๋‹ค๋ฅธ ํฌ์ธํ„ฐ๋“ค๊ณผ GOT ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์ด ์„น์…˜์€ __const, ์ผ๋ถ€ ์ด๋‹ˆ์…œ๋ผ์ด์ € ๋ฐ (ํ•ด๊ฒฐ๋œ ํ›„์˜) GOT ํ…Œ์ด๋ธ”์„ mprotect๋ฅผ ์‚ฌ์šฉํ•ด ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  • __LINKEDIT: ๋ง์ปค(dyld)๋ฅผ ์œ„ํ•œ ์ •๋ณด(์‹ฌ๋ณผ, ๋ฌธ์ž์—ด, ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ” ์—”ํŠธ๋ฆฌ ๋“ฑ)๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. __TEXT๋‚˜ __DATA์— ์†ํ•˜์ง€ ์•Š๋Š” ๋‚ด์šฉ์„ ๋‹ด๋Š” ์ผ๋ฐ˜ ์ปจํ…Œ์ด๋„ˆ์ด๋ฉฐ ๊ทธ ๋‚ด์šฉ์€ ๋‹ค๋ฅธ ๋กœ๋“œ ์ปค๋งจ๋“œ์—์„œ ๊ธฐ์ˆ ๋ฉ๋‹ˆ๋‹ค.
  • dyld ์ •๋ณด: Rebase, Non-lazy/lazy/weak binding opcodes ๋ฐ export ์ •๋ณด
  • Functions starts: ํ•จ์ˆ˜๋“ค์˜ ์‹œ์ž‘ ์ฃผ์†Œ ํ‘œ
  • Data In Code: ๋ฐ์ดํ„ฐ ์„ฌ๋“ค in __text
  • Symbol Table: ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‚ด์˜ ์‹ฌ๋ณผ
  • Indirect Symbol Table: ํฌ์ธํ„ฐ/์Šคํ… ์‹ฌ๋ณผ
  • String Table
  • Code Signature
  • __OBJC: Objective-C ๋Ÿฐํƒ€์ž„์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋Š” __DATA ์„ธ๊ทธ๋จผํŠธ ๋‚ด์˜ ๋‹ค์–‘ํ•œ __objc_* ์„น์…˜์—์„œ๋„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • __RESTRICT: ๋‚ด์šฉ์ด ์—†๋Š” ์„ธ๊ทธ๋จผํŠธ๋กœ, **__restrict**๋ผ๋Š” ๋‹จ์ผ ์„น์…˜(์—ญ์‹œ ๋น„์–ด ์žˆ์Œ)์„ ๊ฐ€์ง€๋ฉฐ, ๋ฐ”์ด๋„ˆ๋ฆฌ ์‹คํ–‰ ์‹œ DYLD ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋ฌด์‹œํ•˜๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

As it was possible to see in the code, segments also support flags (although they arenโ€™t used very much):

  • SG_HIGHVM: Core ์ „์šฉ(์‚ฌ์šฉ ์•ˆ ํ•จ)
  • SG_FVMLIB: ์‚ฌ์šฉ๋˜์ง€ ์•Š์Œ
  • SG_NORELOC: ์„ธ๊ทธ๋จผํŠธ์— ์žฌ๋ฐฐ์น˜ ์—†์Œ
  • SG_PROTECTED_VERSION_1: ์•”ํ˜ธํ™”. ์˜ˆ๋ฅผ ๋“ค์–ด Finder๊ฐ€ ํ…์ŠคํŠธ __TEXT ์„ธ๊ทธ๋จผํŠธ๋ฅผ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

LC_UNIXTHREAD/LC_MAIN

**LC_MAIN**์€ entryoff attribute์— ์—”ํŠธ๋ฆฌํฌ์ธํŠธ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๋กœ๋“œ ์‹œ, dyld๋Š” ๋‹จ์ˆœํžˆ ์ด ๊ฐ’์„ (๋ฉ”๋ชจ๋ฆฌ ์ƒ์˜) **๋ฐ”์ด๋„ˆ๋ฆฌ์˜ ๋ฒ ์ด์Šค(base of the binary)**์— ๋”ํ•œ ํ›„ ํ•ด๋‹น ๋ช…๋ น์œผ๋กœ **์ ํ”„(jumps)**ํ•˜์—ฌ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

**LC_UNIXTHREAD**๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ๊ฐ€์ ธ์•ผ ํ•  ๊ฐ’๋“ค์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ด๋ฏธ deprecated ๋˜์—ˆ์ง€๋งŒ **dyld**๋Š” ์—ฌ์ „ํžˆ ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์„ค์ •๋œ ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’๋“ค์€ ๋‹ค์Œ์„ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

otool -l /usr/lib/dyld
[...]
Load command 13
cmd LC_UNIXTHREAD
cmdsize 288
flavor ARM_THREAD_STATE64
count ARM_THREAD_STATE64_COUNT
x0  0x0000000000000000 x1  0x0000000000000000 x2  0x0000000000000000
x3  0x0000000000000000 x4  0x0000000000000000 x5  0x0000000000000000
x6  0x0000000000000000 x7  0x0000000000000000 x8  0x0000000000000000
x9  0x0000000000000000 x10 0x0000000000000000 x11 0x0000000000000000
x12 0x0000000000000000 x13 0x0000000000000000 x14 0x0000000000000000
x15 0x0000000000000000 x16 0x0000000000000000 x17 0x0000000000000000
x18 0x0000000000000000 x19 0x0000000000000000 x20 0x0000000000000000
x21 0x0000000000000000 x22 0x0000000000000000 x23 0x0000000000000000
x24 0x0000000000000000 x25 0x0000000000000000 x26 0x0000000000000000
x27 0x0000000000000000 x28 0x0000000000000000  fp 0x0000000000000000
lr 0x0000000000000000 sp  0x0000000000000000  pc 0x0000000000004b70
cpsr 0x00000000

[...]

LC_CODE_SIGNATURE

Mach O Entitlements And Ipsw Indexing

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 and this gists.

LC_ENCRYPTION_INFO[_64]

๋ฐ”์ด๋„ˆ๋ฆฌ ์•”ํ˜ธํ™”๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ณต๊ฒฉ์ž๊ฐ€ ํ”„๋กœ์„ธ์Šค๋ฅผ ์นจํ•ดํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ๋คํ”„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

LC_LOAD_DYLINKER

๊ณต์œ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ”„๋กœ์„ธ์Šค ์ฃผ์†Œ ๊ณต๊ฐ„์— ๋งตํ•‘ํ•˜๋Š” dynamic linker ์‹คํ–‰ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์€ ํ•ญ์ƒ /usr/lib/dyld๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. macOS์—์„œ๋Š” dylib ๋งคํ•‘์ด ์ปค๋„ ๋ชจ๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž ๋ชจ๋“œ์—์„œ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ์ ์„ ์œ ์˜ํ•˜์„ธ์š”.

LC_IDENT

๊ตฌ์‹์ด์ง€๋งŒ, panic ์‹œ ๋คํ”„๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ๊ตฌ์„ฑํ•˜๋ฉด Mach-O ์ฝ”์–ด ๋คํ”„๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ์ปค๋„ ๋ฒ„์ „์ด LC_IDENT ๋ช…๋ น์— ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

LC_UUID

๋ฌด์ž‘์œ„ UUID์ž…๋‹ˆ๋‹ค. ์ž์ฒด์ ์œผ๋กœ๋Š” ์ง์ ‘์ ์ธ ์šฉ๋„๋Š” ์ œํ•œ์ ์ด์ง€๋งŒ XNU๊ฐ€ ์ด๋ฅผ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค ์ •๋ณด์™€ ํ•จ๊ป˜ ์บ์‹œํ•ฉ๋‹ˆ๋‹ค. ํฌ๋ž˜์‹œ ๋ฆฌํฌํŠธ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

LC_DYLD_ENVIRONMENT

ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— dyld์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€์—์„œ ์ž„์˜์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ฏ€๋กœ ๋งค์šฐ ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด load command๋Š” #define SUPPORT_LC_DYLD_ENVIRONMENT๋กœ ๋นŒ๋“œ๋œ dyld์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ฒ˜๋ฆฌ๋Š” ๋กœ๋“œ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜๋Š” DYLD_..._PATH ํ˜•ํƒœ์˜ ๋ณ€์ˆ˜๋กœ๋งŒ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

LC_LOAD_DYLIB

์ด load command๋Š” loader(dyld)์—๊ฒŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ๋งํฌํ•˜๋„๋ก ์ง€์‹œํ•˜๋Š” dynamic library ์˜์กด์„ฑ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. Mach-O ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋งˆ๋‹ค ํ•˜๋‚˜์˜ LC_LOAD_DYLIB load command๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • This load command is a structure of type dylib_command (which contains a struct dylib, describing the actual dependent dynamic library):
struct dylib_command {
uint32_t        cmd;            /* LC_LOAD_{,WEAK_}DYLIB */
uint32_t        cmdsize;        /* includes pathname string */
struct dylib    dylib;          /* the library identification */
};

struct dylib {
union lc_str  name;                 /* library's path name */
uint32_t timestamp;                 /* library's build time stamp */
uint32_t current_version;           /* library's current version number */
uint32_t compatibility_version;     /* library's compatibility vers number*/
};

๋˜๋Š” cli์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

otool -L /bin/ls
/bin/ls:
/usr/lib/libutil.dylib (compatibility version 1.0.0, current version 1.0.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)

์ผ๋ถ€ ์ž ์žฌ์  ์•…์„ฑ์ฝ”๋“œ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ:

  • DiskArbitration: USB ๋“œ๋ผ์ด๋ธŒ ๋ชจ๋‹ˆํ„ฐ๋ง
  • AVFoundation: ์˜ค๋””์˜ค ๋ฐ ๋น„๋””์˜ค ์บก์ฒ˜
  • CoreWLAN: Wifi ์Šค์บ”.

Tip

A Mach-O binary can contain one or more constructors, that will be executed before the address specified in LC_MAIN.
The offsets of any constructors are held in the __mod_init_func section of the __DATA_CONST segment.

Mach-O ๋ฐ์ดํ„ฐ

ํŒŒ์ผ์˜ ํ•ต์‹ฌ์—๋Š” load-commands ์˜์—ญ์— ์ •์˜๋œ ์—ฌ๋Ÿฌ ์„ธ๊ทธ๋จผํŠธ๋กœ ๊ตฌ์„ฑ๋œ ๋ฐ์ดํ„ฐ ์˜์—ญ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์„ธ๊ทธ๋จผํŠธ ์•ˆ์—๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์„น์…˜์ด ์กด์žฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ ์„น์…˜์€ ํŠน์ • ํƒ€์ž…์— ๋Œ€ํ•œ ์ฝ”๋“œ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•ฉ๋‹ˆ๋‹ค.

Tip

๋ฐ์ดํ„ฐ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ LC_SEGMENTS_64 ๋กœ๋“œ ์ปค๋งจ๋“œ์— ์˜ํ•ด ๋กœ๋“œ๋˜๋Š” ๋ชจ๋“  ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

https://www.oreilly.com/api/v2/epubs/9781785883378/files/graphics/B05055_02_38.jpg

์ด์—๋Š” ๋‹ค์Œ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค:

  • ํ•จ์ˆ˜ ํ…Œ์ด๋ธ”: ํ”„๋กœ๊ทธ๋žจ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ณด๊ด€ํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ฌ๋ณผ ํ…Œ์ด๋ธ”: ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์™ธ๋ถ€ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ด๋ถ€ ํ•จ์ˆ˜๋‚˜ ๋ณ€์ˆ˜ ์ด๋ฆ„ ๋“ฑ๋„ ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์ธํ•˜๋ ค๋ฉด Mach-O View ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

๋˜๋Š” CLI์—์„œ:

size -m /bin/ls

Objetive-C ๊ณตํ†ต ์„น์…˜

__TEXT ์„ธ๊ทธ๋จผํŠธ (r-x):

  • __objc_classname: ํด๋ž˜์Šค ์ด๋ฆ„(๋ฌธ์ž์—ด)
  • __objc_methname: ๋ฉ”์„œ๋“œ ์ด๋ฆ„(๋ฌธ์ž์—ด)
  • __objc_methtype: ๋ฉ”์„œ๋“œ ํƒ€์ž…(๋ฌธ์ž์—ด)

__DATA ์„ธ๊ทธ๋จผํŠธ (rw-):

  • __objc_classlist: ๋ชจ๋“  Objetive-C ํด๋ž˜์Šค์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ
  • __objc_nlclslist: Non-Lazy Objective-C ํด๋ž˜์Šค์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ
  • __objc_catlist: ์นดํ…Œ๊ณ ๋ฆฌ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ
  • __objc_nlcatlist: Non-Lazy ์นดํ…Œ๊ณ ๋ฆฌ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ
  • __objc_protolist: ํ”„๋กœํ† ์ฝœ ๋ชฉ๋ก
  • __objc_const: ์ƒ์ˆ˜ ๋ฐ์ดํ„ฐ
  • __objc_imageinfo, __objc_selrefs, objc__protorefsโ€ฆ

Swift

  • _swift_typeref, _swift3_capture, _swift3_assocty, _swift3_types, _swift3_proto, _swift3_fieldmd, _swift3_builtin, _swift3_reflstr

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ