Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
botnet-hackpack — Construye un botnet básico de Comando y Control en C | Kitploit
Herramientas/GitHubGitHub/treehacks/botnet-hackpack
Mecanismos de PersistenciaAnálisis de MalwareComando y ControlAprendizaje y EducaciónRed TeamingDesarrollo de Payloads
GitHubtreehacks/botnet-hackpack

botnet-hackpack

Construye un botnet básico de Comando y Control en C

Ver Repositorio
40395hace 5 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

BOTNET C&C SIMPLE

Este hackpack te guiará a través de la implementación de un marco básico que caracteriza fundamentalmente a una botnet. Puede ayudarte si has trabajado con C antes. Si te gustó este tutorial, ¡asegúrate de darle una estrella a este repositorio!

Nota: No uses nada de lo que aprendas aquí con fines malintencionados. Este hackpack es únicamente un caso de estudio de botnets con fines educativos. Los conceptos aprendidos en este hackpack tienen casos de uso de gran alcance (básicamente cualquier cosa relacionada con las redes). Lo más importante, este hackpack está pensado para ser probado e implementado localmente (así que por favor no compartas nada de lo que construyas relacionado con este hackpack con otros hackers). La privacidad es importante, así que respétala.

¿Qué es una botnet?

Antes de construir una botnet, es importante entender qué es una botnet. Una botnet es una red de computadoras capaces de recibir comandos de forma remota y desplegarlos localmente. Opcionalmente, pueden elegir retransmitir información a otros nodos de la red. Se han utilizado para todo, desde ataques de Denegación de Servicio Distribuida hasta el despliegue generalizado de software espía. Puede que hayas oído hablar de muchas botnets en el pasado. Las más destacadas son quizás Mirai y Gameover Zeus, que controlaban 3.8 mil y 3.6 millones de dispositivos IoT, respectivamente. Hay mucha variación en cómo las botnets implementan ciertas tareas. Pero para construir nuestra botnet con éxito, necesitamos asegurar las siguientes características en nuestra red funcional.

Nuestra botnet debería:

  1. Incluir un nodo maestro que controle todos los demás nodos de la red
  2. Desplegar malware disfrazado/nodos esclavos en computadoras anfitrionas
  3. Transmitir comandos desde el nodo maestro al nodo esclavo, ejecutarlos y devolver una salida al maestro

Esta estructura es característica de lo que se conoce como botnets de Comando y Control (C&C). Estas botnets tienen un servidor maestro y muchos servidores esclavos. Sin embargo, este estilo de botnets es anticuado y puede ser derribado fácilmente cortando el acceso al dominio maestro. Las botnets más recientes y sofisticadas siguen una arquitectura peer-to-peer, donde los derechos de administrador se distribuyen entre todos los nodos o un subconjunto de ellos en la red. Estas botnets suponen un gran dolor de cabeza para los expertos en seguridad porque no hay un punto central de control y pueden crecer hasta millones de nodos. Derribar tales botnets es una lectura interesante por sí misma. Sin embargo, para los propósitos de este hackpack, mantengamos las cosas simples. Implementaremos un nodo esclavo simple para una botnet C&C.

alt tag

Implementación

Maestro

Este hackpack se ocupará principalmente de implementar el malware del cliente. Para el servidor maestro, podemos usar un servidor TCP de código abierto llamado Netcat. Netcat no tiene nada que ver con las botnets. Es solo una herramienta conveniente y establecida que podemos reutilizar para enviar paquetes de texto a los clientes y desde ellos (que es todo lo que un maestro realmente es). He ajustado ligeramente el servidor netcat y lo he compilado en un binario llamado "master". ¡No se necesita más trabajo aquí! Nuestro maestro está listo para usar.

Esclavo

Pasemos a la parte más interesante: recibir y ejecutar comandos remotos (nos preocuparemos por disfrazar nuestro malware más tarde). El objetivo aquí es hacer nuestro nodo esclavo lo más simple posible y cumplir con los requisitos detallados anteriormente. Ten en cuenta que muchas constantes han sido definidas en lib/macros.h, así que siéntete libre de usarlas. Todas las firmas de funciones implementadas se pueden encontrar en lib/connect.h o lib/utils.h.

1. Iniciación

