Movimiento lateral sin archivos con objetos COM atrapados

Primer plano de las manos de un hombre tecleando en el ordenador portátil y sosteniendo una tablet en una oficina oscura iluminada de azul

El modelo de objetos componentes (COM) ha sido una piedra angular del desarrollo de Microsoft Windows desde principios de la década de 1990 y sigue siendo muy frecuente en los sistemas operativos y aplicaciones modernos de Windows. La dependencia de componentes COM y el extenso desarrollo de características a lo largo de los años han creado una superficie de ataque generosa. En febrero de 2025, James Forshaw (@tiraniddo) de Google Project Zero publicó una entrada de blog en la que detallaba un enfoque novedoso para abusar de la tecnología de comunicación remota COM distribuida (DCOM) en la que los objetos COM atrapados pueden utilizarse para ejecutar código gestionado .NET en el contexto de un proceso DCOM en el lado del servidor. Forshaw destaca varios casos de uso para la escalada de privilegios y la omisión de Protected Process Light (PPL).

Según la investigación de Forshaw, Mohamed Fakroud (@T3nb3w) publicó una implementación de la técnica para eludir las protecciones PPL a principios de marzo de 2025. Jimmy Bayne (@bohops) y yo realizamos una investigación similar en febrero de 2025, que nos ha llevado a desarrollar una técnica de prueba de concepto de movimiento lateral sin archivos mediante el abuso de objetos COM atrapados.

Fondo

COM es un estándar de interfaz binaria y un nivel de servicio de middleware que permite la exposición de componentes modulares distintos para interactuar entre sí y con las aplicaciones, independientemente del lenguaje de programación subyacente. Por ejemplo, los objetos COM desarrollados en C++ pueden interactuar fácilmente con una aplicación .NET, lo que permite a los desarrolladores integrar diversos módulos de software de manera efectiva. DCOM es una tecnología que permite a los clientes COM comunicarse con servidores COM mediante comunicación interprocesos (IPC) o llamadas a procedimientos remotos (RPC). Muchos servicios de Windows implementan componentes DCOM a los que se puede acceder local o remotamente.

Las clases COM suelen estar registradas y contenidas en el registro de Windows. Un programa cliente interactúa con un servidor COM creando una instancia de la clase COM, conocida como objeto COM. Este objeto proporciona un puntero a una interfaz estandarizada. El cliente utiliza este puntero para acceder a los métodos y propiedades del objeto, lo que facilita la comunicación y la funcionalidad entre el cliente y el servidor.

Los objetos COM suelen ser objetivos de investigación para evaluar la exposición a vulnerabilidades y descubrir características susceptibles de abuso. Un objeto COM atrapado es una clase de error en la que un cliente COM instancia una clase COM en un servidor DCOM fuera de proceso, donde el cliente controla el objeto COM mediante un puntero de objeto serializado por referencia. Dependiendo de la condición, este vector de control puede presentar fallos lógicos relacionados con la seguridad.

El blog de Forshaw describe un caso de uso de bypass PPL en el que la interfaz IDispatch, tal como se expone en la clase COM de WaaSRemediation, se manipula para abusar de objetos COM atrapados y ejecutar código .NET. WaaSRemediation se implementa en el servicio WaaSMedicSvc, que se ejecuta como un proceso de svchost.exe protegido en el contexto de NT: AUTHOR\SYSTEM. La excelente guía de Forshaw fue la base de nuestra investigación aplicada y el desarrollo de una técnica de prueba de concepto de movimiento lateral sin archivos.

Hombre mirando el ordenador

Refuerce su inteligencia de seguridad 


Manténgase a la vanguardia de las amenazas con noticias e información sobre seguridad, IA y mucho más, semanalmente en el boletín Think. 


Resumen de la investigación

Nuestro viaje de investigación comenzó explorando la clase COM WaaSRemediation que soporta la interfaz IDispatch . Esta interfaz permite a los clientes realizar la vinculación tardía. Normalmente, los clientes COM tienen definidas en tiempo de compilación las definiciones de interfaz y de tipo de los objetos que utilizan. En cambio, el enlace tardío permite al cliente descubrir y llamar a los métodos del objeto en tiempo de ejecución. IDispatch incluye el método GetTypeInfo , que devuelve una interfaz ITypeInfo. ITypeInfo tiene métodos que pueden utilizarse para descubrir información sobre el tipo del objeto que lo implementa.

Si una clase COM utiliza una biblioteca de tipos, puede ser consultada por el cliente a través de ITypeLib (obtenida de ITypeInfo-> GetContainingTypeLib) para recuperar la información de tipos. Además, las bibliotecas de tipos también pueden hacer referencia a otras bibliotecas de tipos para obtener información adicional sobre los tipos.

