macOS .Net Applications Injection
Reading time: 5 minutes
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.
To jest podsumowanie posta https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/. Sprawdź go, aby uzyskać więcej szczegółów!
.NET Core Debugging
Ustanawianie sesji debugowania
Zarządzanie komunikacją między debuggerem a debugowanym w .NET odbywa się za pomocą dbgtransportsession.cpp. Ten komponent ustawia dwa nazwane potoki na każdy proces .NET, jak widać w dbgtransportsession.cpp#L127, które są inicjowane za pomocą twowaypipe.cpp#L27. Te potoki mają sufiksy -in
i -out
.
Odwiedzając $TMPDIR
użytkownika, można znaleźć dostępne FIFOs do debugowania aplikacji .Net.
DbgTransportSession::TransportWorker jest odpowiedzialny za zarządzanie komunikacją z debuggerem. Aby zainicjować nową sesję debugowania, debugger musi wysłać wiadomość przez potok out
, zaczynając od struktury MessageHeader
, szczegółowo opisanej w kodzie źródłowym .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];
}
Aby zażądać nowej sesji, ta struktura jest wypełniana w następujący sposób, ustawiając typ wiadomości na MT_SessionRequest
i wersję protokołu na bieżącą wersję:
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);
Ten nagłówek jest następnie wysyłany do celu za pomocą wywołania systemowego write
, a następnie struktura sessionRequestData
zawierająca GUID dla sesji:
write(wr, &sSendHeader, sizeof(MessageHeader));
memset(&sDataBlock.m_sSessionID, 9, sizeof(SessionRequestData));
write(wr, &sDataBlock, sizeof(SessionRequestData));
Operacja odczytu na rurze out
potwierdza sukces lub niepowodzenie nawiązania sesji debugowania:
read(rd, &sReceiveHeader, sizeof(MessageHeader));
Odczyt pamięci
Gdy sesja debugowania jest nawiązana, pamięć można odczytać za pomocą typu wiadomości MT_ReadMemory
. Funkcja readMemory jest szczegółowo opisana, wykonując niezbędne kroki do wysłania żądania odczytu i uzyskania odpowiedzi:
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;
}
Pełny dowód koncepcji (POC) jest dostępny tutaj.
Pisanie do pamięci
Podobnie, pamięć można zapisać za pomocą funkcji writeMemory
. Proces polega na ustawieniu typu wiadomości na MT_WriteMemory
, określeniu adresu i długości danych, a następnie wysłaniu danych:
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;
}
Powiązany POC jest dostępny tutaj.
Wykonanie kodu .NET Core
Aby wykonać kod, należy zidentyfikować obszar pamięci z uprawnieniami rwx, co można zrobić za pomocą vmmap -pages:
vmmap -pages [pid]
vmmap -pages 35829 | grep "rwx/rwx"
Zlokalizowanie miejsca do nadpisania wskaźnika funkcji jest konieczne, a w .NET Core można to zrobić, celując w Dynamic Function Table (DFT). Ta tabela, szczegółowo opisana w jithelpers.h
, jest używana przez środowisko uruchomieniowe do funkcji pomocniczych kompilacji JIT.
Dla systemów x64, poszukiwanie sygnatur może być użyte do znalezienia odniesienia do symbolu _hlpDynamicFuncTable
w libcorclr.dll
.
Funkcja debuggera MT_GetDCB
dostarcza przydatnych informacji, w tym adresu funkcji pomocniczej, m_helperRemoteStartAddr
, wskazującego lokalizację libcorclr.dll
w pamięci procesu. Ten adres jest następnie używany do rozpoczęcia wyszukiwania DFT i nadpisania wskaźnika funkcji adresem shellcode.
Pełny kod POC do wstrzykiwania do PowerShell jest dostępny tutaj.
References
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.