Windows için basit bir sniffer yazıyoruz. Windows için basit bir dinleyici yazma Bir IP paketinin yapısını açıklama

Tünaydın! Bir şekilde işte bir sorun ortaya çıktı - I2C üzerinden çalışan ve protokolünün anlaşılması gereken bir cihaz var. Bu nedenle, I2C arayüzü için gelen ve giden her şeyi I2C üzerinden UART portuna ve ardından dönüştürücü aracılığıyla bilgisayarın COM portuna gönderecek bir sniffer'a ihtiyacımız var.

Başlangıç

Sadece birkaç atmeg8 el altındaydı ve neden onları kullanmamaya karar verdim. Ayrıca, bir koklayıcı şemasıyla ilgili bir soru vardı.

2 seçenek vardı - bir sniffer'ı paralel olarak veya bir devre kesintisinde dahil etmek. Açıkçası, ilk seçenek çok daha basit görünüyor, ki gerçekte tamamen farklı olduğu ortaya çıktı. Ama önce ilk şeyler.

Kısacası, arayüzün kendisi hakkında. I2C (Atmelian dilinde TWI) iki kablo kullanır - SCL ve SDA. Birincisi sinyali saatlemekten, ikincisi doğrudan bilgi iletmekten sorumludur. Arayüz ayrıca BAŞLAT ve DURDUR durumlarına sahiptir.

Bu yüzden ilk düşüncem bir prob alıp, bir yandan atmega8'deki harici kesme bacağına, diğer yandan SDA hattına bağlayıp yükselen kenarı yakalamak ve geçen süreden 0 veya 1'i belirlemek oldu. STOP sinyali doğru bir şekilde işlenmediğinden, bunun çok kötü çalışması gerektiği açıktır.

İkinci düşünce, her şeyi aynı yapmak, ancak SCL hattındaki kesmeyi yakalamak ve kesmeyi kullanarak normal dijital bacağa bağlı SDA hattını okumaktı. Burada aynı STOP durumu dışında her şey daha uygun görünüyordu, ancak onu bir devre tahtasında birleştirmeye ve ne olduğunu görmeye karar verdim.

Aşağıdaki kodda bariz hatalar bulursanız şimdiden özür dilerim, çünkü reddedilen kod seçeneklerini hafızamdan dizlerime geri yükledim.

Kesme işleyici kodu şuna benziyordu:

ISR(INT0_vect) ( cli(); if (bitIsHigh(PINB, 0))) uart_send_char("1"); else uart_send_char("0"); sei(); )
Sıfırlar ve birler limana aktı, ancak verilerin yanlış olduğu hemen ortaya çıktı - beklenenden çok daha azı vardı ve aynı istek tekrarlandığında değiştiler. Sebepleri bulma sürecinde, her şey, bu arada, maksimum 38 kbps sabit hızda çalışan uart arayüzüne erişim nedeniyle verilerin kaybolması gerçeğine indi, I2C'nin kendisi de çalıştı. 100 kb/sn. Uart'ı kabul edilebilir bir hıza aktarmak için gerekli frekansta bir kristalin olmaması nedeniyle UART'ın hızını artırmak mümkün olmadı. Bu nedenle, uart ile yapılan çalışmayı kesmeden çıkarmak gerekliydi. Böyle bir şey var:

Statik uint8_t verisi = 0; statik uint8_t idx = 7; ISR(INT0_vect) ( cli(); veri |= bitIsHigh(PINB, 0)<< (idx--); if (!idx) { uart_send_char(data); data = 0; idx = 7; } sei(); }
Her şey daha kararlı hale geldi, ancak veriler hala bir anlam taşımadı. Algoritma üzerinde birkaç saat çalıştıktan, STOP işlemeyi açtıktan vb. sonra, yine de diğer yöne gitmeye karar verildi.

Doğru yolda

Paralel bir anahtarlama şeması kullanarak bir sniffer uygulamaya ne kadar çalışsam da sonuç alamadım. Buna dayanarak, geriye sadece bir seçenek kaldı - mikrodenetleyiciyi bir boşluğa dahil etmek gerekiyordu, yani hem yanıt cihazı için bir master hem de orijinal master için bir köle olması gerekiyordu. Kafa karıştırıcı gelebilir, ama aslında değil.

