kuji@portfolio:~/projets$ cat portscan-v3.md

Scanneur de port, v3 : multithread

Le nombre de threads devient un paramètre de la ligne de commande, pour adapter le scan à la machine et au réseau.

C Réseau Threads

Source

Lien vers le repo GitHub

Ce qui change

Le fonctionnement (compteur partagé, mutex, timeout de 200 ms) est celui de la version 2. Seule la gestion des threads évolue : figer le nombre de threads à 5 dans le code m'obligeait à recompiler à chaque fois, ce qui n'était pas pratique en CTF.

Utilisation

$ gcc mapping_network_multithread.c -o mapping_network_multithread -pthread
$ ./mapping_network_multithread 127.0.0.1 20 | grep -e SCAN -e OPENED
BEGINNING IP SCAN : 127.0.0.1 with 20 threads
[+] PORT 8080 : OPENED
[+] PORT 9000 : OPENED
SCAN FINISHED.

Ici, 20 threads scannent les ports de 1 à 10 000. Le filtre grep ne garde que les ports ouverts et les lignes de début et de fin.

Limites

Code source

mapping_network_multithread.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <pthread.h>


struct ScanArgs_Mutex{ char* ip_to_scan; pthread_mutex_t* mut;};

int last_port = 10000;
int first_port = 1;

int connect_with_timeout(int s, struct sockaddr_in* addr, int timeout_sec){

    int flags = fcntl(s, F_GETFL, 0);
    fcntl(s, F_SETFL, flags | O_NONBLOCK);

    int res = connect(s, (struct sockaddr*)addr, sizeof(*addr));
    if (res < 0 && errno != EINPROGRESS){
        return -1;
    }

    if (res == 0){
        fcntl(s, F_SETFL, flags);
        return 0;
    }

    fd_set fdset;
    FD_ZERO(&fdset);
    FD_SET(s, &fdset);

    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = timeout_sec;

    res = select(s + 1, NULL, &fdset, NULL, &tv);

    fcntl(s, F_SETFL, flags);

    if (res <= 0){
        return -1;
    }
    int so_error;
    socklen_t len = sizeof(so_error);
    getsockopt(s, SOL_SOCKET, SO_ERROR, &so_error, &len);
    if (so_error != 0){
        return -1;
    }

    return 0;
}


void* thread_scan(void* arg_g){
    struct ScanArgs_Mutex* args = (struct ScanArgs_Mutex*) arg_g;
    struct sockaddr_in configuration_serveur;

    while(1){
        pthread_mutex_lock(args->mut);
        if (first_port > last_port){
            pthread_mutex_unlock(args->mut);
            break;

        }
        int port_to_scan = first_port;
        first_port++;
        pthread_mutex_unlock(args->mut);

        int s = socket(AF_INET, SOCK_STREAM, 0);
        if(s < 0){
            printf("Error while creating socket. Port %d\n", port_to_scan);
            continue;
        }

        memset(&configuration_serveur, 0, sizeof(configuration_serveur));
        configuration_serveur.sin_addr.s_addr = inet_addr(args->ip_to_scan);
        configuration_serveur.sin_family = AF_INET;
        configuration_serveur.sin_port = htons(port_to_scan);

        if (connect_with_timeout(s, &configuration_serveur, 200000) == 0){
            printf("[+] PORT %d : OPENED\n", port_to_scan);
        }
        else{
           printf("[+] PORT %d CLOSED\n", port_to_scan);
        }

        close(s);
    }
    return NULL;
}


int main(int argc, char* argv[]){
    if (argc != 3) {
        printf("Usage: %s <IP_Address> <Nb_Threads>\n", argv[0]);
        return 1;
    }
    char* ip_cible = argv[1];
    int nb_threads = atoi(argv[2]); //(texte -> int)

    printf("BEGINNING IP SCAN : %s with %d threads\n", ip_cible, nb_threads);
    printf("--------------------------\n");

    pthread_mutex_t mut;
    pthread_mutex_init(&mut, NULL);
    struct ScanArgs_Mutex shared_args = {ip_cible, &mut};
    pthread_t* threads = malloc(sizeof(pthread_t) * nb_threads);
    for(int i = 0; i < nb_threads; i++){
        pthread_create(&threads[i], NULL, thread_scan, &shared_args);
    }
    for (int i = 0; i < nb_threads; i++) {
        pthread_join(threads[i], NULL);
    }


    printf("--------------------------\n");
    printf("SCAN FINISHED.\n");
    free(threads);
    pthread_mutex_destroy(&mut);
    return 0;
}