namai - Interneto sąranka
Sniffer vietiniam tinklui su statybininku. Paprasto snifferio rašymas, skirtas „Windows“.

Šiame straipsnyje apžvelgsime, kaip sukurti paprastą „Windows“ OS skirtą snifferį.
Kas domisi, kviečiame į katę.

Įvadas

Tikslas: parašyti programą, kuri fiksuos tinklo srautą (Ethernet, WiFi), perduodamą per IP protokolą.
Įranga: Visual Studio 2005 ar naujesnė versija.
Čia aprašytas požiūris nepriklauso autoriui asmeniškai ir yra sėkmingai naudojamas daugelyje komercinių, taip pat kategoriškai nemokamas programas(sveiki, GPL).
Šis darbas visų pirma skirtas pradedantiesiems tinklo programavimo srityje, tačiau turintiems bent jau bazinių žinių apie lizdus apskritai ir konkrečiai apie Windows lizdus. Čia dažnai rašysiu žinomus dalykus, nes dalykinė sritis specifinė, jei ko nors praleisiu, galva bus netvarka.

Tikiuosi, kad jums tai bus įdomu.

Teorija (skaityti nebūtina, bet rekomenduojama)

Šiuo metu didžioji dauguma šiuolaikinių informaciniai tinklai yra pagrįsti TCP/IP protokolų krūvos pagrindu. TCP/IP protokolų krūva (Transmission Control Protocol/Internet Protocol) yra bendras skirtingų lygių tinklo protokolų, naudojamų tinkluose, pavadinimas. Šiame straipsnyje daugiausia dėmesio skirsime IP protokolui – nukreiptam tinklo protokolas, naudojamas negarantuotam duomenų, suskirstytų į vadinamuosius paketus (tikslesnis terminas – datagrama) pristatymui iš vieno tinklo mazgo į kitą.
Mus ypač domina IP paketai, skirti informacijai perduoti. Tai gana aukštas OSI tinklo duomenų modelio lygis, kai galima atsiriboti nuo įrenginio ir duomenų perdavimo terpės, veikiant tik su loginiu atvaizdavimu.
Visiškai logiška, kad anksčiau ar vėliau turėjo atsirasti perėmimo, kontrolės, apskaitos ir analizės įrankiai tinklo srautą. Tokie įrankiai dažniausiai vadinami srauto analizatoriais, paketų analizatoriais arba snifferiais (iš anglų kalbos į sniff – sniff). tai - tinklo analizatorius srautas, programa arba aparatinės-programinės įrangos įrenginys, skirtas perimti ir vėliau analizuoti arba tik analizuoti tinklo srautą, skirtą kitiems mazgams.

Praktika (išsamus pokalbis)

Šiuo metu sukurta gana daug programinė įranga klausytis eismo. Garsiausias iš jų: Wireshark. Natūralu, kad tikslas nėra skinti laurus - mus domina užduotis perimti srautą tiesiog „klausantis“ tinklo sąsajos. Svarbu suprasti, kad mes nesiruošiame įsilaužti ir perimti svetimas eismo. Mums tereikia peržiūrėti ir analizuoti srautą, einantį per mūsų prieglobą.

Kodėl to gali prireikti:

  1. Peržiūrėkite dabartinį srautą per tinklo ryšį (gaunamasis / išeinantis / bendras).
  2. Peradresuokite srautą tolesnei analizei į kitą pagrindinį kompiuterį.
  3. Teoriškai galite pabandyti jį panaudoti įsilauždami į WiFi tinklą (mes to nedarysime, ar ne?).

Skirtingai nuo Wireshark, kuris yra pagrįstas libpcap/WinPcap biblioteka, mūsų analizatorius nenaudos šios tvarkyklės. Be to, mes iš viso neturėsime vairuotojo ir nerašysime savo NDIS (o siaubo!). Apie tai galite perskaityti šioje temoje. Jis tiesiog bus pasyvus stebėtojas, naudodamasis tik WinSock biblioteka. Šiuo atveju tvarkyklės naudojimas yra nereikalingas.

