macOS XPC

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 μ§€μ›ν•˜κΈ°

κΈ°λ³Έ 정보

XPCλŠ” macOSμ—μ„œ μ‚¬μš©ν•˜λŠ” 컀널인 XNU의 ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신을 μ˜λ―Έν•˜λ©°, macOS와 iOSμ—μ„œ ν”„λ‘œμ„ΈμŠ€ κ°„μ˜ 톡신을 μœ„ν•œ ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€. XPCλŠ” μ‹œμŠ€ν…œμ˜ μ„œλ‘œ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€ 간에 μ•ˆμ „ν•˜κ³  비동기적인 λ©”μ„œλ“œ ν˜ΈμΆœμ„ μˆ˜ν–‰ν•˜λŠ” λ©”μ»€λ‹ˆμ¦˜μ„ μ œκ³΅ν•©λ‹ˆλ‹€. μ΄λŠ” Apple의 λ³΄μ•ˆ νŒ¨λŸ¬λ‹€μž„μ˜ μΌλΆ€λ‘œ, 각 ꡬ성 μš”μ†Œκ°€ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ κΆŒν•œλ§ŒμœΌλ‘œ μ‹€ν–‰λ˜λŠ” κΆŒν•œ 뢄리 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 생성을 κ°€λŠ₯ν•˜κ²Œ ν•˜μ—¬, μ†μƒλœ ν”„λ‘œμ„ΈμŠ€λ‘œ μΈν•œ 잠재적 ν”Όν•΄λ₯Ό μ œν•œν•©λ‹ˆλ‹€.

XPCλŠ” λ™μΌν•œ μ‹œμŠ€ν…œμ—μ„œ μ‹€ν–‰λ˜λŠ” λ‹€μ–‘ν•œ ν”„λ‘œκ·Έλž¨μ΄ 데이터λ₯Ό μ£Όκ³ λ°›κΈ° μœ„ν•œ 일련의 방법인 ν”„λ‘œμ„ΈμŠ€ κ°„ 톡신(IPC)의 ν•œ ν˜•νƒœλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

XPC의 μ£Όμš” 이점은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  1. λ³΄μ•ˆ: μž‘μ—…μ„ μ„œλ‘œ λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€λ‘œ λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ 각 ν”„λ‘œμ„ΈμŠ€λŠ” ν•„μš”ν•œ κΆŒν•œλ§Œ 뢀여받을 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ μ†μƒλ˜λ”λΌλ„ ν”Όν•΄λ₯Ό 쀄일 수 μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.
  2. μ•ˆμ •μ„±: XPCλŠ” 좩돌이 λ°œμƒν•œ ꡬ성 μš”μ†Œλ‘œ μΆ©λŒμ„ κ²©λ¦¬ν•˜λŠ” 데 도움을 μ€λ‹ˆλ‹€. ν”„λ‘œμ„ΈμŠ€κ°€ μΆ©λŒν•˜λ©΄ μ‹œμŠ€ν…œμ˜ λ‚˜λ¨Έμ§€ 뢀뢄에 영ν–₯을 μ£Όμ§€ μ•Šκ³  μž¬μ‹œμž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. μ„±λŠ₯: XPCλŠ” μ„œλ‘œ λ‹€λ₯Έ μž‘μ—…μ„ λ™μ‹œμ— λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ‹€ν–‰ν•  수 μžˆλ„λ‘ ν•˜μ—¬ μ‰½κ²Œ λ™μ‹œμ„±μ„ ν—ˆμš©ν•©λ‹ˆλ‹€.