Abre el archivo bot.c. Al iniciar un nuevo nodo en nuestro servidor, probablemente deberíamos nombrarlo para que el maestro sepa a qué clientes enviar comandos. Hay muchas convenciones de nomenclatura que se pueden usar. Usar una dirección IP es probablemente lo mejor porque es un identificador único para cada cliente. Sin embargo, para hacer las cosas más legibles para los humanos comunes, usemos el nombre de usuario de la computadora. Usando la función de C getenv() con el argumento "USER" se obtiene lo que la computadora tenga almacenado en la variable de entorno USER. Este es uno de los lugares donde se almacena el nombre de usuario, así que usémoslo. Además, ahora que tu esclavo está ejecutándose, busquemos al maestro. Para ello, debemos conocer la dirección IP de nuestro maestro. Cada dispositivo de red tiene una dirección IP. Es responsable de identificar otros nodos y el direccionamiento de ubicación. Además, el maestro puede tener muchos servidores ejecutándose en diferentes puertos. Así que no solo tenemos que conectarnos al maestro, sino que también debemos especificar el puerto correcto. Este puerto es elegido por el maestro, pero puede cambiarse. En este hackpack, queremos probar localmente. Así que usaremos tu computadora como nuestra red. La dirección IP local de cada computadora (a la que "localhost" también resuelve) es "127.0.0.1". En master, especifiqué que se ejecute en el puerto 9999. Con estas tres cosas (dirección IP del maestro, puerto del maestro y nombre del esclavo), podemos iniciar una tubería de comunicaciones entre el servidor y el cliente llamada socket. Pasa estos tres argumentos a la función init_socket() para crear un socket. init_function() no es un comando integrado de C. Más bien, necesitamos implementarlo. Luego, necesitamos asignar algo de espacio en la pila para contener los mensajes entrantes. Seamos bastante generosos aquí y usemos alrededor de 10KB de espacio de pila. Llama a este puntero de pila msg. Por último, hay una declaración para indicar que todo va bien.

root@kitploit:~
char* name = //Get the client's username and store it in name
int channel = //initiate a channel given SERVER, PORT, and name;
//Allocate stack space of size CMD_LENGTH to hold data of type char. Call the stack pointer msg
printf("%s joining the botnet\n", name);

Ahora cambia a lib/connect.c. Implementemos init_channel(). Primero he definido un búfer de pila de caracteres llamado msg de longitud CMD_LENGTH y una construcción especial de redes de C llamada server que contiene información sobre nuestra conexión con el maestro. Primero convierte la dirección IP pasada de un formato legible para humanos (con números y puntos) a un formato binario en orden de bytes de red. Esto se hace con una función especial de C llamada inet_addr() de la librería de sockets. Simplemente toma una dirección IP y la devuelve en binario utilizable por la red. En C, podemos especificar fácilmente una red rellenando los campos de una estructura llamada sockaddr_in. Nuestra instancia de esa estructura se llama server. Necesitamos rellenar 3 campos de esta estructura: server.sin_addr.s_addr (la dirección IP del maestro), server.sin_family (un valor de 1 byte que especifica el dominio de comunicaciones) y server.sin_port (el puerto al que nos conectaremos en el maestro). A sin_family se le pueden dar macros de C que proporciona la librería de sockets. Normalmente, como en este caso, establecemos este campo a AF_INET. Esto significa que nuestra conexión identifica los nodos de la red a través de sus direcciones IP, que es lo que queremos. Sin embargo, también es posible usar PF_INET, que es similar a AF_INET pero especifica que la red puede usar cualquier cosa dentro del protocolo para identificar nodos específicos. También hay muchas supuestas razones históricas de por qué existen ambos, pero eso es algo que realmente no conozco ni me importa. Solo usa . Por último, al establecer el puerto del servidor, debemos pasar a través de una función especial llamada (host to network short). Esto convierte los datos del orden de bytes del host al orden de bytes de red. Este lío de orden de bytes tiene que ver con algo llamado Endianness. Puedes leer más al respecto .

