macOS XPC

macOS XPC

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:

Βασικές Πληροφορίες

Το XPC, που σημαίνει XNU (το πυρήνας που χρησιμοποιείται από το macOS) Inter-Process Communication, είναι ένα πλαίσιο για επικοινωνία μεταξύ διεργασιών στο 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 service έχει ρυθμιστεί με την JoinExistingSession να έχει την τιμή "True" στο αρχείο Info.plist του. Σε αυτήν την περίπτωση, το XPC service θα εκτελείται στην ίδια ασφαλή συνεδρία με την εφαρμογή που το κάλεσε.

Τα XPC services ξεκινούν από τον launchd όταν απαιτούνται και τερματίζονται όταν ολοκληρώνονται όλες οι εργασίες για να απελευθερωθούν οι πόροι του συστήματος. **Οι εφαρμογές μπορούν να χρησιμοποι

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 Event

Οι εφαρμογές μπορούν να εγγραφούν σε διάφορα μηνύματα γεγονότων, επιτρέποντάς τους να εκτελούνται κατά παραγγελία όταν συμβούν τέτοια γεγονότα. Η ρύθμιση για αυτές τις υπηρεσίες γίνεται σε αρχεία plist του launchd, που βρίσκονται στους ίδιους καταλόγους με τα προηγούμενα και περιέχουν ένα επιπλέον κλειδί LaunchEvent.

Έλεγχος Σύνδεσης Διεργασίας XPC

Όταν μια διεργασία προσπαθεί να καλέσει μια μέθοδο μέσω μιας σύνδεσης XPC, η XPC υπηρεσία πρέπει να ελέγξει αν η διεργασία αυτή έχει άδεια να συνδεθεί. Εδώ παρουσιάζονται οι συνηθισμένοι τρόποι ελέγχου και οι συνηθισμένες παγίδες:

pagemacOS XPC Connecting Process Check

Εξουσιοδότηση XPC

Η Apple επιτρέπει επίσης στις εφαρμογές να διαμορφώσουν ορισμένα δικαιώματα και τον τρόπο απόκτησής τους, έτσι ώστε αν η καλούσα διεργασία τα έχει, θα επιτρέπεται να καλέσει μια μέθοδο από την XPC υπηρεσία:

pagemacOS XPC Authorization

XPC Sniffer

Για να καταγράψετε τα μηνύματα 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

Παράδειγμα κώδικα C για επικοινωνία XPC

// 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 επικοινωνίας Objective-C

// 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

Ο παρακάτω κώδικας παρουσιάζει έναν πελάτη που εκτελείται μέσα σε έναν κώδικα Dylb.

```objective-c
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char *argv[]) {
    void *handle;
    int (*add)(int, int);
    char *error;

    handle = dlopen("./libadd.dylib", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    add = dlsym(handle, "add");
    if ((error = dlerror()) != NULL) {
        fprintf(stderr, "%s\n", error);
        return 1;
    }

    printf("The sum is: %d\n", add(5, 3));

    dlclose(handle);
    return 0;
}

Ο παραπάνω κώδικας φορτώνει δυναμικά τη βιβλιοθήκη libadd.dylib και καλεί τη συνάρτηση add που βρίσκεται μέσα σε αυτήν. Η συνάρτηση add πραγματοποιεί την πρόσθεση δύο αριθμών και επιστρέφει το αποτέλεσμα. Το αποτέλεσμα εκτυπώνεται στην οθόνη.

Για να εκτελέσετε τον παραπάνω κώδικα, πρέπει να δημιουργήσετε τη βιβλιοθήκη libadd.dylib που περιέχει τη συνάρτηση add. Μπορείτε να το κάνετε αυτό με τη χρήση του Xcode ή του gcc.

Για παράδειγμα, μπορείτε να δημιουργήσετε ένα αρχείο με τον κώδικα της συνάρτησης add και να το μεταγλωττίσετε σε μια βιβλιοθήκη χρησιμοποιώντας την ακόλουθη εντολή:

gcc -shared -o libadd.dylib add.c

Αφού δημιουργήσετε τη βιβλιοθήκη, μπορείτε να μεταγλωττίσετε και να εκτελέσετε τον παραπάνω κώδικα.

// 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;
}
Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:

Last updated