μœ μΌν•œ 단점은 μ—¬λŸ¬ ν”„λ‘œμ„ΈμŠ€μ—μ„œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λΆ„λ¦¬ν•˜κ³  XPCλ₯Ό 톡해 ν†΅μ‹ ν•˜κ²Œ ν•˜λŠ” 것이 νš¨μœ¨μ„±μ΄ λ–¨μ–΄μ§„λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ˜€λŠ˜λ‚ μ˜ μ‹œμŠ€ν…œμ—μ„œλŠ” 거의 λˆˆμ— 띄지 μ•ŠμœΌλ©° 이점이 더 ν½λ‹ˆλ‹€.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜ νŠΉμ • XPC μ„œλΉ„μŠ€

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ XPC ꡬ성 μš”μ†ŒλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 자체 내뢀에 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, Safariμ—μ„œλŠ” **/Applications/Safari.app/Contents/XPCServices**μ—μ„œ 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. 이듀은 .xpc ν™•μž₯자λ₯Ό κ°€μ§€λ©°(예: com.apple.Safari.SandboxBroker.xpc) μ£Όμš” λ°”μ΄λ„ˆλ¦¬μ™€ ν•¨κ»˜ λ²ˆλ“€λ‘œ μ œκ³΅λ©λ‹ˆλ‹€: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/MacOS/com.apple.Safari.SandboxBroker 및 Info.plist: /Applications/Safari.app/Contents/XPCServices/com.apple.Safari.SandboxBroker.xpc/Contents/Info.plist

당신이 생각할 수 μžˆλ“―μ΄, XPC ꡬ성 μš”μ†ŒλŠ” λ‹€λ₯Έ XPC ꡬ성 μš”μ†Œλ‚˜ μ£Όμš” μ•± λ°”μ΄λ„ˆλ¦¬μ™€ λ‹€λ₯Έ κΆŒν•œκ³Ό νŠΉκΆŒμ„ κ°€μ§ˆ κ²ƒμž…λ‹ˆλ‹€. 단, XPC μ„œλΉ„μŠ€κ°€ Info.plist νŒŒμΌμ—μ„œ JoinExistingSession을 β€œTrueβ€λ‘œ μ„€μ •ν•˜μ—¬ κ΅¬μ„±λœ 경우λ₯Ό μ œμ™Έν•©λ‹ˆλ‹€. 이 경우, XPC μ„œλΉ„μŠ€λŠ” ν˜ΈμΆœν•œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜κ³Ό 같은 λ³΄μ•ˆ μ„Έμ…˜μ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€.

XPC μ„œλΉ„μŠ€λŠ” ν•„μš”ν•  λ•Œ launchd에 μ˜ν•΄ μ‹œμž‘λ˜λ©°, λͺ¨λ“  μž‘μ—…μ΄ μ™„λ£Œλ˜λ©΄ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό ν•΄μ œν•˜κΈ° μœ„ν•΄ μ’…λ£Œλ©λ‹ˆλ‹€. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ νŠΉμ • XPC ꡬ성 μš”μ†ŒλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— μ˜ν•΄μ„œλ§Œ μ‚¬μš©λ  수 μžˆμ–΄ 잠재적인 μ·¨μ•½μ„±κ³Ό κ΄€λ ¨λœ μœ„ν—˜μ„ μ€„μž…λ‹ˆλ‹€.

μ‹œμŠ€ν…œ 전체 XPC μ„œλΉ„μŠ€

μ‹œμŠ€ν…œ 전체 XPC μ„œλΉ„μŠ€λŠ” λͺ¨λ“  μ‚¬μš©μžκ°€ μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ„œλΉ„μŠ€λŠ” launchd λ˜λŠ” Mach μœ ν˜•μœΌλ‘œ, /System/Library/LaunchDaemons, /Library/LaunchDaemons, /System/Library/LaunchAgents, λ˜λŠ” **/Library/LaunchAgents**와 같은 μ§€μ •λœ 디렉토리에 μœ„μΉ˜ν•œ plist νŒŒμΌμ— μ •μ˜λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

이 plist νŒŒμΌμ—λŠ” μ„œλΉ„μŠ€ 이름을 κ°€μ§„ **MachServices**λΌλŠ” 킀와 λ°”μ΄λ„ˆλ¦¬ 경둜λ₯Ό κ°€μ§„ **Program**μ΄λΌλŠ” ν‚€κ°€ ν¬ν•¨λ©λ‹ˆλ‹€:

cat /Library/LaunchDaemons/com.jamf.management.daemon.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Program</key>
<string>/Library/Application Support/JAMF/Jamf.app/Contents/MacOS/JamfDaemon.app/Contents/MacOS/JamfDaemon</string>
<key>AbandonProcessGroup</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>com.jamf.management.daemon</string>
<key>MachServices</key>
<dict>
<key>com.jamf.management.daemon.aad</key>
<true/>
<key>com.jamf.management.daemon.agent</key>
<true/>
<key>com.jamf.management.daemon.binary</key>
<true/>
<key>com.jamf.management.daemon.selfservice</key>
<true/>
<key>com.jamf.management.daemon.service</key>
<true/>
</dict>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