Por último, ¡necesitamos definir la conexión real entre maestro y esclavo! Para ello, define un socket de red a través del cual se puedan enviar datos. Piensa en el maestro como si tuviera muchos 'enchufes eléctricos'. Ahora, necesitamos construir un 'enchufe' en el esclavo que encaje en los 'enchufes de pared' del maestro. Podemos hacer esto usando la función socket() de la librería de sockets. ¡Qué conveniente! socket() toma 3 argumentos: dominio de comunicaciones, tipo de socket y un protocolo. Para el dominio de comunicaciones, probablemente ya lo adivinaste: AF_INET. Para el tipo de socket, queremos que nuestro socket simplemente transmita datos en ambas direcciones. Por lo tanto, usa la macro dada SOCK_STREAM. No nos preocupemos por el protocolo del socket. Esta es una red bastante fundamental, así que usemos un valor de 0 que denota el protocolo predeterminado. La función devuelve un int que representa el socket. Guarda este valor en channel. A continuación, queremos poner en marcha nuestro socket (conectando el esclavo al enchufe de pared del maestro). Llama a la función de C connect(). Esta toma tres argumentos: el channel, la estructura sockaddr y el tamaño de la estructura en bytes. Si connect() devuelve un entero positivo, ¡tu conexión con el maestro fue exitosa! Para probar nuestra nueva conexión, ¡enviemos un saludo al maestro! Llena nuestro búfer de mensajes y usa respond() (aún por implementar) para enviar a través de channel de vuelta al maestro. Finalmente, queremos que la función devuelva esta conexión exitosa.

root@kitploit:~
int init_channel (char *ip, int port, char *name) {
	char msg[CMD_LENGTH];
	struct sockaddr_in server;

	server.sin_addr.s_addr = //convert the ip to network byte order
	server.sin_family = //set the server's communications domain
  server.sin_port = //convert port to network byte order
  
  int channel = //define a SOCK_STREAM socket
  
  if(channel < 0) {
    perror ("socket:");
    exit(1);
  }
  
  int connection_status = //use the defined channel to connect the slave to the master server
  
  if (connection_status < 0) {
    perror ("connect:");
    exit(1);
  }

  //send a greeting message back to master by loading a string into msg (hint: snprintf will come in handy)
  respond (channel, msg);
  return channel;
}

2. Escuchando mensajes

Una vez que el esclavo está conectado al maestro, necesita estar escuchando constantemente mensajes y actuar de inmediato ante un comando. Entonces, usemos un bucle while infinito para recibir y analizar estos mensajes. En bot.c, debajo de la declaración printf, agrega un bucle while infinito que llame a dos funciones: recieve() y parse() en ese orden. Ambas funciones toman channel y el búfer de pila msg como argumentos. Puedes encontrar sus firmas de función en lib/utils.h. Esto debería verse algo así:

root@kitploit:~
Infinite Loop {
  recieve(...);
  parse(...);
}

Ve a utils.c para implementar recieve() y respond(). recieve() toma mensajes del canal y respond() envía mensajes de vuelta a través del canal. Los parámetros de respond() son la dirección del socket, s, y nuestro búfer de pila, msg_buf. Queremos usar la función de C write() para escribir lo que contenga el búfer de pila en el canal y devolver su estado. write() necesita 3 argumentos: dirección del socket, búfer de mensaje y longitud del mensaje.

root@kitploit:~
int respond(int s, char *msg_buf) {
    //write the contents of msg_buf into socket s and return status
}

recieve() también es una función auxiliar simple. Restablece el búfer msg (pista: usa memset()). Ahora, llama a la función read() de la librería de sockets para leer msg. read() toma 3 argumentos: dirección del socket, búfer de mensaje y la longitud máxima esperada del mensaje.

root@kitploit:~
int recieve(int s, char *msg) {
    //reset the msg buffer
    int read_status = //read contents of socket s into msg
    if (read_status) {
      perror("log:");
      exit(1);
    }
    return 0;
}

3. Ejecutando comandos

¡Casi listo! Nuestra botnet es bastante aburrida en este momento. Solo puede recibir y transmitir mensajes a través de un socket. Hagamos que realmente ejecute lo que recibe en el Terminal. Primero implementamos la función parse(). Hace exactamente lo que sugiere su nombre: analiza el comando. Podríamos hacer una simple verificación de errores para ver si un mensaje está mal formado. También queremos ignorar silenciosamente los mensajes que se reciben pero no están destinados a él. El mensaje tendrá el formato del maestro: (nombre de la botnet):(comando a ejecutar). Ya hice lo primero por ti. Si las dos verificaciones pasan, pasemos el comando a la función execute().

