Creando un módulo para la extracción de claves privadas en Windows 10 con ibombshell

La semana pasada hablamos sobre la extracción de claves privadas SSH en Windows 10. Hoy quería enseñar lo sencillo que es crear un módulo de ibombshell, el cual será liberado este mes en cuanto Álvaro Nuñez y yo terminemos unos detalles. Recordando que ibombshell tiene dos modos de ejecución, uno el denominado everywhere con Powershell y el denominado silentlygracias a un C2 escrito en Python

Cuando hablamos de módulos hablamos de la posibilidad de incorporar funcionalidad al C2 de Python. En el caso de querer crear una nueva funcionalidad para el modo everywherese debe añadir en el Githubcorrespondiente, en nuestro caso será el de ElevenPaths, la función de Powershell necesaria. Como se explicó en el artículo dedicado a ibombshelles necesario tener clara la estructura de directorios y ficheros en el Github, ya que la consola hará uso de dicha estructura. 

Primera parte. Creación de la función

En primer lugar, vamos a crear una función para extraer las claves privadas SSH en Windows 10. Esta función se obtiene del conocimiento de esta técnica y tiene un requisito importante y es que el proceso dónde se ejecute dicha función se esté ejecutando con integridad alta. Es lógico aplicar una serie de comentarios en la función o en la ayuda de la función sobre este tema. 

El aspecto de la función puede ser algo parecido a lo que se puede ver en la imagen. La función extract-sshprivatekeycomprueba en primer lugar si existe el pathHKCU:\Software\OpenSSH\Agent\Keys. En caso de existir, recorre el número de claves almacenadas en la ruta. Por cada clave, se lista el valor de Commentque es el nombre de la clave en ASCII. Por último, se recupera el valor de clave en binario y se codifica en base64. Aquí acaba la función.

Hay que recordar que, posteriormente, habría que hacer uso del script parse_mem.pypara obtener el valor ASCII de la clave privada. Lo importante sería poder utilizar esta información en una vía remota, pero cabe la posibilidad de utilizar en el modo everywherede ibombshell


Si listamos las funciones disponibles en la shellcon el comando showcommandsnos aparece la siguiente ruta post/extract-sshprivatekey. Esto es gracias al mapeo que se puede encontrar en la raíz del repositorio, en el fichero functions.txt, en el que se relaciona las funciones con las rutas del repositorio. 

Una vez descargada a memoria la función, ésta se queda en el providerde funciones con el nombre sshprivatekey. Como he comentado anteriormente, si el entorno dónde se ejecuta la función tiene privilegios podremos ejecutarla, si no nos devolverá un error, tal y como se puede visualizar en la imagen. 


Ahora, vamos a suponer que tenemos privilegio en el proceso. Realizando el mismo proceso comentado anteriormente, el resultado es distinto, la función ejecutada en ibombshelldevuelve los nombres de las claves y el base64del binario de la clave privada. Con ese base64 se debe ejecutar parse_mem.pypara obtener la clave privada en ASCII. La función extract-sshprivatekeyes una versión nuestra que se ha realizado para este artículo y que queda dentro del repositorio para su uso en auditoría o pentesting. 


Segunda parte. Creando el módulo para nuestro panel en Python

Lo primero es entender el formato que tiene un módulo de ibombshellen Python. La idea es sencilla, que cuando el pentesterejecute el módulo en Pythonéste genere la función de Powershelly la instrucción para invocarla. Esta información es almacenada en un fichero que el warrior, o proceso que ejecutaibombshellen remoto, leerá mediante una petición HTTP.

Recuperando el esquema con el que jugamos en nuestro panel en Pythony la interacción con el warrior de ibombshellvemos la siguiente imagen. En esta imagen, se puede ver que es el warriorel que, cuando es ejecutado en la máquina remota, realiza una petición hacia nuestro C2 registrando la dirección IP y el nombre o ID. Esto es a través de una petición HTTP, a través de un GET. Posteriormente, tras el registro, el warrior realiza una petición HTTP para verificar si hay algún tipo de función o funciones que deba, primero cargar en memoria y posteriormente ejecutar. 


El usuario del C2 al configurar un módulo y ejecutar el run, lo que está haciendo es almacenar en un fichero la función correspondiente y las instrucciones que se deben ejecutar en el warrior de ibombshellen Powershell. Cuando el warriorlee el fichero, ya carga la función y las instrucciones las ejecuta. Posteriormente, el warriorenvía los resultados a través de un POST que se realiza al mismo recurso en el panel de Python

Ahora, entendamos qué partes tiene un módulo de ibombshellen Python. Se proporcionará una clase denominada CustomModule. El cual tiene el constructor y un método run_module. Como se puede ver, un módulo no será algo complejo. 

En el constructor tenemos una variable information, la cual es un diccionario que proporciona varios atributos y varios valores. Suele ser tema informativo, nombre del módulo, autor, descripción, etcétera. Por otro lado, se tiene la variable options. Esta variable es un diccionario que tiene los atributos del módulo. Por cada atributo se tiene una lista en el que se indica si el atributo tendrá algún valor, su descripción y si es obligatorio. 


El método run_module implementará lo que se va a ejecutar cuando el pentester haga ‘run’, una vez configurado el módulo. Lo primero que se hace en esta función es verificar si el warrior configurado por el usuario existe. Para ello se comprueban los ficheros creados por ibombshell sobre los que se comunicará el warrior ejecutado en remoto. El ID de dicho warrior debe existir en forma de fichero. 


Por último, se añade a la variable functionla instrucción que hará que el warriorremoto ejecute la función cargada. No es más que el propio nombre de la función. En este caso, depende de la configuración del módulo, ya que una función puede tener N formas de ser ejecutada. Es decir, una función puede ser ejecutada con varios parámetros o argumentos, por lo que utilizaremos selectores o bifurcaciones para los diferentes casos y acabaremos agregando a la variable functionla instrucción necesaria, en función de la configuración del módulo. 


A continuación, os dejo un video dónde se puede ver el funcionamiento del nuevo módulo y los resultados que éste proporciona. El repositorio de Github de ibombshell.