macOS MACF

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 ์ง€์›ํ•˜๊ธฐ

๊ธฐ๋ณธ ์ •๋ณด

MACF๋Š” ์šด์˜์ฒด์ œ์— ๋‚ด์žฅ๋œ ๋ณด์•ˆ ์‹œ์Šคํ…œ์ธ **Mandatory Access Control Framework(๊ฐ•์ œ ์ ‘๊ทผ ์ œ์–ด ํ”„๋ ˆ์ž„์›Œํฌ)**์˜ ์•ฝ์ž์ž…๋‹ˆ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ ํŒŒ์ผ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฐ ์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค์™€ ๊ฐ™์€ ์‹œ์Šคํ…œ์˜ ํŠน์ • ๋ถ€๋ถ„์— ๋ˆ„๊ฐ€ ๋˜๋Š” ๋ฌด์—‡์ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์—„๊ฒฉํ•œ ๊ทœ์น™์„ ์„ค์ •ํ•˜์—ฌ ์ปดํ“จํ„ฐ๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ทœ์น™์„ ์ž๋™์œผ๋กœ ์ ์šฉํ•จ์œผ๋กœ์จ MACF๋Š” ๊ถŒํ•œ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž์™€ ํ”„๋กœ์„ธ์Šค๋งŒ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์—ฌ ๋ฌด๋‹จ ์ ‘๊ทผ์ด๋‚˜ ์•…์˜์  ํ™œ๋™์˜ ์œ„ํ—˜์„ ์ค„์ž…๋‹ˆ๋‹ค.

MACF๋Š” ์‹ค์ œ๋กœ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ์ง€ ์•Š๊ณ  ๋‹จ์ˆœํžˆ ๋™์ž‘์„ **๊ฐ€๋กœ์ฑˆ๋‹ค(intercepts)**๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”. ์‹ค์ œ ๊ฒฐ์ •์€ AppleMobileFileIntegrity.kext, Quarantine.kext, Sandbox.kext, TMSafetyNet.kext ๋ฐ mcxalr.kext์™€ ๊ฐ™์ด ํ˜ธ์ถœ๋˜๋Š” policy modules(kernel extensions)์— ์˜ํ•ด ๋‚ด๋ ค์ง‘๋‹ˆ๋‹ค.

  • ์ •์ฑ…์€ ์ง‘ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค (return 0 non-zero on some operation)
  • ์ •์ฑ…์€ ๋ชจ๋‹ˆํ„ฐ๋งํ•  ์ˆ˜ ์žˆ๋‹ค (return 0, so as not to object but piggyback on hook to do something)
  • MACF static policy๋Š” ๋ถ€ํŒ… ์‹œ ์„ค์น˜๋˜๋ฉฐ ์ ˆ๋Œ€ ์ œ๊ฑฐ๋˜์ง€ ์•Š๋Š”๋‹ค
  • MACF dynamic policy๋Š” KEXT(kextload)์— ์˜ํ•ด ์„ค์น˜๋˜๋ฉฐ ์ด๋ก ์ ์œผ๋กœ๋Š” kextunloaded๋  ์ˆ˜ ์žˆ๋‹ค
  • iOS์—์„œ๋Š” static policy๋งŒ ํ—ˆ์šฉ๋˜๋ฉฐ macOS์—์„œ๋Š” static + dynamic์ด ํ—ˆ์šฉ๋œ๋‹ค
  • https://newosxbook.com/xxr/index.php

ํ๋ฆ„

  1. ํ”„๋กœ์„ธ์Šค๊ฐ€ syscall/mach trap์„ ์ˆ˜ํ–‰ํ•œ๋‹ค
  2. ๊ด€๋ จ ํ•จ์ˆ˜๊ฐ€ kernel ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ๋œ๋‹ค
  3. ํ•จ์ˆ˜๊ฐ€ MACF๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค
  4. MACF๋Š” ํ•ด๋‹น ํ•จ์ˆ˜์— ํ›…์„ ์š”์ฒญํ•œ ์ •์ฑ… ๋ชจ๋“ˆ๋“ค์„ ํ™•์ธํ•œ๋‹ค
  5. MACF๊ฐ€ ๊ด€๋ จ ์ •์ฑ…๋“ค์„ ํ˜ธ์ถœํ•œ๋‹ค
  6. ์ •์ฑ…๋“ค์ด ํ•ด๋‹น ๋™์ž‘์„ ํ—ˆ์šฉํ• ์ง€ ๊ฑฐ๋ถ€ํ• ์ง€ ํ‘œ์‹œํ•œ๋‹ค

Caution

Apple๋งŒ MAC Framework KPI๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณดํ†ต MACF๋กœ ๊ถŒํ•œ์„ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜๋“ค์€ ๋งคํฌ๋กœ MAC_CHECK๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์†Œ์ผ“์„ ์ƒ์„ฑํ•˜๋Š” syscall์˜ ๊ฒฝ์šฐ mac_socket_check_create๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ์ด ํ•จ์ˆ˜๋Š” MAC_CHECK(socket_check_create, cred, domain, type, protocol);์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๋งคํฌ๋กœ MAC_CHECK๋Š” security/mac_internal.h์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