Kaip tai? Labai paprasta.
Pagrindinis žingsnis paverčiant paprastą tinklo taikomąją programą tinklo analizatoriumi yra tinklo sąsajos perjungimas į laisvą režimą, kuris leis jai priimti paketus, adresuotus kitoms tinklo sąsajoms. Šis režimas priverčia tinklo plokštę priimti visus kadrus, neatsižvelgiant į tai, kam jie tinkle skirti.

Pradedant nuo Windows 2000 (NT 5.0), tapo labai lengva sukurti programą, skirtą klausytis tinklo segmento, nes ją tinklo tvarkyklė leidžia perjungti lizdą į visų paketų priėmimo režimą.

Promiscuous režimo įjungimas
ilga vėliava = 1; SOCKET lizdas; #define SIO_RCVALL 0x98000001 ioctlsocket(socket, SIO_RCVALL, &RS_Flag);

Mūsų programa veikia su IP paketais ir naudoja Windows Sockets bibliotekos 2.2 versiją bei neapdorotus lizdus. Norint gauti tiesioginę prieigą prie IP paketo, lizdas turi būti sukurtas taip:

Neapdoroto lizdo sukūrimas
s = lizdas (AF_INET, SOCK_RAW, IPPROTO_IP);

Čia vietoj konstantos SOCK_STREAM(TCP protokolas) arba SOCK_DGRAM(UDP protokolas), mes naudojame reikšmę SOCK_RAW. Paprastai tariant, darbas su neapdorotais lizdais įdomus ne tik eismo fiksavimo požiūriu. Tiesą sakant, mes visiškai kontroliuojame pakuotės formavimą. O tiksliau – formuojame rankiniu būdu, kas leidžia, pavyzdžiui, siųsti konkretų ICMP paketą...

Pirmyn. Yra žinoma, kad IP paketą sudaro antraštė, paslaugų informacija ir, tiesą sakant, duomenys. Patariu pasižvalgyti čia ir atnaujinti savo žinias. Apibūdinkime IP antraštę struktūros pavidalu (dėl puikaus straipsnio apie RSDN):

IP paketo struktūros aprašymas
typedef struct _IPHeader ( unsigned char ver_len; // antraštės versija ir ilgis unsigned char tos; // paslaugos tipas nepasirašytas trumpas ilgis; // viso paketo ilgis nepasirašytas trumpas id; // Id unsigned short flgs_offset; // vėliavėlės ir poslinkis nepasirašyti char ttl ; // visą laiką nepasirašytas char protokolas; // protokolas nepasirašytas trumpas xsum; // kontrolinė suma unsigned long src; // siuntėjo IP adresas unsigned long dest; // paskirties IP adresas nepasirašytas trumpas *paramai; // parametrai (iki 320 bitai) unsigned char *duomenys; // duomenys (iki 65535 oktetų) )IPHeader;

Pagrindinė klausymo algoritmo funkcija atrodys taip:

Vieno paketo fiksavimo funkcija
IPHeader* RS_Sniff() ( IPHeader *hdr; int count = 0; count = recv(RS_SSocket, (char*)&RS_Buffer, sizeof(RS_Buffer), 0); if (count >= sizeof(IPHeader)) ( hdr = (LPIPHeader) )malloc(MAX_PACKET_SIZE); memcpy(hdr, RS_Buffer, MAX_PACKET_SIZE); RS_UpdateNetStat(count, hdr); grąžinti hdr; ) kitaip grąžinti 0; )

Čia viskas paprasta: mes gauname duomenų dalį naudodami standartinę lizdo funkciją recv, tada nukopijuokite juos į tokią struktūrą kaip IP antraštė.
Ir galiausiai paleidžiame nesibaigiantis ciklas paketo gaudymas:

