WinPcap и отправка пакета
От: yaser Украина  
Дата: 17.03.07 10:52
Оценка:
Написано что в пкап есть ndis драйвер. После установки winpcap в сетевых устройствах не появляется нового устройства.
1. так и должно быть?
2. Для того чтобы отправить пакет нужно выбрать интерфейс. Я хотел бы отправлять пакеты на ndis драйвер pcap. Какой интерфейс я должен выбрать?
Re: WinPcap и отправка пакета
От: oziro Нигерия  
Дата: 18.03.07 00:51
Оценка:
Здравствуйте, yaser, Вы писали:

Y>Написано что в пкап есть ndis драйвер. После установки winpcap в сетевых устройствах не появляется нового устройства.

Y>1. так и должно быть?
ага

Y>2. Для того чтобы отправить пакет нужно выбрать интерфейс. Я хотел бы отправлять пакеты на ndis драйвер pcap. Какой интерфейс я должен выбрать?

эээ... надо выбрать тот интерфейс, на который хочешь послать. если одна сетевая карточка, но обычно там присутствует 2 (!) интерфейса
  • DialUp Generic чего-то там...
  • Твоя_Сетевая_Карточка
    Первый — это , как я помню, всякие соединения PPP, VPN , поддерживаемые виндой,
    Вторая — собственно, карточка сетевая. Скорее всего тебе она и нужна.
    Испольхуя вызовы библиотеки winpcap, ты выберешь необходимый интерфейс, прибиндишься к нему и сможешь туда слать (ну и принимать). Все это есть в доках на winpcap, причем очень доходчиво написано, примеров много, посмотри внимательней. Используя вызовы библиотеки ты тем самым "отправляешь" "пакеты" на ndis драйвер
    Как-то так, пусть меня подправят если чооо
  • Re[2]: WinPcap и отправка пакета
    От: yaser Украина  
    Дата: 18.03.07 12:47
    Оценка:
    Здравствуйте, oziro, Вы писали:

    O>Здравствуйте, yaser, Вы писали:


    Y>>Написано что в пкап есть ndis драйвер. После установки winpcap в сетевых устройствах не появляется нового устройства.

    Y>>1. так и должно быть?
    O>ага

    Y>>2. Для того чтобы отправить пакет нужно выбрать интерфейс. Я хотел бы отправлять пакеты на ndis драйвер pcap. Какой интерфейс я должен выбрать?

    O>эээ... надо выбрать тот интерфейс, на который хочешь послать. если одна сетевая карточка, но обычно там присутствует 2 (!) интерфейса
    O>
  • DialUp Generic чего-то там...
    O>
  • Твоя_Сетевая_Карточка
    O>Первый — это , как я помню, всякие соединения PPP, VPN , поддерживаемые виндой,
    O>Вторая — собственно, карточка сетевая. Скорее всего тебе она и нужна.
    O>Испольхуя вызовы библиотеки winpcap, ты выберешь необходимый интерфейс, прибиндишься к нему и сможешь туда слать (ну и принимать). Все это есть в доках на winpcap, причем очень доходчиво написано, примеров много, посмотри внимательней. Используя вызовы библиотеки ты тем самым "отправляешь" "пакеты" на ndis драйвер
    O>Как-то так, пусть меня подправят если чооо

    Возможно я не прав, но я так понял что виртуальное устройство нужно чтобы организовать свой TCP/IP стек, а winpcap даст возможность через свой ndis драйвер бросать пакеты на этот стек.

    теперь осталось понять:
    1.как при помощи pcap_sendpacket отправить IP пакет? мож кто-то даст семпл как это сделать.
    2. Интересно как работает IP/TCP стек. Скажем если я отправил IP пакет у которого адрес получателя не 127.0.0.1 дойдет ли он до программ на моих компьютере?
  • Re[3]: WinPcap и отправка пакета
    От: oziro Нигерия  
    Дата: 18.03.07 19:49
    Оценка:
    Здравствуйте, yaser, Вы писали:

    Y>теперь осталось понять:

    Y>1.как при помощи pcap_sendpacket отправить IP пакет? мож кто-то даст семпл как это сделать.

    Если мне не изменяет память, винпикап позволяет работать с сеткой на канальном уровне, это уровень ethernet фреймов (ну и другого чего может быть на канальном уровне). Причем для того что бы что то осмысленное отправить в сеть — тебе нужно будет сформировать корректный ethernet-frame, в него вложить корректный ip пакет и тд., т.е. никаких средств библиотека для генерации фреймов-пакетов не предоставляет. Указываешь pcap_sendpacket на массив того чего хочешь выплюнуть в сеть, это может быть что угодно! Семпл должен быть в доке, сейчас винпикап не стоит у меня.

    По приему же можешь настроить фильтр например "ethernet фреймы определенного типа", или "только udp пакеты" — винпикап будет тебе их калбеком отдавать (или просто, ты ожидая прихода, ждешь флага). Остальные пойдут мимо, по виндовому стеку далее.

    Y>2. Интересно как работает IP/TCP стек. Скажем если я отправил IP пакет у которого адрес получателя не 127.0.0.1 дойдет ли он до программ на моих компьютере?

    Ничего не понял Как работает стек — тут я пас, лучше почитай чего нить типа Руссиновича (сеть в виндовз) и Стивенса(вообще про TCP/IP). Про пакет который "не 127.0.0.1" — тоже не понял %) до чего он дойдет и куда? Винпикап выловит все, что поступит на указанный сетевой интерфейс, и покажет тебе если ты попросишь об этом. Корректно сформированный и отправленый в сеть IP-пакет дойдет до туда, куда ты его послал %)
    Re[3]: WinPcap и отправка пакета
    От: denisio_mcp  
    Дата: 19.03.07 07:21
    Оценка: +1
    Здравствуйте, yaser, Вы писали:

    Y>2. Интересно как работает IP/TCP стек. Скажем если я отправил IP пакет у которого адрес получателя не 127.0.0.1 дойдет ли он до программ на моих компьютере?


    Дойдет. Только снифером ты ево не поймаешь... Особенность стека Windows при работе с локальными адресами.
    ... << RSDN@Home 1.2.0 alpha rev. 0>>
    Re[4]: WinPcap и отправка пакета
    От: yaser Украина  
    Дата: 20.03.07 08:08
    Оценка:
    Здравствуйте, denisio_mcp, Вы писали:

    _>Здравствуйте, yaser, Вы писали:


    Y>>2. Интересно как работает IP/TCP стек. Скажем если я отправил IP пакет у которого адрес получателя не 127.0.0.1 дойдет ли он до программ на моих компьютере?


    _>Дойдет. Только снифером ты ево не поймаешь... Особенность стека Windows при работе с локальными адресами.


    В общем пытаюсь написать небольшую програмку, кот. будет отправлять серверу удп пакеты через winpcap.
    написал:

    #include "stdafx.h"
    #pragma pack(1)

    #define WIN32_LEAN_AND_MEAN

    #include <winsock2.h>
    #include <ws2tcpip.h>

    #include <stdio.h>
    #include <stdlib.h>
    #include <pcap.h>
    #include <string>

    #define MAX_MESSAGE 4068
    #define MAX_PACKET 4096
    //
    // Set up some default values
    //
    #define DEFAULT_PORT 5000
    #define DEFAULT_IP "127.0.0.1"
    #define DEFAULT_COUNT 1
    #define DEFAULT_MESSAGE "This is a test"

    //
    // Define the IP header. Make the version and length fields one
    // character since we can't declare two 4-bit fields without
    // the compiler aligning them on at least a 1-byte boundary.
    //
    typedef struct ip_hdr
    {
    unsigned char ip_verlen; // IP version & length
    unsigned char ip_tos; // IP type of service
    unsigned short ip_totallength; // Total length
    unsigned short ip_id; // Unique identifier
    unsigned short ip_offset; // Fragment offset field
    unsigned char ip_ttl; // Time to live
    unsigned char ip_protocol; // Protocol(TCP, UDP, etc.)
    unsigned short ip_checksum; // IP checksum
    unsigned int ip_srcaddr; // Source address
    unsigned int ip_destaddr; // Destination address
    } IP_HDR, *PIP_HDR, FAR* LPIP_HDR;
    //
    // Define the UDP header
    //
    typedef struct udp_hdr
    {
    unsigned short src_portno; // Source port number
    unsigned short dst_portno; // Destination port number
    unsigned short udp_length; // UDP packet length
    unsigned short udp_checksum; // UDP checksum (optional)
    } UDP_HDR, *PUDP_HDR;

    //
    // Global variables
    //
    unsigned long dwToIP, // IP to send to
    dwFromIP; // IP to send from (spoof)
    unsigned short iToPort, // Port to send to
    iFromPort; // Port to send from (spoof)
    DWORD dwCount; // Number of times to send
    char strMessage[MAX_MESSAGE]; // Message to send

    //
    // Function: checksum
    //
    // Description:
    // This function calculates the 16-bit one's complement sum
    // for the supplied buffer
    //
    USHORT checksum(USHORT *buffer, int size)
    {
    unsigned long cksum=0;

    while (size > 1)
    {
    cksum += *buffer++;
    size -= sizeof(USHORT);
    }
    if (size)
    {
    cksum += *(UCHAR*)buffer;
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);

    return (USHORT)(~cksum);
    }

    //
    // Function: main
    //
    // Description:
    // First parse command line arguments and load Winsock. Then
    // create the raw socket and set the IP_HDRINCL option.
    // Following this, assemble the IP and UDP packet headers by
    // assigning the correct values and calculating the checksums.
    // Then fill in the data and send to its destination.
    //
    int main(int argc, char **argv)
    {
    WSADATA wsd;
    SOCKET s;
    BOOL bOpt;
    struct sockaddr_in remote; // IP addressing structures
    IP_HDR ipHdr;
    UDP_HDR udpHdr;
    int ret;
    DWORD i;
    unsigned short iTotalSize, // Lots of sizes needed to fill
    iUdpSize, // the various headers with
    iUdpChecksumSize,
    iIPVersion,
    iIPSize,
    cksum = 0;
    char buf[MAX_PACKET],
    *ptr = NULL;
    IN_ADDR addr;

    iToPort = DEFAULT_PORT;
    iFromPort = DEFAULT_PORT;
    dwToIP = inet_addr("141.1.1.1");
    dwFromIP = inet_addr(DEFAULT_IP);
    dwCount = DEFAULT_COUNT;
    strcpy(strMessage, DEFAULT_MESSAGE);
    // Parse command line arguments, and print them out
    //
    // ValidateArgs(argc, argv);
    addr.S_un.S_addr = dwFromIP;
    printf("From IP: <%s>\n Port: %d\n", inet_ntoa(addr),
    iFromPort);
    addr.S_un.S_addr = dwToIP;
    printf("To IP: <%s>\n Port: %d\n", inet_ntoa(addr),
    iToPort);
    printf("Message: [%s]\n", strMessage);
    printf("Count: %d\n", dwCount);

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
    printf("WSAStartup() failed: %d\n", GetLastError());
    return -1;
    }
    // Creating a raw socket
    //
    s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,0);
    if (s == INVALID_SOCKET)
    {
    printf("WSASocket() failed: %d\n", WSAGetLastError());
    return -1;
    }

    // Enable the IP header include option
    //
    bOpt = TRUE;
    ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt,
    sizeof(bOpt));
    if (ret == SOCKET_ERROR)
    {
    printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
    return -1;
    }
    // Initalize the IP header
    //
    iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + strlen(strMessage);

    iIPVersion = 4;
    iIPSize = sizeof(ipHdr) / sizeof(unsigned long);
    //
    // IP version goes in the high-order 4 bits of ip_verlen. The
    // IP header length (in 32-bit words) goes in the lower 4 bits.
    //
    ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;
    ipHdr.ip_tos = 0; // IP type of service
    ipHdr.ip_totallength = htons(iTotalSize); // Total packet len
    ipHdr.ip_id = 0; // Unique identifier: set to 0
    ipHdr.ip_offset = 0; // Fragment offset field
    ipHdr.ip_ttl = 128; // Time to live
    ipHdr.ip_protocol = 0x11; // Protocol(UDP)
    ipHdr.ip_checksum = 0 ; // IP checksum
    ipHdr.ip_srcaddr = dwFromIP; // Source address
    ipHdr.ip_destaddr = dwToIP; // Destination address
    //
    // Initalize the UDP header
    //
    iUdpSize = sizeof(udpHdr) + strlen(strMessage);

    udpHdr.src_portno = htons(iFromPort) ;
    udpHdr.dst_portno = htons(iToPort) ;
    udpHdr.udp_length = htons(iUdpSize) ;
    udpHdr.udp_checksum = 0 ;
    //
    // Build the UDP pseudo-header for calculating the UDP checksum.
    // The pseudo-header consists of the 32-bit source IP address,
    // the 32-bit destination IP address, a zero byte, the 8-bit
    // IP protocol field, the 16-bit UDP length, and the UDP
    // header itself along with its data (padded with a 0 if
    // the data is odd length).
    //
    iUdpChecksumSize = 0;
    ptr = buf;
    ZeroMemory(buf, MAX_PACKET);

    memcpy(ptr, &ipHdr.ip_srcaddr, sizeof(ipHdr.ip_srcaddr));
    ptr += sizeof(ipHdr.ip_srcaddr);
    iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);

    memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr));
    ptr += sizeof(ipHdr.ip_destaddr);
    iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);

    ptr++;
    iUdpChecksumSize += 1;

    memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol));
    ptr += sizeof(ipHdr.ip_protocol);
    iUdpChecksumSize += sizeof(ipHdr.ip_protocol);

    memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length));
    ptr += sizeof(udpHdr.udp_length);
    iUdpChecksumSize += sizeof(udpHdr.udp_length);

    memcpy(ptr, &udpHdr, sizeof(udpHdr));
    ptr += sizeof(udpHdr);
    iUdpChecksumSize += sizeof(udpHdr);

    for(i = 0; i < strlen(strMessage); i++, ptr++)
    *ptr = strMessage[i];
    iUdpChecksumSize += strlen(strMessage);

    cksum = checksum((USHORT *)buf, iUdpChecksumSize);
    udpHdr.udp_checksum = cksum;
    //
    // Now assemble the IP and UDP headers along with the data
    // so we can send it
    //
    ZeroMemory(buf, MAX_PACKET);
    ptr = buf;

    memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr);
    memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);
    memcpy(ptr, strMessage, strlen(strMessage));

    // Apparently, this SOCKADDR_IN structure makes no difference.
    // Whatever we put as the destination IP addr in the IP header
    // is what goes. Specifying a different destination in remote
    // will be ignored.
    //
    remote.sin_family = AF_INET;
    remote.sin_port = htons(iToPort);
    remote.sin_addr.s_addr = dwToIP;

    /*for(i = 0; i < dwCount; i++)
    {
    ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote,
    sizeof(remote));
    if (ret == SOCKET_ERROR)
    {
    printf("sendto() failed: %d\n", WSAGetLastError());
    break;
    }
    else
    printf("sent %d bytes\n", ret);
    }*/
    pcap_t *fp;
    char errbuf[PCAP_ERRBUF_SIZE+1];
    // MS Lookback device ( Адаптер замыкания )
    std::string nmdevice = "\\Device\\NPF_{CE1B8EC8-0DAD-4971-BFF4-BA79A07F2849}";
    if ((fp = pcap_open_live(nmdevice.c_str(), // name of the device
    65536, // portion of the packet to capture. It doesn't matter in this case
    1, // promiscuous mode (nonzero means promiscuous)
    1000, // read timeout
    errbuf // error buffer
    )) == NULL)
    {
    fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
    return 2;
    }
    u_char* packet = new u_char[iTotalSize + 18];
    memset(packet,0, iTotalSize + 14);
    memmove(packet+14, buf, iTotalSize);
    packet[0]=1;
    packet[1]=1;
    packet[2]=1;
    packet[3]=1;
    packet[4]=1;
    packet[5]=1;

    /* set mac source to 2:2:2:2:2:2 */
    packet[6]=2;
    packet[7]=2;
    packet[8]=2;
    packet[9]=2;
    packet[10]=2;
    packet[11]=2;
    packet[12] = 0x08;
    packet[13] = 0;

    /* Send down the packet */
    if (pcap_sendpacket(fp, // Adapter
    packet, // buffer with the packet
    iTotalSize + 18 // size
    ) != 0)
    {
    fprintf(stderr,"\nError sending the packet: \n", pcap_geterr(fp));
    return 3;
    }
    delete packet;
    pcap_close(fp);

    closesocket(s) ;
    WSACleanup() ;

    return 0;
    }

    Если через сокет отправлять пакет, то дохоит до UDP сервера , если через пкап — то недоходит.
    Что я неправильно делаю, пакет сформировал или надо как-то хитро настроить адаптер замыкания?
    Адаптеру замыкания прописал адрес 141.1.1.1/255.255.255.0
    Re[5]: WinPcap и отправка пакета
    От: oziro Нигерия  
    Дата: 20.03.07 13:39
    Оценка:
    Сорри сейчас время нет, попозже.

    Попробуй сниффером http://wireshark.org/ посмотреть какой пакет у тебя вылазит в сеть. И вылазит ли. Сниф пакеты разбирает сам, если он глюканет (не поймет) значит косяк.
    Re[6]: WinPcap и отправка пакета
    От: oziro Нигерия  
    Дата: 20.03.07 13:57
    Оценка:
    O>Попробуй сниффером http://wireshark.org/ посмотреть какой пакет у тебя вылазит в сеть. И вылазит ли. Сниф пакеты разбирает сам, если он глюканет (не поймет) значит косяк.

    Для того что бы вылез — МАС-адрес поставь широковещательный, IP-адрес желательно какой-нибудь из местной сетки (или типа 192,168,1,1). Интерфейс, к чему подключится winpcap выбери свою сетевую карточку. тогда он таки вылезет в сеть (пакет) и снифом ты сможешь поймать. возможно косяк с CRC
    Re[7]: WinPcap и отправка пакета
    От: yaser Украина  
    Дата: 23.03.07 12:43
    Оценка:
    Здравствуйте, oziro, Вы писали:

    O>>Попробуй сниффером http://wireshark.org/ посмотреть какой пакет у тебя вылазит в сеть. И вылазит ли. Сниф пакеты разбирает сам, если он глюканет (не поймет) значит косяк.


    O>Для того что бы вылез — МАС-адрес поставь широковещательный, IP-адрес желательно какой-нибудь из местной сетки (или типа 192,168,1,1). Интерфейс, к чему подключится winpcap выбери свою сетевую карточку. тогда он таки вылезет в сеть (пакет) и снифом ты сможешь поймать. возможно косяк с CRC


    в общем помог, пасиба. а wirshark очень класная программа, особенно для анализа пакетов.
    Re[8]: WinPcap и отправка пакета
    От: StatusKVO Россия  
    Дата: 05.04.08 17:08
    Оценка:
    Здравствуйте, yaser, Вы писали:

    Y>Здравствуйте, oziro, Вы писали:


    O>>>Попробуй сниффером http://wireshark.org/ посмотреть какой пакет у тебя вылазит в сеть. И вылазит ли. Сниф пакеты разбирает сам, если он глюканет (не поймет) значит косяк.


    O>>Для того что бы вылез — МАС-адрес поставь широковещательный, IP-адрес желательно какой-нибудь из местной сетки (или типа 192,168,1,1). Интерфейс, к чему подключится winpcap выбери свою сетевую карточку. тогда он таки вылезет в сеть (пакет) и снифом ты сможешь поймать. возможно косяк с CRC


    Y>в общем помог, пасиба. а wirshark очень класная программа, особенно для анализа пакетов.


    Помог-то помог, а поделиться в чем ошибка не хочешь?
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.