
API de Python para uso con la especificación External C2 de Cobalt Strike
Framework en Python para usar con la especificación External C2 de Cobalt Strike, según se describe en la especificación.
El objetivo principal del diseño es ser una implementación muy modular de la especificación external c2 que proporcione suficiente abstracción para implementar fácilmente canales C2 para Cobalt Strike. Idealmente, todo lo que un usuario tendría que hacer es crear un módulo transport, un módulo encoder y completar un archivo de configuración para implementar un nuevo canal.
Necesitarás realizar varios cambios de configuración antes de ponerlo en funcionamiento. Necesitarás:
builds/client/dbox/dbox_client.py, cambiar token por el generado en el paso 2.builds/server/utils/transports/transport_dbox.py hacer el mismo cambio que en el paso 3.cd builds/client/dbox && ./compile_dll.shstart_externalc2.cna desde tu cliente CS.cd builds/server/ && ./dbox_server.pyEnlace al video de demostración: https://www.youtube.com/watch?v=nTRHSh_uCcA
Este proyecto consta de tres partes principales:
El builder construye dinámicamente las implementaciones del cliente y del servidor según la configuración especificada. Idealmente, el cliente podría distribuirse como un único archivo compilado, como un dll o exe.
El cliente es esencialmente el payload que se ejecuta en el endpoint, denominado third-party client dentro de la especificación. La lógica del cliente es principalmente estática:
transporttransporttransport en busca de nuevas tareastransportLas configuraciones necesarias para los mecanismos de transporte y codificación se copian estáticamente en el cliente. La lógica de las funciones para los mecanismos de transporte y codificación también se copian estáticamente desde sus respectivos módulos.
La lógica de inyección de procesos se determina desde el builder.
El servidor es la aplicación que actúa como intermediario en la comunicación entre el cliente y el servidor c2, denominado third-party Client Controller dentro de la especificación. La lógica del servidor es principalmente estática, pero admite salida verbose y debug para ayudar en el desarrollo:
encodertransporttransportencodertransporttransportencoderLa determinación de qué módulo encoder y transport importa el servidor se obtiene de los valores almacenados en config.py.
No se importan módulos transport o encoder no utilizados.
Las siguientes tablas describen las funciones compartidas entre los módulos encoding y transport, y el cliente. Las funciones compartidas son esencialmente el mismo código exacto.
UNA NOTA MUY IMPORTANTE: Los datos enviados a las funciones sendData y recvData del cliente deben ser datos sin procesar, mientras que los datos enviados a las funciones sendData y retrieveData del módulo de transporte deben estar ya codificados o decodificados según sea necesario.
| Función Transport | Función Cliente | Descripción |
|---|---|---|
| prepTransport |
| Función Codificador | Función Cliente | Descripción |
|---|---|---|
| encode | encode | Define las modificaciones realizadas a los datos sin procesar para prepararlos para el transporte |
| decode | decode | Define las modificaciones realizadas a los datos sin procesar recibidos del transporte para ser reenviados a su destino |
Primero, determina qué módulo de transporte y codificación deseas usar. Usaremos transport_gmail y encoder_b64url para el siguiente ejemplo.
A continuación, modifica server/config.py según tus necesidades, asegurándote de que ENCODER_MODULE y TRANSPORT_MODULE estén configurados correctamente y apunten a tus módulos deseados:
EXTERNAL_C2_ADDR = "127.0.0.1"
EXTERNAL_C2_PORT = "2222"
C2_PIPE_NAME = "foobar"
C2_BLOCK_TIME = 100
C2_ARCH = "x86"
IDLE_TIME = 5
ENCODER_MODULE = "encoder_b64url"
TRANSPORT_MODULE = "transport_gmail"
verbose = False
debug = False
A continuación, modifica la sección de configuración para tu módulo transport y encoder seleccionados.
Asegúrate de que la sección de configuración en client/mechanism/$mechanism_client.py coincida con las configuraciones que hayas definido hasta ahora.
En la máquina que ejecuta el servidor, ejecuta:
python server.py
Para una salida más detallada, puedes ejecutar:
python server.py -v
Para una salida más detallada y adicional útil para depuración, puedes ejecutar:
python server.py -d
A continuación, ejecuta el cliente en el endpoint de destino.
Si todo funcionó, se registrará un nuevo beacon en la consola de Cobalt Strike con el que podrás interactuar.
¿Por qué escribirías esto?: No había muchas implementaciones publicadas de la especificación, y de las que están publicadas, o no están en un lenguaje que conozco o no tienen la modularidad y abstracción que buscaba.
¿Por qué Python 2?: Soy vago y es fácil implementar nuevos canales de transporte y codificación en él.
Tu código apesta: Eso no es una pregunta.
¿Puedo enviar nuevos módulos de transporte y/o codificador?: ¡Sí, por favor! Envía un pull request y estaré encantado de revisarlo.
Se implementará una abstracción y modularidad similar en el componente cliente también, para soportar diferentes métodos de inyección de procesos para el payload del beacon y otras características en la hoja de ruta.
Actualmente, falta la funcionalidad del builder, que está planificada para construir dinámicamente implementaciones del cliente y del servidor, pero está en la hoja de ruta.
| prepTransport |
| Realiza las preconfiguraciones necesarias para utilizar el mecanismo de transporte |
| sendData | sendData | Define cómo se envían los datos a través del mecanismo de transporte |
| retrieveData | recvData | Define cómo se reciben los datos a través del mecanismo de transporte |