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

Scanneur de port, v2 : 5 threads

Le scan est réparti sur 5 threads qui se partagent les ports grâce à un mutex, et l'attente par port passe de 2 secondes à 200 ms.

C Réseau Threads

Source

Lien vers le repo GitHub

Ce qui change

La technique de connexion (connect_with_timeout) reste celle de la version 1. Ce qui change, c'est la façon de répartir le travail : la v1 était trop lente pour un usage réel en CTF, ce qui m'a poussé à paralléliser le scan.

Utilisation

$ gcc mapping_network_5threads.c -o mapping_network_5threads -pthread
$ ./mapping_network_5threads 127.0.0.1 | grep OPENED
[+] PORT 8080 : OPENED
[+] PORT 9000 : OPENED

Sans grep, le programme affiche une ligne par port, soit 10 000 lignes. L'ordre des résultats peut varier d'une exécution à l'autre.

Limites

Code source

mapping_network_5threads.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 != 2) {
        printf("Usage: %s <IP_Address>\n", argv[0]);
        return 1;
    }
    char* ip_cible = argv[1];

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

    pthread_mutex_t mut;
    pthread_mutex_init(&mut, NULL);
    struct ScanArgs_Mutex args1 = {ip_cible, &mut};
    struct ScanArgs_Mutex args2 = {ip_cible, &mut};
    struct ScanArgs_Mutex args3 = {ip_cible, &mut};
    struct ScanArgs_Mutex args4 = {ip_cible, &mut};
    struct ScanArgs_Mutex args5 = {ip_cible, &mut};
    pthread_t thread1;
    pthread_t thread2;
    pthread_t thread3;
    pthread_t thread4;
    pthread_t thread5;
    pthread_create(&thread1, NULL, thread_scan, &args1);
    pthread_create(&thread2, NULL, thread_scan, &args2);
    pthread_create(&thread3, NULL, thread_scan, &args3);
    pthread_create(&thread4, NULL, thread_scan, &args4);
    pthread_create(&thread5, NULL, thread_scan, &args5);

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);
    pthread_join(thread5, NULL);


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