root@kitploit:~
int parse (int s, char *msg, char* name) {
  char *target = msg;
  
  //check whether the msg was targetted for this client. If no, then silently drop the packet by returning 0
  
  char *cmd = strchr(msg, ':');
  if (cmd == NULL) {
    printf("Incorrect formatting. Reference: TARGET: command");
    return -1;
  }
 
  //adjust the cmd pointer to the start of the actual command
  //adjust the terminated character to the end of the command
  //print a local statement detailing what command was recieved
  
  execute (s, cmd);
  return 0;
}

Ahora la parte genial. execute() debe canalizar cualquier comando que reciba hacia el terminal y escribir cualquier salida en el socket de vuelta al maestro. Crea un búfer de pila para almacenar cada línea de entrada. Luego usa la función de C popen() para ejecutar la entrada y almacenar la salida en el archivo f (hay muchas maneras de abordar esto en este punto. Puedes personalizar tu botnet para hacer cosas realmente geniales con la entrada del maestro y realizar colaboraciones/actualizaciones autónomas con otros nodos de la botnet. Siéntete libre de ser tan creativo como quieras. Por ahora nos ceñiremos a nuestro objetivo básico). Recorre f línea por línea y envía todo a través de tu socket. ¡Cierra f y listo!

root@kitploit:~
int execute (int s, char *cmd) {
  FILE *f = //use popen to run the command locally
  if (!f) return -1;
  while (!feof (f)) {
    //parse through f line by line and send any output back to master
  }
  fclose(f);
  return 0;
}

Compila tu nueva botnet con el siguiente comando de terminal:

root@kitploit:~
gcc -lcurl lib/connect.c lib/utils.c bot.c -o bin/slave

Ejecuta bin/master en una ventana de terminal y bin/slave en otras ventanas. Escribe comandos como (nombre de usuario del esclavo):(comando remoto de terminal). ¡Felicitaciones! ¡Acabas de construir una botnet!

4. Disfrazando tu malware

Hay cosas realmente geniales que puedes hacer para disfrazar y desplegar malware. De hecho, es un campo entero por derecho propio. Un ejemplo de lo que puedes hacer es enmascarar el malware como una imagen. Usemos una imagen de un panda. He añadido una función simple en utils.c que descarga con curl una imagen de un panda y la presenta en Preview. Esto le da al usuario la sensación de estar abriendo una imagen de un panda cuando, en realidad, el usuario está ejecutando tu malware. Para añadir esto, incluye las siguientes líneas de código en bot.c:

root@kitploit:~
char* open_cmd = alias_img();
system(open_cmd);
free(open_cmd);

A continuación, haz clic derecho en cualquier imagen y elige Obtener información. Haz lo mismo con bin/slave. Arrastra la miniatura de la imagen sobre la miniatura del ejecutable bin/slave. Esto debería cambiar su apariencia en el escritorio. Sin embargo, todavía nos falta la característica extensión de archivo .png. Cambia el nombre de tu ejecutable a

root@kitploit:~
panda⒈png

Ahora, esto parece un archivo png. Sin embargo, empleamos el carácter Unicode "1." en lugar de "." para ocultar el hecho de que esto sigue siendo un ejecutable Unix. Hay muchos trucos Unix más creíbles que se pueden emplear, como el carácter LEFT-TO-RIGHT OVERRIDE para enmascarar nombres de archivos ejecutables. En casos más extremos, puedes incrustar código dentro de imágenes y macros de archivo para que se ejecuten concurrentemente cuando se abra el archivo anfitrión (algo así como un caballo de Troya....). Sin embargo, como nadie en TreeHacks es un ciberdelincuente, no deberíamos preocuparnos mucho por esas técnicas ;).

5. Extensiones

Ahora que tienes una botnet completamente funcional, hay muchas extensiones con las que puedes desafiarte. Nuestra botnet sigue siendo bastante poco interesante. No puede hacer mucho a menos que el usuario haga clic en ella cada vez. Aquí hay algunas sugerencias:

1. Lograr persistencia.