Atmega8'de yalnızca bir donanım I2C'si bulunduğundan, protokolün çalışması için yazılım desteği yazmanız gerektiği açıktır.

Sonuç aşağıdaki koddur:

ISR(TWI_vect) ( cli(); uint8_t durum = TWSR; uint8_t b; char s; s = 0; _delay_ms(1); geçiş (durum & I2C_STATUS_MASK) ( durum I2C_STATUS_SR_RX_ADR_ACK:/* durum I2CACK_STATUS_sd(s): AW:"); uart_send_int(TWDR); i2csoft_start(); i2csoft_open_write(I2C_ADDRESS); ara; durum I2C_STATUS_SR_RX_DATA_ACK:/* durum I2C_STATUS_SR_RX_DATA_NACK:*/ b = TWDR; s); i2csoft_write_byte(b); break; durum I2C_STATUS_SR_RX_STOP_RESTART: uart_send_str("E\n"); _delay_ms(10); do ( _delay_us(5); i2csoft_start(); ) while (!i2csoft_open_read(I)); durum I2C_STATUS_BUS_ERROR: uart_send_str("B\n"); break; durum TW_ST_SLA_ACK: uart_send_str("-AR:"); uart_send_int(TWDR); b = i2csoft_read_byte(); sprintf(s, "%);.2X" uart_send_str(s); TWDR = b; ara; durum TW_ST_DATA_ACK: b = i2csoft_read_byte(); sprintf(s, "%.2X", b); uart_send_str(s); TWDR = b; ara; durum TW_ST_DATA_NACK: durum TW_ST_ : b = i2csoft_read_byte(yanlış); uart_send_str("L\n"); kırmak; varsayılan: uart_send_char("U"); uart_send_int(durum); uart_send_char(" "); kırmak; ) TWCR |= (1<Ana cihaz, I2C atmega donanımına bağlanır, yürütme cihazı, biri SCL modunda, diğeri SDA'da çalışan herhangi 2 dijital bacağa bağlanır. Yukarıdaki kodun yaptığı tek şey, I2C aracılığıyla bir kesinti almak ve yazılım arayüzünde benzer bir duruma neden olurken, hizmet bilgileri ne olduğunu anlamaya yardımcı olmak için uart'a yazılır. Ayarlanan gecikmeler belirli bir cihaz için seçilmiştir ve diğerleri için biraz farklılık gösterebilir. Sonuç olarak, oldukça sağlam bir sniffer elde ediyoruz.

İlgilenen olursa kaynak kodu şuradan alınabilir.

Bu yazıda, Windows işletim sistemi için basit bir sniffer oluşturmaya bakacağız.
Kimin umurunda, kedinin altına hoşgeldin.

Tanıtım

Hedef: IP protokolü üzerinden iletilen ağ trafiğini (Ethernet, WiFi) yakalayacak bir program yazın.
Tesisler: Visual Studio 2005 veya üstü.
Burada açıklanan yaklaşım, kişisel olarak yazara ait değildir ve kategorik olarak olduğu kadar birçok ticari alanda da başarıyla uygulanmıştır. ücretsiz programlar(merhaba, GPL).
Bu çalışma öncelikle ağ programlamaya yeni başlayanlar için tasarlanmıştır, ancak genel olarak soketler ve özellikle windows soketleri hakkında en azından temel bilgilere sahiptir. Burada sık sık bilinen şeyler yazacağım çünkü konu alanı belirli, bir şeyi kaçırırsanız kafanız karışır.

Umarım bunu ilginç bulursun.

Teori (okuma isteğe bağlıdır, ancak arzu edilir)

AT şu an modernlerin büyük çoğunluğu bilgi ağları TCP/IP protokol yığınının temeline dayanır. TCP/IP (İletim Kontrol Protokolü/İnternet Protokolü) protokol yığını, ağlarda kullanılan farklı düzeylerdeki ağ protokollerinin toplu adıdır. Bu makalede, esas olarak IP protokolü ile ilgileneceğiz - bir ağ düğümünden diğerine sözde paketlere bölünmüş (daha doğru bir terim bir datagramdır) verilerin garanti edilmeyen teslimi için kullanılan yönlendirilebilir bir ağ protokolü.
Bizi özellikle ilgilendiren, bilgi aktarımına yönelik IP paketleridir. Bu oldukça yüksek bir seviyedir. ağ OSI modeli veriler, cihazdan ve veri aktarım ortamından soyutlamanın mümkün olduğu durumlarda, yalnızca mantıksal bir temsil ile çalışır.
Ağ trafiğine müdahale, kontrol, muhasebe ve analiz için er ya da geç araçların ortaya çıkması oldukça mantıklıdır. Bu tür araçlara genellikle trafik analizörleri, paket analizörleri veya koklayıcılar denir (İngilizce'den sniff - sniff'e). Bu, bir ağ trafiği analizörü, bir program veya donanım ve yazılım cihazı olup, araya girip ardından analiz etmek veya yalnızca diğer düğümlere yönelik ağ trafiğini analiz etmek için tasarlanmıştır.

Alıştırma yapın (konuya odaklanın)

Şu anda, oldukça fazla yaratıldı yazılım trafiği dinlemek için. Bunların en ünlüsü: Wireshark. Doğal olarak, amaç defnelarını toplamaya değmez - ağ arayüzünün olağan "dinlenmesi" ile trafiği engelleme göreviyle ilgileniyoruz. Bilgisayar korsanlığı ve müdahaleleriyle meşgul olmayacağımızı anlamak önemlidir. yabancı trafik. Sadece sunucumuzdan geçen trafiği görüntülemeniz ve analiz etmeniz yeterlidir.

Neden gerekli olabilir:

  1. Ağ bağlantısı üzerinden mevcut trafik akışını görüntüleyin (gelen/giden/toplam).
  2. Daha fazla analiz için trafiği başka bir ana bilgisayara yönlendirin.
  3. Teorik olarak, bir WiFi ağını hacklemek için kullanmayı deneyebilirsiniz (bunu yapmayacağız, değil mi?).
libpcap/WinPcap kitaplığını temel alan Wireshark'ın aksine, analizörümüz bu sürücüyü kullanmayacaktır. Orada ne var, hiç şoförümüz olmayacak ve kendi NDIS'imizi (korku!) Bununla ilgili okuyabilirsiniz. kullanarak sadece pasif bir gözlemci olacak. bir tek WinSock kitaplığı. Bu durumda bir sürücü kullanmak gereksizdir.

Nasıl yani? Çok basit.
Basitleştirmede önemli bir adım ağ uygulaması ağ analizöründe, ağ arayüzünü, ağdaki diğer arayüzlere yönelik paketleri almasına izin verecek olan dinleme moduna (karmaşık mod) geçirmektir. Bu mod, ağ kartını, ağda kime yönlendirildiklerine bakılmaksızın tüm çerçeveleri kabul etmeye zorlar.

Windows 2000'den (NT 5.0) başlayarak, bir ağ kesiminde dinlemek için bir program oluşturmak çok kolay hale geldi, çünkü ağ sürücüsü, soketi tüm paketleri alma moduna geçirmenizi sağlar.

Karışık modu etkinleştirme
uzun bayrak = 1; SOKET soketi; #define SIO_RCVALL 0x98000001 ioctlsocket(soket, SIO_RCVALL, &RS_Flag);
Programımız IP paketleri üzerinde çalışır ve Windows Sockets kitaplığı sürüm 2.2 ve ham soketleri kullanır. Bir IP paketine doğrudan erişmek için soket aşağıdaki gibi oluşturulmalıdır:
Ham Soket Oluşturma
s = soket(AF_INET, SOCK_RAW, IPPROTO_IP);
Burada sabit yerine SOCK_STREAM(TCP protokolü) veya SOCK_DGRAM(UDP protokolü), değeri kullanıyoruz SOCK_RAW. Genel olarak konuşursak, ham soketlerle çalışmak sadece trafiği yakalama açısından ilginç değildir. Aslında, alıyoruz tam kontrol paketin oluşumu için. Veya daha doğrusu, örneğin belirli bir ICMP paketi göndermeye izin veren manuel olarak oluştururuz ...

Devam et. Bir IP paketinin bir başlık, hizmet bilgisi ve aslında verilerden oluştuğu bilinmektedir. Bilginizi tazelemek için buraya bakmanızı tavsiye ederim. IP başlığını bir yapı olarak tanımlayalım (RSDN'deki harika makale sayesinde):

IP paketinin yapısının açıklaması
typedef struct _IPHeader ( unsigned char ver_len; // başlık sürümü ve uzunluk imzasız char tos; // hizmet tipi imzasız kısa uzunluk; // tüm paketin uzunluğu imzasız kısa kimlik; // Id imzasız kısa flgs_offset; // işaretler ve işaretsiz ofset char ttl ; // ömür boyu imzasız karakter protokolü; // protokol imzasız kısa xsum; // toplamı kontrol et imzasız uzun src; // gönderen IP adresi imzasız uzun hedef; // hedef IP adresi imzasız kısa *paramlar; // parametreler (320 bite kadar) unsigned char *veri; // veri (65535 sekizliye kadar) )IPHeader;
Dinleme algoritmasının ana işlevi şöyle görünecektir:
Tek Paket Yakalama İşlevi
IPHeader* RS_Sniff() ( IPHeader *hdr; int sayı = 0; sayım = recv(RS_SSocket, (char*)&RS_Buffer, sizeof(RS_Buffer), 0); if (sayım >= sizeof(IPHeader)) ( hdr = (LPIPHeader) )malloc(MAX_PACKET_SIZE); memcpy(hdr, RS_Buffer, MAX_PACKET_SIZE); RS_UpdateNetStat(count, hdr); hdr döndür; ) yoksa 0 döndür; )
Burada her şey basit: standart soket işlevini kullanarak verinin bir kısmını alıyoruz tekrar ve ardından bunları aşağıdaki gibi bir yapıya kopyalayın IPBaşlığı.
Ve son olarak, sonsuz bir paket yakalama döngüsü başlatıyoruz:
Ağ arayüzümüzü vuracak tüm paketleri yakalamak
while (true) ( ​​IPHeader* hdr = RS_Sniff(); // IP paketini if ​​(hdr) işle ( // konsolda üstbilgiyi yazdır ) )
biraz offtopik
Bundan sonra, yazar bazı önemli fonksiyonları ve değişkenleri RS_ ile (Ham Soketlerden) öneklendirmiştir. Proje 3-4 yıl önce yapıldı ve ham soketlerle çalışmak için tam teşekküllü bir kütüphane yazmak için çılgın bir fikir vardı. Çoğu zaman olduğu gibi, (yazar için) herhangi bir önemli sonuç elde ettikten sonra, coşku azaldı ve mesele eğitim örneğinden öteye gitmedi.

Prensip olarak, daha ileri gidebilir ve yukarıdaki tüm sonraki protokollerin başlıklarını tanımlayabilirsiniz. Bunu yapmak için alanı analiz etmek gerekir. protokol yapıda IPBaşlığı. IP kapsüllü paketin sahip olduğu protokole bağlı olarak başlığın renklendirildiği kod örneğine bakın (evet, bir anahtar olmalı, kahretsin!).

/* * Paket vurgulama */ void ColorPacket(const IPHeader *h, const u_long haddr, const u_long whost = 0) ( if (h->xsum) SetConsoleTextColor(0x17); // paket boş değilse SetConsoleTextColor(0x07) ) ; // boş paket if (haddr == h->src) ( SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/ FOREGROUND_RED | FOREGROUND_INTENSITY); // "native" dönüş paketi ) else if (haddr == h->dest ) ( SetConsoleTextColor(BACKGROUND_INTENSITY |*/ FOREGROUND_GREEN | FOREGROUND_INTENSITY); // "native" alma paketi ) if (h->protocol == PROT_ICMP || h->protocol == PROT_IGMPColor)(0 SetConsoleTextColor) (SetConsoleTextColor) // ICMP paketi ) else if(h->protocol == PROT_IP || h->protocol == 115) ( SetConsoleTextColor(0x4F); // IP-in-IP paketi, L2TP ) else if(h- >protocol = = 53 || h->protocol == 56) ( SetConsoleTextColor(0x4C); // TLS, Şifreli IP ) if(whost == h->dest || whost == h->src) ( SetConsoleTextColor (0x0A) ; ))

Ancak, bu önemli ölçüde bu makalenin kapsamı dışındadır. Eğitim örneğimiz için trafiğin geldiği ve gittiği hostların ip adreslerine bakıp birim zamandaki miktarını hesaplamak oldukça yeterli olacaktır (bitmiş program programın sonunda arşivdedir). makale).

IP başlık verilerini görüntülemek için, datagram başlığını (ama verileri değil) bir dizgeye dönüştürmek için bir fonksiyon uygulanmalıdır. Örnek bir uygulama olarak, aşağıdaki seçeneği sunabiliriz:

Bir IP Başlığını Dizeye Dönüştürme
satır içi karakter* iph2str(IPHeader *iph) ( const int BUF_SIZE = 1024; char *r = (char*)malloc(BUF_SIZE); memset((void*)r, 0, BUF_SIZE); sprintf(r, "ver=% d hlen=%d tos=%d len=%d id=%d bayraklar=0x%X offset=%d ttl=%dms prot=%d crc=0x%X src=%s hedef=%s", BYTE_H (iph->ver_len), BYTE_L(iph->ver_len)*4, iph->tos, ntohs(iph->uzunluk), ntohs(iph->id), IP_FLAGS(ntohs(iph->flgs_offset)), IP_OFFSET (ntohs(iph->flgs_offset)), iph->ttl, iph->protocol, ntohs(iph->xsum), nethost2str(iph->src), nethost2str(iph->hedef)); return r; )
Yukarıdaki temel bilgilere dayanarak, IP trafiğini yerel olarak dinlemeyi uygulayan çok küçük bir program (korkunç isim ss, İngilizce basit dinleyicinin kısaltması) elde ediyoruz. Arayüzü şekilde aşağıda gösterilmiştir.

Birkaç yıl önce olduğu gibi, kaynak ve ikili kodu olduğu gibi sağlıyorum. Şimdi bakmaya korkuyorum ama yine de oldukça okunaklı (elbette bu kadar özgüvenli olamazsınız). Derleme için Visual Studio Express 2005 bile yeterli olacaktır.

Neyle sonuçlandık:

  • Sniffer, kullanıcı modunda çalışır, ancak yönetici ayrıcalıkları gerektirir.
  • Paketler filtrelenmez, olduğu gibi görüntülenir (özel filtreler eklenebilir - ilgileniyorsanız bu konuyu bir sonraki makalede ayrıntılı olarak ele almamızı öneririm).
  • WiFi trafiği de yakalanır (hepsi şuna bağlıdır: belirli modelçip, birkaç yıl önce benim için yaptığı gibi sizin için çalışmayabilir), ancak bunu harika bir şekilde yapabilen ancak paraya mal olan AirPcap olmasına rağmen.
  • Datagram akışının tamamı bir dosyaya kaydedilir (makalenin sonunda ekli arşive bakın).
  • Program, 2000 numaralı bağlantı noktasında sunucu olarak çalışır. Bir ana bilgisayara telnet yapabilir ve trafik akışlarını izleyebilirsiniz. Bağlantı sayısı yirmi ile sınırlıdır (kod benim değil, internette buldum ve deneyler için kullandım; silmedim - yazık)
İlginiz için teşekkür ederim, Khabrovites ve Khabrovites'i tebrik ediyoruz ve önümüzdeki Noel ile her şey!

Bu yazıda, Windows işletim sistemi için basit bir sniffer oluşturmaya bakacağız.
Kimin umurunda, kedinin altına hoşgeldin.

Tanıtım

Hedef: IP protokolü üzerinden iletilen ağ trafiğini (Ethernet, WiFi) yakalayacak bir program yazın.
Tesisler: Visual Studio 2005 veya üstü.
Burada açıklanan yaklaşım kişisel olarak yazara ait değildir ve birçok ticari ve kategorik olarak ücretsiz programlarda (merhaba, GPL) başarıyla kullanılmaktadır.
Bu çalışma öncelikle ağ programlamaya yeni başlayanlar için tasarlanmıştır, ancak genel olarak soketler ve özellikle windows soketleri hakkında en azından temel bilgilere sahiptir. Burada sık sık bilinen şeyler yazacağım çünkü konu alanı belirli, bir şeyi kaçırırsanız kafanız karışır.

Umarım bunu ilginç bulursun.

Teori (okuma isteğe bağlıdır, ancak arzu edilir)

Şu anda, modern bilgi ağlarının büyük çoğunluğu, TCP / IP protokol yığınının temeline dayanmaktadır. TCP/IP (İletim Kontrol Protokolü/İnternet Protokolü) protokol yığını, ağlarda kullanılan farklı düzeylerdeki ağ protokollerinin toplu adıdır. Bu makalede, esas olarak IP protokolü ile ilgileneceğiz - bir ağ düğümünden diğerine sözde paketlere bölünmüş (daha doğru bir terim bir datagramdır) verilerin garanti edilmeyen teslimi için kullanılan yönlendirilebilir bir ağ protokolü.
Bizi özellikle ilgilendiren, bilgi aktarımına yönelik IP paketleridir. Bu, cihazdan ve veri iletim ortamından soyutlamak mümkün olduğunda, yalnızca mantıksal bir temsille çalışan OSI ağ veri modelinin yeterince yüksek bir seviyesidir.
Ağ trafiğine müdahale, kontrol, muhasebe ve analiz için er ya da geç araçların ortaya çıkması oldukça mantıklıdır. Bu tür araçlara genellikle trafik analizörleri, paket analizörleri veya koklayıcılar denir (İngilizce'den sniff - sniff'e). Bu, bir ağ trafiği analizörü, bir program veya donanım ve yazılım cihazı olup, araya girip ardından analiz etmek veya yalnızca diğer düğümlere yönelik ağ trafiğini analiz etmek için tasarlanmıştır.

Alıştırma yapın (konuya odaklanın)

Şu anda trafiği dinlemek için bir çok yazılım oluşturulmuştur. Bunların en ünlüsü: Wireshark. Doğal olarak, amaç defnelarını toplamaya değmez - ağ arayüzünün olağan "dinlenmesi" ile trafiği engelleme göreviyle ilgileniyoruz. Bilgisayar korsanlığı ve müdahaleleriyle meşgul olmayacağımızı anlamak önemlidir. yabancı trafik. Sadece sunucumuzdan geçen trafiği görüntülemeniz ve analiz etmeniz yeterlidir.

Neden gerekli olabilir:

  1. Ağ bağlantısı üzerinden mevcut trafik akışını görüntüleyin (gelen/giden/toplam).
  2. Daha fazla analiz için trafiği başka bir ana bilgisayara yönlendirin.
  3. Teorik olarak, bir WiFi ağını hacklemek için kullanmayı deneyebilirsiniz (bunu yapmayacağız, değil mi?).

libpcap/WinPcap kitaplığını temel alan Wireshark'ın aksine, analizörümüz bu sürücüyü kullanmayacaktır. Orada ne var, hiç şoförümüz olmayacak ve kendi NDIS'imizi (korku!) Bu konu hakkında okuyabilirsiniz. kullanarak sadece pasif bir gözlemci olacak. bir tek WinSock kitaplığı. Bu durumda bir sürücü kullanmak gereksizdir.

Nasıl yani? Çok basit.
Basit bir ağ uygulamasını bir ağ çözümleyicisine dönüştürmenin önemli bir adımı, ağ arabirimini, ağdaki diğer arabirimlere gönderilen paketleri almasına izin verecek şekilde karışık moda geçirmektir. Bu mod, ağ kartını, ağda kime yönlendirildiklerine bakılmaksızın tüm çerçeveleri kabul etmeye zorlar.

Windows 2000'den (NT 5.0) başlayarak, bir ağ kesiminde dinlemek için bir program oluşturmak çok kolay hale geldi, çünkü ağ sürücüsü, soketi tüm paketleri alma moduna geçirmenizi sağlar.

Karışık modu etkinleştirme
uzun bayrak = 1; SOKET soketi; #define SIO_RCVALL 0x98000001 ioctlsocket(soket, SIO_RCVALL, &RS_Flag);

Programımız IP paketleri üzerinde çalışır ve Windows Sockets kitaplığı sürüm 2.2 ve ham soketleri kullanır. Bir IP paketine doğrudan erişmek için soket aşağıdaki gibi oluşturulmalıdır:

Ham Soket Oluşturma
s = soket(AF_INET, SOCK_RAW, IPPROTO_IP);

Burada sabit yerine SOCK_STREAM(TCP protokolü) veya SOCK_DGRAM(UDP protokolü), değeri kullanıyoruz SOCK_RAW. Genel olarak konuşursak, ham soketlerle çalışmak sadece trafiği yakalama açısından ilginç değildir. Aslında, paketin oluşumu üzerinde tam kontrole sahibiz. Veya daha doğrusu, örneğin belirli bir ICMP paketi göndermeye izin veren manuel olarak oluştururuz ...

Devam et. Bir IP paketinin bir başlık, hizmet bilgisi ve aslında verilerden oluştuğu bilinmektedir. Bilginizi tazelemek için buraya bakmanızı tavsiye ederim. IP başlığını bir yapı olarak tanımlayalım (RSDN'deki harika makale sayesinde):

IP paketinin yapısının açıklaması
typedef struct _IPHeader ( unsigned char ver_len; // başlık sürümü ve uzunluk imzasız char tos; // hizmet tipi imzasız kısa uzunluk; // tüm paketin uzunluğu imzasız kısa kimlik; // Id imzasız kısa flgs_offset; // işaretler ve işaretsiz ofset char ttl ; // ömür boyu imzasız karakter protokolü; // protokol imzasız kısa xsum; // sağlama toplamı imzasız uzun kaynak; // kaynak IP adresi imzasız uzun hedef; // hedef IP adresi imzasız kısa *params; // parametreler (320'ye kadar) bit) unsigned char *veri; // veri (65535 sekizliye kadar) )IPHeader;

Dinleme algoritmasının ana işlevi şöyle görünecektir:

Tek Paket Yakalama İşlevi
IPHeader* RS_Sniff() ( IPHeader *hdr; int sayı = 0; sayım = recv(RS_SSocket, (char*)&RS_Buffer, sizeof(RS_Buffer), 0); if (sayım >= sizeof(IPHeader)) ( hdr = (LPIPHeader) )malloc(MAX_PACKET_SIZE); memcpy(hdr, RS_Buffer, MAX_PACKET_SIZE); RS_UpdateNetStat(count, hdr); hdr döndür; ) yoksa 0 döndür; )

Burada her şey basit: standart soket işlevini kullanarak verinin bir kısmını alıyoruz tekrar ve ardından bunları aşağıdaki gibi bir yapıya kopyalayın IPBaşlığı.
Ve son olarak, sonsuz bir paket yakalama döngüsü başlatıyoruz:

Ağ arayüzümüzü vuracak tüm paketleri yakalamak
while (true) ( ​​IPHeader* hdr = RS_Sniff(); // IP paketini if ​​(hdr) işle ( // konsolda üstbilgiyi yazdır ) )
biraz offtopik

Bundan sonra, yazar bazı önemli fonksiyonları ve değişkenleri RS_ ile (Ham Soketlerden) öneklendirmiştir. Proje 3-4 yıl önce yapıldı ve ham soketlerle çalışmak için tam teşekküllü bir kütüphane yazmak için çılgın bir fikir vardı. Çoğu zaman olduğu gibi, (yazar için) herhangi bir önemli sonuç elde ettikten sonra, coşku azaldı ve mesele eğitim örneğinden öteye gitmedi.

Prensip olarak, daha ileri gidebilir ve yukarıdaki tüm sonraki protokollerin başlıklarını tanımlayabilirsiniz. Bunu yapmak için alanı analiz etmek gerekir. protokol yapıda IPBaşlığı. IP kapsüllü paketin sahip olduğu protokole bağlı olarak başlığın renklendirildiği kod örneğine bakın (evet, bir anahtar olmalı, kahretsin!).

/* * Paket vurgulama */ void ColorPacket(const IPHeader *h, const u_long haddr, const u_long whost = 0) ( if (h->xsum) SetConsoleTextColor(0x17); // paket boş değilse SetConsoleTextColor(0x07) ) ; // boş paket if (haddr == h->src) ( SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/ FOREGROUND_RED | FOREGROUND_INTENSITY); // "native" dönüş paketi ) else if (haddr == h->dest ) ( SetConsoleTextColor(BACKGROUND_INTENSITY |*/ FOREGROUND_GREEN | FOREGROUND_INTENSITY); // "native" alma paketi ) if (h->protocol == PROT_ICMP || h->protocol == PROT_IGMPColor)(0 SetConsoleTextColor) (SetConsoleTextColor) // ICMP paketi ) else if(h->protocol == PROT_IP || h->protocol == 115) ( SetConsoleTextColor(0x4F); // IP-in-IP paketi, L2TP ) else if(h- >protocol = = 53 || h->protocol == 56) ( SetConsoleTextColor(0x4C); // TLS, Şifreli IP ) if(whost == h->dest || whost == h->src) ( SetConsoleTextColor (0x0A) ; ))

Ancak, bu önemli ölçüde bu makalenin kapsamı dışındadır. Eğitim örneğimiz için trafiğin geldiği ve gittiği hostların ip adreslerine bakıp birim zamandaki miktarını hesaplamak oldukça yeterli olacaktır (bitmiş program programın sonunda arşivdedir). makale).

IP başlık verilerini görüntülemek için, datagram başlığını (ama verileri değil) bir dizgeye dönüştürmek için bir fonksiyon uygulanmalıdır. Örnek bir uygulama olarak, aşağıdaki seçeneği sunabiliriz:

Bir IP Başlığını Dizeye Dönüştürme
satır içi karakter* iph2str(IPHeader *iph) ( const int BUF_SIZE = 1024; char *r = (char*)malloc(BUF_SIZE); memset((void*)r, 0, BUF_SIZE); sprintf(r, "ver=% d hlen=%d tos=%d len=%d id=%d bayraklar=0x%X offset=%d ttl=%dms prot=%d crc=0x%X src=%s hedef=%s", BYTE_H (iph->ver_len), BYTE_L(iph->ver_len)*4, iph->tos, ntohs(iph->uzunluk), ntohs(iph->id), IP_FLAGS(ntohs(iph->flgs_offset)), IP_OFFSET (ntohs(iph->flgs_offset)), iph->ttl, iph->protocol, ntohs(iph->xsum), nethost2str(iph->src), nethost2str(iph->hedef)); return r; )

Yukarıdaki temel bilgilere dayanarak, IP trafiğini yerel olarak dinlemeyi uygulayan çok küçük bir program (korkunç isim ss, İngilizce basit dinleyicinin kısaltması) elde ediyoruz. Arayüzü şekilde aşağıda gösterilmiştir.

Birkaç yıl önce olduğu gibi, kaynak ve ikili kodu olduğu gibi sağlıyorum. Şimdi bakmaya korkuyorum ama yine de oldukça okunaklı (elbette bu kadar özgüvenli olamazsınız). Derleme için Visual Studio Express 2005 bile yeterli olacaktır.

Neyle sonuçlandık:

  • Sniffer, kullanıcı modunda çalışır, ancak yönetici ayrıcalıkları gerektirir.
  • Paketler filtrelenmez, olduğu gibi görüntülenir (özel filtreler eklenebilir - ilgileniyorsanız bu konuyu bir sonraki makalede ayrıntılı olarak ele almamızı öneririm).
  • WiFi trafiği de kaydedilir (hepsi belirli çip modeline bağlıdır, birkaç yıl önce benim için yaptığı gibi sizin için çalışmayabilir), ancak bunu harika bir şekilde yapabilen ancak maliyetli olan AirPcap olmasına rağmen.
  • Datagram akışının tamamı bir dosyaya kaydedilir (makalenin sonunda ekli arşive bakın).
  • Program, 2000 numaralı bağlantı noktasında sunucu olarak çalışır. Bir ana bilgisayara telnet yapabilir ve trafik akışlarını izleyebilirsiniz. Bağlantı sayısı yirmi ile sınırlıdır (kod benim değil, internette buldum ve deneyler için kullandım; silmedim - yazık)

İlginiz için teşekkür ederim, Iok'u tebrik ederim ve gelecek Noel'de her şey yolunda!


Üst