**LaunchDameons**에 μžˆλŠ” 것듀은 root에 μ˜ν•΄ μ‹€ν–‰λ©λ‹ˆλ‹€. λ”°λΌμ„œ κΆŒν•œμ΄ μ—†λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ 이듀 쀑 ν•˜λ‚˜μ™€ 톡신할 수 μžˆλ‹€λ©΄ κΆŒν•œ μƒμŠΉμ΄ κ°€λŠ₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

XPC 객체

  • xpc_object_t

λͺ¨λ“  XPC λ©”μ‹œμ§€λŠ” 직렬화 및 역직렬화λ₯Ό λ‹¨μˆœν™”ν•˜λŠ” 사전 κ°μ²΄μž…λ‹ˆλ‹€. κ²Œλ‹€κ°€, libxpc.dylibλŠ” λŒ€λΆ€λΆ„μ˜ 데이터 μœ ν˜•μ„ μ„ μ–Έν•˜λ―€λ‘œ μˆ˜μ‹ λœ 데이터가 μ˜ˆμƒλœ μœ ν˜•μΈμ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. C APIμ—μ„œ λͺ¨λ“  κ°μ²΄λŠ” xpc_object_t이며(κ·Έ μœ ν˜•μ€ xpc_get_type(object)λ₯Ό μ‚¬μš©ν•˜μ—¬ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€).
λ˜ν•œ, xpc_copy_description(object) ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 디버깅 λͺ©μ μœΌλ‘œ μœ μš©ν•  수 μžˆλŠ” 객체의 λ¬Έμžμ—΄ ν‘œν˜„μ„ 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.
이 객체듀은 xpc_<object>_copy, xpc_<object>_equal, xpc_<object>_hash, xpc_<object>_serialize, xpc_<object>_deserialize와 같은 ν˜ΈμΆœν•  수 μžˆλŠ” λͺ‡ κ°€μ§€ λ©”μ„œλ“œλ₯Ό κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€β€¦

xpc_object_tλŠ” xpc_<objetType>_create ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ μƒμ„±λ˜λ©°, 이 ν•¨μˆ˜λŠ” λ‚΄λΆ€μ μœΌλ‘œ _xpc_base_create(Class, Size)λ₯Ό ν˜ΈμΆœν•˜μ—¬ 객체의 클래슀 μœ ν˜•(ν•˜λ‚˜μ˜ XPC_TYPE_*)κ³Ό 크기(메타데이터λ₯Ό μœ„ν•΄ μΆ”κ°€λ‘œ 40Bκ°€ 크기에 좔가됨)λ₯Ό μ§€μ •ν•©λ‹ˆλ‹€. μ΄λŠ” 객체의 데이터가 40B μ˜€ν”„μ…‹μ—μ„œ μ‹œμž‘λ¨μ„ μ˜λ―Έν•©λ‹ˆλ‹€.
λ”°λΌμ„œ xpc_<objectType>_tλŠ” xpc_object_t의 ν•˜μœ„ ν΄λž˜μŠ€μ™€ 같은 것이며, μ΄λŠ” os_object_t*의 ν•˜μœ„ ν΄λž˜μŠ€κ°€ λ©λ‹ˆλ‹€.

Warning

xpc_dictionary_[get/set]_<objectType>λ₯Ό μ‚¬μš©ν•˜μ—¬ ν‚€μ˜ μœ ν˜•κ³Ό μ‹€μ œ 값을 κ°€μ Έμ˜€κ±°λ‚˜ μ„€μ •ν•˜λŠ” 것은 κ°œλ°œμžμ—¬μ•Ό ν•œλ‹€λŠ” 점에 μœ μ˜ν•˜μ‹­μ‹œμ˜€.

  • xpc_pipe

