Creando un PortScanner en C

Imagine una bahía donde atracan muchos barcos privados. La ubicación se llama puerto marítimo, literalmente un puerto en o sobre el mar. Todos los que quieren atracar allí y solicitan servicios de desembarque utilizan el mismo puerto. Los puertos marítimos funcionan con números de amarre asignados a embarcaciones individuales. El nombre del puerto y el número de amarre se combinan en el «quién, qué y dónde» de la identificación del barco.

El concepto de dirección IP y puerto es similar. Aquí, sea_port_name es similar a la dirección IP, mientras que la última coincide con network_port_no.

Los puertos están numerados para mantener la coherencia y la programación. Los puertos más utilizados y más conocidos son los numerados del 0 al 1023 dedicados al uso de Internet, pero pueden extenderse mucho más para fines especializados. A cada conjunto o intervalo de puertos se le asignan tareas o funciones especializadas y, por lo general, eso es todo lo que hacen. Por lo general, todos los servicios o funciones del sistema idénticos usan los mismos números de puerto en los servidores receptores y se mantienen consistentes en cualquier situación.

Cuando un delincuente apunta a una casa para un robo, generalmente lo primero que verifica es si hay una ventana o puerta abierta a través de la cual se puede acceder a la casa. Los técnicos de seguridad a menudo usan dispositivos/software, conocidos como escáneres de puertos, que les permiten escanear todos los puertos para auditar las computadoras en busca de vulnerabilidades. Cada vez que hay puertos abiertos en la computadora personal, existe la posibilidad de pérdida de datos, la aparición de un virus y, en ocasiones, incluso el compromiso total del sistema.

Desarrollar un escáner de puertos no es tan difícil como parece. El resultado final del escáner será el siguiente:

INPUT : IPv4 address, Port Range
FUNCTION : Enter an IP address and a port range 
           where the program will then attempt to
           find open ports on the given computer 
           by connecting to each of them. On any 
           successful connection ports, mark the 
           port as open.
OUTPUT : Status of port (open/closed)

El proceso de tres pasos para crear un escáner de puertos

Paso 1: Creando el main()

Creamos una función main() que toma los argumentos requeridos (server_ip, start_port, end_port). La IP del servidor debe ser IPv4, aunque también podemos extenderla para que acepte IPv6. Inténtalo tú mismo !!

int main(int argc, char *argv[])
{
    if (argc < 4)
    {
        printf ("Please enter the server IP address"
                " and range of ports to be scanned\n");
        printf ("USAGE: %s IPv4 First_Port Last_Port\n", 
                argv[0]);
        exit(1);
    }
    char tIP[16] = {0};
    strcpy(tIP, argv[1]); // Copy the IPv4 address
    char First_Port[6] = {0};
    strcpy(First_Port, argv[2]); // Copy the start_port
    char Last_Port[6] = {0};
    strcpy(Last_Port, argv[3]); // Copy the end_port

    // Start port-scanner
    port_scanner(tIP, First_Port, Last_Port);
    return 0;
}

Paso 2: Creación de port_scanner()

  • Cree una nueva función, port_scanner(). Atravesamos todos los puertos en el rango proporcionado y luego verificamos cada uno de ellos.
  • Cree una «sugerencia de estructura addrinfo» e inicialícela con los valores adecuados.
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

‘sugerencias’ es un puntero opcional a una estructura addrinfo, tal como lo define . Esta estructura se puede utilizar para proporcionar sugerencias sobre el tipo de socket que admite o desea utilizar la persona que llama. – desde la página de manual de FreeBSD.

  • Inicialice un puntero para server_address que obtendremos del servidor.
    Ahora, llame a «getaddrinfo(tIP, tport, &hints, &serv_addr)» con los parámetros adecuados. La función getaddrinfo() asigna e inicializa una lista enlazada de estructuras addrinfo, una para cada dirección de red que coincida con el Node y el servicio, sujeto a las restricciones impuestas por las sugerencias, y devuelve un puntero al inicio de la lista en el cuarto parámetro, en este caso “ serv_addr” . Los elementos de la lista vinculada están vinculados por el campo ai_next .

Información adicional:
Hay varias razones por las que la lista enlazada puede tener más de una estructura addrinfo, que incluyen: el host de la red es multitarjeta, accesible a través de múltiples protocolos (p. ej., tanto AF_INET como AF_INET6); o el mismo servicio está disponible desde múltiples tipos de socket (una dirección SOCK_STREAM y otra dirección SOCK_DGRAM, por ejemplo).
Normalmente, la aplicación debería intentar usar las direcciones en el orden en que se devuelven.

Paso 3: Conexión contra los enchufes

Recorra toda la información de addrinfo recibida en la lista vinculada y cree un socket. Los valores para el «socket()» están presentes en la estructura addrinfo obtenida anteriormente. (Cada Node de la lista_enlazada se recorre usando el puntero «temp».)

sockfd = socket(temp->ai_family, temp->ai_socktype, 
                temp->ai_protocol);
if (sockfd < 0) 
{
     printf("Port %d is NOT open.\n", port);
     continue; 
}

Si falla la creación del socket, intente usar los valores en otros Nodes. Una vez que la creación del socket tenga éxito, intente conectarse a él usando «conectar()». Si la conexión es exitosa, entonces felicidades, el socket está ABIERTO, de lo contrario intente con los otros Nodes addrinfo. Si ninguno de ellos funciona desde la lista_enlazada, entonces el socket está CERRADO. Aquí está el código para el mismo,

status = connect(sockfd, temp->ai_addr, 
                 temp->ai_addrlen);
if (status<0) 
{
    printf("Port %d is NOT open.\n", port);
    close(sockfd);
    continue;
}

printf("Port %d is open.\n", port);
close(sockfd);

La función “freeaddrinfo()” libera la memoria que se asignó para la lista enlazada asignada dinámicamente “serv_addr”. Es una buena práctica usar esto en lugar de “gratis()”.

El código fuente completo de este tutorial se puede descargar desde aquí .

Nota: El código de este programa no es largo, pero es muy importante cómo se derivan las direcciones usando getaddrinfo. Casi todas las aplicaciones de red en c tienen primeros 2 pasos similares. El tercer paso depende del propósito de la aplicación .

Para obtener más información sobre la estructura devuelta por freeaddrinfo, lea esta documentación y los detalles de los argumentos de socket, consulte esta documentación.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *