Movimiento lateral sin archivos con objetos COM atrapados

Primer plano de las manos de un hombre tecleando en un 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 los componentes COM y el amplio desarrollo de características a lo largo de los años ha creado una generosa superficie de ataque. En febrero de 2025, James Forshaw (@tiraniddo) de Google Project Zero publicó una entrada en su blog en la que detallaba un nuevo método para abusar de la tecnología de comunicación remota Distributed COM (DCOM), mediante el cual los objetos COM atrapados pueden utilizarse para ejecutar código .NET gestionado en el contexto de un proceso DCOM del lado del servidor. Forshaw destaca varios casos de uso para la escalada de privilegios y la elusión del proceso protegido ligero (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 de comunicación remota que permite a los clientes COM comunicarse con servidores COM a través de la comunicación entre procesos (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 marshaleado por referencia. En función de las condiciones, 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. El excelente recorrido 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 un secuestro COM 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 .NET Framework. 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 nos mantuvimos centrados 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: A través de 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 Remote Registry 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 la clase System.Object

Dolores 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 gestionado 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 único argumento, por lo que acabamos utilizando una solución poco elegante. 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
Buscar la sobrecarga adecuada de 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). Por lo tanto, si ForsHops.exe limpiaba sus referencias COM o se cerraba, también lo haría la baliza que se ejecutaba en el svchost.exe del equipo remoto. Probamos diferentes soluciones, como bloquear indefinidamente el subproceso principal de nuestro ensamblado .NET, ejecutar código shell en otro subproceso y hacer que ForsHops.exe dejara bloqueado el subproceso del exploit, pero ninguna resultó elegante.

El hilo principal del cargador .NET se bloquea mientras el código shell se ejecuta en un hilo independiente
El hilo principal del cargador .NET se bloquea mientras el código shell se ejecuta en un hilo independiente

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
Baliza exitosa en Windows 2019 Server
Baliza 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 los cambios después de que se cierre Beacon
ForShops.exe elimina los cambios cuando se cierra Beacon

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
  • Detección de la manipulación (o creación) de la siguiente clave del registro: HKLM\SOFTWARE\Classes\CLSID\{0BE35203-8F91-11CE-9DE3-00AA004BB851}\TreatAs (clave TreatAs de 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}
  • Búsqueda la presencia de valores activados de OnlyUseLatestCLR y AllowDCOMReflection en HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\. NETFramework
  • Habilitación del firewall basado en host para restringir el acceso a puertos efímeros DCOM siempre que sea posible

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

regla 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 opinión sobre esta investigación y por proporcionar una reseña del contenido de las entradas del 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