Según la entrada de blog de Forshaw, WaaSRemediation hace referencia a la biblioteca de tipos WaaSRemediationLib, que a su vez hace referencia a stdole (Automatización OLE). WaaSRemediationLib utiliza dos clases COM de esa biblioteca, StdFont y StdPicture. Al realizar COM Hijacking en el objeto StdFont modificando su clave de registro TreatAs, la clase apuntará a otra clase COM de nuestra elección, como System.Object en el marco .NET. Cabe destacar que Forshaw señala que StdPicture no es viable, ya que este objeto realiza una comprobación de instanciación fuera de proceso, por lo que mantuvimos el foco en el uso de StdFont.

Los objetos .NET nos interesan por el método GetTypede System.Object . A través de GetType, podemos realizar una reflexión de.NET para, finalmente, acceder a Assembly.Load. Aunque se eligió System.Object, este tipo resulta ser la raíz de la jerarquía de tipos en .NET. Por lo tanto, se podría utilizar cualquier objeto .NET COM.

Con la etapa inicial establecida, había otros dos valores DWORD en la clave HKLM\Software\Microsoft\.NetFramework necesarios para hacer realidad nuestro caso de uso percibido:

  • AllowDCOMReflection: como señaló Forshaw, este valor habilitado nos permite realizar una reflexión arbitraria para llamar a cualquier método .NET. Normalmente, .NET Reflection over DCOM se evita debido a las mitigaciones abordadas en MS14-009.
  • OnlyUseLatestCLR: usando Procmon, hemos descubierto que este valor debe estar habilitado para cargar la última versión del .NET CLR (versión 4), de lo contrario la versión 2 se carga por defecto.

Al confirmar que se podía cargar la última versión del CLR y.NET en nuestras pruebas iniciales, supimos que íbamos por buen camino.

Del proceso local al ordenador remoto

Centrándonos en los aspectos programáticos remotos, primero usamos el registro remoto para manipular los valores de la clave de registro de .NetFramework y secuestrar el objeto StdFont en la máquina de destino. A continuación, cambiamos CoCreateInstance por CoCreateInstanceEx para instanciar el objeto COM WaaSRemediation en el objetivo remoto y obtener un puntero a la interfaz IDispatch .

Con un puntero a IDispatch, llamamos al método miembro GetTypeInfo para obtener un puntero a la interfaz ITypeInfo, que está atrapada en el servidor. Los métodos miembro llamados a partir de entonces se producen en el lado del servidor. Después de identificar la referencia de interés de la biblioteca de tipos contenida (stdole) y derivar la referencia de objeto de clase posterior de interés (StdFont), finalmente utilizamos el método "remotable" CreateInstance en la interfaz ITypeInfo para redirigir el flujo de enlace de objetos StdFont (a través de la manipulación previa de TreatAs) para crear una instancia de System.Object.

Dado que AllowDCOMReflection está correctamente configurado, podemos realizar una reflexión .NET sobre DCOM para acceder a Assembly.Load y cargar un ensamblado .NET en el servidor COM. Dado que utilizamos Assembly.Load sobre DCOM, esta técnica de movimiento lateral no tiene archivos, ya que la transferencia de bytes del ensamblado la gestiona la magia de comunicación remota de DCOM. Para obtener una explicación detallada de este flujo técnico desde la instanciación de objetos hasta la reflexión, consulte el siguiente diagrama:

diagrama de flujo que muestra la instanciación de la clase System.Object
Flujo de instanciación de clases System.Object

Dificultades del desarrollo

Nuestro primer y principal problema era llamar a Assembly.Load_3, a través de IDispatch->Invoke. Invoke pasa una matriz de objetos de argumentos a la función de destino, y Load_3 es la sobrecarga de Assembly.Load que toma una única matriz de bytes. Por tanto, necesitábamos envolver el SAFEARRAY de bytes dentro de otro SAFEARRAY de VARIANTs : inicialmente, intentábamos pasar un solo SAFEARRAY de bytes.

código que muestra cómo crear un equivalente no gestionado de Object Byte
Creación de un equivalente no administrado de Object Byte

Otro problema era encontrar la sobrecarga de Assembly.Load adecuada. Las funciones auxiliares se tomaron del código CVE-2014-0257 de Forshaw, que incluía la función GetStaticMethod . Esta función utilizaba la reflexión de .NET sobre DCOM para encontrar un método estático dado un puntero de tipo, el nombre del método y su conteo de parámetros. Assembly.Load tiene dos sobrecargas estáticas que toman un solo argumento; como tal, terminamos usando una solución hacky. Nos dimos cuenta de que la tercera instancia de Load con un solo argumento era nuestra elección correcta.

Código utilizado para buscar la sobrecarga de Assembly.Load adecuada
Buscando la sobrecarga adecuada Assembly.Load

Dificultades operativas

Uno de los mayores inconvenientes que observamos con esta técnica fue que la baliza generada tendría su vida útil limitada al cliente COM; en este caso, la vida útil de la aplicación de nuestro binario de armamento "ForsHops.exe" (con un nombre elegante, por supuesto). Así que, si ForsHops.exe limpiaba sus referencias COM o salía, también lo haría la baliza que estaba funcionando bajo la svchost.exe de la máquina remota. Probamos diferentes soluciones, como hacer que nuestro ensamblaje .NET colgara indefinidamente su subproceso principal, ejecutar shellcode en otro subproceso y hacer que ForsHops.exe dejara el subproceso de explotar colgado, pero nada fue elegante.

