Vamos a verificar manualmente los permisos del servicio `RpcEptMapper` utilizando la GUI de `regedit`. Una cosa que me gusta mucho de la ventana de _Configuración avanzada de seguridad_ es la pestaña de _Permisos efectivos_. Puedes elegir cualquier nombre de usuario o grupo y ver inmediatamente los permisos efectivos que se otorgan a este principal sin necesidad de inspeccionar todos los ACE por separado. La siguiente captura de pantalla muestra el resultado para la cuenta de bajo privilegio `lab-user`.
La mayoría de los permisos son estándar (por ejemplo: `Query Value`), pero uno en particular destaca: `Create Subkey`. El nombre genérico correspondiente a este permiso es `AppendData/AddSubdirectory`, que es exactamente lo que informó el script:
¿Qué significa exactamente? Significa que no podemos simplemente modificar el valor `ImagePath`, por ejemplo. Para hacerlo, necesitaríamos el permiso `WriteData/AddFile`. En su lugar, solo podemos crear una nueva subclave.
En este punto, sabemos que podemos crear subclaves arbitrarias en `HKLM\SYSTEM\CurrentControlSet\Services\RpcEptMapper`, pero no podemos modificar subclaves y valores existentes. Estas subclaves ya existentes son `Parameters` y `Security`, que son bastante comunes para los servicios de Windows.
Por lo tanto, la primera pregunta que vino a mi mente fue: _¿hay alguna otra subclave predefinida - como `Parameters` y `Security` - que podríamos aprovechar para modificar efectivamente la configuración del servicio y alterar su comportamiento de alguna manera?_
Para responder a esta pregunta, mi plan inicial fue enumerar todas las claves existentes e intentar identificar un patrón. La idea era ver qué subclaves son _significativas_ para la configuración de un servicio. Empecé a pensar en cómo podría implementarlo en PowerShell y luego ordenar el resultado. Sin embargo, antes de hacerlo, me pregunté si esta estructura de registro ya estaba documentada. Entonces, busqué en Google algo como `windows service configuration registry site:microsoft.com` y aquí está el primer [resultado](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/hklm-system-currentcontrolset-services-registry-tree) que salió.
¡Parece prometedor, verdad? A primera vista, la documentación no parecía exhaustiva y completa. Considerando el título, esperaba ver algún tipo de estructura de árbol detallando todas las subclaves y valores que definen la configuración de un servicio, pero claramente no estaba allí.
Aun así, eché un vistazo rápido a cada párrafo. Y rápidamente encontré las palabras clave "_**Performance**_" y "_**DLL**_". Bajo el subtítulo "**Perfomance**", podemos leer lo siguiente:
> **Performance**: _Una clave que especifica información para el monitoreo opcional de rendimiento. Los valores bajo esta clave especifican **el nombre de la DLL de rendimiento del controlador** y **los nombres de ciertas funciones exportadas en esa DLL**. Puede agregar entradas de valor a esta subclave usando entradas AddReg en el archivo INF del controlador._
Según este breve párrafo, uno teóricamente puede registrar una DLL en un servicio de controlador para monitorear su rendimiento gracias a la subclave `Performance`. **¡OK, esto es realmente interesante!** Esta clave no existe por defecto para el servicio `RpcEptMapper`, por lo que parece que es _exactamente_ lo que necesitamos. Hay un pequeño problema, sin embargo, este servicio definitivamente no es un servicio de controlador. De todos modos, todavía vale la pena intentarlo, pero necesitamos más información sobre esta función de "Monitoreo de rendimiento" primero.
> **Nota:** en Windows, cada servicio tiene un `Tipo` dado. Un tipo de servicio puede ser uno de los siguientes valores: `SERVICE_KERNEL_DRIVER (1)`, `SERVICE_FILE_SYSTEM_DRIVER (2)`, `SERVICE_ADAPTER (4)`, `SERVICE_RECOGNIZER_DRIVER (8)`, `SERVICE_WIN32_OWN_PROCESS (16)`, `SERVICE_WIN32_SHARE_PROCESS (32)` o `SERVICE_INTERACTIVE_PROCESS (256)`.
Después de buscar en Google, encontré este recurso en la documentación: [Creación de la clave de rendimiento de la aplicación](https://docs.microsoft.com/en-us/windows/win32/perfctrs/creating-the-applications-performance-key).
En primer lugar, hay una estructura de árbol agradable que enumera todas las claves y valores que debemos crear. Luego, la descripción da la siguiente información clave:
Si sigue los enlaces que se incluyen en este recurso, incluso encontrará el prototipo de estas funciones junto con algunos ejemplos de código: [Implementación de OpenPerformanceData](https://docs.microsoft.com/en-us/windows/win32/perfctrs/implementing-openperformancedata).
Gracias a todos los fragmentos de información que pude recopilar a lo largo de la documentación, escribir una DLL simple de prueba de concepto debería ser bastante sencillo. Pero aún así, ¡necesitamos un plan!
Cuando necesito explotar algún tipo de vulnerabilidad de secuestro de DLL, suelo empezar con una función de ayuda de registro simple y personalizada. El propósito de esta función es escribir información clave en un archivo cada vez que se invoca. Por lo general, registro el PID del proceso actual y del proceso padre, el nombre del usuario que ejecuta el proceso y la línea de comandos correspondiente. También registro el nombre de la función que desencadenó este evento de registro. De esta manera, sé qué parte del código se ejecutó.
En mis otros artículos, siempre omití la parte de desarrollo porque asumí que era más o menos obvia. Pero también quiero que mis publicaciones en el blog sean amigables para principiantes, así que hay una contradicción. Remediare esta situación aquí detallando el proceso. Entonces, iniciemos Visual Studio y creemos un nuevo proyecto de "Aplicación de consola C++". Tenga en cuenta que podría haber creado un proyecto de "Biblioteca de vínculo dinámico (DLL)", pero en realidad encuentro más fácil empezar con una aplicación de consola.
Por supuesto, eso no es lo que queremos. Queremos crear una DLL, no un EXE, por lo que tenemos que reemplazar la función `main` con `DllMain`. Puede encontrar un código esqueleto para esta función en la documentación: [Inicializar una DLL](https://docs.microsoft.com/es-es/cpp/build/run-time-library-behavior#initialize-a-dll).
En paralelo, también necesitamos cambiar la configuración del proyecto para especificar que el archivo compilado de salida debe ser un DLL en lugar de un EXE. Para hacerlo, puedes abrir las propiedades del proyecto y, en la sección "**General**", seleccionar "**Biblioteca dinámica (.dll)**" como el "**Tipo de configuración**". Justo debajo de la barra de título, también puedes seleccionar "**Todas las configuraciones**" y "**Todas las plataformas**" para que esta configuración se aplique globalmente.
Entonces, podemos poblar la DLL con las tres funciones que vimos en la documentación. La documentación también indica que deberían devolver `ERROR_SUCCESS` si tienen éxito.
Bien, ahora el proyecto está correctamente configurado, `DllMain` está implementado, tenemos una función auxiliar de registro y las tres funciones requeridas. Sin embargo, falta una última cosa. Si compilamos este código, `OpenPerfData`, `CollectPerfData` y `ClosePerfData` solo estarán disponibles como funciones internas, por lo que necesitamos **exportarlas**. Esto se puede lograr de varias maneras. Por ejemplo, podríamos crear un archivo [DEF](https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files) y luego configurar el proyecto adecuadamente. Sin embargo, prefiero usar la palabra clave `__declspec(dllexport)` ([doc](https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport)), especialmente para un proyecto pequeño como este. De esta manera, solo tenemos que declarar las tres funciones al principio del código fuente.
Finalmente, podemos seleccionar _**Release/x64**_ y "_**Build the solution**_". Esto producirá nuestro archivo DLL: `.\DllRpcEndpointMapperPoc\x64\Release\DllRpcEndpointMapperPoc.dll`.
Antes de continuar, siempre me aseguro de que mi carga útil funcione correctamente probándola por separado. El poco tiempo invertido aquí puede ahorrar mucho tiempo después al evitar que se adentre en un callejón sin salida durante una fase hipotética de depuración. Para hacerlo, simplemente podemos usar `rundll32.exe` y pasar el nombre del DLL y el nombre de una función exportada como parámetros.
¡Genial! El archivo de registro fue creado y, si lo abrimos, podemos ver dos entradas. La primera se escribió cuando la DLL fue cargada por `rundll32.exe`. La segunda se escribió cuando se llamó a `OpenPerfData`. ¡Se ve bien! 😊
Bien, ahora podemos centrarnos en la vulnerabilidad real y comenzar creando la clave y los valores de registro necesarios. Podemos hacer esto manualmente usando `reg.exe` / `regedit.exe` o programáticamente con un script. Dado que ya pasé por los pasos manuales durante mi investigación inicial, mostraré una forma más limpia de hacer lo mismo con un script de PowerShell. Además, crear claves y valores de registro en PowerShell es tan fácil como llamar a `New-Item` y `New-ItemProperty`, ¿verdad? ![:thinking:](https://github.githubassets.com/images/icons/emoji/unicode/1f914.png)
`Se denegó el acceso al registro solicitado`... Hmmm, ok... Parece que no será tan fácil después de todo. ![:stuck\_out\_out\_tongue:](https://github.githubassets.com/images/icons/emoji/unicode/1f61b.png)
Realmente no investigué este problema, pero supongo que cuando llamamos a `New-Item`, `powershell.exe` intenta abrir la clave de registro principal con algunos indicadores que corresponden a permisos que no tenemos.
De todos modos, si los cmdlets integrados no hacen el trabajo, siempre podemos bajar un nivel e invocar las funciones de DotNet directamente. De hecho, las claves de registro también se pueden crear con el siguiente código en PowerShell.
¡Aquí vamos! Al final, he creado el siguiente script para crear la clave y valores apropiados, esperar por alguna entrada del usuario y finalmente terminar limpiando todo.
El último paso ahora es **¿cómo engañamos al servicio RPC Endpoint Mapper para que cargue nuestra DLL de rendimiento?** Desafortunadamente, no he registrado todas las diferentes cosas que intenté. Hubiera sido realmente interesante en el contexto de esta publicación de blog resaltar lo tediosa y consumidora de tiempo que puede ser la investigación a veces. De todos modos, una cosa que encontré en el camino es que se pueden consultar _Contadores de rendimiento_ utilizando WMI (_Windows Management Instrumentation_), lo cual no es demasiado sorprendente después de todo. Más información aquí: [_Tipos de contadores de rendimiento de WMI_](https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-performance-counter-types).
> _Los tipos de contador aparecen como el calificador CounterType para propiedades en_ [_Win32\_PerfRawData_](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfrawdata) _clases, y como el calificador CookingType para propiedades en_ [_Win32\_PerfFormattedData_](https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-perfformatteddata) _clases._
Esperaba obtener una ejecución de código arbitrario como `NETWORK SERVICE` en el contexto del servicio `RpcEptMapper` como máximo, pero parece que obtuve un resultado mucho mejor de lo esperado. De hecho, obtuve una ejecución de código arbitrario en el contexto del servicio `WMI` en sí, que se ejecuta como `LOCAL SYSTEM`. ¡Qué increíble es eso! ![:sunglasses:](https://github.githubassets.com/images/icons/emoji/unicode/1f60e.png)
> **Nota:** si hubiera obtenido una ejecución de código arbitrario como `NETWORK SERVICE`, habría estado a solo un token de la cuenta `LOCAL SYSTEM` gracias al truco que James Forshaw demostró hace unos meses en esta publicación de blog: [Compartiendo una sesión de inicio de sesión un poco demasiado](https://www.tiraniddo.dev/2020/04/sharing-logon-session-little-too-much.html).
No sé cómo esta vulnerabilidad ha pasado desapercibida durante tanto tiempo. Una explicación es que otras herramientas probablemente buscaban acceso completo de escritura en el registro, mientras que `AppendData/AddSubdirectory` era suficiente en este caso. En cuanto a la "configuración incorrecta" en sí, supondría que la clave del registro se estableció de esta manera para un propósito específico, aunque no puedo pensar en un escenario concreto en el que los usuarios tengan algún tipo de permiso para modificar la configuración de un servicio.
Decidí escribir sobre esta vulnerabilidad públicamente por dos razones. La primera es que la hice pública, sin darme cuenta inicialmente, el día que actualicé mi script PrivescCheck con la función `GetModfiableRegistryPath`, que fue hace varios meses. La segunda es que el impacto es bajo. Requiere acceso local y solo afecta a versiones antiguas de Windows que ya no tienen soporte (a menos que haya comprado el Soporte Extendido...). En este punto, si todavía está utilizando Windows 7 / Server 2008 R2 sin aislar adecuadamente estas máquinas en la red primero, entonces evitar que un atacante obtenga privilegios de SYSTEM probablemente sea lo menos de sus preocupaciones.
Aparte del lado anecdótico de esta vulnerabilidad de escalada de privilegios, creo que esta configuración de registro de "Rendimiento" abre oportunidades realmente interesantes para la post-explotación, el movimiento lateral y la evasión de AV/EDR. Ya tengo algunos escenarios particulares en mente, pero aún no los he probado. ¿Continuará?...
- ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
- **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
- **Comparte tus trucos de hacking enviando PR al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.