**xpc_pipe**λŠ” ν”„λ‘œμ„ΈμŠ€κ°€ ν†΅μ‹ ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆλŠ” FIFO νŒŒμ΄ν”„μž…λ‹ˆλ‹€(톡신은 Mach λ©”μ‹œμ§€λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€).
νŠΉμ • Mach 포트λ₯Ό μ‚¬μš©ν•˜μ—¬ XPC μ„œλ²„λ₯Ό μƒμ„±ν•˜λ €λ©΄ xpc_pipe_create() λ˜λŠ” xpc_pipe_create_from_port()λ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ λ©”μ‹œμ§€λ₯Ό μˆ˜μ‹ ν•˜λ €λ©΄ xpc_pipe_receive 및 xpc_pipe_try_receiveλ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.

xpc_pipe κ°μ²΄λŠ” 두 개의 Mach ν¬νŠΈμ™€ 이름(μžˆλŠ” 경우)에 λŒ€ν•œ 정보가 ν¬ν•¨λœ **xpc_object_t**μž…λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, plist /System/Library/LaunchDaemons/com.apple.secinitd.plist에 μžˆλŠ” 데λͺ¬ secinitdλŠ” com.apple.secinitdλΌλŠ” νŒŒμ΄ν”„λ₯Ό κ΅¬μ„±ν•©λ‹ˆλ‹€.

**xpc_pipe**의 μ˜ˆλŠ” **launchd**에 μ˜ν•΄ μƒμ„±λœ bootstrap pipe둜, Mach 포트λ₯Ό κ³΅μœ ν•  수 있게 ν•©λ‹ˆλ‹€.

  • NSXPC*

이듀은 XPC μ—°κ²°μ˜ 좔상을 ν—ˆμš©ν•˜λŠ” Objective-C κ³ κΈ‰ κ°μ²΄μž…λ‹ˆλ‹€.
λ˜ν•œ, μ΄λŸ¬ν•œ κ°μ²΄λŠ” 이전 객체듀보닀 DTrace둜 λ””λ²„κΉ…ν•˜κΈ°κ°€ 더 μ‰½μŠ΅λ‹ˆλ‹€.

  • GCD Queues

XPCλŠ” λ©”μ‹œμ§€λ₯Ό μ „λ‹¬ν•˜κΈ° μœ„ν•΄ GCDλ₯Ό μ‚¬μš©ν•˜λ©°, xpc.transactionq, xpc.io, xpc-events.add-listenerq, xpc.service-instance와 같은 νŠΉμ • λ””μŠ€νŒ¨μΉ˜ 큐λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€β€¦

XPC μ„œλΉ„μŠ€

이듀은 λ‹€λ₯Έ ν”„λ‘œμ νŠΈμ˜ XPCServices 폴더에 μœ„μΉ˜ν•œ .xpc ν™•μž₯자λ₯Ό κ°€μ§„ λ²ˆλ“€μž…λ‹ˆλ‹€. Info.plistμ—μ„œ CFBundlePackageType이 **XPC!**둜 μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
이 νŒŒμΌμ—λŠ” Application, User, System λ˜λŠ” _SandboxProfileκ³Ό 같은 λ‹€λ₯Έ ꡬ성 ν‚€κ°€ 있으며, μ΄λŠ” μƒŒλ“œλ°•μŠ€λ₯Ό μ •μ˜ν•˜κ±°λ‚˜ _AllowedClientsλŠ” μ„œλΉ„μŠ€μ— μ—°λ½ν•˜λŠ” 데 ν•„μš”ν•œ κΆŒν•œ λ˜λŠ” IDλ₯Ό λ‚˜νƒ€λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ ꡬ성 μ˜΅μ…˜μ€ μ„œλΉ„μŠ€κ°€ μ‹œμž‘λ  λ•Œ μœ μš©ν•©λ‹ˆλ‹€.

μ„œλΉ„μŠ€ μ‹œμž‘ν•˜κΈ°

앱은 xpc_connection_create_mach_serviceλ₯Ό μ‚¬μš©ν•˜μ—¬ XPC μ„œλΉ„μŠ€μ— 연결을 μ‹œλ„ν•˜λ©°, 그런 λ‹€μŒ launchdλŠ” 데λͺ¬μ„ μ°Ύκ³  **xpcproxy**λ₯Ό μ‹œμž‘ν•©λ‹ˆλ‹€. **xpcproxy**λŠ” κ΅¬μ„±λœ μ œν•œμ„ μ‹œν–‰ν•˜κ³  제곡된 FD 및 Mach 포트둜 μ„œλΉ„μŠ€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

