Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > C/C++ Сетевое программирование
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.09.2018, 22:35   #1
sashok_2005
Пользователь
 
Регистрация: 26.03.2017
Сообщений: 11
Печаль C++ Снифер

Здрасте. Пишу снифер на c++ (что-то по типу Wireshark, без WinPcap) вот что пока получилось:
Код:
#include <iostream>
#include <winsock2.h>
#include <bitset>

#define SIO_RCVALL         0x98000001

using namespace std;

typedef struct IPPacket //Структура ip пакета
{
    unsigned char  ip_ver_hlen;
    unsigned char  ip_tos;
    unsigned short ip_length;
    unsigned short ip_id;
    unsigned short ip_flag_offset;
    unsigned char  ip_ttl;
    unsigned char  ip_protocol;
    unsigned short ip_xsum;
    unsigned int   ip_srcaddr;
    unsigned int   ip_dstaddr;
    unsigned char  ip_data[];
};

typedef struct TCPHeader // Структура TCP заголовка
{
    unsigned short tcp_srcport;
    unsigned short tcp_dstport;
    unsigned int tcp_sn;
    unsigned int tcp_acksn;
    unsigned char tcp_hlen:4;
    unsigned char tcp_flag_offset:6;
    unsigned char tcp_flags:6;
    unsigned short tcp_window;
    unsigned short tcp_xsum;
    unsigned short tcp_urg_pointer;
    unsigned char tcp_opt_data[];
};

typedef struct UDPHeader // Структура UDP заголовка
{
    unsigned short udp_srcport;
    unsigned short udp_dstport;
    unsigned short udp_length;
    unsigned short udp_xsum;
    unsigned char  udp_data[];
};

void ShowPacketInfo(IPPacket* iph){ // Информация об IP пакете
    cout<<"Version: "<<static_cast<int>(iph->ip_ver_hlen >> 4)<<endl;
    cout<<"Header length: "<<static_cast<int>(iph->ip_ver_hlen & 15)<<endl;
    cout<<"ToS: "<<bitset<8>(iph->ip_tos)<<endl;
    cout<<"Packet length: "<<iph->ip_length<<endl;
    cout<<"Id: "<<iph->ip_id<<endl;
    cout<<"Flags: "<<bitset<3>(iph->ip_flag_offset >> 13)<<endl;
    cout<<"Offset: "<<bitset<13>(iph->ip_flag_offset & 8191)<<endl;
    cout<<"TTL: "<<static_cast<int>(iph->ip_ttl)<<endl;
    cout<<"Protocol: ";
    switch(iph->ip_protocol){
case IPPROTO_TCP:
    cout<<"TCP";
    break;
case IPPROTO_UDP:
    cout<<"UDP";
    break;
default:
    cout<<"Unknown";
    break;
    }
    cout<<endl;
    cout<<"Xsum: "<<iph->ip_xsum<<endl;
    IN_ADDR sa;
    sa.s_addr = iph->ip_srcaddr;
    cout<<"Src: "<<inet_ntoa(sa)<<endl;
    sa.s_addr = iph->ip_dstaddr;
    cout<<"Dst: "<<inet_ntoa(sa)<<endl;
}

void ShowPacketData(IPPacket* iph, int type){ // Данные IP пакета
    cout<<"IPData: "<<endl;
    if(type == 1){//HEX
        for(int i = 0; i < iph->ip_length - (iph->ip_ver_hlen & 15) * 32; i++){
            char bf[2];
            itoa(static_cast<short>(iph->ip_data[i]), bf, 16);
            if(bf[1] == 0){
                bf[1] = bf[0];
                bf[0] = '0';
            }
            cout<<bf<<' ';

            if(i%16 == 0 & i != 0){
                cout<<endl;
            }
        }
    }else{//char
        for(int i = 0; i < iph->ip_length - (iph->ip_ver_hlen & 15) * 32; i++){
            if(iph->ip_data[i] == 0){
                cout<<'.';
            }else{
                cout<<iph->ip_data[i];
            }
            if(i%64==0 & i!=0){
                cout<<endl;
            }
        }
    }
    cout<<endl;
}