el subproceso principal de.NET loader se bloquea mientras el código de shell se ejecuta en otro subproceso
el subproceso principal de.NET loader se bloquea mientras el código de shell se ejecuta en otro subproceso

En su estado actual, ForsHops.exe se ejecuta hasta que se cierra la baliza, momento en el que elimina sus operaciones de registro. Hay oportunidades de mejora, pero lo dejaremos como ejercicio para el lector.

demostración de la ejecución de ForShops.exe
Ejecución de ForShops.exe
Señal de alerta exitosa en Windows 2019 Server
Señal de alerta exitosa en Windows 2019 Server
captura de pantalla de Beacon ejecutándose en un proceso svchost de PPL
Beacon se ejecuta en un proceso PPL svchost
ejemplo de ForShops.exe eliminando cambios después de que la baliza sale
ForShops.exe eliminando los cambios después de la salida de la baliza

Recomendaciones defensivas

La guía de detección propuesta por Samir Bousseaden (@SBousseaden) tras la publicación de su implementación por Mohamed Fakroud también se aplica a esta técnica de movimiento lateral:

  • Detección de eventos de carga CLR dentro del proceso svchost.exe de WaaSMedicSvc
  • Detectando manipulación (o creación) del registro de la siguiente clave: HKLM\SOFTWARE\Classes\CLSID\{0BE35203-8F91-11CE-9DE3-00AA004BB851}\TreatAs (TreatAs key of StandardFont CLSID)

Además, recomendamos implementar los siguientes controles adicionales:

  • Detección de la manipulación DACL de HKLM\SOFTWARE\Classes\CLSID\{0BE35203-8F91-11CE-9DE3-00AA004BB851}
  • Buscando la presencia de valores habilitados de OnlyUseLatestCLR y AllowDCOMReflection en HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\. NETFramework
  • Habilitar el firewall basado en el host para restringir el acceso efímero a los puertos de DCOM siempre que sea posible

Además, aproveche la siguiente regla de prueba de concepto YARA para detectar el ejecutable estándar ForsHops.exe:

rule Detect_Standard_ForsHops_PE_By_Hash

{
    meta:   
        description = "Detects the standard ForShops PE file by strings"
        reference = "GitHub Project: https://github.com/xforcered/ForsHops/"
    strings:
        $s1 = "System.Reflection.Assembly, mscorlib" wide
        $s2 = "{72566E27-1ABB-4EB3-B4F0-EB431CB1CB32}" wide
        $s3 = "{34050212-8AEB-416D-AB76-1E45521DB615}" wide
        $s4 = "GetType" wide
        $s5 = "Load" wide

    condition:
        all of them
}

Conclusión

Nuestra implementación amplía ligeramente el abuso de COM explicado en el blog de Forshaw al aprovechar los objetos COM atrapados para el movimiento lateral en lugar de la ejecución local para eludir la PPL. Por lo tanto, sigue siendo susceptible a las mismas detecciones que las implementaciones que realizan ejecución local.

Puede encontrar el código de movimiento lateral de prueba de concepto de ForsHops.exe aquí.

Agradecimiento

Un agradecimiento especial a Dwight Hohnstein (@djhohnstein) y Sanjiv Kawa (@sanjivkawa) por dar su feedback sobre esta investigación y por proporcionar reseñas del contenido de entrada de blog.

Recursos

Mixture of Experts | 12 de diciembre, episodio 85

Descifrar la IA: resumen semanal de noticias

Únase a nuestro panel de ingenieros, investigadores, responsables de producto y otros profesionales de talla mundial que se abren paso entre el bullicio de la IA para ofrecerle las últimas noticias y conocimientos al respecto.

Soluciones relacionadas
Soluciones de seguridad para la empresa

Transforme su programa de seguridad con las soluciones del mayor proveedor de seguridad empresarial.

Explore las soluciones de ciberseguridad
Servicios de ciberseguridad

Transforme su negocio y gestione el riesgo con servicios de consultoría de ciberseguridad, nube y seguridad gestionada.

    Explore los servicios de ciberseguridad
    Ciberseguridad de la inteligencia artificial (IA)

    Mejore la velocidad, la precisión y la productividad de los equipos de seguridad con soluciones de ciberseguridad basadas en IA.

    Explore la ciberseguridad de la IA
    Dé el siguiente paso

    Tanto si necesita soluciones de seguridad de datos, de gestión de endpoints o de gestión de identidades y accesos (IAM), nuestros expertos están dispuestos a trabajar con usted para lograr una posición de seguridad sólida. Transforme su empresa y gestione los riesgos con un líder de la industria mundial mundial en consultoría de ciberseguridad, cloud y servicios de seguridad gestionados.

    Explore las soluciones de ciberseguridad Descubra los servicios de ciberseguridad