Resolver tambien MAC_POLICY_ITERATE, MAC_CHECK_CALL, MAC_CHECK_RSLT


#define MAC_CHECK(check, args...) do {                                   \
error = 0;                                                           \
MAC_POLICY_ITERATE({                                                 \
if (mpc->mpc_ops->mpo_ ## check != NULL) {                   \
MAC_CHECK_CALL(check, mpc);                          \
int __step_err = mpc->mpc_ops->mpo_ ## check (args); \
MAC_CHECK_RSLT(check, mpc);                          \
error = mac_error_select(__step_err, error);         \
}                                                            \
});                                                                  \
} while (0)

์ฐธ๊ณ ๋กœ check๋ฅผ socket_check_create๋กœ, args...๋ฅผ (cred, domain, type, protocol)๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด:

// Note the "##" just get the param name and append it to the prefix
#define MAC_CHECK(socket_check_create, args...) do {                                   \
error = 0;                                                           \
MAC_POLICY_ITERATE({                                                 \
if (mpc->mpc_ops->mpo_socket_check_create != NULL) {                   \
MAC_CHECK_CALL(socket_check_create, mpc);                          \
int __step_err = mpc->mpc_ops->mpo_socket_check_create (args); \
MAC_CHECK_RSLT(socket_check_create, mpc);                          \
error = mac_error_select(__step_err, error);         \
}                                                            \
});                                                                  \
} while (0)

๋„์šฐ๋ฏธ ๋งคํฌ๋กœ๋ฅผ ํ™•์žฅํ•˜๋ฉด ๊ตฌ์ฒด์ ์ธ ์ œ์–ด ํ๋ฆ„์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค:

do {                                                // MAC_CHECK
error = 0;
do {                                            // MAC_POLICY_ITERATE
struct mac_policy_conf *mpc;
u_int i;
for (i = 0; i < mac_policy_list.staticmax; i++) {
mpc = mac_policy_list.entries[i].mpc;
if (mpc == NULL) {
continue;
}
if (mpc->mpc_ops->mpo_socket_check_create != NULL) {
DTRACE_MACF3(mac__call__socket_check_create,
void *, mpc, int, error, int, MAC_ITERATE_CHECK); // MAC_CHECK_CALL
int __step_err = mpc->mpc_ops->mpo_socket_check_create(args);
DTRACE_MACF2(mac__rslt__socket_check_create,
void *, mpc, int, __step_err);                    // MAC_CHECK_RSLT
error = mac_error_select(__step_err, error);
}
}
if (mac_policy_list_conditional_busy() != 0) {
for (; i <= mac_policy_list.maxindex; i++) {
mpc = mac_policy_list.entries[i].mpc;
if (mpc == NULL) {
continue;
}
if (mpc->mpc_ops->mpo_socket_check_create != NULL) {
DTRACE_MACF3(mac__call__socket_check_create,
void *, mpc, int, error, int, MAC_ITERATE_CHECK);
int __step_err = mpc->mpc_ops->mpo_socket_check_create(args);
DTRACE_MACF2(mac__rslt__socket_check_create,
void *, mpc, int, __step_err);
error = mac_error_select(__step_err, error);
}
}
mac_policy_list_unbusy();
}
} while (0);
} while (0);

๋‹ค์‹œ ๋งํ•ด, MAC_CHECK(socket_check_create, ...)๋Š” ๋จผ์ € ์ •์  ์ •์ฑ…์„ ์ˆœํšŒํ•˜๊ณ , ์กฐ๊ฑด์ ์œผ๋กœ ์ž ๊ธˆ์„ ์„ค์ •ํ•˜์—ฌ ๋™์  ์ •์ฑ…์„ ๋ฐ˜๋ณตํ•˜๋ฉฐ, ๊ฐ hook ์ฃผ์œ„์— DTrace ํ”„๋กœ๋ธŒ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ , ๋ชจ๋“  hook์˜ ๋ฐ˜ํ™˜ ์ฝ”๋“œ๋ฅผ mac_error_select()๋ฅผ ํ†ตํ•ด ๋‹จ์ผ error ๊ฒฐ๊ณผ๋กœ ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

Labels

MACF๋Š” ์ •์ฑ…์ด ํŠน์ • ์ ‘๊ทผ์„ ํ—ˆ์šฉํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์‚ฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” labels๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. labels ๊ตฌ์กฐ์ฒด ์„ ์–ธ ์ฝ”๋“œ๋Š” found here, ์ด๋Š” here์˜ struct ucred ๋‚ด๋ถ€ cr_label ๋ถ€๋ถ„์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋ผ๋ฒจ์€ ํ”Œ๋ž˜๊ทธ์™€ ์ผ์ • ์ˆ˜์˜ slots๋ฅผ ํฌํ•จํ•˜๋ฉฐ, ์ด๋Š” MACF policies to allocate pointers๊ฐ€ ํฌ์ธํ„ฐ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Sanbox๋Š” ์ปจํ…Œ์ด๋„ˆ ํ”„๋กœํ•„์„ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค

MACF Policies

MACF Policy๋Š” ํŠน์ • ์ปค๋„ ์ž‘์—…์— ์ ์šฉ๋  ๊ทœ์น™๊ณผ ์กฐ๊ฑด์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

์ปค๋„ ํ™•์žฅ(kernel extension)์€ mac_policy_conf struct๋ฅผ ๊ตฌ์„ฑํ•œ ๋‹ค์Œ mac_policy_register๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. From here:

#define mpc_t	struct mac_policy_conf *

/**
@brief Mac policy configuration

This structure specifies the configuration information for a
MAC policy module.  A policy module developer must supply
a short unique policy name, a more descriptive full name, a list of label
namespaces and count, a pointer to the registered enty point operations,
any load time flags, and optionally, a pointer to a label slot identifier.

The Framework will update the runtime flags (mpc_runtime_flags) to
indicate that the module has been registered.

If the label slot identifier (mpc_field_off) is NULL, the Framework
will not provide label storage for the policy.  Otherwise, the
Framework will store the label location (slot) in this field.

The mpc_list field is used by the Framework and should not be
modified by policies.
*/
/* XXX - reorder these for better aligment on 64bit platforms */
struct mac_policy_conf {
const char		*mpc_name;		/** policy name */
const char		*mpc_fullname;		/** full name */
const char		**mpc_labelnames;	/** managed label namespaces */
unsigned int		 mpc_labelname_count;	/** number of managed label namespaces */
struct mac_policy_ops	*mpc_ops;		/** operation vector */
int			 mpc_loadtime_flags;	/** load time flags */
int			*mpc_field_off;		/** label slot */
int			 mpc_runtime_flags;	/** run time flags */
mpc_t			 mpc_list;		/** List reference */
void			*mpc_data;		/** module data */
};

์ด ์ •์ฑ…๋“ค์„ ๊ตฌ์„ฑํ•˜๋Š” ์ปค๋„ ์ต์Šคํ…์…˜์€ mac_policy_register ํ˜ธ์ถœ์„ ํ™•์ธํ•˜๋ฉด ์‰ฝ๊ฒŒ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ต์Šคํ…์…˜์˜ ๋””์Šค์–ด์…ˆ๋ธ”์„ ํ™•์ธํ•˜๋ฉด ์‚ฌ์šฉ๋œ mac_policy_conf ๊ตฌ์กฐ์ฒด๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

MACF ์ •์ฑ…์€ ๋™์ ์œผ๋กœ ๋“ฑ๋ก ๋ฐ ๋“ฑ๋ก ํ•ด์ œ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์— ์œ ์˜ํ•˜์„ธ์š”.

mac_policy_conf์˜ ์ฃผ์š” ํ•„๋“œ ์ค‘ ํ•˜๋‚˜๋Š” **mpc_ops**์ž…๋‹ˆ๋‹ค. ์ด ํ•„๋“œ๋Š” ์ •์ฑ…์ด ๊ด€์‹ฌ ์žˆ๋Š” ์—ฐ์‚ฐ๋“ค์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋ฐฑ ๊ฐœ์˜ ์—ฐ์‚ฐ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“  ํ•ญ๋ชฉ์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ ๋‹ค์Œ ์ •์ฑ…์ด ๊ด€์‹ฌ ์žˆ๋Š” ํ•ญ๋ชฉ๋งŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์—ฌ๊ธฐ:

