Knihovna Winpcap a její základní použití

18. 10. 2006
Doba čtení: 9 minut

Sdílet

Winpcap je knihovna, která umožňuje přistupovat k síti a síťovým zařízením. Standardní API sice umožňuje pracovat s transportní i IP vrstvou modelu TCP/IP, ovšem programátor mnohdy potřebuje nahlédnout i do nižší vrstvy, a to jde přes běžné API velice obtížně a kostrbatě (pokud vůbec). V tu chvíli je čas na winpcap.

Základní informace o knihovně

Možná někoho hned v úvodu zarazilo, že publikuji článek o vývoji pro platformu Windows (protože winpcap je pouze pro platformu Windows) právě zde. Důvody jsou dva. První, winpcap samotná je open-source knihovna (je šířena pod BSD open-source licencí). A druhým důvodem je, že z části je to port knihovny libpcap, takže princip programování je prakticky totožný (stejně tak jako např. soketové programování) a i zdrojové kódy by měly fungovat s malými úpravami na jiných systémech právě s knihovnou libpcap – minimálně každý kód napsaný za pomocí libpcap by měl jít zkompilovat i s winpcap (a to včetně typů proměnných, hlavičkové soubory winpcapu definují všechny na unixových systémech běžně používané, avšak na Windows nepojmenované typy).

Co je tedy winpcap zač? Jak už jsem nakousl v úvodu, tato knihovna umožňuje programátorovi přistupovat přímo k syrovým (raw) datům odebíraným ze sítě. Dokáže získat kompletní obsah paketů přicházejících z – i docházejících do daného zařízení. Má soubor vlastních filtrovacích pravidel (takže nežádoucí pakety se do vašeho programu vůbec nedostanou). Také zaznamenává statistické informace o síťovém provozu. Několikrát už jsem četl či zaslechl, že Winpcap umí pouze pasivně „sniffovat“. Toto tvrzení se tak úplně nezakládá na pravdě, i když si ukážeme, jak na to (bohužel v tomto článku na to čas ani prostor není). Také nesmíme zapomenout, že knihovna plně podporuje čtení a zápis do souborů v libpcap formátu. A ještě jedna důležitá poznámka, některé obzvláště paranoidní antiviry mohou hlásit, že Winpcap je vir či trojan, ale vzhledem k tomu, že zdrojový kód je otevřený a možnost vlastní kompilace je detailně popsána, si myslím, že tuto možnost můžeme s klidem v duši vyloučit.

Winpcap je tedy vhodná pro tvorbu minimálně tohoto druhu aplikací:

  • síťové a protokolové analyzátory
  • síťové monitory
  • loggery provozu
  • generátory provozu
  • IDS – obranné detekční systémy
  • bezpečnostní nástroje
  • síťové scannery

Nechci nyní rozebírat, jak přesně knihovna pracuje (to si nechám na jindy), pouze ve zkratce. První částí knihovny je ovladač NPF (Netgroup packet filter), který přímo komunikuje s ovladači síťových karet a získává od nich právě syrová data. Pak jsou tu knihovny packet.dll a wpcap.dll, které tvoří API pro knihovnu – ovládají NPF a tvoří rozhraní mezi ním a uživatelskou aplikací.

V úvodu jsem nakousl Winapi v souvislosti s Winpcap. Jak už jsem naznačil v předchozím odstavci, Winpcap je na Winapi nezávislá (pracuje jakoby vedle windowsovských soketů), ovšem využívá ve své implementaci některé funkce z Winsock. Pomocí raw soketů z téže knihovny lze sice také získat jakási „syrová“ data, ovšem ty systém před předáním poupraví. Navíc se o raw soketech vývojářských stránkách Microsoftu příliš nedozvíte a musíte hledat jinde. Naproti tomu Winpcap je zdokumentovaná velmi dobře.

