macOS XPC
Reading time: 14 minutes
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाएँ देखें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमारे Twitter 🐦 @hacktricks_live** का पालन करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
Basic Information
XPC, जिसका मतलब XNU (macOS द्वारा उपयोग किया जाने वाला कर्नेल) इंटर-प्रोसेस कम्युनिकेशन है, macOS और iOS पर प्रोसेस के बीच संचार के लिए एक ढांचा है। XPC सुरक्षित, असिंक्रोनस मेथड कॉल्स करने के लिए एक तंत्र प्रदान करता है जो सिस्टम पर विभिन्न प्रोसेस के बीच होता है। यह एप्पल के सुरक्षा सिद्धांत का एक हिस्सा है, जो विशेषाधिकार-सेपरेटेड एप्लिकेशन्स के निर्माण की अनुमति देता है जहाँ प्रत्येक घटक केवल उन्हीं अनुमतियों के साथ चलता है जिनकी उसे अपने कार्य को करने के लिए आवश्यकता होती है, इस प्रकार एक समझौता किए गए प्रोसेस से संभावित नुकसान को सीमित करता है।
XPC एक प्रकार के इंटर-प्रोसेस कम्युनिकेशन (IPC) का उपयोग करता है, जो एक सेट है विभिन्न प्रोग्रामों के लिए जो एक ही सिस्टम पर चल रहे हैं, डेटा को आगे-पीछे भेजने के लिए।
XPC के प्राथमिक लाभों में शामिल हैं:
- सुरक्षा: विभिन्न प्रोसेस में कार्यों को अलग करके, प्रत्येक प्रोसेस को केवल वही अनुमतियाँ दी जा सकती हैं जिनकी उसे आवश्यकता होती है। इसका मतलब है कि यदि कोई प्रोसेस समझौता कर लिया जाता है, तो उसके पास नुकसान करने की सीमित क्षमता होती है।
- स्थिरता: XPC क्रैश को उस घटक तक सीमित करने में मदद करता है जहाँ वे होते हैं। यदि कोई प्रोसेस क्रैश हो जाता है, तो इसे बिना बाकी सिस्टम को प्रभावित किए पुनः प्रारंभ किया जा सकता है।
- प्रदर्शन: XPC आसान समवर्तीता की अनुमति देता है, क्योंकि विभिन्न कार्यों को विभिन्न प्रोसेस में एक साथ चलाया जा सकता है।
एकमात्र नुकसान यह है कि किसी एप्लिकेशन को कई प्रोसेस में अलग करना और उन्हें XPC के माध्यम से संचारित करना कम प्रभावी है। लेकिन आज के सिस्टम में यह लगभग ध्यान देने योग्य नहीं है और लाभ बेहतर हैं।
Application Specific XPC services
एक एप्लिकेशन के 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 सेवा को JoinExistingSession इसके Info.plist फ़ाइल में “True” पर सेट किया गया है। इस मामले में, XPC सेवा उस सुरक्षा सत्र में चलेगी जो एप्लिकेशन ने इसे कॉल किया।
XPC सेवाएँ launchd द्वारा आवश्यकतानुसार शुरू की जाती हैं और सभी कार्यों के पूर्ण होने पर सिस्टम संसाधनों को मुक्त करने के लिए बंद कर दी जाती हैं। एप्लिकेशन-विशिष्ट XPC घटक केवल एप्लिकेशन द्वारा उपयोग किए जा सकते हैं, इस प्रकार संभावित कमजोरियों से जुड़े जोखिम को कम करते हैं।
System Wide XPC services
सिस्टम-व्यापी XPC सेवाएँ सभी उपयोगकर्ताओं के लिए सुलभ हैं। ये सेवाएँ, चाहे launchd या Mach-प्रकार की हों, plist फ़ाइलों में परिभाषित की जानी चाहिए जो निर्दिष्ट निर्देशिकाओं में स्थित होती हैं जैसे /System/Library/LaunchDaemons
, /Library/LaunchDaemons
, /System/Library/LaunchAgents
, या /Library/LaunchAgents
।
इन 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
में चलने वाले प्रक्रियाएँ रूट द्वारा चलाए जाते हैं। इसलिए यदि एक अप्रिविलेज्ड प्रक्रिया इनमें से किसी के साथ बात कर सकती है, तो यह विशेषाधिकार बढ़ाने में सक्षम हो सकती है।
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 संदेशों का उपयोग होता है)।
एक XPC सर्वर बनाने के लिए xpc_pipe_create()
या xpc_pipe_create_from_port()
को कॉल करके इसे एक विशिष्ट Mach पोर्ट का उपयोग करके बनाया जा सकता है। फिर, संदेश प्राप्त करने के लिए xpc_pipe_receive
और xpc_pipe_try_receive
को कॉल किया जा सकता है।
ध्यान दें कि xpc_pipe
ऑब्जेक्ट एक xpc_object_t
है जिसमें इसके स्ट्रक्चर में उपयोग किए गए दो Mach पोर्ट और नाम (यदि कोई हो) की जानकारी होती है। नाम, उदाहरण के लिए, डेमन secinitd
अपने plist /System/Library/LaunchDaemons/com.apple.secinitd.plist
में पाइप को com.apple.secinitd
के रूप में कॉन्फ़िगर करता है।
एक xpc_pipe
का उदाहरण bootstrap pipe है जो launchd
द्वारा बनाया गया है जिससे Mach पोर्ट साझा करना संभव हो जाता है।
NSXPC*
ये Objective-C उच्च स्तर के ऑब्जेक्ट हैं जो XPC कनेक्शनों का अमूर्तकरण करने की अनुमति देते हैं।
इसके अलावा, इन ऑब्जेक्ट्स को DTrace के साथ डिबग करना पिछले ऑब्जेक्ट्स की तुलना में आसान है।
GCD Queues
XPC संदेशों को पास करने के लिए GCD का उपयोग करता है, इसके अलावा यह कुछ डिस्पैच कतारें उत्पन्न करता है जैसे xpc.transactionq
, xpc.io
, xpc-events.add-listenerq
, xpc.service-instance
...
XPC सेवाएँ
ये .xpc
एक्सटेंशन वाले बंडल हैं जो अन्य परियोजनाओं के XPCServices
फ़ोल्डर के अंदर स्थित हैं और Info.plist
में उनके पास CFBundlePackageType
XPC!
पर सेट होता है।
इस फ़ाइल में अन्य कॉन्फ़िगरेशन कुंजी होती हैं जैसे ServiceType
जो Application, User, System या _SandboxProfile
हो सकती है जो एक सैंडबॉक्स को परिभाषित कर सकती है या _AllowedClients
जो आवश्यक अधिकार या ID को इंगित कर सकती है जो सेवा से संपर्क करने के लिए आवश्यक है। ये और अन्य कॉन्फ़िगरेशन विकल्प सेवा को लॉन्च करते समय कॉन्फ़िगर करने के लिए उपयोगी होंगे।
सेवा शुरू करना
ऐप xpc_connection_create_mach_service
का उपयोग करके XPC सेवा से कनेक्ट करने का प्रयास करता है, फिर launchd डेमन को ढूंढता है और xpcproxy
शुरू करता है। xpcproxy
कॉन्फ़िगर की गई प्रतिबंधों को लागू करता है और प्रदान किए गए FDs और 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 सेवा को यह जांचना चाहिए कि क्या उस प्रक्रिया को कनेक्ट करने की अनुमति है। यहाँ इसे जांचने के सामान्य तरीके और सामान्य pitfalls हैं:
macOS XPC Connecting Process Check
XPC प्राधिकरण
Apple भी ऐप्स को कुछ अधिकारों को कॉन्फ़िगर करने और उन्हें प्राप्त करने का तरीका निर्धारित करने की अनुमति देता है, इसलिए यदि कॉल करने वाली प्रक्रिया के पास ये हैं, तो इसे XPC सेवा से एक विधि को कॉल करने की अनुमति दी जाएगी:
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;
}
# 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 संचार उद्देश्य-सी कोड उदाहरण
// 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
}
# 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 कोड के अंदर क्लाइंट
// 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
(जो libxpc
से है) विभिन्न होस्टों के माध्यम से XPC के माध्यम से संवाद करने की अनुमति देती है।
जो सेवाएँ दूरस्थ XPC का समर्थन करती हैं, उनके plist में UsesRemoteXPC कुंजी होगी जैसे कि /System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist
के मामले में है। हालाँकि, सेवा launchd
के साथ पंजीकृत होगी, यह UserEventAgent
है जिसमें प्लगइन्स com.apple.remoted.plugin
और com.apple.remoteservicediscovery.events.plugin
कार्यक्षमता प्रदान करते हैं।
इसके अलावा, 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)
HackTricks का समर्थन करें
- सदस्यता योजनाएँ देखें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमारे Twitter 🐦 @hacktricks_live** का पालन करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।