struct mac_policy_ops {
mpo_audit_check_postselect_t		*mpo_audit_check_postselect;
mpo_audit_check_preselect_t		*mpo_audit_check_preselect;
mpo_bpfdesc_label_associate_t		*mpo_bpfdesc_label_associate;
mpo_bpfdesc_label_destroy_t		*mpo_bpfdesc_label_destroy;
mpo_bpfdesc_label_init_t		*mpo_bpfdesc_label_init;
mpo_bpfdesc_check_receive_t		*mpo_bpfdesc_check_receive;
mpo_cred_check_label_update_execve_t	*mpo_cred_check_label_update_execve;
mpo_cred_check_label_update_t		*mpo_cred_check_label_update;
[...]

๊ฑฐ์˜ ๋ชจ๋“  ํ›…์€ ํ•ด๋‹น ์ž‘์—…๋“ค ์ค‘ ํ•˜๋‚˜๊ฐ€ ๊ฐ€๋กœ์ฑ„์งˆ ๋•Œ MACF์— ์˜ํ•ด ์ฝœ๋ฐฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ mpo_policy_* ํ›…๋“ค์€ ์˜ˆ์™ธ์ธ๋ฐ, ์ด๋Š” mpo_hook_policy_init()๊ฐ€ ๋“ฑ๋ก ์‹œ(์ฆ‰ mac_policy_register() ์ดํ›„) ํ˜ธ์ถœ๋˜๋Š” ์ฝœ๋ฐฑ์ด๊ณ  mpo_hook_policy_initbsd()๋Š” BSD ์„œ๋ธŒ์‹œ์Šคํ…œ์ด ์ œ๋Œ€๋กœ ์ดˆ๊ธฐํ™”๋œ ํ›„ ๋Šฆ์€ ๋“ฑ๋ก ์‹œ์— ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ, mpo_policy_syscall ํ›…์€ ์–ด๋–ค kext๋“  private ioctl ์Šคํƒ€์ผ ํ˜ธ์ถœ interface๋ฅผ ๋…ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด user client๋Š” ์ •์ˆ˜ํ˜• code์™€ ์„ ํƒ์  arguments๋ฅผ ํฌํ•จํ•ด policy name์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ง€์ •ํ•˜์—ฌ mac_syscall (#381)์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด, **Sandbox.kext**๊ฐ€ ์ด๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

kext์˜ **__DATA.__const***๋ฅผ ํ™•์ธํ•˜๋ฉด ์ •์ฑ…์„ ๋“ฑ๋กํ•  ๋•Œ ์‚ฌ์šฉ๋œ mac_policy_ops ๊ตฌ์กฐ์ฒด๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ•ด๋‹น ํฌ์ธํ„ฐ๊ฐ€ mpo_policy_conf ๋‚ด๋ถ€์˜ ์˜คํ”„์…‹์— ์œ„์น˜ํ•ด ์žˆ๊ณ , ๊ทธ ์˜์—ญ์— ์กด์žฌํ•˜๋Š” NULL ํฌ์ธํ„ฐ์˜ ๊ฐœ์ˆ˜๋กœ๋„ ์ฐพ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ, ๋“ฑ๋ก๋œ ๊ฐ ์ •์ฑ…๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ๋˜๋Š” ๊ตฌ์กฐ์ฒด **_mac_policy_list**๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋คํ”„ํ•˜๋ฉด ์ •์ฑ…์„ ๊ตฌ์„ฑํ•œ kext๋“ค์˜ ๋ชฉ๋ก์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ์Šคํ…œ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ์ •์ฑ…์„ ๋คํ”„ํ•˜๋ ค๋ฉด ๋„๊ตฌ xnoop์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

xnoop offline .

Xn๐Ÿ‘€p> macp
mac_policy_list(@0xfffffff0447159b8): 3 Mac Policies@0xfffffff0447153f0
0: 0xfffffff044886f18:
mpc_name: AppleImage4
mpc_fullName: AppleImage4 hooks
mpc_ops: mac_policy_ops@0xfffffff044886f68
1: 0xfffffff0448d7d40:
mpc_name: AMFI
mpc_fullName: Apple Mobile File Integrity
mpc_ops: mac_policy_ops@0xfffffff0448d72c8
2: 0xfffffff044b0b950:
mpc_name: Sandbox
mpc_fullName: Seatbelt sandbox policy
mpc_ops: mac_policy_ops@0xfffffff044b0b9b0
Xn๐Ÿ‘€p> dump mac_policy_opns@0xfffffff0448d72c8
Type 'struct mac_policy_opns' is unrecognized - dumping as raw 64 bytes
Dumping 64 bytes from 0xfffffff0448d72c8

๊ทธ๋Ÿฐ ๋‹ค์Œ check policy์˜ ๋ชจ๋“  ์ฒดํฌ๋ฅผ ๋‹ค์Œ์œผ๋กœ ๋คํ”„ํ•ฉ๋‹ˆ๋‹ค:

Xn๐Ÿ‘€p> dump mac_policy_ops@0xfffffff044b0b9b0
Dumping 2696 bytes from 0xfffffff044b0b9b0 (as struct mac_policy_ops)

mpo_cred_check_label_update_execve(@0x30): 0xfffffff046d7fb54(PACed)
mpo_cred_check_label_update(@0x38): 0xfffffff046d7348c(PACed)
mpo_cred_label_associate(@0x58): 0xfffffff046d733f0(PACed)
mpo_cred_label_destroy(@0x68): 0xfffffff046d733e4(PACed)
mpo_cred_label_update_execve(@0x90): 0xfffffff046d7fb60(PACed)
mpo_cred_label_update(@0x98): 0xfffffff046d73370(PACed)
mpo_file_check_fcntl(@0xe8): 0xfffffff046d73164(PACed)
mpo_file_check_lock(@0x110): 0xfffffff046d7309c(PACed)
mpo_file_check_mmap(@0x120): 0xfffffff046d72fc4(PACed)
mpo_file_check_set(@0x130): 0xfffffff046d72f2c(PACed)
mpo_reserved08(@0x168): 0xfffffff046d72e3c(PACed)
mpo_reserved09(@0x170): 0xfffffff046d72e34(PACed)
mpo_necp_check_open(@0x1f0): 0xfffffff046d72d9c(PACed)
mpo_necp_check_client_action(@0x1f8): 0xfffffff046d72cf8(PACed)
mpo_vnode_notify_setextattr(@0x218): 0xfffffff046d72ca4(PACed)
mpo_vnode_notify_setflags(@0x220): 0xfffffff046d72c84(PACed)
mpo_proc_check_get_task_special_port(@0x250): 0xfffffff046d72b98(PACed)
mpo_proc_check_set_task_special_port(@0x258): 0xfffffff046d72ab4(PACed)
mpo_vnode_notify_unlink(@0x268): 0xfffffff046d72958(PACed)
mpo_vnode_check_copyfile(@0x290): 0xfffffff046d726c0(PACed)
mpo_mount_check_quotactl(@0x298): 0xfffffff046d725c4(PACed)
...

XNU์—์„œ์˜ MACF ์ดˆ๊ธฐํ™”

์ดˆ๊ธฐ ๋ถ€ํŠธ์ŠคํŠธ๋žฉ๊ณผ mac_policy_init()

  • MACF๋Š” ๋งค์šฐ ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. XNU ์‹œ์ž‘ ์ฝ”๋“œ์˜ bootstrap_thread์—์„œ ipc_bootstrap ์ดํ›„์— XNU๋Š” mac_policy_init()์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค(mac_base.c).
  • mac_policy_init()์€ ์ „์—ญ mac_policy_list(์ •์ฑ… ์Šฌ๋กฏ์˜ ๋ฐฐ์—ด ๋˜๋Š” ๋ฆฌ์ŠคํŠธ)๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  XNU ๋‚ด๋ถ€์—์„œ MAC(Mandatory Access Control) ์ธํ”„๋ผ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ์ดํ›„ mac_policy_initmach()์ด ํ˜ธ์ถœ๋˜์–ด ๋‚ด์žฅ๋˜๊ฑฐ๋‚˜ ๋ฒˆ๋“ค๋œ ์ •์ฑ…๋“ค์˜ ์ปค๋„ ์ธก ๋“ฑ๋ก์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

mac_policy_initmach()์™€ โ€œsecurity extensionsโ€ ๋กœ๋”ฉ

  • mac_policy_initmach()์€ ์‚ฌ์ „ ๋กœ๋“œ๋œ(๋˜๋Š” โ€œpolicy injectionโ€ ๋ฆฌ์ŠคํŠธ์— ์žˆ๋Š”) kernel extension(kext)์„ ๊ฒ€์‚ฌํ•˜๊ณ  ํ•ด๋‹น Info.plist์—์„œ AppleSecurityExtension ํ‚ค๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

  • Info.plist์— <key>AppleSecurityExtension</key>(๋˜๋Š” true)๋ฅผ ์„ ์–ธํ•œ kext๋“ค์€ โ€œ๋ณด์•ˆ ํ™•์žฅโ€์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค โ€” ์ฆ‰ MAC ์ •์ฑ…์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ MACF ์ธํ”„๋ผ์— ํ›…์„ ๊ฑฐ๋Š” ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค.

  • ๊ทธ ํ‚ค๋ฅผ ํฌํ•จํ•˜๋Š” Apple kext์˜ ์˜ˆ๋กœ๋Š” ALF.kext, AppleMobileFileIntegrity.kext (AMFI), Sandbox.kext, Quarantine.kext, TMSafetyNet.kext, CoreTrust.kext, AppleSystemPolicy.kext ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค(๋“ฑ๋“ฑ).

  • ์ปค๋„์€ ์ด๋Ÿฌํ•œ kext๋“ค์ด ์กฐ๊ธฐ์— ๋กœ๋“œ๋˜๋„๋ก ๋ณด์žฅํ•œ ๋’ค ๋ถ€ํŒ… ์ค‘์— ์ด๋“ค์˜ ๋“ฑ๋ก ๋ฃจํ‹ด์„ ํ˜ธ์ถœ(mac_policy_register๋ฅผ ํ†ตํ•ด)ํ•˜์—ฌ mac_policy_list์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ ์ •์ฑ… ๋ชจ๋“ˆ(kext)์€ ํ›…๋“ค(mpc_ops)์„ ํฌํ•จํ•œ mac_policy_conf ๊ตฌ์กฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์ด๋Š” ๋‹ค์–‘ํ•œ MAC ์ž‘์—…(vnode ๊ฒ€์‚ฌ, exec ๊ฒ€์‚ฌ, ๋ผ๋ฒจ ์—…๋ฐ์ดํŠธ ๋“ฑ)์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • ๋กœ๋“œ ์‹œ ํ”Œ๋ž˜๊ทธ์—๋Š” MPC_LOADTIME_FLAG_NOTLATE์™€ ๊ฐ™์ด โ€œ์กฐ๊ธฐ์— ๋กœ๋“œ๋˜์–ด์•ผ ํ•จโ€์„ ์˜๋ฏธํ•˜๋Š” ๊ฐ’์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ(๋”ฐ๋ผ์„œ ๋Šฆ์€ ๋“ฑ๋ก ์‹œ๋„๊ฐ€ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค)โ€ฆ

  • ๋“ฑ๋ก์ด ์™„๋ฃŒ๋˜๋ฉด ๊ฐ ๋ชจ๋“ˆ์€ ํ•ธ๋“ค์„ ๋ฐ›๊ณ  mac_policy_list์˜ ์Šฌ๋กฏ์„ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค.

  • ์ดํ›„ MAC ํ›…(์˜ˆ: vnode ์ ‘๊ทผ, exec ๋“ฑ)์ด ํ˜ธ์ถœ๋  ๋•Œ MACF๋Š” ๋“ฑ๋ก๋œ ๋ชจ๋“  ์ •์ฑ…์„ ์ˆœํšŒํ•˜์—ฌ ๊ณต๋™ ๊ฒฐ์ •์„ ๋‚ด๋ฆฝ๋‹ˆ๋‹ค.

  • ํŠนํžˆ AMFI(Apple Mobile File Integrity)๋Š” ์ด๋Ÿฌํ•œ ๋ณด์•ˆ ํ™•์žฅ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น kext์˜ Info.plist์—๋Š” ๋ณด์•ˆ ์ •์ฑ…์ž„์„ ํ‘œ์‹œํ•˜๋Š” AppleSecurityExtension ํ‚ค๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ปค๋„ ๋ถ€ํŒ…์˜ ์ผํ™˜์œผ๋กœ ์ปค๋„ ๋กœ๋“œ ๋กœ์ง์€ ๋งŽ์€ ์„œ๋ธŒ์‹œ์Šคํ…œ์ด ์˜์กดํ•˜๊ธฐ ์ „์— โ€œ๋ณด์•ˆ ์ •์ฑ…โ€(AMFI ๋“ฑ)์ด ์ด๋ฏธ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปค๋„์€ โ€œ์•ž์œผ๋กœ์˜ ์ž‘์—…์„ ์œ„ํ•ด AppleMobileFileIntegrity (AMFI), Sandbox, Quarantine ์ •์ฑ…์„ ํฌํ•จํ•œ โ€ฆ ๋ณด์•ˆ ์ •์ฑ…์„ ๋กœ๋“œํ•จ์œผ๋กœ์จ ์ค€๋น„ํ•œ๋‹คโ€๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

cd /System/Library/Extensions
find . -name Info.plist | xargs grep AppleSecurityExtension 2>/dev/null

./AppleImage4.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>
./ALF.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>
./CoreTrust.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>
./AppleMobileFileIntegrity.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>
./Quarantine.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>
./Sandbox.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>
./AppleSystemPolicy.kext/Contents/Info.plist:	<key>AppleSecurityExtension</key>

KPI ์ข…์†์„ฑ ๋ฐ MAC ์ •์ฑ… kext์—์„œ์˜ com.apple.kpi.dsep

MAC ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” kext๋ฅผ ์ž‘์„ฑํ•  ๋•Œ(์˜ˆ: mac_policy_register() ๋“ฑ ํ˜ธ์ถœ), kext ๋ง์ปค(kxld)๊ฐ€ ํ•ด๋‹น ์‹ฌ๋ณผ์„ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋„๋ก KPI(Kernel Programming Interfaces)์— ๋Œ€ํ•œ ์ข…์†์„ฑ์„ ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ kext๊ฐ€ MACF์— ์˜์กดํ•จ์„ ์„ ์–ธํ•˜๋ ค๋ฉด Info.plist์— com.apple.kpi.dsep๋ฅผ ๋ช…์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(find . Info.plist | grep AppleSecurityExtension). ๊ทธ๋Ÿฌ๋ฉด kext๋Š” mac_policy_register, mac_policy_unregister ๋ฐ MAC ํ›… ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์™€ ๊ฐ™์€ ์‹ฌ๋ณผ์„ ์ฐธ์กฐํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์‹ฌ๋ณผ์„ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด com.apple.kpi.dsep๋ฅผ ์ข…์†์„ฑ์œผ๋กœ ๋‚˜์—ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Example Info.plist snippet (inside your .kext):

<key>OSBundleLibraries</key>
<dict>
<key>com.apple.kpi.dsep</key>
<string>18.0</string>
<key>com.apple.kpi.libkern</key>
<string>18.0</string>
<key>com.apple.kpi.bsd</key>
<string>18.0</string>
<key>com.apple.kpi.mach</key>
<string>18.0</string>
โ€ฆ (other kpi dependencies as needed)
</dict>

MACF ํ˜ธ์ถœ

์ฝ”๋“œ์—์„œ #if CONFIG_MAC ๊ฐ™์€ ์กฐ๊ฑด ๋ธ”๋ก ์•ˆ์— MACF์— ๋Œ€ํ•œ ํ˜ธ์ถœ์ด ์ •์˜๋œ ๊ฒƒ์„ ํ”ํžˆ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ด๋Ÿฌํ•œ ๋ธ”๋ก ๋‚ด๋ถ€์—์„œ๋Š” ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๊ถŒํ•œ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด MACF๋ฅผ ํ˜ธ์ถœํ•˜๋Š” mac_proc_check* ๊ฐ™์€ ํ˜ธ์ถœ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. MACF ํ˜ธ์ถœ์˜ ํ˜•์‹์€ ๋ณดํ†ต mac_<object>_<opType>_opName ์ž…๋‹ˆ๋‹ค.

๊ฐ์ฒด(object)๋Š” ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค: bpfdesc, cred, file, proc, vnode, mount, devfs, ifnet, inpcb, mbuf, ipq, pipe, sysv[msg/msq/shm/sem], posix[shm/sem], socket, kext.
opType์€ ๋ณดํ†ต ์ž‘์—…์„ ํ—ˆ์šฉํ•˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” check ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฃผ์–ด์ง„ ๋™์ž‘์— ๋Œ€ํ•ด kext๊ฐ€ ๋ฐ˜์‘ํ•˜๋„๋ก ํ—ˆ์šฉํ•˜๋Š” notify๋ฅผ ์ฐพ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

You can find an example in https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/bsd/kern/kern_mman.c#L621:

int
mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval)
{
[...]
#if CONFIG_MACF
			error = mac_file_check_mmap(vfs_context_ucred(ctx),
			    fp->fp_glob, prot, flags, file_pos + pageoff,
&maxprot);
if (error) {
(void)vnode_put(vp);
goto bad;
}
#endif /* MAC */
[...]

๊ทธ ๋‹ค์Œ mac_file_check_mmap์˜ ์ฝ”๋“œ๋Š” https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_file.c#L174์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

mac_file_check_mmap(struct ucred *cred, struct fileglob *fg, int prot,
int flags, uint64_t offset, int *maxprot)
{
int error;
int maxp;

maxp = *maxprot;
MAC_CHECK(file_check_mmap, cred, fg, NULL, prot, flags, offset, &maxp);
if ((maxp | *maxprot) != *maxprot) {
panic("file_check_mmap increased max protections");
}
*maxprot = maxp;
return error;
}

์ด๋Š” MAC_CHECK ๋งคํฌ๋กœ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ, ํ•ด๋‹น ์ฝ”๋“œ๋Š” https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/security/mac_internal.h#L261์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

/*
* MAC_CHECK performs the designated check by walking the policy
* module list and checking with each as to how it feels about the
* request.  Note that it returns its value via 'error' in the scope
* of the caller.
*/
#define MAC_CHECK(check, args...) do {                              \
error = 0;                                                      \
MAC_POLICY_ITERATE({                                            \
if (mpc->mpc_ops->mpo_ ## check != NULL) {              \
DTRACE_MACF3(mac__call__ ## check, void *, mpc, int, error, int, MAC_ITERATE_CHECK); \
int __step_err = mpc->mpc_ops->mpo_ ## check (args); \
DTRACE_MACF2(mac__rslt__ ## check, void *, mpc, int, __step_err); \
error = mac_error_select(__step_err, error);         \
}                                                           \
});                                                             \
} while (0)

์ด ๋งคํฌ๋กœ๋Š” ๋“ฑ๋ก๋œ ๋ชจ๋“  mac ์ •์ฑ…์„ ์ˆœํšŒํ•˜๋ฉด์„œ ๊ฐ ์ •์ฑ…์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ทธ ์ถœ๋ ฅ์„ error ๋ณ€์ˆ˜์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด error ๊ฐ’์€ ์„ฑ๊ณต ์ฝ”๋“œ์— ์˜ํ•ด mac_error_select๋กœ๋งŒ ์žฌ์ •์˜๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์–ด๋–ค ๊ฒ€์‚ฌ๋ผ๋„ ์‹คํŒจํ•˜๋ฉด ์ „์ฒด ๊ฒ€์‚ฌ๊ฐ€ ์‹คํŒจํ•˜๊ณ  ํ•ด๋‹น ์ž‘์—…์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Tip

ํ•˜์ง€๋งŒ ๋ชจ๋“  MACF ์ฝœ์•„์›ƒ์ด ๋™์ž‘์„ ๊ฑฐ๋ถ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, mac_priv_grant๋Š” ๋งคํฌ๋กœ MAC_GRANT๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ, ์ด ๋งคํฌ๋กœ๋Š” ์–ด๋–ค ์ •์ฑ…์ด๋ผ๋„ 0์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์š”์ฒญ๋œ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค:

/*
* MAC_GRANT performs the designated check by walking the policy
* module list and checking with each as to how it feels about the
* request.  Unlike MAC_CHECK, it grants if any policies return '0',
* and otherwise returns EPERM.  Note that it returns its value via
* 'error' in the scope of the caller.
*/
#define MAC_GRANT(check, args...) do {                              \
   error = EPERM;                                                  \
   MAC_POLICY_ITERATE({                                            \
	if (mpc->mpc_ops->mpo_ ## check != NULL) {                  \
	        DTRACE_MACF3(mac__call__ ## check, void *, mpc, int, error, int, MAC_ITERATE_GRANT); \
	        int __step_res = mpc->mpc_ops->mpo_ ## check (args); \
	        if (__step_res == 0) {                              \
	                error = 0;                                  \
	        }                                                   \
	        DTRACE_MACF2(mac__rslt__ ## check, void *, mpc, int, __step_res); \
	    }                                                           \
   });                                                             \
} while (0)

priv_check & priv_grant

These callas are meant to check and provide (tens of) ๊ถŒํ•œ defined in bsd/sys/priv.h.
์ผ๋ถ€ ์ปค๋„ ์ฝ”๋“œ๋Š” ํ”„๋กœ์„ธ์Šค์˜ KAuth ์ž๊ฒฉ์ฆ๋ช…๊ณผ ๊ถŒํ•œ ์ฝ”๋“œ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ฐ€์ง€๊ณ  bsd/kern/kern_priv.c์˜ priv_check_cred()๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด ํ˜ธ์ถœ์€ mac_priv_check๋ฅผ ํ˜ธ์ถœํ•ด ์–ด๋–ค ์ •์ฑ…์ด ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ๊ฑฐ๋ถ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๊ทธ ๋‹ค์Œ mac_priv_grant๋ฅผ ํ˜ธ์ถœํ•ด ์–ด๋–ค ์ •์ฑ…์ด ํ•ด๋‹น privilege๋ฅผ ๋ถ€์—ฌํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

proc_check_syscall_unix

This hook allows to intercept all system calls. In bsd/dev/[i386|arm]/systemcalls.c itโ€™s possible to see the declared function unix_syscall, which contains this code:

#if CONFIG_MACF
if (__improbable(proc_syscall_filter_mask(proc) != NULL && !bitstr_test(proc_syscall_filter_mask(proc), syscode))) {
error = mac_proc_check_syscall_unix(proc, syscode);
if (error) {
goto skip_syscall;
}
}
#endif /* CONFIG_MACF */

์ด๋Š” ํ˜ธ์ถœ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค์˜ bitmask์—์„œ ํ˜„์žฌ syscall์ด mac_proc_check_syscall_unix๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•œ๋‹ค. syscalls๋Š” ๋งค์šฐ ์ž์ฃผ ํ˜ธ์ถœ๋˜๋ฏ€๋กœ ๋งค๋ฒˆ mac_proc_check_syscall_unix๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ํ”ผํ•˜๋Š” ๊ฒƒ์ด ์œ ๋ฆฌํ•˜๋‹ค.

์ฐธ๊ณ ๋กœ ํ”„๋กœ์„ธ์Šค์˜ bitmask syscalls๋ฅผ ์„ค์ •ํ•˜๋Š” ํ•จ์ˆ˜ proc_set_syscall_filter_mask()๋Š” Sandbox๊ฐ€ sandboxed processes์˜ ๋งˆ์Šคํฌ๋ฅผ ์„ค์ •ํ•  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.

๋…ธ์ถœ๋œ MACF syscalls

์ผ๋ถ€ syscalls๋ฅผ ํ†ตํ•ด MACF์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” security/mac.h์— ์ •์˜๋˜์–ด ์žˆ๋‹ค:

/*
* Extended non-POSIX.1e interfaces that offer additional services
* available from the userland and kernel MAC frameworks.
*/
#ifdef __APPLE_API_PRIVATE
__BEGIN_DECLS
int      __mac_execve(char *fname, char **argv, char **envv, mac_t _label);
int      __mac_get_fd(int _fd, mac_t _label);
int      __mac_get_file(const char *_path, mac_t _label);
int      __mac_get_link(const char *_path, mac_t _label);
int      __mac_get_pid(pid_t _pid, mac_t _label);
int      __mac_get_proc(mac_t _label);
int      __mac_set_fd(int _fildes, const mac_t _label);
int      __mac_set_file(const char *_path, mac_t _label);
int      __mac_set_link(const char *_path, mac_t _label);
int      __mac_mount(const char *type, const char *path, int flags, void *data,
struct mac *label);
int      __mac_get_mount(const char *path, struct mac *label);
int      __mac_set_proc(const mac_t _label);
int      __mac_syscall(const char *_policyname, int _call, void *_arg);
__END_DECLS
#endif /*__APPLE_API_PRIVATE*/

์ฐธ๊ณ  ์ž๋ฃŒ

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 ์ง€์›ํ•˜๊ธฐ