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

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:

c
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:

c
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:

c
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:

c
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:

c
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:

c
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:

bash
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