Ovšem nic není ideální, Winpcap má také svá omezení. Winpcap jsou určeny pouze pro platformu Windows, momentální verze (3.1) už oficiálně nepodporují staré verze (9×/ME). Windows Vista by měly spolupracovat s verzí 3.1, ovšem pro kvalitní podporu byste měli použít verzi 4.0. Co se týče typu sítě, Winpcap se vyvíjí primárně pro etherenetové sítě, podpora jiných sítí (PPP, VPN, …) sice existuje, ovšem není úplně stoprocentní. Pro více informací nahlédněte do faq (pouze v angličtině). Zvláštní kapitolou jsou wi-fi sítě. Společnost CACE Technologies nabízí zařízení AirCap, pomocí kterého (a samozřejmě Winpcapu) lze wi-fi komunikaci odposlouchávat. Toto je v současnosti jediné možné řešení. Další omezení spočívá v nefunkčnosti Winpcapu a loopbacku. To je ten nedostatek, který způsobuje limitace Windows. Winpcap také nemusí spolupracovat s některými firewally nebo jinými, typově stejnými, knihovnami. Pokud máte potíže tohoto druhu, zkuste daný software odinstalovat. Nakonec je třeba ještě zdůraznit, že Winpcap neobsahuje žádné mechanismy, jak pakety zahazovat či blokovat, proto jej nelze využít pro tvorbu firewallu apod.

Poslední (pouze pořadím, nikoli důležitostí), co potřebujeme znát, než se pustíme do samotného vývoje, je programovací jazyk. Samotná knihovna je napsána v jazyce c, jazyk c (popřípadě c++) se nabízí i jako hlavní jazyk pro vývoj programů. Toho se budu držet i já (spíš budu využívat jazyka c++). Ovšem programovat lze například i v jakémkoli jazyce podporujícím ActiveX díky produktu PacketX. Javisté zase přivítají projekt Jpcap, což je javová třída postavená na libpcap/winpcap. A v neposlední řadě, s Winpcap lze pracovat i v c#, viz Packet sniffing with Winpcap na codeproject.com.

Co potřebujeme pro vývoj

Alespoň jeden z operačních systémů: Windows 9×/Me, NT4/2000, XP/2003, Vista beta1 běžící na x86 architektuře (64 bit architektura je podporována podle stránek autorů od verze 4.0) Winpcap – bez samotné knihovny program pod ní napsaný spustit nelze, stáhnout můžete ze http://www.win­pcap.org/insta­ll/default.htm, já budu používat verzi 3.1 (verze 4.0 byla v době psaní článku ve stádiu beta).

Developer´s pack – pro kompilaci programů budeme potřebovat developer´s pack neboli balíček pro vývojáře. Více o něm se dozvíte v následujícím odstavci. Ze stránky http://www.win­pcap.org/devel­.htm tedy stáhneme developer´s pack opět pro verzi 3.1 Kompilátor jazyka C/C++ – já osobně budu používat Dev-C++ ve verzi 4.9.9.2, postup instalace ovšem uvedu i pro kompilátory od firmy Borland, protože je odlišná od jiných běžných kompilátorů.

Zdrojové kódy winpcap – Samozřejmostí je možnost neinstalovat hotový balík, ale provést kompilaci ze zdrojových kódů. Tomuto tématu se ovšem já věnovat nebudu, zdrojové kódy lze stáhnout na www.winpcap.org a postup jak zkompilovat naleznete na www.winpcap.or­g/docs/docs31/html/grou­p__compilation­.html (v angličtině).

Developer´s pack

V developer´s packu nalezneme knihovny, hlavičkové soubory, dokumentaci a ukázkové příklady. O prvních dvou věcech bude řeč v následující kapitole. Dokumentace je zpracovaná pomocí nástroje doxygen, najdete zde vše podstatné o knihovně, ovšem je pouze anglicky. Ukázkové příklady jsou psány v jazyce c, jsou docela přehledně komentovány anglickým jazykem (někde jsem tuším zahlédl i italštinu).

