Toto v žiadnom prípade nie sú všetky možnosti ktoré libpcap poskytuje. Dalšie skúmanie je len na vás, odkazujem vás hlavne na zdrojové kódy nástroja tcpdump.
libpcap
libpcap, ako už bolo spomenuté, nám umožnuje jednoducho a efektívne vo vlastných programoch zachytávať sieťovú komunikáciu. Veľa známych programov je na tejto knižnici postavených, spomeniem napr. tcpdump, wireshark, snort. Ak ho ešte v systéme nainštalovaný nemáte (máte zlý systém ;)), stiahnuť si ho môžete z www.tcpdump.org alebo použite balíčkovací systém vašej distribúcie.Bližší pohľad na packet capturing
Packet capturing(sniffing), teda zachytávanie packetov, je činnosť, pri ktorej zachytávame a zbierame dáta ktoré cestujú po sieti. Od príchodu dát k sieťovej karte po odovzdanie dát do uživatelského priestoru - to prebieha približne takto: sieťová karta obdrží packet, skontroluje, či je adresovaný jej a ak hej vyvolá IRQ (interrupt request - spôsob, akým komunikuje hardware so softwarom). IRQ dalej obslúži príslušný ovládač karty ktorý spracuje dáta a uloží ich do zásobníka nazývaného "networking stack". Odtiaľ už je spracovávaný jednotlivými aplikáciami, pre ktoré sú dáta určené (v skutočnosti je to zložitejšie ale pre naše potreby to stačí takto). Pri packet capturingu, to prebieha rovnako, až na to, že dáta nie sú len uložené v "networking stacku", ale putujú aj do "packet filtru" - časti kernelu, ktorá umožnuje packet capturing. Kdežto aplikácia obrdží väčšinou dáta v už spracovanej forme, z packet filtru budeme dáta ťahať nespracované, raw. To znamená, že každú vrstvu si musíme spracovať sami. Pre lepšiu predstavu si to môžeme nakresliť do grafu:Promiskuitný mód
Promiskuitný mód je vlastnosť sieťovej karty, ktorá nám umožnuje zachytávať a sledovať aj tie packety, ktoré niesú určené pre ňu samotnú.Struktúra aplikácie
Pri každej aplikácií využívajúcej libpcap musíme splniť niekoľko krokov, ktoré sú popísané nižšie.- Získať názov rozhrania, na ktorom budeme sniffovať.
- Inciliazovať pcap. Predáme mu názov rozhrania, môžme špecifikovať aj iné možnosti ako promiskutný mód karty atd. Pcap vytvorí tzv. sniffing session, s ktorou budeme následne manipulovať pomocou "popisovačov" (descriptorov).
- Zvoliť a aplikovať filter. Krok pozostáva z troch častí, vytvoriť filter, "skompilovať" ho a aplikovať na popisovač. Skompilovať sa tu nemyslí ako preklad kódu do strojových inštrukcií ako tradične, jedná sa terminológiu libpcap. Tento bod je samozrejme nepovinný, filter používať nemusíme.
- Začať samotný sniffing. Opäť môžeme špecifikovať parametre ako napr. počet zachytených packetov.
- Zavrieť session.
Základné operácie
Poznámka: Všetky konštanty, funkcie, datové typy sú definované v hlavičkovom súbore pcap.hZískanie názvu sieťového rozrhania
Prvým krokom teda je získať nejaké sieťové rozhranie, nad ktorým budeme operovať. Môžeme požiadať užívateľa, aby ho zadal sám, ale väčšinou budeme používať tzv. "default device". To, ktoré to bude závisí od operačného systému. Na GNU/Linux je to väčšinou eth0. Získať názov defaultného rozhrania nám pomôže funkcia 'pcap_lookupdev'. Jej prototyp je nasledujúcichar *pcap_lookupdev(char *errbuf)Vracia názov defaultného rozhrania a ako argument príjma ukazateľ na pole char o veľkosti PCAP_ERRBUF_SIZE, do ktorého následne uloží chybovú správu (ak nastala chyba). V prípade chyby vracia NULL. Poznámka: Tzv. errbuf príjmajú ako argument mnohé funkcie.
Program, ktorý len získa a vypíše názov defaultného rozhrania by teda vyzeral takto:
#include <pcap.h> #include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { char errbuff[PCAP_ERRBUF_SIZE]; char *device; device = pcap_lookupdev(errbuff); if(device == NULL) { fprintf(stderr, "%s\n", errbuff); _exit(-1); } printf("Default device: %s\n", device); return 0; }Treba pripomenúť, že treba prilinkovať libpcap. Pri gcc len zadáte parameter -lpcap. Samotný pcap obsahuje viac funkcií pre tento účel. Napr 'pcap_findalldevs'. Cieľom článku ale nie je zachádzať až do podrobností. Ak vás to zaujme, všetky potrebné informácie nájdete na manuálovej stránke pcap a v zdrojových kódoch tcpdumpu.
Poznámka: Tento, aj všetky programy uvedené neskôr je potrebné spúštať z právami užívateľa root.
Otvorenie sniffing session
Tento bod je prekvapivo jednoduchý. Stačí zavolať funkciu pcap_open_live ktorá má nasledujúci prototyp:pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)Prvý parameter je jasný - rozhranie. Druhý udáva maximálnu veľkosť zachytených dát v bytoch. Nízka hodnota môže byť užitočná hlavne ak nemáme záujem o dáta ktoré packet nesie ale len o hlavičky protokolov. Naopak, ak nechceme prísť ani o jediný byt, je dobré nastaviť hodnotu na 65535 čo je bežná hodnota MTU vo väčšine sietí. Tretí argument ako už jeho názov vypovedá určuje, či bude karta v promiskuitnom móde, alebo nie. Ak je hodnota true (akákoľvek nenulová) bude rozhranie uvedené do promiskuitného módu. Stvrtý paramter udáva timeout v milisekundách. Timeout určuje, koľko bude kernel čakať kým nám poskytne nejaké dáta. Medzitým ich samozrejme bude hromadiť. Kvôli platformovým rozdielom je lepšie túto hodnotu nenastavovať na nulu. Môžeme sa napr. inšpirovať tcpdumpom a nastaviť ju na 1000. Posledný argument je, nám známy, errbuf. Funkcia vracia pri úspechu ukazateľ na popisovač, ktorý je typu pcap_t. Opäť libpcap poskytuje viacero možností ale základ je najdôležitejší a ten je táto funkcia.
Zachytávanie packetov
Zatiaľ čo pri veľmi jednododuchej aplikácií, akú si napíšeme nakonci si vystačíme s funkciou 'pcap_next', pri zložitejších už je oveľa vhodnejšia funkcia 'pcap_loop'. 'pcap_loop' si predstavíme v druhej časti teraz je čas na 'pcap_next'. Má nasledujúci prototyp:const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);Funkcia zachytí len jeden packet a následne na dáta v ňom vráti ukazateľ typu const u_char. Ako prvý argument príjma získaný popisovač. Druhý argument je ukazateľ na štruktúru 'pcap_pkthdr', ktorá vyzerá nasledujúco:
struct pcap_pkthdr { struct timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length this packet (off wire) */ };Položka 'ts' obsahuje časový údaj o tom, kedy bol packet zachytený, 'caplen' udáva počet bytov, ktoré sú nám zneho k dispozícií (max je druhý parameter 'pcap_open_live'), tretí udáva skutočnú veľkosť packetu. Kedže analýzou zachytených dát sa budeme zaoberať až v druhej časti, nebudem to tu teraz rozoberať. Za zmienku stojí, že 'pcap_next' len volá 'pcap_dispatch'. Už bolo uvádzané, že takto do detailu zachádzať nechcem, možno niečo pridám do druhej časti.
Trochu praxe
Doteraz to boli len teoretické "žvásty", je čas niečo naprogramovať. Napíšeme si jednoduchý program, ktorý zachytí jeden packet a zobrazí o ňom informácie. Môžeme síce dať pcap_next do cyklu a sniffovat donekonečna ale tento spôsob je vrcholne nespoľahlivý a je lepšie použiť funkciu 'pcap_loop', ktorú si predstavíme nabudúce. Ku kódu niet čo vysvetlovať, hádam len že funkcia 'pcap_close' (neočakávane) zatvára popisovač.#include <stdio.h> #include <unistd.h> #include <pcap.h> #define SNAPLEN 65535 int main(int argc, char **argv) { char errbuff[PCAP_ERRBUF_SIZE]; char *device; const u_char *packet; //zatial nepotrebne pcap_t *sd; struct pcap_pkthdr packet_header; device = pcap_lookupdev(errbuff); if(device == NULL) { fprintf(stderr, "%s\n", errbuff); _exit(1); } sd = pcap_open_live(device, SNAPLEN, 0, 1000, errbuff); if(sd == NULL) { fprintf(stderr, "%s\n", errbuff); _exit(1); } packet = pcap_next(sd, &packet_header); printf("Packet!\nTime: %sLength: %d bytes\n", ctime((const time_t *)&(packet_header.ts.tv_sec)), packet_header.len); pcap_close(sd); return 0; }
kontrolna otazka: nie je potrebne mat na prepnutie karty do promiskuitneho modu podporu v ovladaci ?
minimalne u wifi kariet to je potrebne ...
dakujem za ozrejmenie ;-)
A pri wifi kartach nejde o prepnutie do promiskuitneho modu (to je eth vrstva) ale o prepnutie do monitor modu (co je skor radio vrstva).
http://sk.wikipedia.org/wiki/OSI_model