Как слушать ICMP пакеты?

Тема в разделе "WASM.BEGINNERS", создана пользователем _sheva740, 8 дек 2008.

  1. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    Добрый день!
    Хочу чтобы по пингу с заданной командой в буфере пакета - троян выполнял свое действие.
    Локальная сеть предприятия 192.168.1.0/32.
    Подскажите пожалуйста как определить КТО меня пингует?
    Вот пытаюсь слушать ICMP пакеты, но откликается только не локальный ping.
    Если кто-то удаленно из сети шлет ping прожка молчит :dntknw:((
    Файрволов нет - проверенно.
    Сам исходник переписал с linux - аналога взятого на opennet.ru.
    Под linux не пишу, но там говорят что работает.
    Код (Text):
    1. #include "stdio.h"
    2. #include "winsock2.h"
    3. #include "windows.h"
    4. #pragma comment(lib,"ws2_32.lib")
    5.  
    6.  
    7. int main(int argc, char* argv[])
    8. {
    9.     WSADATA wsd;
    10.     if (WSAStartup (MAKEWORD (2,2), &wsd) != 0)
    11.     {
    12.         printf ("error WSAStartup() init\n");
    13.         return 0;
    14.     }
    15.  
    16.    SOCKET sc;
    17.    SOCKADDR_IN addr;
    18.    char buf [1024];
    19.    int len;
    20.    int iplen;
    21.    int res;
    22.    iplen = sizeof (addr);
    23.    len = sizeof (buf);
    24.  
    25.     LPPROTOENT lpproto;
    26.     int proto;
    27.     addr.sin_family = AF_INET;
    28.     addr.sin_addr.s_addr = htonl(INADDR_ANY);
    29.  
    30.     if ((lpproto = getprotobyname("icmp")) == NULL)
    31.         proto = IPPROTO_ICMP;
    32.     else
    33.         proto = lpproto->p_proto;
    34.         sc = socket(AF_INET, SOCK_RAW, proto);
    35.  
    36.         if (sc == INVALID_SOCKET) printf ("error socket() ");  
    37.         if (bind (sc,(LPSOCKADDR) &addr,sizeof (addr)) != 0) printf ("error bind()");
    38.         //for(;;)
    39.         //{
    40.             res = recvfrom (sc,buf,len,0,(LPSOCKADDR) &addr,&iplen);
    41.             if (res == SOCKET_ERROR)
    42.             {
    43.                 printf ("error recvfrom() = %d \n",GetLastError ());
    44.             }
    45.             else
    46.             {
    47.                 printf ("length: %d\tip: %s\tbuffer: %s\n",iplen,(LPSTR) inet_ntoa (addr.sin_addr),buf);
    48.             }
    49.         //}
    50.     return 0;
    51. }
    Подскажите почему не отрабатывает если пингую из локалки ?
     
  2. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    А что значит молчит?
    Тут поток тормозит всмысле?
    Попробуй создать сокет который будет принимать все пакеты включая IP хидер
    и уже от него перейти к icmp
     
  3. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    only
    >А что значит молчит?
    >Тут поток тормозит всмысле?

    да просто ожидает чего-то на строке :
    Код (Text):
    1.  res = recvfrom (sc,buf,len,0,(LPSOCKADDR) &addr,&iplen);
    >Попробуй создать сокет который будет принимать все пакеты включая IP хидер
    и уже от него перейти к icmp

    да это придется обычный снифер ставить, фильтровать протокол icmp из ip заголовка
    Не пойму почему это не работает ?
     
  4. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    сменить протокол тут
    на IPPROTO_IP
    проверить версию и протокол следующего уровня чтобы был IPPROTO_ICMP(вроде 1)
    ну и перейти к ICMP просто прибавив размер IP хидера

    вообще и фильтровать не нужно, просто посмотреть приходят ли IP
    а в дампе посмотреть что там icmp или нет
     
  5. ECk

    ECk Member

    Публикаций:
    0
    Регистрация:
    9 апр 2004
    Сообщения:
    454
    Адрес:
    Russia
    если под винду пишется данный код, лучше юзать SIO_RCVALL
     
  6. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    _sheva740
    кстати да, как заметил ECk походу тебе еще это нужно добавить
    ну или что то подобное
    Код (Text):
    1.         SocketIoctlMode = RCVALL_ON;
    2.         Result = ioctlsocket(sc, SIO_RCVALL, &SocketIoctlMode);
    3.         if(Result == SOCKET_ERROR)
    4.         {
    5.             Status = IOCTL_REQUEST_FAILED;
    6.             return Status;
    7.         }
     
  7. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    only
    Первый мой вывод - Все пробы и исправления в конце концов все равно снифер дали :)
    Второй - не все что идет под *nix - ами "безропотно" переносится на win32.
     
  8. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    _sheva740
    Минут за 10 можно нагуглить как минимум 2 десятка снифферов для виндовс.
     
  9. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    only
    >Минут за 10 можно нагуглить как минимум 2 десятка снифферов для виндовс.
    да ты прав, но 3-4 только будут работать под XP, и может 1 - под Vista
     
  10. Ation

    Ation New Member

    Публикаций:
    0
    Регистрация:
    6 авг 2005
    Сообщения:
    92
    Адрес:
    Zaporozhie
    - ставишь протокол как посоветовал only ( IPPROTO_ICMP )
    - ставишь опцию что хочешь получать и хедеры тоже (чтоб из IP пакета вытянуть адреса), опцию не помню, это гуглится.
    - в MSDN четко сказано, для работы с сырыми сокетами надо делать bind на конкретный адаптер.
    - потом говоришь что хочешь получать все (SIO_RCVALL, см выше) - так ты будешь получать исходящий и входящий ICMP траффик.
    - просто recv в цикле.
    - смотришь и радуешся :)
     
  11. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    _sheva740

    ну вот так можно
    это точно работает под виндой
    вырезано кусками но смысл думаю ясен

    инициализация подсистемы
    Код (Text):
    1. _STATUS InitSubsystem()
    2. {
    3.     _STATUS Status = _SUCCESS;
    4.     WSADATA WsaData = {0};
    5.     DWORD Result = {0};
    6.  
    7.     WSAStartup(0, &WsaData);
    8.     Result = WSAStartup(WsaData.wHighVersion, &WsaData);
    9.     if(Result)
    10.     {
    11.         Status = _WSASTARTUP_FAILED;
    12.         return Status;
    13.     }
    14.     return Status;
    15. }
    инициализация сокета
    Код (Text):
    1.     Status = InitSubsystem();
    2.     if(Status != _SUCCESS)
    3.         return Status;
    4.  
    5.         ListnerDescr->Listner = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    6.         if(ListnerDescr->Listner == INVALID_SOCKET)
    7.         {
    8.             DeinitListener(ListnerDescr);
    9.             Status = LISTEN_SOCKET_INIT_FAILED;
    10.             return Status;
    11.         }
    12.         Result = gethostname(HostName, HOST_NAME_MAX_LEN/*256*/);
    13.         if(Result == SOCKET_ERROR)
    14.         {
    15.             DeinitListener(ListnerDescr);
    16.             Status = CANT_OBTAIN_LOCAL_HOST_NAME;
    17.             return Status;
    18.         }
    19.         HostDescr = gethostbyname(HostName);
    20.         Result = (DWORD)HostDescr;
    21.         if(!Result)
    22.         {
    23.             DeinitListener(ListnerDescr);
    24.             Status = CANT_OBTAIN_LOCAL_HOST_DESCRIPTOR;
    25.             return Status;
    26.         }
    27.         SocketDescr.sin_family = AF_INET;
    28.         SocketDescr.sin_addr.S_un.S_addr = ((IN_ADDR *)HostDescr->h_addr_list[0])->S_un.S_addr;
    29.         for(i = 0; i < (u_short)(~0)+1; i++)
    30.         {
    31.             SocketDescr.sin_port = (u_short)i;
    32.             Result = bind(ListnerDescr->Listner, (SOCKADDR *)&SocketDescr, sizeof(SOCKADDR));
    33.             if(Result == SOCKET_ERROR && WSAGetLastError() != WSAEINVAL)
    34.             {
    35.                 DeinitListener(ListnerDescr);
    36.                 Status = RAWSOCKSNIFFER_HOST_DESCRIPTOR_BINDING_ERROR;
    37.                 return Status;
    38.             }
    39.             else if(Result != SOCKET_ERROR)
    40.                 break;
    41.         }
    42.         SocketIoctlMode = RCVALL_ON;
    43.         Result = ioctlsocket(ListnerDescr->Listner, SIO_RCVALL, &SocketIoctlMode);
    44.         if(Result == SOCKET_ERROR)
    45.         {
    46.             DeinitListener(ListnerDescr);
    47.             Status = IOCTL_REQUEST_FAILED;
    48.             return Status;
    49.         }
    50.         if(Result == SOCKET_ERROR)
    51.         {
    52.             DeinitListener(ListnerDescr);
    53.             Status = ALL_PORTS_ARE_IN_USE;
    54.             return Status;
    55.         }
    56.         ListnerDescr->Thread.Handle = CreateThread(0, 0, (PTHREAD_START_ROUTINE)ListenerThread, ListnerDescr, 0, &ListnerDescr->Thread.Id);
    57.         if(!ListnerDescr->Thread.Handle)
    58.         {
    59.             DeinitListener(ListnerDescr);
    60.             Status = CANT_CREATE_LISTENER_THREAD;
    61.             return Status;
    62.         }
    анализ
    Код (Text):
    1. _STATUS ListenerThread(_LISTENER_DESCR *ListnerDescr)
    2. {
    3.  
    4.     _STATUS Status = _SUCCESS;
    5.     DWORD Result = {0};
    6.     DWORD BytesGot = {0};
    7.     ULONG MaxFrarmentSize = {0};
    8.     DWORD OptSize = {0};
    9.     PVOID RecvData = {0};
    10.     DWORD RecvDataOldProt = {0};
    11.    
    12.     __try
    13.     {
    14.         BytesGot = 0;
    15.         OptSize = sizeof(MaxFrarmentSize);
    16.         Result = getsockopt(ListnerDescr->Listner, SOL_SOCKET, SO_MAX_MSG_SIZE, (PCHAR)&MaxFrarmentSize, &OptSize);
    17.         if(Result == SOCKET_ERROR)
    18.         {
    19.             Status = _MAX_MSG_SIZE_UNKNOWN;
    20.             DeinitListener(ListnerDescr);
    21.             return Status;
    22.         }
    23.         ListnerDescr->Data.PVoid = (PBYTE)VirtualAlloc(0, MaxFrarmentSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
    24.         if(!ListnerDescr->Data.PByte)
    25.         {
    26.             Status = _MEMORY_ALLOCATION_ERROR;
    27.             DeinitListener(ListnerDescr);
    28.             return Status;
    29.         }
    30.         do
    31.         {
    32.             BytesGot = recv(ListnerDescr->Listner, (PCHAR)ListnerDescr->Data.PByte, MaxFrarmentSize, 0);
    33.             Result = BytesGot;
    34.             if(Result == SOCKET_ERROR)
    35.             {
    36.                 Status = _RECEIVE_ERROR;
    37.                 DeinitListener(ListnerDescr);
    38.                 return Status;
    39.             }
    40.                     if(BytesGot)
    41.                     {
    42.                             RecvData = VirtualAlloc(0, BytesGot, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    43.                             if(!RecvData)
    44.                             {
    45.                                 Status = _MEMORY_ALLOCATION_ERROR;
    46.                                 DeinitListener(ListnerDescr);
    47.                                 return Status;
    48.                             }
    49.                             memcpy(RecvData, ListnerDescr->Data.PVoid, BytesGot);
    50.                             Result = VirtualProtect(RecvData, BytesGot, PAGE_READONLY, &RecvDataOldProt);
    51.                             if(!Result)
    52.                             {
    53.                                 VirtualFree(RecvData, 0, MEM_RELEASE);
    54.                                 Status = _MEMORY_PROTECTION_CHANGE_ERROR;
    55.                                 DeinitListener(ListnerDescr);
    56.                                 return Status;
    57.                             }
    58.                                                        //тут можно RecvData передать какому-либу зарегистрированному у тебя колбеку
    59.                     VirtualFree(RecvData, 0, MEM_RELEASE);
    60.             }
    61.         }while(TRUE);
    62.     }
    63.     __except(EXCEPTION_EXECUTE_HANDLER)
    64.     {
    65.         if(ListnerDescr->Listner)
    66.         {
    67.             shutdown(ListnerDescr->Listner, SD_RECEIVE);
    68.             closesocket(ListnerDescr->Listner);
    69.         }
    70.         Status = _UNHANDLED_EXCEPTION;
    71.         DeinitListener(ListnerDescr);
    72.         return Status;
    73.     }
    74.     DeinitListener(ListnerDescr);
    75.     return Status;
    76. }
    Ation
    Ну эта опция только для IPPROTO_IP и работает только при передаче данных, указывает на то что отправитель будет сам создавать IP хидер, если уж хочется и IP хидер, то тогда нужно сокет связанный с IP(IPPROTO_IP) создавать, а не с вложенным в него ICMP(IPPROTO_ICMP)
     
  12. _sheva740

    _sheva740 New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2005
    Сообщения:
    1.539
    Адрес:
    Poland
    Ation
    only
    Большое спасибо - разобрался !!!