Inyecci贸n de Aplicaciones .Net en macOS
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 馃挰 Discord group or the telegram group or follow us on Twitter 馃惁 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Este es un resumen de la publicaci贸n https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/. 隆Cons煤ltalo para m谩s detalles!
Depuraci贸n de .NET Core
Estableciendo una Sesi贸n de Depuraci贸n
El manejo de la comunicaci贸n entre el depurador y el depurado en .NET es gestionado por dbgtransportsession.cpp. Este componente establece dos tuber铆as nombradas por cada proceso .NET como se ve en dbgtransportsession.cpp#L127, que son iniciadas a trav茅s de twowaypipe.cpp#L27. Estas tuber铆as tienen el sufijo -in
y -out
.
Al visitar el $TMPDIR
del usuario, se pueden encontrar FIFOs de depuraci贸n disponibles para depurar aplicaciones .Net.
DbgTransportSession::TransportWorker es responsable de gestionar la comunicaci贸n desde un depurador. Para iniciar una nueva sesi贸n de depuraci贸n, un depurador debe enviar un mensaje a trav茅s de la tuber铆a out
comenzando con una estructura MessageHeader
, detallada en el c贸digo fuente de .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];
}
Para solicitar una nueva sesi贸n, esta estructura se completa de la siguiente manera, estableciendo el tipo de mensaje en MT_SessionRequest
y la versi贸n del protocolo en la versi贸n actual:
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);
Este encabezado se env铆a al objetivo utilizando la llamada al sistema write
, seguido de la estructura sessionRequestData
que contiene un GUID para la sesi贸n:
write(wr, &sSendHeader, sizeof(MessageHeader));
memset(&sDataBlock.m_sSessionID, 9, sizeof(SessionRequestData));
write(wr, &sDataBlock, sizeof(SessionRequestData));
Una operaci贸n de lectura en el out
pipe confirma el 茅xito o fracaso del establecimiento de la sesi贸n de depuraci贸n:
read(rd, &sReceiveHeader, sizeof(MessageHeader));
Lectura de Memoria
Una vez que se establece una sesi贸n de depuraci贸n, se puede leer la memoria utilizando el MT_ReadMemory
tipo de mensaje. La funci贸n readMemory se detalla, realizando los pasos necesarios para enviar una solicitud de lectura y recuperar la respuesta:
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;
}
La prueba de concepto completa (POC) est谩 disponible aqu铆.
Escribiendo en Memoria
De manera similar, se puede escribir en memoria utilizando la funci贸n writeMemory
. El proceso implica establecer el tipo de mensaje en MT_WriteMemory
, especificar la direcci贸n y la longitud de los datos, y luego enviar los datos:
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;
}
El POC asociado est谩 disponible aqu铆.
Ejecuci贸n de C贸digo .NET Core
Para ejecutar c贸digo, es necesario identificar una regi贸n de memoria con permisos rwx, lo que se puede hacer utilizando vmmap -pages:
vmmap -pages [pid]
vmmap -pages 35829 | grep "rwx/rwx"
Localizar un lugar para sobrescribir un puntero de funci贸n es necesario, y en .NET Core, esto se puede hacer apuntando a la Dynamic Function Table (DFT). Esta tabla, detallada en jithelpers.h
, es utilizada por el runtime para funciones auxiliares de compilaci贸n JIT.
Para sistemas x64, se puede utilizar la b煤squeda de firmas para encontrar una referencia al s铆mbolo _hlpDynamicFuncTable
en libcorclr.dll
.
La funci贸n del depurador MT_GetDCB
proporciona informaci贸n 煤til, incluyendo la direcci贸n de una funci贸n auxiliar, m_helperRemoteStartAddr
, que indica la ubicaci贸n de libcorclr.dll
en la memoria del proceso. Esta direcci贸n se utiliza luego para iniciar una b煤squeda de la DFT y sobrescribir un puntero de funci贸n con la direcci贸n del shellcode.
El c贸digo completo de POC para inyecci贸n en PowerShell es accesible aqu铆.
Referencias
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 馃挰 Discord group or the telegram group or follow us on Twitter 馃惁 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.