XPC μ„œλΉ„μŠ€ 검색 속도λ₯Ό κ°œμ„ ν•˜κΈ° μœ„ν•΄ μΊμ‹œκ°€ μ‚¬μš©λ©λ‹ˆλ‹€.

xpcproxy의 μž‘μ—…μ„ 좔적할 수 μžˆμŠ΅λ‹ˆλ‹€:

supraudit S -C -o /tmp/output /dev/auditpipe

XPC λΌμ΄λΈŒλŸ¬λ¦¬λŠ” kdebugλ₯Ό μ‚¬μš©ν•˜μ—¬ xpc_ktrace_pid0 및 xpc_ktrace_pid1λ₯Ό ν˜ΈμΆœν•˜λŠ” μž‘μ—…μ„ κΈ°λ‘ν•©λ‹ˆλ‹€. μ‚¬μš©λ˜λŠ” μ½”λ“œλŠ” λ¬Έμ„œν™”λ˜μ–΄ μžˆμ§€ μ•ŠμœΌλ―€λ‘œ /usr/share/misc/trace.codes에 μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€. 이듀은 0x29 접두사λ₯Ό κ°€μ§€λ©°, 예λ₯Ό λ“€μ–΄ ν•˜λ‚˜λŠ” 0x29000004: XPC_serializer_packμž…λ‹ˆλ‹€.
μœ ν‹Έλ¦¬ν‹° xpcproxyλŠ” 0x22 접두사λ₯Ό μ‚¬μš©ν•˜λ©°, 예λ₯Ό λ“€μ–΄: 0x2200001c: xpcproxy:will_do_preexec.

XPC 이벀트 λ©”μ‹œμ§€

μ‘μš© ν”„λ‘œκ·Έλž¨μ€ λ‹€μ–‘ν•œ 이벀트 λ©”μ‹œμ§€μ— ꡬ독할 수 있으며, μ΄λŸ¬ν•œ μ΄λ²€νŠΈκ°€ λ°œμƒν•  λ•Œ μš”μ²­μ— 따라 μ‹œμž‘λ  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ„œλΉ„μŠ€μ˜ 섀정은 이전과 λ™μΌν•œ 디렉토리에 μœ„μΉ˜ν•œ launchd plist νŒŒμΌμ—μ„œ 이루어지며, μΆ”κ°€ LaunchEvent ν‚€λ₯Ό ν¬ν•¨ν•©λ‹ˆλ‹€.

XPC μ—°κ²° ν”„λ‘œμ„ΈμŠ€ 확인

ν”„λ‘œμ„ΈμŠ€κ°€ XPC 연결을 톡해 λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λ €κ³  ν•  λ•Œ, XPC μ„œλΉ„μŠ€λŠ” ν•΄λ‹Ή ν”„λ‘œμ„ΈμŠ€κ°€ μ—°κ²°ν•  수 μžˆλŠ”μ§€ 확인해야 ν•©λ‹ˆλ‹€. 이λ₯Ό ν™•μΈν•˜λŠ” 일반적인 방법과 일반적인 함정은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

macOS XPC Connecting Process Check

XPC κΆŒν•œ λΆ€μ—¬

Apple은 λ˜ν•œ 앱이 일뢀 κΆŒν•œμ„ κ΅¬μ„±ν•˜κ³  이λ₯Ό μ–»λŠ” 방법을 μ„€μ •ν•  수 μžˆλ„λ‘ ν—ˆμš©ν•˜λ―€λ‘œ, 호좜 ν”„λ‘œμ„ΈμŠ€κ°€ 이λ₯Ό κ°€μ§€κ³  μžˆλ‹€λ©΄ XPC μ„œλΉ„μŠ€μ˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆλ„λ‘ ν—ˆμš©λ©λ‹ˆλ‹€:

macOS XPC Authorization

XPC μŠ€λ‹ˆνΌ

XPC λ©”μ‹œμ§€λ₯Ό μŠ€λ‹ˆν•‘ν•˜λ €λ©΄ xpcspyλ₯Ό μ‚¬μš©ν•  수 있으며, μ΄λŠ” Fridaλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

# Install
pip3 install xpcspy
pip3 install xpcspy --no-deps # To not make xpcspy install Frida 15 and downgrade your Frida installation