int main(int argc, char *argv[])
{
    cout<<"Start...\n";
    WSAData WSData;
    WSAStartup(0x202,&WSData);
    SOCKET s;
    char name[128];
    HOSTENT* phe;
    SOCKADDR_IN sa;
    unsigned long flag = 1;
    s = socket( AF_INET, SOCK_RAW, IPPROTO_IP );
    gethostname(name, sizeof(name));
    phe = gethostbyname( name );
    ZeroMemory( &sa, sizeof(sa) );
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = ((struct in_addr *)phe->h_addr_list[0])->s_addr;
    bind(s, (SOCKADDR *)&sa, sizeof(SOCKADDR));
    ioctlsocket(s, SIO_RCVALL, &flag);
    int count=0;
    int c = 0;
    while( c == 0 ) // До первого IP пакета
    {
        char Buffer[65500];
        count = recv( s, Buffer, sizeof(Buffer), 0 );
        if( count >= sizeof(IPPacket) )
        {
            c = 1;
            IPPacket* iph = (IPPacket *)Buffer;
            ShowPacketInfo(iph);
            ShowPacketData(iph, 0);
            if(iph->ip_protocol == IPPROTO_TCP){
                TCPHeader* tcp = (TCPHeader *) iph->ip_data;
                cout<<tcp->tcp_srcport; // Вывод № порта
            }
            if(iph->ip_protocol == IPPROTO_UDP){
                UDPHeader* udp = (UDPHeader *) iph->ip_data;
                cout<<udp->udp_srcport; // Вывод № порта
            }
        }
    }

    WSACleanup ();
    system("PAUSE");
    return 0;
}
Вобщем что эта штука делает:
1: Ловит один IP пакет;
2: Показывает его заголовок(версия, длина, флаги и т.д.);
3: Показывает его даннные
Код:
char ip_data[];
Он показывает заголовок нормально, но у меня всегда выходят слишком длинные пакеты, по 10000, 20000 байт(но в Wireshark'е пакеты максимум длины 100), ещё какоето странное смещение с единицей.
Данные показывает в начале нормально (как видно на 1-ом изображении), но потом долго идут нули (точки). А потом происходит какаята хрень, как видно из 2-го рисунка.
Вобщем помогите, что нужно зделать что бы Ip пакет показывался нормальною
Изображения
Тип файла: png wsock1.png (17.5 Кб, 165 просмотров)
Тип файла: png wsock2.png (30.1 Кб, 128 просмотров)
sashok_2005 вне форума Ответить с цитированием
Старый 01.09.2018, 23:29   #2
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

Цитата:
Сообщение от sashok_2005 Посмотреть сообщение
у меня всегда выходят слишком длинные пакеты, по 10000, 20000 байт
Цитата:
Сообщение от wiki
The fields in the header are packed with the most significant byte first (big endian)
Используйте ntohl
Цитата:
Функция ntohl осуществляет перевод целого числа из сетевого порядка байт в порядок байт, принятый на компьютере.
Black Fregat вне форума Ответить с цитированием
Старый 02.09.2018, 10:01   #3
sashok_2005
Пользователь
 
Регистрация: 26.03.2017
Сообщений: 11
Смех

Ну вроде всё получилось, ntohl не подошла, зато ntohs самое то. Толбко пакет немного обрывается, но это как нибудь потом. И теперь порт правильно показывается.
В общем СПАСИБО.
Изображения
Тип файла: png Sniff1.png (24.1 Кб, 138 просмотров)
Тип файла: png Sniff2.png (23.1 Кб, 136 просмотров)
Тип файла: png Sniff3.png (17.1 Кб, 126 просмотров)
sashok_2005 вне форума Ответить с цитированием
Старый 02.09.2018, 16:06   #4
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

Цитата:
Сообщение от sashok_2005 Посмотреть сообщение
ntohl не подошла, зато ntohs самое то
Перепутал, виноват.. Спать хотелось
Black Fregat вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Снифер COM tarakan1983 Общие вопросы Delphi 2 13.05.2017 15:07
HTTP/S Снифер EliteDeN Общие вопросы Delphi 0 27.10.2013 22:08
не реагирует снифер megostudent Работа с сетью в Delphi 2 22.04.2012 16:59
Снифер с ведением лога Ghost of Night Софт 2 14.07.2011 03:35
Снифер на Delphi. SuperMooDuck Работа с сетью в Delphi 7 04.02.2008 18:16