Instalace

1)Pokud nemáme, nainstalujeme základní balík knihovny winpcap. Nainstalování knihovny ověříme v okně „přidat nebo odebrat programy“ (nalezneme v ovládacích panelech). Pokud chcete mít stoprocentní jistotu, ověřte funkčnost některým programem využívajícím winpcap (např.: windump).

2)Ovladač NPF se instaluje pokaždé po novém startu os dynamicky při prvním spuštění programu využívajícího winpcap. A tento krok potřebuje práva administrátora. V případě, že pracujete pod účtem s omezenými právy, je potřeba se přepnout na účet administrátora (administrátora počítače požádat) a v registrech v klíči HKEY_LOCAL_MAC­HINE\SYSTEM\Cu­rrentControlSet\Ser­vices\NPF\Start přepsat hodnotu z 0×3 na 0×2 (automatický start) nebo na 0×1 (systémový start). Ověřit nastavení spouštění a aktuální stav ovladače NPF lze provést následujícím způsobem: v nabídce start zvolte spustit…->zadejte „msinfo32“, rozbalte položku Programové prostředí, klikněte na Systémové ovladače, najděte ovladač npf a překontrolujte hodnoty u něho uvedené.

3)Rozbalíme stažený developer´s pack

a) kompilátory od Borlandu – winpcap oficiálně podporuje pouze Microsoft Visual C++, jehož knihovny jsou ve formátu COFF, ovšem Borland používá jiný formát knihoven – OMF. Naštěstí existuje jednoduchá pomoc, v adresáři, kde se nachází kompilátor Borlandu by měl být i soubor coff2omf.exe, který přebírá 2 parametry, první je knihovna ve formátu COFF a druhý je název výsledné knihovny ve formátu OMF. Tímto způsobem stačí převést knihovny packet.lib a wpcap.lib (například tedy coff2omf.exe packet.lib packetomf.lib). Dále pak nastavit cesty ke knihovnám (samozřejmě těm převedeným) a hlavičkovým souborům a vše by mělo bez problémů fungovat.

b) Ostatní(Dev-C++, MSVC++) – pouze nastavíme cestu k hlavičkovým souborům a knihovnám. V Dev-C++, Tools(Nástroje)->Compiler options (Nastavení překladače)->Directories (Adresáře) a tam záložky Libraries (knihovny), C includes (hlavičkové soubory) a C++ includes.

Praktická část

Nyní se konečně dostáváme k tomu podstatnému, psaní programů. Ještě ale než začneme, měl bych vás seznámit se zásadami:

Do každého zdrojového kódu musíte vložit hlavičkový soubor pcap.h. Dále je potřeba přilinkovat k projektu (či globálně) knihovnu wpcap.lib/libwpcap.a. V DEV-C++ by tedy mělo stačit přidat -l wpcap. Ovšem knihovna libwpcap.a neobsahuje několik funkcí pracujících se vzdálenou stanicí. V těchto případech musíme připojit knihovnu wpcap.lib (bez parametru -l a píšeme celou cestu ke knihovně).

Jak už jsem psal, některé funkce využívají knihovnu winsock, proto je potřeba přidat hlavičkový soubor knihovny winsock. Protože programujeme prakticky každý program pro Windows, potřebujeme hlavičkový soubor windows.h, který obsahuje direktivu na vložení souboru winsock.h resp. winsock2.h, můžeme vkládat rovnou ten. Dále je samozřejmě potřeba přilinkovat knihovnu winsock. V DEV-C++ přidáme k parametrům linkeru -l wsock32. Pokud používáte Win32 specifické funkce, měli byste (před samotný program) přidat direktivu preprocesoru WPCAP. Pokud používáte remotní funkce, musíte přidat direktivu HAVE_REMOTE.

A teď už skutečně k samotnému programování. V prvním příkladu si ukážeme, jak zjistit seznam síťových zařízení a nějaké informace o nich.