# Start sniffing
xpcspy -U -r -W <bundle-id>
## Using filters (i: for input, o: for output)
xpcspy -U <prog-name> -t 'i:com.apple.*' -t 'o:com.apple.*' -r

또 λ‹€λ₯Έ κ°€λŠ₯ν•œ λ„κ΅¬λŠ” XPoCe2μž…λ‹ˆλ‹€.

XPC 톡신 C μ½”λ“œ 예제

// gcc xpc_server.c -o xpc_server

#include <xpc/xpc.h>

static void handle_event(xpc_object_t event) {
if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
// Print received message
const char* received_message = xpc_dictionary_get_string(event, "message");
printf("Received message: %s\n", received_message);

// Create a response dictionary
xpc_object_t response = xpc_dictionary_create(NULL, NULL, 0);
xpc_dictionary_set_string(response, "received", "received");

// Send response
xpc_connection_t remote = xpc_dictionary_get_remote_connection(event);
xpc_connection_send_message(remote, response);

// Clean up
xpc_release(response);
}
}

static void handle_connection(xpc_connection_t connection) {
xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
handle_event(event);
});
xpc_connection_resume(connection);
}

int main(int argc, const char *argv[]) {
xpc_connection_t service = xpc_connection_create_mach_service("xyz.hacktricks.service",
dispatch_get_main_queue(),
XPC_CONNECTION_MACH_SERVICE_LISTENER);
if (!service) {
fprintf(stderr, "Failed to create service.\n");
exit(EXIT_FAILURE);
}

xpc_connection_set_event_handler(service, ^(xpc_object_t event) {
xpc_type_t type = xpc_get_type(event);
if (type == XPC_TYPE_CONNECTION) {
handle_connection(event);
}
});

xpc_connection_resume(service);
dispatch_main();

return 0;
}
```bash # Compile the server & client gcc xpc_server.c -o xpc_server gcc xpc_client.c -o xpc_client

Save server on it’s location

cp xpc_server /tmp

Load daemon

sudo cp xyz.hacktricks.service.plist /Library/LaunchDaemons sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.service.plist

Call client

./xpc_client

Clean

sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.service.plist sudo rm /Library/LaunchDaemons/xyz.hacktricks.service.plist /tmp/xpc_server

## XPC 톡신 Objective-C μ½”λ“œ 예제

<div class="mdbook-tabs-container">
<nav class="mdbook-tabs">
<button class="mdbook-tab active" data-tabname="oc_xpc_server.m">oc_xpc_server.m</button>
<button class="mdbook-tab" data-tabname="oc_xpc_client.m">oc_xpc_client.m</button>
<button class="mdbook-tab" data-tabname="xyz.hacktricks.svcoc.plist">xyz.hacktricks.svcoc.plist</button>
</nav>
<div class="mdbook-tab-content" data-tabname="oc_xpc_server.m">

```objectivec
// gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server
#include <Foundation/Foundation.h>

@protocol MyXPCProtocol
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply;
@end

@interface MyXPCObject : NSObject <MyXPCProtocol>
@end


@implementation MyXPCObject
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply {
NSLog(@"Received message: %@", some_string);
NSString *response = @"Received";
reply(response);
}
@end

@interface MyDelegate : NSObject <NSXPCListenerDelegate>
@end


@implementation MyDelegate

- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)];

MyXPCObject *my_object = [MyXPCObject new];

newConnection.exportedObject = my_object;

[newConnection resume];
return YES;
}
@end

int main(void) {

NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:@"xyz.hacktricks.svcoc"];

id <NSXPCListenerDelegate> delegate = [MyDelegate new];
listener.delegate = delegate;
[listener resume];

sleep(10); // Fake something is done and then it ends
}
```bash # Compile the server & client gcc -framework Foundation oc_xpc_server.m -o oc_xpc_server gcc -framework Foundation oc_xpc_client.m -o oc_xpc_client

Save server on it’s location

cp oc_xpc_server /tmp

Load daemon

sudo cp xyz.hacktricks.svcoc.plist /Library/LaunchDaemons sudo launchctl load /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist

Call client

./oc_xpc_client

Clean

sudo launchctl unload /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist sudo rm /Library/LaunchDaemons/xyz.hacktricks.svcoc.plist /tmp/oc_xpc_server

## Dylb μ½”λ“œ λ‚΄μ˜ ν΄λΌμ΄μ–ΈνŠΈ
```objectivec
// gcc -dynamiclib -framework Foundation oc_xpc_client.m -o oc_xpc_client.dylib
// gcc injection example:
// DYLD_INSERT_LIBRARIES=oc_xpc_client.dylib /path/to/vuln/bin

