macOS Process Abuse
Last updated
Last updated
Μάθετε & εξασκηθείτε στο Hacking του AWS:Εκπαίδευση HackTricks AWS Red Team Expert (ARTE) Μάθετε & εξασκηθείτε στο Hacking του GCP: Εκπαίδευση HackTricks GCP Red Team Expert (GRTE)
Μια διεργασία είναι μια εκτέλεση ενός εκτελέσιμου προγράμματος, ωστόσο οι διεργασίες δεν εκτελούν κώδικα, αυτές είναι νήματα. Επομένως, οι διεργασίες είναι απλώς δοχεία για την εκτέλεση νημάτων παρέχοντας μνήμη, περιγραφείς, θύρες, δικαιώματα...
Παραδοσιακά, οι διεργασίες ξεκινούσαν εντός άλλων διεργασιών (εκτός από το PID 1) καλώντας το fork
το οποίο θα δημιουργούσε μια ακριβή αντιγραφή της τρέχουσας διεργασίας και στη συνέχεια η παιδική διεργασία θα καλούσε γενικά το execve
για να φορτώσει το νέο εκτελέσιμο και να το εκτελέσει. Στη συνέχεια, εισήχθη η vfork
για να κάνει αυτή τη διαδικασία πιο γρήγορη χωρίς αντιγραφή μνήμης.
Στη συνέχεια εισήχθη το posix_spawn
συνδυάζοντας τα vfork
και execve
σε μία κλήση και δεχόμενο flags:
POSIX_SPAWN_RESETIDS
: Επαναφορά των αναγνωριστικών σε πραγματικά αναγνωριστικά
POSIX_SPAWN_SETPGROUP
: Ορισμός ομάδας διεργασίας
POSUX_SPAWN_SETSIGDEF
: Ορισμός προεπιλεγμένης συμπεριφοράς σήματος
POSIX_SPAWN_SETSIGMASK
: Ορισμός μάσκας σήματος
POSIX_SPAWN_SETEXEC
: Εκτέλεση στην ίδια διεργασία (όπως το execve
με περισσότερες επιλογές)
POSIX_SPAWN_START_SUSPENDED
: Έναρξη σε κατάσταση αναστολής
_POSIX_SPAWN_DISABLE_ASLR
: Έναρξη χωρίς ASLR
_POSIX_SPAWN_NANO_ALLOCATOR:
Χρήση του Nano allocator του libmalloc
_POSIX_SPAWN_ALLOW_DATA_EXEC:
Επιτρέπεται το rwx
στα τμήματα δεδομένων
POSIX_SPAWN_CLOEXEC_DEFAULT
: Κλείσιμο όλων των περιγραφών αρχείων κατά το exec(2) από προεπιλογή
_POSIX_SPAWN_HIGH_BITS_ASLR:
Τυχαία ανακατάταξη υψηλών bits του ASLR slide
Επιπλέον, το posix_spawn
επιτρέπει την καθορισμό ενός πίνακα posix_spawnattr
που ελέγχει κάποιες πτυχές της διεργασίας που δημιουργείται, και posix_spawn_file_actions
για την τροποποίηση της κατάστασης των περιγραφέων.
Όταν μια διεργασία τερματίζεται, στέλνει τον κωδικό επιστροφής στη γονική διεργασία (αν η γονική διεργασία έχει τερματιστεί, η νέα γονική είναι το PID 1) με το σήμα SIGCHLD
. Η γονική διεργασία πρέπει να λάβει αυτήν την τιμή καλώντας wait4()
ή waitid()
και μέχρι να συμβεί αυτό, το παιδί παραμένει σε κατάσταση zombie όπου εξακολουθεί να εμφανίζεται στη λίστα αλλά δεν καταναλώνει πόρους.
Τα PIDs, αναγνωριστικά διεργασιών, αναγνωρίζουν μια μοναδική διεργασία. Στο XNU τα PIDs είναι 64bit αυξανόμενα μονοτονικά και ποτέ δεν τυλίγονται (για να αποφευχθούν οι καταχρήσεις).
Οι διεργασίες μπορούν να εισαχθούν σε ομάδες για να είναι πιο εύκολο να τις χειριστεί κανείς. Για παράδειγμα, εντολές σε ένα σενάριο κελιού θα είναι στην ίδια ομάδα διεργασιών, οπότε είναι δυνατό να τους σταλθούν σήματα μαζί χρησιμοποιώντας το kill για παράδειγμα.
Είναι επίσης δυνατό να ομαδοποιηθούν διεργασίες σε συνεδρίες. Όταν μια διεργασία ξεκινά μια συνεδρία (setsid(2)
), οι διεργασίες-παιδιά τίθενται μέσα στη συνεδρία, εκτός αν ξεκινήσουν τη δική τους συνεδρία.
Η συναλλαγή είναι ένας άλλος τρόπος να ομαδοποιηθούν διεργασίες στο Darwin. Μια διεργασία που εντάσσεται σε μια συναλλαγή της επιτρέπεται να έχει πρόσβαση σε κοινούς πόρους, να μοιράζεται ένα λογιστικό ή να αντιμετωπίζει το Jetsam. Οι συναλλαγές έχουν διαφορετικούς ρόλους: Ηγέτη, XPC υπηρεσία, Επέκταση.
Κάθε διεργασία διαθέτει διαπιστευτήρια που ταυτοποιούν τα προνόμιά της στο σύστημα. Κάθε διεργασία θα έχει έναν κύριο uid
και έναν κύριο gid
(αν και ενδέχεται να ανήκει σε πολλές ομάδες).
Είναι επίσης δυνατό να αλλάξετε το αναγνωριστικό χρήστη και ομάδας αν το δυαδικό έχει το bit setuid/setgid
.
Υπάρχουν αρκετές λειτουργίες για ορισμό νέων uids/gids.
Η κλήση συστήματος persona
παρέχει ένα εναλλακτικό σύνολο διαπιστευτηρίων. Η υιοθέτηση μιας προσωπικότητας υποθέτει το uid, gid και τη συμμετοχή σε ομάδες ταυτόχρονα. Στο πηγαίο κώδικα είναι δυνατό να βρείτε τη δομή:
Νήματα POSIX (pthreads): Το macOS υποστηρίζει τα POSIX threads (pthreads
), τα οποία αποτελούν μέρος μιας πρότυπης διεπαφής νημάτων για τη γλώσσα C/C++. Η υλοποίηση των pthreads στο macOS βρίσκεται στο /usr/lib/system/libsystem_pthread.dylib
, το οποίο προέρχεται από το δημόσια διαθέσιμο έργο libpthread
. Αυτή η βιβλιοθήκη παρέχει τις απαραίτητες λειτουργίες για τη δημιουργία και διαχείριση νημάτων.
Δημιουργία Νημάτων: Η συνάρτηση pthread_create()
χρησιμοποιείται για τη δημιουργία νέων νημάτων. Εσωτερικά, αυτή η συνάρτηση καλεί την bsdthread_create()
, η οποία είναι μια χαμηλότερου επιπέδου κλήση συστήματος ειδική για τον πυρήνα XNU (ο πυρήνας στον οποίο βασίζεται το macOS). Αυτή η κλήση συστήματος παίρνει διάφορες σημαίες που προέρχονται από το pthread_attr
(χαρακτηριστικά) που καθορίζουν τη συμπεριφορά του νήματος, συμπεριλαμβανομένων των πολιτικών προγραμματισμού και του μεγέθους της στοίβας.
Προεπιλεγμένο Μέγεθος Στοίβας: Το προεπιλεγμένο μέγεθος στοίβας για νέα νήματα είναι 512 KB, το οποίο είναι επαρκές για τις τυπικές λειτουργίες αλλά μπορεί να προσαρμοστεί μέσω των χαρακτηριστικών του νήματος αν χρειάζεται περισσότερος ή λιγότερος χώρος.
Αρχικοποίηση Νήματος: Η συνάρτηση __pthread_init()
είναι κρίσιμη κατά την εγκατάσταση του νήματος, χρησιμοποιώντας το όρισμα env[]
για να αναλύσει μεταβλητές περιβάλλοντος που μπορεί να περιλαμβάνουν λεπτομέρειες σχετικά με τη θέση και το μέγεθος της στοίβας.
Έξοδος Νημάτων: Τα νήματα τερματίζονται συνήθως καλώντας την pthread_exit()
. Αυτή η συνάρτηση επιτρέπει σε ένα νήμα να τερματίσει καθαρά, εκτελώντας την απαραίτητη καθαριότητα και επιτρέποντας στο νήμα να στείλει έναν τιμή επιστροφής σε οποιονδήποτε συνδέοντα.
Καθαρισμός Νήματος: Κατά την κλήση της pthread_exit()
, η συνάρτηση pthread_terminate()
καλείται, η οποία χειρίζεται την αφαίρεση όλων των σχετικών δομών νήματος. Απελευθερώνει τις θύρες Mach thread (το Mach είναι το υποσύστημα επικοινωνίας στον πυρήνα XNU) και καλεί την bsdthread_terminate
, μια κλήση συστήματος που αφαιρεί τις δομές σε επίπεδο πυρήνα που σχετίζονται με το νήμα.
Για τη διαχείριση πρόσβασης σε κοινούς πόρους και την αποφυγή συνθηκών ανταγωνισμού, το macOS παρέχει αρκετούς πρωτογενείς μηχανισμούς συγχρονισμού. Αυτοί είναι κρίσιμοι σε περιβάλλοντα πολλαπλών νημάτων για να διασφαλίσουν την ακεραιότητα δεδομένων και τη σταθερότητα του συστήματος:
Κλειδώματα (Mutexes):
Κανονικό Κλείδωμα (Υπογραφή: 0x4D555458): Κανονικό κλείδωμα με μνημονικό αποτύπωμα 60 bytes (56 bytes για το κλείδωμα και 4 bytes για την υπογραφή).
Γρήγορο Κλείδωμα (Υπογραφή: 0x4d55545A): Παρόμοιο με ένα κανονικό κλείδωμα αλλά βελτιστοποιημένο για ταχύτερες λειτουργίες, επίσης μεγέθους 60 bytes.
Μεταβλητές Συνθήκης (Condition Variables):
Χρησιμοποιούνται για την αναμονή συγκεκριμένων συνθηκών να συμβούν, με μέγεθος 44 bytes (40 bytes συν 4-byte υπογραφή).
Χαρακτηριστικά Μεταβλητής Συνθήκης (Υπογραφή: 0x434e4441): Χαρακτηριστικά διαμόρφωσης για μεταβλητές συνθήκης, μεγέθους 12 bytes.
Μία Φορά Μεταβλητή (Once Variable) (Υπογραφή: 0x4f4e4345):
Βεβαιώνει ότι ένα τμήμα κώδικα αρχικοποίησης εκτελείται μόνο μία φορά. Το μέγεθός του είναι 12 bytes.
Κλειδώματα Ανάγνωσης-Εγγραφής (Read-Write Locks):
Επιτρέπει πολλαπλούς αναγνώστες ή έναν συγγραφέα ταυτόχρονα, διευκολύνοντας την αποτελεσματική πρόσβαση σε κοινά δεδομένα.
Κλείδωμα Ανάγνωσης-Εγγραφής (Υπογραφή: 0x52574c4b): Μέγεθος 196 bytes.
Χαρακτηριστικά Κλειδώματος Ανάγνωσης-Εγγραφής (Υπογραφή: 0x52574c41): Χαρακτηριστικά για τα κλειδώματα ανάγνωσης-εγγραφής, μέγεθους 20 bytes.
Τα τελευταία 4 bytes αυτών των αντικειμένων χρησιμοποιούνται για την ανίχνευση υπερχείλισης.
Οι Τοπικές Μεταβλητές Νήματος (TLV) στο πλαίσιο των αρχείων Mach-O (το μορφότυπο για εκτελέσιμα στο macOS) χρησιμοποιούνται για να δηλώσουν μεταβλητές που είναι συγκεκριμένες για κάθε νήμα σε μια εφαρμογή πολλαπλών νημάτων. Αυτό εξασφαλίζει ότι κάθε νήμα έχει τη δική του ξεχωριστή περίπτωση μιας μεταβλητής, παρέχοντας έναν τρόπο για να αποφευχθούν συγκρούσεις και να διατηρηθεί η ακεραιότητα δεδομένων χωρίς την ανάγκη εμφανούς μηχανισμών συγχρονισμού όπως τα κλειδώματα.
Σε γλώσσες όπως η C και συναφείς, μπορείτε να δηλώσετε μια τοπική μεταβλητή νήματος χρησιμοποιώντας τη λέξη-κλειδί __thread
. Έτσι λειτουργεί στο παράδειγμά σας:
Αυτό το απόσπασμα ορίζει το tlv_var
ως μεταβλητή τοπικού νήματος. Κάθε νήμα που εκτελεί αυτόν τον κώδικα θα έχει το δικό του tlv_var
, και οι αλλαγές που κάνει ένα νήμα στο tlv_var
δεν θα επηρεάσουν το tlv_var
σε άλλο νήμα.
Στο δυαδικό Mach-O, τα δεδομένα που σχετίζονται με τις τοπικές μεταβλητές νήματος οργανώνονται σε συγκεκριμένες ενότητες:
__DATA.__thread_vars
: Αυτή η ενότητα περιέχει τα μεταδεδομένα σχετικά με τις τοπικές μεταβλητές νήματος, όπως οι τύποι τους και η κατάσταση αρχικοποίησης.
__DATA.__thread_bss
: Αυτή η ενότητα χρησιμοποιείται για τις τοπικές μεταβλητές νήματος που δεν αρχικοποιούνται ρητά. Είναι μέρος της μνήμης που διατίθεται για δεδομένα που αρχικοποιούνται με μηδενικές τιμές.
Το Mach-O παρέχει επίσης μια συγκεκριμένη διεπαφή API που ονομάζεται tlv_atexit
για τη διαχείριση των τοπικών μεταβλητών νήματος όταν ένα νήμα τερματίζεται. Αυτή η API σάς επιτρέπει να καταχωρίσετε καταστροφείς - ειδικές συναρτήσεις που καθαρίζουν τα δεδομένα τοπικών μεταβλητών όταν ένα νήμα τερματίζεται.
Εάν η μεταβλητή περιβάλλοντος PYTHONINSPECT
είναι ορισμένη, η διαδικασία python θα μεταβεί σε ένα python cli μόλις ολοκληρωθεί. Είναι επίσης δυνατόν να χρησιμοποιηθεί το PYTHONSTARTUP
για να υποδείξει ένα σενάριο python που θα εκτελεστεί στην αρχή μιας διαδραστικής συνεδρίας.
Ωστόσο, σημειώστε ότι το σενάριο PYTHONSTARTUP
δεν θα εκτελεστεί όταν το PYTHONINSPECT
δημιουργεί τη διαδραστική συνεδρία.
Άλλες μεταβλητές περιβάλλοντος όπως PYTHONPATH
και PYTHONHOME
θα μπορούσαν επίσης να είναι χρήσιμες για να κάνουν μια εντολή python να εκτελέσει αυθαίρετο κώδικα.
Σημειώστε ότι τα εκτελέσιμα που έχουν συνταχθεί με το pyinstaller
δεν θα χρησιμοποιήσουν αυτές τις μεταβλητές περιβάλλοντος ακόμη κι αν εκτελούνται χρησιμοποιώντας ένα ενσωματωμένο python.
Συνολικά, δεν μπόρεσα να βρω έναν τρόπο για να κάνω την python να εκτελέσει αυθαίρετο κώδικα καταχρώμενη μεταβλητές περιβάλλοντος. Ωστόσο, οι περισσότεροι άνθρωποι εγκαθιστούν την python χρησιμοποιώντας το Hombrew, το οποίο θα εγκαταστήσει την python σε μια εγγράψιμη τοποθεσία για τον προεπιλεγμένο διαχειριστή χρήστη. Μπορείτε να το αρπάξετε με κάτι σαν:
Ακόμα και ο root θα εκτελέσει αυτόν τον κώδικα όταν τρέχει την python.
Shield (Github) είναι μια εφαρμογή ανοιχτού κώδικα που μπορεί να ανιχνεύσει και να μπλοκάρει ενέργειες εισαγωγής διεργασιών:
Χρησιμοποιώντας Μεταβλητές Περιβάλλοντος: Θα παρακολουθεί την ύπαρξη οποιασδήποτε από τις ακόλουθες μεταβλητές περιβάλλοντος: DYLD_INSERT_LIBRARIES
, CFNETWORK_LIBRARY_PATH
, RAWCAMERA_BUNDLE_PATH
και ELECTRON_RUN_AS_NODE
Χρησιμοποιώντας κλήσεις task_for_pid
: Για να βρει όταν μια διεργασία θέλει να πάρει τη θύρα εργασίας μιας άλλης που επιτρέπει την εισαγωγή κώδικα στη διεργασία.
Παράμετροι εφαρμογών Electron: Κάποιος μπορεί να χρησιμοποιήσει τις παραμέτρους γραμμής εντολών --inspect
, --inspect-brk
και --remote-debugging-port
για να ξεκινήσει μια εφαρμογή Electron σε λειτουργία εντοπισμού σφαλμάτων και έτσι να εισάγει κώδικα σε αυτήν.
Χρησιμοποιώντας συμβολικούς συνδέσμους ή σκληρούς συνδέσμους: Συνήθως το πιο κοινό κακόβουλο είναι να τοποθετήσουμε ένα σύνδεσμο με τα δικαιώματα του χρήστη μας, και να τον κατευθύνουμε προς μια τοποθεσία με υψηλότερα δικαιώματα. Η ανίχνευση είναι πολύ απλή τόσο για σκληρούς όσο και για συμβολικούς συνδέσμους. Αν η διαδικασία που δημιουργεί τον σύνδεσμο έχει ένα διαφορετικό επίπεδο δικαιωμάτων από το αρχείο-στόχο, δημιουργούμε μια ειδοποίηση. Δυστυχώς, στην περίπτωση των συμβολικών συνδέσμων, η αποκλειστική δράση δεν είναι δυνατή, καθώς δεν έχουμε πληροφορίες σχετικά με τον προορισμό του συνδέσμου πριν τη δημιουργία του. Αυτό είναι ένα περιορισμός του πλαισίου EndpointSecuriy της Apple.
Σε αυτήν την ανάρτηση στο blog μπορείτε να βρείτε πώς είναι δυνατό να χρησιμοποιηθεί η συνάρτηση task_name_for_pid
για να λάβετε πληροφορίες σχετικά με άλλες διεργασίες που εισάγουν κώδικα σε μια διεργασία και στη συνέχεια να λάβετε πληροφορίες σχετικά με αυτήν την άλλη διεργασία.
Σημειώστε ότι για να καλέσετε αυτήν τη συνάρτηση πρέπει να είστε το ίδιο uid με αυτόν που εκτελεί τη διεργασία ή root (και επιστρέφει πληροφορίες σχετικά με τη διεργασία, όχι έναν τρόπο για εισαγωγή κώδικα).