Užfiksuokime visus paketus, kurie pasiekia mūsų tinklo sąsają
while (true) (IPHeader* hdr = RS_Sniff(); // apdoroja IP paketą, jei (hdr) ( // spausdinkite antraštę konsolėje) )
Šiek tiek offtopic

Čia ir toliau autorius kai kurioms svarbioms funkcijoms ir kintamiesiems sukūrė RS_ (iš Raw Sockets) priešdėlį. Projektą įgyvendinau prieš 3–4 metus ir man kilo beprotiška mintis parašyti visavertę biblioteką darbui su neapdorotais lizdais. Kaip dažnai nutinka, gavus reikšmingų (autoriui) rezultatų, entuziazmas išblėso ir reikalas neperžengė lavinimo pavyzdžio.

Iš esmės galite eiti toliau ir aprašyti visų paskesnių aukščiau esančių protokolų antraštes. Norėdami tai padaryti, turite išanalizuoti lauką protokolas struktūroje IP antraštė. Pažvelkite į pavyzdinį kodą (taip, ten turėtų būti jungiklis, po velnių!), kur antraštė yra spalvota, priklausomai nuo to, kokį protokolą paketas įdėtas į IP:

/* * Paketo paryškinimas spalva */ void ColorPacket(const IPHeader *h, const u_long haddr, const u_long whost = 0) ( if (h->xsum) SetConsoleTextColor(0x17); // jei paketas nėra tuščias SetConsoleTextColor(0x07) ; // tuščias paketas if (haddr == h->src) ( SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/ FOREGROUND_RED | FOREGROUND_INTENSITY); // paketas grąžinamas "elone" = "native" h->dest ) ( SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/ FOREGROUND_GREEN | FOREGROUND_INTENSITY); // "Savasis" priėmimo paketas ) if (h->protocol == PROT_ICMP || = PROT_ICMP || h->Protocol. (0x70) ; // ICMP paketas ) else if(h->protocol == PROT_IP || h->protocol == 115) ( SetConsoleTextColor(0x4F); // IP-in-IP paketas, L2TP ) else if(h - >protocol == 53 || h->protocol == 56) ( SetConsoleTextColor(0x4C); // TLS, IP su šifravimu ) if(whost == h->dest || whost == h->src) ( SetConsoleTextColor (0x0A); ) )

Tačiau tai gerokai nepatenka į šio straipsnio taikymo sritį. Mūsų mokymo pavyzdžiui pakaks pažvelgti į kompiuterių, iš kurių ir į kuriuos ateina srautas, IP adresus ir apskaičiuoti jo kiekį per laiko vienetą (baigta programa yra archyve straipsnio pabaigoje) .

Kad būtų rodomi IP antraštės duomenys, turite įdiegti funkciją, kuri konvertuoja datagramos antraštę (bet ne duomenis) į eilutę. Kaip įgyvendinimo pavyzdį galime pasiūlyti šią parinktį:

IP antraštės konvertavimas į eilutę
eilutinis char* 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 vėliavėlės=0x%X poslinkis=%d ttl=%dms prot=%d crc=0x%X src=%s dest=%s", BYTE_H (iph->ver_len), BYTE_L(iph->ver_len)*4, iph->tos, ntohs(iph->ilgis), 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->dest)); grąžinti r; )

Remdamiesi aukščiau pateikta pagrindine informacija, gauname šią nedidelę programą (baisus pavadinimas ss, paprastas sniffer trumpinys), kuri įgyvendina vietinį IP srauto klausymąsi. Jo sąsaja parodyta žemiau esančiame paveikslėlyje.

Pateikiu šaltinio ir dvejetainį kodą tokį, koks jis yra, kaip ir prieš keletą metų. Dabar man baisu į tai žiūrėti, bet vis dėlto jis gana skaitomas (žinoma, negalima taip pasitikėti savimi). Kompiliavimui užteks net ir Visual Studio Express 2005.

Kuo mes baigėsi:

  • Sniffer veikia vartotojo režimu, tačiau jam reikia administratoriaus teisių.
  • Paketai nefiltruojami ir rodomi tokie, kokie yra (galite pridėti pasirinktinių filtrų – jei susidomėjote, siūlau pažvelgti į šią temą išsamiai kitame straipsnyje).
  • Taip pat fiksuojamas WiFi srautas (viskas priklauso nuo konkretus modelis lustas, jis gali jums neveikti, kaip man prieš keletą metų), nors yra „AirPcap“, kuris gali tai padaryti nuostabiai, tačiau kainuoja pinigus.
  • Visas datagramos srautas įrašomas į failą (žr. straipsnio pabaigoje pridėtą archyvą).
  • Programa veikia kaip serveris prie 2000 prievado. Galite prisijungti prie pagrindinio kompiuterio naudodami telnet priemonę ir stebėti srautus. Ryšių skaičius ribojamas iki dvidešimties (kodas ne mano, radau jį internete ir panaudojau eksperimentams; neištryniau - gaila)

Dėkoju už dėmesį, linkiu jums ir visiems linksmų Kalėdų!

Šiame straipsnyje apžvelgsime, kaip sukurti paprastą „Windows“ OS skirtą snifferį.
Kas domisi, kviečiame į katę.

Įvadas

Tikslas: parašyti programą, kuri fiksuos tinklo srautą (Ethernet, WiFi), perduodamą per IP protokolą.
Įranga: Visual Studio 2005 ar naujesnė versija.
Čia aprašytas metodas nepriklauso autoriui asmeniškai ir yra sėkmingai naudojamas daugelyje komercinių, taip pat visiškai nemokamų programų (labas, GPL).
Šis darbas visų pirma skirtas pradedantiesiems tinklo programavimo srityje, tačiau turintiems bent jau bazinių žinių apie lizdus apskritai ir konkrečiai apie Windows lizdus. Čia dažnai rašysiu žinomus dalykus, nes dalykinė sritis specifinė, jei ko nors praleisiu, galva bus netvarka.

Tikiuosi, kad jums tai bus įdomu.

Teorija (skaityti nebūtina, bet rekomenduojama)

Šiuo metu didžioji dauguma šiuolaikinių informacinių tinklų yra pagrįsti TCP/IP protokolų krūva. TCP/IP protokolų krūva (Transmission Control Protocol/Internet Protocol) yra bendras skirtingų lygių tinklo protokolų, naudojamų tinkluose, pavadinimas. Šiame straipsnyje mus daugiausia domins IP protokolas – maršrutinio tinklo protokolas, naudojamas negarantuotam duomenų, suskirstytų į vadinamuosius paketus (tikslesnis terminas – datagrama), pristatymui iš vieno tinklo mazgo į kitą.
Mus ypač domina IP paketai, skirti informacijai perduoti. Tai gana aukštas OSI tinklo duomenų modelio lygis, kai galima atsiriboti nuo įrenginio ir duomenų perdavimo terpės, veikiant tik su loginiu atvaizdavimu.
Visiškai logiška, kad anksčiau ar vėliau turėjo atsirasti tinklo srauto perėmimo, stebėjimo, įrašymo ir analizės įrankiai. Tokie įrankiai dažniausiai vadinami srauto analizatoriais, paketų analizatoriais arba snifferiais (iš anglų kalbos į sniff – sniff). Tai tinklo srauto analizatorius, programa arba aparatinės-programinės įrangos įrenginys, skirtas perimti ir vėliau analizuoti arba tik analizuoti tinklo srautą, skirtą kitiems mazgams.

Praktika (išsamus pokalbis)

Šiuo metu yra sukurta gana daug programinės įrangos srautui klausytis. Garsiausias iš jų: Wireshark. Natūralu, kad tikslas nėra skinti laurus - mus domina užduotis perimti srautą tiesiog „klausantis“ tinklo sąsajos. Svarbu suprasti, kad mes nesiruošiame įsilaužti ir perimti svetimas eismo. Mums tereikia peržiūrėti ir analizuoti srautą, einantį per mūsų prieglobą.

Kodėl to gali prireikti:

  1. Peržiūrėkite dabartinį srautą per tinklo ryšį (gaunamasis / išeinantis / bendras).
  2. Peradresuokite srautą tolesnei analizei į kitą pagrindinį kompiuterį.
  3. Teoriškai galite pabandyti jį panaudoti įsilauždami į WiFi tinklą (mes to nedarysime, ar ne?).
Skirtingai nuo Wireshark, kuris yra pagrįstas libpcap/WinPcap biblioteka, mūsų analizatorius nenaudos šios tvarkyklės. Be to, mes iš viso neturėsime vairuotojo ir nerašysime savo NDIS (o siaubo!). Apie tai galite perskaityti. Jis tiesiog bus pasyvus stebėtojas, naudodamasis tik WinSock biblioteka. Šiuo atveju tvarkyklės naudojimas yra nereikalingas.

Kaip tai? Labai paprasta.
Pagrindinis žingsnis paverčiant paprastą tinklo taikomąją programą tinklo analizatoriumi yra tinklo sąsajos perjungimas į laisvą režimą, kuris leis jai priimti paketus, adresuotus kitoms tinklo sąsajoms. Šis režimas priverčia tinklo plokštę priimti visus kadrus, neatsižvelgiant į tai, kam jie tinkle skirti.

Pradedant nuo Windows 2000 (NT 5.0), tapo labai lengva sukurti programą, skirtą klausytis tinklo segmento, nes jo tinklo tvarkyklė leidžia nustatyti, kad lizdas priimtų visus paketus.

Promiscuous režimo įjungimas
ilga vėliava = 1; SOCKET lizdas; #define SIO_RCVALL 0x98000001 ioctlsocket(socket, SIO_RCVALL, &RS_Flag);
Mūsų programa veikia su IP paketais ir naudoja Windows Sockets bibliotekos 2.2 versiją bei neapdorotus lizdus. Norint gauti tiesioginę prieigą prie IP paketo, lizdas turi būti sukurtas taip:
Neapdoroto lizdo sukūrimas
s = lizdas (AF_INET, SOCK_RAW, IPPROTO_IP);
Čia vietoj konstantos SOCK_STREAM(TCP protokolas) arba SOCK_DGRAM(UDP protokolas), mes naudojame reikšmę SOCK_RAW. Paprastai tariant, darbas su neapdorotais lizdais įdomus ne tik eismo fiksavimo požiūriu. Tiesą sakant, mes visiškai kontroliuojame pakuotės formavimą. O tiksliau – formuojame rankiniu būdu, kas leidžia, pavyzdžiui, siųsti konkretų ICMP paketą...

Pirmyn. Yra žinoma, kad IP paketą sudaro antraštė, paslaugų informacija ir, tiesą sakant, duomenys. Patariu pasižvalgyti čia ir atnaujinti savo žinias. Apibūdinkime IP antraštę struktūros pavidalu (dėl puikaus straipsnio apie RSDN):

IP paketo struktūros aprašymas
typedef struct _IPHeader ( unsigned char ver_len; // antraštės versija ir ilgis unsigned char tos; // paslaugos tipas nepasirašytas trumpas ilgis; // viso paketo ilgis nepasirašytas trumpas id; // Id unsigned short flgs_offset; // vėliavėlės ir poslinkis nepasirašyti char ttl ; // visą laiką nepasirašytas char protokolas; // protokolas nepasirašytas trumpas xsum; // kontrolinė suma unsigned long src; // siuntėjo IP adresas unsigned long dest; // paskirties IP adresas nepasirašytas trumpas *paramai; // parametrai (iki 320 bitai) unsigned char *duomenys; // duomenys (iki 65535 oktetų) )IPHeader;
Pagrindinė klausymo algoritmo funkcija atrodys taip:
Vieno paketo fiksavimo funkcija
IPHeader* RS_Sniff() ( IPHeader *hdr; int count = 0; count = recv(RS_SSocket, (char*)&RS_Buffer, sizeof(RS_Buffer), 0); if (count >= sizeof(IPHeader)) ( hdr = (LPIPHeader) )malloc(MAX_PACKET_SIZE); memcpy(hdr, RS_Buffer, MAX_PACKET_SIZE); RS_UpdateNetStat(count, hdr); grąžinti hdr; ) kitaip grąžinti 0; )
Čia viskas paprasta: mes gauname duomenų dalį naudodami standartinę lizdo funkciją recv, tada nukopijuokite juos į tokią struktūrą kaip IP antraštė.
Ir galiausiai pradedame nesibaigiančią paketų fiksavimo kilpą:
Užfiksuokime visus paketus, kurie pasiekia mūsų tinklo sąsają
while (true) (IPHeader* hdr = RS_Sniff(); // apdoroja IP paketą, jei (hdr) ( // spausdinkite antraštę konsolėje) )
Šiek tiek offtopic
Čia ir toliau autorius kai kurioms svarbioms funkcijoms ir kintamiesiems sukūrė RS_ (iš Raw Sockets) priešdėlį. Projektą įgyvendinau prieš 3–4 metus ir man kilo beprotiška mintis parašyti visavertę biblioteką darbui su neapdorotais lizdais. Kaip dažnai nutinka, gavus reikšmingų (autoriui) rezultatų, entuziazmas išblėso ir reikalas neperžengė lavinimo pavyzdžio.

Iš esmės galite eiti toliau ir aprašyti visų paskesnių aukščiau esančių protokolų antraštes. Norėdami tai padaryti, turite išanalizuoti lauką protokolas struktūroje IP antraštė. Pažvelkite į pavyzdinį kodą (taip, ten turėtų būti jungiklis, po velnių!), kur antraštė yra spalvota, priklausomai nuo to, kokį protokolą paketas įdėtas į IP:

/* * Paketo paryškinimas spalva */ void ColorPacket(const IPHeader *h, const u_long haddr, const u_long whost = 0) ( if (h->xsum) SetConsoleTextColor(0x17); // jei paketas nėra tuščias SetConsoleTextColor(0x07) ; // tuščias paketas if (haddr == h->src) ( SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/ FOREGROUND_RED | FOREGROUND_INTENSITY); // paketas grąžinamas "elone" = "native" h->dest ) ( SetConsoleTextColor(BACKGROUND_BLUE | /*BACKGROUND_INTENSITY |*/ FOREGROUND_GREEN | FOREGROUND_INTENSITY); // "Savasis" priėmimo paketas ) if (h->protocol == PROT_ICMP || = PROT_ICMP || h->Protocol. (0x70) ; // ICMP paketas ) else if(h->protocol == PROT_IP || h->protocol == 115) ( SetConsoleTextColor(0x4F); // IP-in-IP paketas, L2TP ) else if(h - >protocol == 53 || h->protocol == 56) ( SetConsoleTextColor(0x4C); // TLS, IP su šifravimu ) if(whost == h->dest || whost == h->src) ( SetConsoleTextColor (0x0A); ) )

Tačiau tai gerokai nepatenka į šio straipsnio taikymo sritį. Mūsų mokymo pavyzdžiui pakaks pažvelgti į kompiuterių, iš kurių ir į kuriuos ateina srautas, IP adresus ir apskaičiuoti jo kiekį per laiko vienetą (baigta programa yra archyve straipsnio pabaigoje) .

Kad būtų rodomi IP antraštės duomenys, turite įdiegti funkciją, kuri konvertuoja datagramos antraštę (bet ne duomenis) į eilutę. Kaip įgyvendinimo pavyzdį galime pasiūlyti šią parinktį:

IP antraštės konvertavimas į eilutę
eilutinis char* 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 vėliavėlės=0x%X poslinkis=%d ttl=%dms prot=%d crc=0x%X src=%s dest=%s", BYTE_H (iph->ver_len), BYTE_L(iph->ver_len)*4, iph->tos, ntohs(iph->ilgis), 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->dest)); grąžinti r; )
Remdamiesi aukščiau pateikta pagrindine informacija, gauname šią nedidelę programą (baisus pavadinimas ss, paprastas sniffer trumpinys), kuri įgyvendina vietinį IP srauto klausymąsi. Jo sąsaja parodyta žemiau esančiame paveikslėlyje.

Pateikiu šaltinio ir dvejetainį kodą tokį, koks jis yra, kaip ir prieš keletą metų. Dabar man baisu į tai žiūrėti, bet vis dėlto jis gana skaitomas (žinoma, negalima taip pasitikėti savimi). Kompiliavimui užteks net ir Visual Studio Express 2005.

Kuo mes baigėsi:

  • Sniffer veikia vartotojo režimu, tačiau jam reikia administratoriaus teisių.
  • Paketai nefiltruojami ir rodomi tokie, kokie yra (galite pridėti pasirinktinių filtrų – jei susidomėjote, siūlau pažvelgti į šią temą išsamiai kitame straipsnyje).
  • Taip pat fiksuojamas WiFi srautas (viskas priklauso nuo konkretaus lusto modelio, jums gali netikti, kaip man prieš keletą metų), nors yra AirPcap, kuris gali tai padaryti nuostabiai, bet kainuoja.
  • Visas datagramos srautas įrašomas į failą (žr. straipsnio pabaigoje pridėtą archyvą).
  • Programa veikia kaip serveris prie 2000 prievado. Galite prisijungti prie pagrindinio kompiuterio naudodami telnet priemonę ir stebėti srautus. Ryšių skaičius ribojamas iki dvidešimties (kodas ne mano, radau jį internete ir panaudojau eksperimentams; neištryniau - gaila)
Dėkoju už dėmesį, sveikinu Chabrovsko ir Chabrovkos gyventojus ir visus, Linksmų Kalėdų!

Laba diena Kažkaip darbe iškilo bėda – buvo įrenginys, kuris veikė per I2C ir kurio protokolą reikėjo perprasti. Todėl mums reikia I2C sąsajos sniferio, kuris išvestų viską, kas ateina ir išeina per I2C į UART prievadą, o tada per keitiklį į kompiuterio COM prievadą.

Pradėti

Turėjau tik porą Atmeg8 ir nusprendžiau, kodėl jų nepanaudojus. Toliau iškilo uostiklio grandinės klausimas.

Buvo 2 variantai - įjungti sniferį lygiagrečiai arba atviroje grandinėje. Akivaizdu, kad pirmasis variantas atrodo daug paprastesnis, kuris iš tikrųjų pasirodė visiškai neteisingas. Bet pirmiausia pirmiausia.

Trumpai apie pačią sąsają. I2C (Atmel TWI) naudoja du laidus - SCL ir SDA. Pirmasis yra atsakingas už signalo laikrodį, antrasis yra atsakingas už tiesioginį informacijos perdavimą. Sąsaja taip pat turi START ir STOP būsenas.

Taigi, mano pirmoji mintis buvo paimti zondą ir, viena vertus, prijungti jį prie atmega8 išorinės pertraukimo kojos, kita vertus, prie SDA linijos ir užfiksuoti priekinį kraštą ir pagal praėjusį laiką nustatyti 0 arba 1. Akivaizdu, kad tai turėjo veikti labai prastai, nes STOP signalas nebuvo tinkamai apdorotas.

Antroji mintis buvo padaryti tą patį, bet užfiksuoti SCL linijos pertrūkį ir naudojant pertrūkį perskaityti SDA liniją, prijungtą prie įprastos skaitmeninės kojos. Čia viskas atrodė gyvybingiau, išskyrus tą pačią STOP būseną, bet nusprendžiau pabandyti surinkti ją ant duonos lentos ir pažiūrėti, kas atsitiks.

Iš anksto atsiprašau, jei žemiau esančiame kode radote akivaizdžių klaidų, nes atmestas kodo versijas atkuriu iš atminties ant kelių.

Pertraukimų tvarkyklės kodas atrodė taip:

ISR(INT0_vect) ( cli(); if (bitIsHigh(PINB, 0)) uart_send_char("1"); else uart_send_char("0"); sei(); )
Į uostą plūstelėjo nuliai ir vienetai, tačiau iškart tapo akivaizdu, kad duomenys neteisingi – jų buvo daug mažiau nei tikėtasi ir pasikartojus ta pačia užklausa ji pasikeitė. Išsiaiškinus priežastis, viskas susivedė į tai, kad duomenys buvo prarasti dėl prieigos prie uart sąsajos, kuri, beje, veikė maksimaliu stabiliu 38 kbit/s greičiu, o I2C pats dirbo 100 kbit/s greičiu. Nebuvo įmanoma padidinti UART greičio, nes trūko reikiamo dažnio kristalo, kad UART pasiektų priimtiną greitį. Todėl iš pertraukos reikėjo pašalinti darbą su uart. Gavau kažką tokio:

Statiniai uint8_t duomenys = 0; statinis uint8_t idx = 7; ISR(INT0_vect) ( cli(); duomenys |= bitIsHigh(PINB, 0)<< (idx--); if (!idx) { uart_send_char(data); data = 0; idx = 7; } sei(); }
Viskas tapo stabiliau, bet duomenys vis tiek neturėjo prasmės. Po kelių valandų darbo su algoritmu, įjungus STOP apdorojimą ir pan., buvo nuspręsta eiti kitu keliu.

Teisinga linkme

Kad ir kiek bandžiau įdiegti sniferį naudodamas lygiagrečią grandinę, nieko neišėjo. Remiantis tuo, liko tik viena galimybė - reikėjo įtraukti mikrovaldiklį į tarpą, tai yra, jis turi būti ir pagrindinis atsako įtaisas, ir vergas pirminiam valdikliui. Turbūt skamba painiai, bet iš tikrųjų taip nėra.

Kadangi atmega8 turi tik vieną aparatinę I2C, akivaizdu, kad norint dirbti, reikia parašyti programinės įrangos palaikymą protokolui.

Rezultatas buvo toks kodas:

ISR (TWI_VECT) (cli (); uint8_t status = twsr; uint8_t b; char s; AW:"); uart_send_int(TWDR); i2csoft_start(); i2csoft_open_write(I2C_ADDRESS); pertrauka; atvejis I2C_STATUS_SR_RX_DATA_ACK:/* atvejis I2C_STATUS_SR_RX_DATA_NACK:*/ b = TWDR, end_s(b.str.s); s); i2csoft_write_byte (b); pertrauka; atvejis I2C_STATUS_SR_RX_STOP_RESTART: uart_send_str("E\n"); _delay_ms(10); do ( _delay_us(5); i2csoft_start(); ) while (!i2csoft_start(); ) while (!i2csoft_2;break_AD(IESS)2); atvejis I2C_STATUS_BUS_ERROR: uart_send_str("B\n"); pertrauka; atvejis TW_ST_SLA_ACK: uart_send_str("-AR:"); uart_send_int(TWDR); b = i2csoft_read_byte(); sprintf(s",, b "%.2. uart_send_str(s); TWDR = b; pertrauka; atvejis TW_ST_DATA_ACK: b = i2csoft_read_byte(); sprintf(s, " %.2X", b); uart_send_str(s); TWDR = b; pertrauka; atvejis TW_ST_DATA_NACK: TW_DATA:_ b = i2csoft_read_byte(false); uart_send_str("L\n"); pertrauka; numatytoji: uart_send_char("U"); uart_send_int(statusas); uart_send_char(" "); pertrauka; ) TWCR |= (1<Pagrindinis įrenginys yra prijungtas prie atmega aparatinės I2C, vykdymo įrenginys prijungtas prie bet kokių 2 skaitmeninių kojų, kurių viena veikia SCL režimu, kita SDA. Visas aukščiau pateiktas kodas yra pertraukimas per I2C ir programinės įrangos sąsajoje sukelia panašią būseną, o paslaugų informacija įrašoma į uart, kad būtų lengviau suprasti, kas vyksta. Nustatyti vėlavimai buvo pasirinkti konkrečiam įrenginiui ir gali šiek tiek skirtis kitiems. Dėl to gauname labai gerą uostytoją.

Jei kam įdomu, šaltinius galima paimti iš



 


Skaityti:



Atsisiųskite „Minecraft“, skirtą „Android“: visos versijos

Atsisiųskite „Minecraft“, skirtą „Android“: visos versijos

- tai labai populiarus žaidimas, kuris dabar tapo prieinamas Android įrenginiams! Tradiciškai jame valdysite užimtą personažą...

Parsisiųsti minecraft 1 modifikacijas

Parsisiųsti minecraft 1 modifikacijas

Šiame skyriuje galite visiškai nemokamai ir greitai atsisiųsti žaidimui „Minecraft Pocket Edition“ reikalingą modifikaciją. Mūsų svetainėje yra...

ModPack Zeus002 atsisiuntimo modifikacijos yra World Of Tanks modifikacijų paketas

ModPack Zeus002 atsisiuntimo modifikacijos yra World Of Tanks modifikacijų paketas

Tarp tanklaivių populiariausia sekcija yra įvairūs WoT modifikacijų rinkiniai. „WoT“ modifikacijų rinkinių tipai Sukūrė populiarių vaizdo įrašų kūrėjų...

Kodėl minecraft man netinka?

Kodėl minecraft man netinka?

„Minecraft“ paleidimo problemos kyla gana dažnai. Yra keletas priežasčių. Kompiuteris gali tiesiog neturėti Java priedo, be...

tiekimo vaizdas RSS