#import <Foundation/Foundation.h>

@protocol MyXPCProtocol
- (void)sayHello:(NSString *)some_string withReply:(void (^)(NSString *))reply;
@end

__attribute__((constructor))
static void customConstructor(int argc, const char **argv)
{
NSString*  _serviceName = @"xyz.hacktricks.svcoc";

NSXPCConnection* _agentConnection = [[NSXPCConnection alloc] initWithMachServiceName:_serviceName options:4096];

[_agentConnection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(MyXPCProtocol)]];

[_agentConnection resume];

[[_agentConnection remoteObjectProxyWithErrorHandler:^(NSError* error) {
(void)error;
NSLog(@"Connection Failure");
}] sayHello:@"Hello, Server!" withReply:^(NSString *response) {
NSLog(@"Received response: %@", response);
}    ];
NSLog(@"Done!");

return;
}

Remote XPC

RemoteXPC.framework (from libxpc)μ—μ„œ μ œκ³΅ν•˜λŠ” 이 κΈ°λŠ₯은 μ„œλ‘œ λ‹€λ₯Έ 호슀트 간에 XPCλ₯Ό 톡해 톡신할 수 있게 ν•΄μ€λ‹ˆλ‹€.
원격 XPCλ₯Ό μ§€μ›ν•˜λŠ” μ„œλΉ„μŠ€λŠ” /System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist와 같이 plist에 UsesRemoteXPC ν‚€λ₯Ό κ°€μ§‘λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ„œλΉ„μŠ€κ°€ launchd에 λ“±λ‘λ˜λ”λΌλ„, κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 것은 com.apple.remoted.plugin 및 com.apple.remoteservicediscovery.events.plugin ν”ŒλŸ¬κ·ΈμΈμ„ κ°€μ§„ UserEventAgentμž…λ‹ˆλ‹€.

λ˜ν•œ, RemoteServiceDiscovery.frameworkλŠ” com.apple.remoted.pluginμ—μ„œ 정보λ₯Ό κ°€μ Έμ˜¬ 수 있게 ν•΄μ£Όλ©°, get_device, get_unique_device, connect와 같은 ν•¨μˆ˜λ₯Ό λ…ΈμΆœν•©λ‹ˆλ‹€β€¦

연결이 μ‚¬μš©λ˜κ³  μ„œλΉ„μŠ€μ˜ μ†ŒμΌ“ fdκ°€ μˆ˜μ§‘λ˜λ©΄, remote_xpc_connection_* 클래슀λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

CLI 도ꡬ /usr/libexec/remotectl을 μ‚¬μš©ν•˜μ—¬ λ‹€μŒκ³Ό 같은 λ§€κ°œλ³€μˆ˜λ‘œ 원격 μ„œλΉ„μŠ€μ— λŒ€ν•œ 정보λ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€:

/usr/libexec/remotectl list # Get bridge devices
/usr/libexec/remotectl show ...# Get device properties and services
/usr/libexec/remotectl dumpstate # Like dump withuot indicateing a servie
/usr/libexec/remotectl [netcat|relay] ... # Expose a service in a port
...

BridgeOS와 호슀트 κ°„μ˜ 톡신은 μ „μš© IPv6 μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€. MultiverseSupport.frameworkλŠ” 톡신에 μ‚¬μš©λ  fdλ₯Ό κ°€μ§„ μ†ŒμΌ“μ„ μ„€μ •ν•  수 있게 ν•΄μ€λ‹ˆλ‹€.
netstat, nettop λ˜λŠ” μ˜€ν”ˆ μ†ŒμŠ€ μ˜΅μ…˜μΈ netbottom을 μ‚¬μš©ν•˜μ—¬ μ΄λŸ¬ν•œ 톡신을 μ°ΎλŠ” 것이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

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 μ§€μ›ν•˜κΈ°