Las botnets pueden convertirse realmente en fuentes confiables de actividad maliciosa para los atacantes si de alguna manera permanecen en una computadora incluso cuando esta se apaga. Intenta jugar con cómo puedes iniciar tu esclavo nuevamente cada vez al arrancar. De esta manera, una vez que un usuario hace clic en el malware, ha infectado su computadora hasta que la limpie. Una sugerencia para lograr esto es convertir tu proceso ejecutable en un daemon. Luego, genera un archivo de configuración que agregue tu ejecutable a una lista de daemons que deberían ejecutarse al inicio (las aplicaciones de almacenamiento en la nube, las plataformas de mensajería de equipo, etc. ya hacen esto). Aprende más sobre eso aquí.

2. Implementar una red peer to peer

Implementar una red peer to peer no es más que reorganizar el diseño de la red. Sin embargo, la clave de la red P2P es que el administrador/atacante puede lograr el control maestro a través de cualquier nodo de la red. Entonces, el atacante debería tener algún tipo de llave maestra e inicio de sesión cifrado que le permita el control maestro de cualquier nodo. Lee más sobre cómo funcionan las redes peer to peer aquí.

3. Añade varios niveles de engaño

La estructura maestro-esclavo que implementaste no es muy segura. Los esclavos pueden liberarse fácilmente eliminando el nodo maestro. De manera óptima, cambiarías a un diseño P2P. Sin embargo, también puedes aumentar ligeramente la seguridad del maestro dirigiendo sus comandos aleatoriamente a través de una serie de bots controlados por el atacante antes de que se desplieguen en la botnet. Esto dificulta que los expertos localicen el centro de comando y rastreen las llamadas de la botnet entre los nodos atacantes y los nodos clientes.

4. Explora protocolos de red adecuados

Quizás, lo más importante, quieras jugar más con las redes. Nuestra red es lo más simple posible. En muchos sentidos, es extremadamente débil y definitivamente no es rigurosa. Por lo tanto, es posible que quieras explorar protocolos establecidos para redes, como Internet Relay Chat (IRC), para construir una red más adecuada. Aunque lleva tiempo, es extremadamente educativo y una inversión bien empleada. Lee más sobre eso aquí: https://oramind.com/tutorial-how-to-make-an-irc-server-connection/.

5. Intenta implementar tu propio maestro

En este hackpack, usamos un proyecto de código abierto disponible gratuitamente para sustituir a nuestro servidor maestro. Sin embargo, hay muchos inconvenientes involucrados. Primero, no podemos personalizar nuestro servidor maestro para enviar comandos automatizados a través de nuestra red. Está limitado únicamente al uso de entrada de línea de comandos. Segundo, habrás notado que todos los esclavos en la botnet reciben cada comando. Nuestra condición para la ejecución es verificar si el nombre del objetivo coincide con el nombre del esclavo. Si es falso, el comando se descarta silenciosamente. Esto se conoce como red de difusión (broadcast). Algo más óptimo podría ser una red de multidifusión (multicast). En una red de difusión, un nodo retransmite paquetes a todos sus nodos conectados. En un sistema de multidifusión, se puede especificar un cierto subconjunto de nodos para recibir los paquetes. Además, usar una red de multidifusión mueve la asignación de comandos del cliente al servidor maestro, donde corresponde. Implementa tu propio maestro para cambiar la botnet de broadcast a multicast.

Para una guía completa de programación de redes, consulta esto: http://beej.us/guide/bgnet/output/html/multipage/index.html.

¡Espero que te hayas divertido!

Licencia

MIT

Acerca de HackPacks 🌲

Los HackPacks son construidos por el equipo de TreeHacks para ayudar a los hackers a construir grandes proyectos en nuestro hackathon que se lleva a cabo cada febrero en Stanford. Creemos que todos, sin importar su nivel de habilidad, pueden aprender a hacer cosas increíbles, y esta es una de las formas en que ayudamos a facilitar la cultura hacker. Publicamos nuestros hackpacks como código abierto (junto con nuestra tecnología interna) para que todos puedan aprender de ellos y usarlos! Siéntete libre de usarlos en tus propios hackathons, talleres y cualquier otra cosa que promueva la construcción :)

Si estás interesado en asistir a TreeHacks, puedes postularte en nuestro sitio web durante el período de aplicación.

Puedes seguirnos aquí en GitHub para ver todo el trabajo de código abierto que hacemos (¡amamos los issues, las contribuciones y los comentarios de cualquier tipo!), y en Facebook, Twitter e Instagram para ver actualizaciones generales de TreeHacks.

Descargar herramienta
printf
AF_INET
port
htons()
aquí
msg
init_channel()