[c++, winapi] Sniffer przy użyciu rawsocket

0

Witam
Ostatnio próbuję napisać sobie prostego sniffera przy użyciu rawsocket i napisałem sobie klasę o nazwie cinque oto jej kod:

#include <winsock2.h> 

#define MAX_PACKET_SIZE 65535 
#ifndef SIO_RCVALL 
#  define SIO_RCVALL    _WSAIOW(IOC_VENDOR,1) 
#endif 

typedef struct _IP_HEADER_ 
{ 
   BYTE  ver_ihl;        // Version (4 bits) and Internet Header Length (4 bits) 
   BYTE  type;           // Type of Service (8 bits) 
   WORD  length;         // Total size of packet (header + data)(16 bits) 
   WORD  packet_id;      // (16 bits) 
   WORD  flags_foff;     // Flags (3 bits) and Fragment Offset (13 bits) 
   BYTE  time_to_live;   // (8 bits) 
   BYTE  protocol;       // (8 bits) 
   WORD  hdr_chksum;     // Header check sum (16 bits) 
   DWORD source_ip;      // Source Address (32 bits) 
   DWORD destination_ip; // Destination Address (32 bits) 
} IPHEADER; 

class cinque 
{ 
    private: 
        WSADATA wsaData; 
        SOCKET s_socket; 
        SOCKADDR_IN sockaddr; 
        SOCKADDR sockaddr_from; 
        char ip[20]; 
        char packet[MAX_PACKET_SIZE]; 
        //char source_ip[20]; 
        char destination_ip[20]; 
        IPHEADER *ip_header; 


    public: 
        unsigned int error; 

        cinque(); 
        ~cinque(); 
        void Recv(char *source_ip); 

}; 


cinque::cinque() 
{ 
    error = 0; 

    if ( WSAStartup( MAKEWORD(2,2),  &wsaData ) !=0 ) 
    { 
        error = 1; 
    } 

    s_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 

    if(s_socket == INVALID_SOCKET) 
    { 
        error = 2; 
    } 

   char hostname[128]; 
   PHOSTENT phostent; 

   gethostname(hostname, sizeof(hostname)); 

   phostent = gethostbyname(hostname); 

    memcpy((char FAR *)&(sockaddr.sin_addr),phostent->h_addr,phostent->h_length); 
    sockaddr.sin_family = AF_INET; 
    sockaddr.sin_port = htons(0); 

    if(bind(s_socket, (PSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) 
    { 
        error = 3; 
    } 

    int optval = 1; 
    DWORD    dwLen = 0; 

    if ( WSAIoctl( s_socket, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &dwLen, NULL, NULL ) == SOCKET_ERROR ) 
    { 
        error = 4; 
    } 
} 

cinque::~cinque() 
{ 
    closesocket(s_socket); 
    WSACleanup(); 
} 

void cinque::Recv(char *source) 
{ 
    if(recv(s_socket, packet, MAX_PACKET_SIZE, 0) > 0) 
    { 
        ip_header = (IPHEADER *) packet; 
        in_addr in; 
        in.S_un.S_addr = ip_header->source_ip; 
        strcpy(source, inet_ntoa(in)); 
    } 
} 

Później napisałem program który miał sprawdzić działanie tego programu i niestety nie działa. Oto jego kod:

#include <cinque.h> 
#include <iostream> 

int main() 
{ 
    cinque snif; 
    char ip[20]; 

    while(1) 
    { 
        std::cout<<"Listenig..."; 
        snif.Recv(ip); 
        std::cout<<ip; 
    } 
} 

Proszę o jakieś wskazówki lub uwagi dlaczego to nie działa. Myślę że jest to spowodowane tym że rawsocket'y mają wprowadzone jakieś ograniczenia w systemach windows xp i wyższych. Jeśli to jest przyczyną to proszę o podanie linków do jakichś bibliotek lub sposobu aby uzyskać takie uprawnienia.
z góry dziękuję
pozdro

0

tez kiedys probowalem to zrobic, nie dziala.

zostaje ci NDIS filter driver, powodzenia przy pisaniu plikow .inf :-D

0
Radziol napisał(a)

Proszę o jakieś wskazówki lub uwagi dlaczego to nie działa.

To ja poprosze o wskazowke co konkretnie sie dzieje, ze stwierdziles objaw nie dzialania.

0

Według tego co zrozumiałem z kursów to podczas przesyłania jakiegoś pakietu mój program powinien go przechwycić i w tym wypadku podać ip. Gdy uruchamiam program i wchodzę na jakąś stronę internetową to program powinien przechwycić dany pakiet i wyświetlić ip. (Nie wiem czy dobrze to zrozumiałem) Program cały czas oczekuje na pakiet i nie wyświetla żadnego ip.

0

czyli error ma po wykonaniu konstruktora wartosc 0 ?

0

error ma wartość 3 czyli wyskakuje w tej linijce:

if(bind(s_socket, (PSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN)) != SOCKET_ERROR)
    {
        error = 3;
    }

ale jest to błąd w kodzie. Powinno być:

if(bind(s_socket, (PSOCKADDR)&sockaddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    {
        //error = 3;
        error = WSAGetLastError();
    }

i teraz error = 0.
Gdy testowałem ten program jeszcze z tym błędem (pierwszą wersją kodu powyżej) program zaczął mi wypisywać adresy ip(myślę że ten poprawiony kod nie miał znaczenia ponieważ nie sprawdzałem nigdzie parametru error). Nie wiem czy to ma jakieś znaczenie ale miałem wtedy uruchomionego bit torrenta który ściągał. Później już nigdy nie pokazał mi ip.

0

Zmien sposob wyswietlania tego ip, bo wszystko wydaje sie w porzadku, jesli ioctl nie zwraca bledu: Zamien std::cout << ip; na for(int i = 0; i < 4; i++) printf("%3.2X", ip[i]);. Proponuje takze strcpy zamienic na memcpy w metodzie recv.

0

Jak to nic nie da to daj po prostu INADDR_ANY w sin.s_addr.

1 użytkowników online, w tym zalogowanych: 0, gości: 1