Domanda

Voglio scrivere uno strumento di analisi in tempo reale per il traffico wireless.

Qualcuno sa come leggere da un dispositivo promiscuo (o sniffing) in C?

So che è necessario disporre dell'accesso root per farlo. Mi chiedevo se qualcuno sapesse quali funzioni sono necessarie per farlo. Le prese normali non sembrano avere senso qui.

È stato utile?

Soluzione

Su Linux si utilizza un socket PF_PACKET per leggere i dati da un dispositivo non elaborato, ad esempio un'interfaccia Ethernet in esecuzione in modalità promiscua:

s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

Questo invierà copie di ogni pacchetto ricevuto fino al socket. Tuttavia, è molto probabile che tu non voglia davvero ogni pacchetto. Il kernel può eseguire un primo livello di filtraggio utilizzando BPF, il Berkeley Packet Filter . BPF è essenzialmente una macchina virtuale basata su stack: gestisce un piccolo set di istruzioni come:

ldh = load halfword (from packet)  
jeq = jump if equal  
ret = return with exit code  

Il codice di uscita di BPF dice al kernel se copiare o meno il pacchetto nel socket. È possibile scrivere direttamente programmi BPF relativamente piccoli, usando setsockopt (s, SOL_SOCKET, SO_ATTACH_FILTER,). (ATTENZIONE: il kernel prende uno struct sock_fprog, non uno struct bpf_program, non confonderli o il tuo programma non funzionerà su alcune piattaforme).

Per qualsiasi cosa ragionevolmente complessa, vuoi davvero usare libpcap. BPF è limitato in ciò che può fare, in particolare nel numero di istruzioni che può eseguire per pacchetto. libpcap si occuperà di suddividere un filtro complesso in due parti, con il kernel che esegue un primo livello del filtro e il codice dello spazio utente più capace che elimina i pacchetti che in realtà non voleva vedere.

libpcap estrae anche l'interfaccia del kernel dal codice dell'applicazione. Linux e BSD usano API simili, ma Solaris richiede DLPI e Windows usa qualcos'altro.

Altri suggerimenti

Una volta ho dovuto ascoltare su frame Ethernet grezzi e ho finito per creare un wrapper per questo. Chiamando la funzione con il nome del dispositivo, ex eth0 ho ricevuto in cambio un socket che era in modalità promiscua. Quello che devi fare è creare un socket raw e quindi metterlo in modalità promiscua. Ecco come l'ho fatto.

int raw_init (const char *device)
{
    struct ifreq ifr;
    int raw_socket;

    memset (&ifr, 0, sizeof (struct ifreq));

    /* Open A Raw Socket */
    if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1)
    {
        printf ("ERROR: Could not open socket, Got #?\n");
        exit (1);
    }

    /* Set the device to use */
    strcpy (ifr.ifr_name, device);

    /* Get the current flags that the device might have */
    if (ioctl (raw_socket, SIOCGIFFLAGS, &ifr) == -1)
    {
        perror ("Error: Could not retrive the flags from the device.\n");
        exit (1);
    }

    /* Set the old flags plus the IFF_PROMISC flag */
    ifr.ifr_flags |= IFF_PROMISC;
    if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1)
    {
        perror ("Error: Could not set flag IFF_PROMISC");
        exit (1);
    }
    printf ("Entering promiscuous mode\n");

    /* Configure the device */

    if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0)
    {
        perror ("Error: Error getting the device index.\n");
        exit (1);
    }

    return raw_socket;
}

Quindi quando hai il tuo socket puoi semplicemente usare select per gestire i pacchetti quando arrivano.

È possibile utilizzare la libreria pcap (consultare http://www.tcpdump.org/pcap.htm ) utilizzato anche da tcpdump e Wireshark.

Perché non dovresti usare qualcosa come WireShark ?

È open source, quindi almeno potresti imparare alcune cose da esso se non vuoi semplicemente usarlo.

WireShark su Linux ha la capacità di catturare le informazioni dell'intestazione PLCP (protocollo di convergenza del livello fisico).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top