Krok 1 – zjištění seznamu. Viz následující kód :

 if (pcap_findalldevs(&seznam, chyba) == -1)
    {
        cerr << "Chyba pri sestavovani seznamu zarizeni:" << chyba << endl ;
        exit(1);
    } 

Funkce pcap_findalldevs() vyhledá všechny dostupná síťová zařízení a naplní jimi strukturu pcap_if_t (v našem příkladě „seznam“). Proměnná „chyba“ je typu char a v případě chyby bude obsahovat chybovou hlášku.

Krok 2  – výpis. Kód:

for(zarizeni = seznam; zarizeni != NULL; zarizeni= zarizeni->next) {
        cout << ++i << zarizeni->name ;
        if (zarizeni->description)
            cout << zarizeni->description << endl ;

 } 

Vytvořili jsme ještě jednu strukturu typu pcap_if_t „zarizeni“, která v každém průchodu cyklem je nastavená na jedno zařízení + nese informace o ještě nevypsaných zařízeních. Z této struktury vypisujeme všechny informace, které nás zajímají.

Krok 3 – uvolnění zdrojů. Kód:

pcap_freealldevs(seznam); 

Tato funkce uvolní seznam zařízení, volejte ji pokaždé, kdy už daný seznam nebude potřeba.

ict ve školství 24

Ukázka

Na závěr uvedu příklad, který dělá přesně to, co jsem popsal výše, pouze vypisuje více informací (pro převod adres na tečkovou notaci využívám knihovny winsock).

#include <iostream>
#include <pcap.h>

using namespace std;

int main(int argc, char *argv[]) {

    //incializace winsocku

    WSAData wsadata ;
    if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0 ) {

        cerr << "Nepodarilo se inicializovat sockety! " << endl ;
        exit(-1) ;

    }

    pcap_if_t *seznam, *zarizeni ;
    char chyba[PCAP_ERRBUF_SIZE];

    //zjistime seznam zarizeni

    if (pcap_findalldevs(&seznam, chyba) == -1){

        cerr << "Chyba pri sestavovani seznamu zarizeni:" << chyba << endl ;
        exit(-2);
    }

    //vypiseme

    int i=0;

    for(zarizeni = seznam; zarizeni != NULL; zarizeni= zarizeni->next) {

        cout << ++i << ". " << zarizeni->name << " - " ;

        if (zarizeni->description)
            cout << zarizeni->description << endl ;

         pcap_addr_t *a;

         for(a=zarizeni->addresses; a; a=a->next ) {

             //pokud je IPv4 adresa vypiseme info

             if (a->addr->sa_family == AF_INET) {

                 cout << "\tAdress family je AF_INET (IPv4)" << endl ;

                 if (a->addr)
                    cout << "\tIP adresa: " << inet_ntoa(((struct sockaddr_in *)a->addr)->sin_addr) << endl ;
                 if (a->netmask)
                   cout << "\tMaska: " << inet_ntoa(((struct sockaddr_in *)a->netmask)->sin_addr) << endl ;
                 if (a->broadaddr)
                 cout << "\tBroadcast adresa: " << inet_ntoa(((struct sockaddr_in *)a->broadaddr)->sin_addr) << endl ;
                 if (a->dstaddr)
                 cout << "\tCilova adresa: " <<  inet_ntoa(((struct sockaddr_in *)a->dstaddr)->sin_addr) << endl ;
                 break;
             }
         }
    }

    if (i == 0)
        cout << "Nebylo nalezeno zadne zarizeni" << endl ;

    //uvolnime zdroje

    WSACleanup();
    pcap_freealldevs(seznam);

    system("PAUSE");
    return EXIT_SUCCESS;
} 

A to už je opravdu vše. Další článek bude kompletně programovací (co nejméně povídání a teorie), pokusím se vás provést všemi kouty této knihovny.

Programovali jste někdy pod MS Windows?

Autor článku