macOS .Net Applications Injection
Reading time: 6 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Αυτή είναι μια περίληψη της ανάρτησης https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/. Ελέγξτε την για περισσότερες λεπτομέρειες!
.NET Core Debugging
Establishing a Debugging Session
Η διαχείριση της επικοινωνίας μεταξύ του debugger και του debuggee στο .NET γίνεται από το dbgtransportsession.cpp. Αυτό το συστατικό ρυθμίζει δύο ονομαστικούς σωλήνες ανά διαδικασία .NET όπως φαίνεται στο dbgtransportsession.cpp#L127, οι οποίοι ξεκινούν μέσω του twowaypipe.cpp#L27. Αυτοί οι σωλήνες έχουν το επίθημα -in
και -out
.
Επισκεπτόμενος το $TMPDIR
του χρήστη, μπορεί κανείς να βρει διαθέσιμα FIFOs αποσφαλμάτωσης για εφαρμογές .Net.
DbgTransportSession::TransportWorker είναι υπεύθυνος για τη διαχείριση της επικοινωνίας από έναν debugger. Για να ξεκινήσει μια νέα συνεδρία αποσφαλμάτωσης, ένας debugger πρέπει να στείλει ένα μήνυμα μέσω του σωλήνα out
που ξεκινά με μια δομή MessageHeader
, λεπτομερώς στον πηγαίο κώδικα .NET:
struct MessageHeader {
MessageType m_eType; // Message type
DWORD m_cbDataBlock; // Size of following data block (can be zero)
DWORD m_dwId; // Message ID from sender
DWORD m_dwReplyId; // Reply-to Message ID
DWORD m_dwLastSeenId; // Last seen Message ID by sender
DWORD m_dwReserved; // Reserved for future (initialize to zero)
union {
struct {
DWORD m_dwMajorVersion; // Requested/accepted protocol version
DWORD m_dwMinorVersion;
} VersionInfo;
...
} TypeSpecificData;
BYTE m_sMustBeZero[8];
}
Για να ζητήσετε μια νέα συνεδρία, αυτή η δομή συμπληρώνεται ως εξής, ορίζοντας τον τύπο μηνύματος σε MT_SessionRequest
και την έκδοση πρωτοκόλλου στην τρέχουσα έκδοση:
static const DWORD kCurrentMajorVersion = 2;
static const DWORD kCurrentMinorVersion = 0;
// Configure the message type and version
sSendHeader.m_eType = MT_SessionRequest;
sSendHeader.TypeSpecificData.VersionInfo.m_dwMajorVersion = kCurrentMajorVersion;
sSendHeader.TypeSpecificData.VersionInfo.m_dwMinorVersion = kCurrentMinorVersion;
sSendHeader.m_cbDataBlock = sizeof(SessionRequestData);
Αυτή η κεφαλίδα αποστέλλεται στη συνέχεια στον στόχο χρησιμοποιώντας την κλήση συστήματος write
, ακολουθούμενη από τη δομή sessionRequestData
που περιέχει ένα GUID για τη συνεδρία:
write(wr, &sSendHeader, sizeof(MessageHeader));
memset(&sDataBlock.m_sSessionID, 9, sizeof(SessionRequestData));
write(wr, &sDataBlock, sizeof(SessionRequestData));
Μια λειτουργία ανάγνωσης στον σωλήνα out
επιβεβαιώνει την επιτυχία ή την αποτυχία της εγκαθίδρυσης της συνεδρίας αποσφαλμάτωσης:
read(rd, &sReceiveHeader, sizeof(MessageHeader));
Ανάγνωση Μνήμης
Μόλις καθοριστεί μια συνεδρία αποσφαλμάτωσης, η μνήμη μπορεί να διαβαστεί χρησιμοποιώντας τον τύπο μηνύματος MT_ReadMemory
. Η συνάρτηση readMemory περιγράφεται λεπτομερώς, εκτελώντας τα απαραίτητα βήματα για να στείλει ένα αίτημα ανάγνωσης και να ανακτήσει την απάντηση:
bool readMemory(void *addr, int len, unsigned char **output) {
// Allocation and initialization
...
// Write header and read response
...
// Read the memory from the debuggee
...
return true;
}
Η πλήρης απόδειξη της έννοιας (POC) είναι διαθέσιμη εδώ.
Γράφοντας Μνήμη
Ομοίως, η μνήμη μπορεί να γραφτεί χρησιμοποιώντας τη λειτουργία writeMemory
. Η διαδικασία περιλαμβάνει την ρύθμιση του τύπου μηνύματος σε MT_WriteMemory
, καθορίζοντας τη διεύθυνση και το μήκος των δεδομένων, και στη συνέχεια στέλνοντας τα δεδομένα:
bool writeMemory(void *addr, int len, unsigned char *input) {
// Increment IDs, set message type, and specify memory location
...
// Write header and data, then read the response
...
// Confirm memory write was successful
...
return true;
}
Η σχετική POC είναι διαθέσιμη εδώ.
.NET Core Εκτέλεση Κώδικα
Για να εκτελέσετε κώδικα, πρέπει να εντοπίσετε μια περιοχή μνήμης με άδειες rwx, κάτι που μπορεί να γίνει χρησιμοποιώντας vmmap -pages:
vmmap -pages [pid]
vmmap -pages 35829 | grep "rwx/rwx"
Η τοποθέτηση ενός σημείου για την επαναγραφή ενός δείκτη συνάρτησης είναι απαραίτητη, και στο .NET Core, αυτό μπορεί να γίνει στοχεύοντας τον Dynamic Function Table (DFT). Αυτός ο πίνακας, που περιγράφεται στο jithelpers.h
, χρησιμοποιείται από το runtime για τις βοηθητικές συναρτήσεις JIT compilation.
Για συστήματα x64, η αναζήτηση υπογραφών μπορεί να χρησιμοποιηθεί για να βρεθεί μια αναφορά στο σύμβολο _hlpDynamicFuncTable
στο libcorclr.dll
.
Η συνάρτηση debugger MT_GetDCB
παρέχει χρήσιμες πληροφορίες, συμπεριλαμβανομένης της διεύθυνσης μιας βοηθητικής συνάρτησης, m_helperRemoteStartAddr
, που υποδεικνύει την τοποθεσία του libcorclr.dll
στη μνήμη της διαδικασίας. Αυτή η διεύθυνση χρησιμοποιείται στη συνέχεια για να ξεκινήσει μια αναζήτηση για το DFT και να επαναγραφεί ένας δείκτης συνάρτησης με τη διεύθυνση του shellcode.
Ο πλήρης κώδικας POC για την ένεση στο PowerShell είναι προσβάσιμος εδώ.
Αναφορές
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.