Pokaż wyniki 1 do 2 z 2

Temat: [C++]Sniffer z biblioteką libpcap

  1. #1

    Domyślnie [C++]Sniffer z biblioteką libpcap

    [ Pomyślałem, że umieszcze to tu, może komuś się przyda, chociaż niektórzy to już widzieli, jest to już stare ]


    Sniffer w cpp z wykorzystaniem libpcap


    Biblioteka libpcap pozwala na przechwytywanie pakietów, pracę w trybie PROMISC, ogólnie będzie odpowiedzialna za całą brudną robotę związaną z naszym snifferem.
    Instalacja.
    No więc musimy zainstalować potrzebne pakiety:
    Kod:
    aptitude install libpcap0.8 libpcap-dev
    Każdy instaluje sposobem według uznania, można skompilować ze żródeł.

    A więc nasz sniffer podzielimy na dwa moduły, części. Pierwszy będzie odpowiedzialny za przygotowanie karty sieciowej do nasłuchu, zainstalowaniu filtrów, oraz uruchomi funkcję przechwytującą pakiety. Moduł drugi będzie to funkcja obsługująca każdy złapany pakiet z osobna. Funkcja prowadząca nasłuch (ta z modułu pierwszego) będzie uruchamiała funkcję z modułu drugiego dla każdego odebranego pakietu. Tak więc eksperymentować najlepiej jest na funkcji obsługującje pakiety.
    A więc kod modułu pierwszego wraz z komentarzami.(tą część lepiej zostawić w spokoju).

    Kod:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <pcap.h>  //tutaj mamy plik nagłówkowy biblioteki
    
    void packet_handler(u_char* param,const struct pcap_pkthdr* header,const u_char* pkt_data);
    //deklaracja procedury odpowiedzialnej za obsługę pakietu
    //jej implementacja będzie później
    
    //przyjmujemy założenie, że pierwszym argumentem będzie nazwa urządzenia (eth0, ath0), a drugim filtr
    // oczywiście jeżeli filtr będzie wielowyrazowy ujmujemy go w apostrofy, np. 'ip and tcp', 'tcp and port 80'
    int main(int argc,char* argv[])
    {
    if(argc<3)
    {
    printf(" Uzycie: %s <urzadzenie> <filtr>.\n",argv[0]);
    exit(1);
    }
    char* dev=argv[1]; nazwa urzadzenia
    pcap_t* fp;
    char errbuf[PCAP_ERRBUF_SIZE]; //jeżeli będziemy chcieli obsługiwać błędy
    int res;
    u_int netmask,ip_addr;
    struct bpf_program fcode;
    char* packet_filter=argv[2];
    
    if(pcap_lookupnet(dev,&ip_addr,&netmask,errbuf)==-1)
    {
    printf("Nie można uzyskać maski: %s\n",errbuf);
    ip_addr=0;
    netmask=0;
    }
    //otwieramy urządenie
    if((fp=pcap_open_live(dev,65536,1,1000,errbuf))==NULL)
    {
    printf("Nie można otworzyć urządzenia: %s\n",errbuf);
    exit(1);
    }
    //kompilacja filtra
    if(pcap_compile(fp,&fcode,packet_filter,0,netmask)<0)
    {
    printf("Składnia filtru jest niepoprawna.\n");
    pcap_close(fp);
    exit(1);
    }
    //ustawienie filtra
    if(pcap_setfilter(fp,&fcode)<0)
    {
    printf("Blad podczas ustawiania filtru.\n");
    pcap_close(fp);
    exit(1);
    }
    printf("\n\nNasłuchiwanie na %s.\n\n"dev);
    pcap_loop(fp,0,packet_handler,NULL); //i to jest funkcja przechwytująca pakiety
    // i wysyłająca je do procedury packet_handler
    //zakończy się gdy wciśniemy Ctrl+C
    pcap_close(fp);
    return 0;
    }
    Ok, główna część programu jest utworzona, teraz przejdziemy do części trudniejsze i ciekawszej, czyli do implementacji funkcji packet_handler.
    Właśnie w tej procedurze będziemy rozpoznawali protokół odczytywali adres ip, numer portu itp
    Jak pokażę tylko jak rozpoznać adres ip źródłowy i docelowy, myślę, że wstawienie dodatkowych opcji będzie łatwe. sam zrobiłem rozpoznawanie wiadomości ICMP
    No to lecimy dalej z kodem
    Kod:
    // nagłówek IP
    // jakby ktoś chciał to może poszukać sobie gotowca w źródłach systemu
    struct ipheader
    {
    unsigned char ip_hl:4,ip_v:4;
    unsigned char ip_tos;
    unsigned short int ip_len;
    unsigned short int ip_id;
    insigned short int ip_off;
    unsigned char ip_ttl;
    unsigned char ip_p;
    unsigned short int ip_sum;
    unsigned int ip_src;
    unsigned int ip_dst;
    };
    //chyba nie muszę tłumaczyć budowy nagłówka IP?
    //jakby ktoś nie wiedział to jest wikipedia
    
    void packet_handler(u_char* param,const struct pcap_pkthdr* header,const u_char* pkt_data)
    //jako trzeci parametr otrzymujemy cały pakiet, pozostałe dwa - nie wiem co oznaczają
    {
    ipheader* ih;
    char sourceIP[16],destIP[16];
    sockaddr_in source_addr,dest_addr;
    ih=(struct ipheader*)(pkt_data+14); //pomijamy 14 bajtów zarezerwowane dla nagłówka ethernet
    //z góry zakładan, że to ethernet, chyba mało z was ma token ring czy FDDI
    source_addr.sin_addr.s_addr=ih->ip_src;
    dest_addr.sin_addr.s_addr=ih->ip_dst;
    strncpy(sourceIP,inet_ntoa(source_addr.sin_addr),16);
    strncpy(destIP,inet_ntoa(dest_addr.sin_addr),16);
    //właśnie uzyskaliśmy adresy IP, teraz można je wyświetlić
    printf("%-16s   >>    %-16s\n",sourceIP,destIP);
    }
    No i teraz najważniejsza rzecz - kompilacja
    Kod:
    g++ sniffer.cpp -o sniffer -lpcap
    uruchamiać na konce root!!! Przykład
    Kod:
    ./sniffer ath0 'tcp and port 8074'
    Dalsze eksperymenty
    No więc najlepiej jest dodawać nowe rzeczy do procedury packet_handler. Tam możemy odczytać z pakietu interesujące dane. Przyda się wiedza o budowie protokołów sieciowych.
    No i teraz możecie napisać sniffer gg, łapacz haseł, nawet aplikację do pasywnego rozpoznawania systemu.
    Uwaga: kod całkowicie został napisany własnoręcznie więc mogą występować błędy. Jakby ktoś miał jakiś problem - pisać.
    "a imię jego będzie czterdzieści i cztery"
    A. Mickiewicz Dziady cz. III

  2. #2

    Domyślnie

    Hej!

    Tak sobie myślę, że może przydałby się komuś jakiś tutorial pisania sniffera pod windowsem, z biblioteką winpcap. Już napisałem o libpcap pod Linuksem, ale jak widzę nie każdy korzysta z tego systemu. Ja sam wolę używać Linuksa. Do tego karta sieciowa nie działa mi pod windą w trybie PROMISC. Znudziła mi się już nauka do matury i chce napisać coś przydatnego.

    Na początek odsyłam do pierwszej części, ponieważ zasada pisania sniffera jest taka sama. Różnica tkwi w przygotowaniu karty do nasłuchu.

    1. Instalacja biblioteki i konfiguracja środowiska.
    Potrzebne na pliki znajdziemy na stronie: http://www.winpcap.org/. W menu po lewej stronie klikamy Get WinPcap, następnie pobieramy najnowszą stabilną wersję (jak widzę teraz 4.0.2). Zapisujemy, instalujemy. Teraz ze strony pobieramy pliki dla programistów. Z menu wybieramy Development i pobieramy WinPcap Developer's Packs w tej wersji co zainstalowane sterowniki. Pobrane archiwum należy rozpakować np do C:\ (utworzy się nam folder WpdPack). Kolejną rzeczą do zrobienia jest konfiguracja środowiska. Pokażę na przykładzie Dev-C++. W nowo utworzonym projekcie klikamy Projekt->Opcje projektu. Klikamy zakładkę Pliki/katalogi W polu Katalog bibliotek dodajemy C:\WpdPack\Lib, a w polu Katalog plików nagłówkowych dodajemy C:\WpdPack\Include. Klikamy Ok.

    Do projektu należy dodać biblioteki statyczne libwsock32.a; libwpcap.a; WpdPack/Lib/libpacket.a.

    2. Piszemy sniffera!
    Kod programu.
    Kod:
    //pliki nagłówkowe
    #include <stdio.h>
    #include <winsock2.h> //niekoniecznie
    #include <pcap.h>  //pliki nagłówkowe winpcap
    #include <remote-ext.h>  //a ten potrzebny do szukania urządzeń
    
    //funkcja zwrotna
    void packet_handler(u_char* param,const struct pcap_pkthdr* header,const u_char* pkt_data);
    //nie będę już o niej pisał, gdyż może być taka sama jak dla libpcap
    
    int main()
    {
        //potrzebne zmienne
        pcap_if_t *alldevs,*d; //lista urządzeń
        pcap_t *fp; //dane urządenie na którym będziemy nasłuchiwać
        u_int inum,i=0;
        char errbuf[PCAP_ERRBUF_SIZE]; //buffor na kody błędów
        int res;
        u_int netmask;  //maska sieci potrzebna przy filtrowaniu pakietów
        char packet_filter[512]; //filtr
        struct bpf_program fcode;
    	
        WSADATA wsd; //niepotrzebne, ale jakby ktoś chciał się pobawić....
    	WSAStartup(MAKEWORD(2,0),&wsd);
    	
        //listowanie kart sieciowych, modemów itp. w systemie
        if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf)==-1)
        {
            fprintf(stderr,"Blad w pcap_findalldevs_ex: %s\n",errbuf);
            exit(1);
        }
    	
    	printf("Dostepne urzadenia:\n");
    	
    	//Pokazywanie listy urządzeń
        for(d=alldevs;d;d=d->next)
        {
            printf("%d. %s\n    ",++i,d->name);
            if(d->description)
                printf(" (%s)\n",d->description);
            else
                printf(" (Brak opisu)\n");
        }
        if(i==0)
        {
            printf("\nBrak urzadzen\n");
            return -1;
        }
    	
    	printf("Podaj numer urzadzenia (1-%d): ",i);
    	scanf("%d",&inum);
    	
    	if((inum<1)||(inum>i))
    	{
    	    printf("Numer z poza przedzialu.\n");
    		pcap_freealldevs(alldevs);
    		return -1;
    	}
    	
    	//wybórk konkretnego sprzetu
        for(d=alldevs,i=0;i<inum-1;d=d->next,i++);
    	
    	//otwarcie urządenia
        if((fp=pcap_open(d->name,//nazwa urzadenia
                                65536, //wielkosc pakietu, 65536 gearantuje ze zostanie przeczytany cały pakiet
                                PCAP_OPENFLAG_PROMISCUOUS, //promiscuous mode //jakby komuś nie działało daje 0
                                1000, //czas oczekiwania
                                NULL,errbuf))==NULL)
    	{
    	    fprintf(stderr,"\nNie można otworzyć urzadenia. %s nie obslugiwane przez WinPcap\n");
            pcap_freealldevs(alldevs);
            return -1;
        }
    	
    	if(d->addresses!=NULL)
        //pobranie maski pierwszego adresu ip urządzenia
        netmask=((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
        else netmask=0xffffff;
    	//ustawienie filtra
    	printf("Podaj filtr:");
    	scanf("%s",packet_filter);
    	//przykłady ip ; ip and tcp ; ip and not udp ; host 192.168.1.43
    	if(pcap_compile(fp,&fcode,packet_filter,1,netmask)<0)
        {
            fprintf(stderr,"\nNie mozna skompilowac sprawdz skladnie.\n");
            pcap_freealldevs(alldevs);
            return -1;
        }
        //wstawianie filtru
        if(pcap_setfilter(fp,&fcode)<0)
        {
            fprintf(stderr,"\nBlad podczas ustawiania filtru.\n");
            pcap_freealldevs(alldevs);
            return -1;
        }
    	//juz nie potrzebujemy listy urządzen
        pcap_freealldevs(alldevs);
    	
        printf("Węszymy :)\n");
        pcap_loop(fp,0,packet_handler,NULL);
        //Ctrl+C i pętla jest przerywana
    	
        //jak trzeba
        WSACleanup();
    	
        return 0;
    }

    Myślę, że ten art pomoże komuś przy początkach w pisaniu sniffera. Oczywiście należy sięgnąć do dokumentacji, ale pierwsze lody przełamane i już nie powinno być większych trudności.

    Jak będę miał czas to napiszę jakąś przyzwoitą procedurę zwrotną.

    20:06 7 maja 2009
    "a imię jego będzie czterdzieści i cztery"
    A. Mickiewicz Dziady cz. III

Podobne wątki

  1. Odpowiedzi: 7
    Autor: 01-07-2009, 08:48
  2. Pytanie o sniffer
    By wirknc in forum Newbie - dla początkujących!
    Odpowiedzi: 3
    Autor: 03-12-2008, 11:30
  3. Sniffer GG
    By nek in forum Newbie - dla początkujących!
    Odpowiedzi: 7
    Autor: 01-04-2008, 11:28
  4. wireshark jakos wifi sniffer
    By eoor in forum TCP/IP/Analiza/Badanie
    Odpowiedzi: 5
    Autor: 07-20-2007, 15:27
  5. jak działa sniffer??
    By Spoofy in forum Newbie - dla początkujących!
    Odpowiedzi: 3
    Autor: 03-11-2007, 11:59

Zasady Postowania

  • Nie możesz zakładać nowych tematów
  • Nie możesz pisać wiadomości
  • Nie możesz dodawać załączników
  • Nie możesz edytować swoich postów
  •  
Subskrybuj