zoukankan      html  css  js  c++  java
  • win32

    可以从Windows Sockets 2开始, 

    虽然微软提供了官方工具, Microsoft Network Monitor 3.4, 不过我们如果能够通过相关的代码和api的调用来深入研究的话,那就大大提升了我们的学习水平。

    主要用到socket, bind 和 recvfrom函数。

    代码样本:

    #include "stdio.h"
    #include "winsock2.h"
    
    #pragma comment(lib,"ws2_32.lib") //For winsock
    #pragma warning(disable:4996)
    
    #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1) //this removes the need of mstcpip.h
    
    void StartSniffing(SOCKET Sock); //This will sniff here and there
    
    void ProcessPacket(char*, int); //This will decide how to digest
    void PrintIpHeader(char*);
    void PrintUdpPacket(char*, int);
    void PrintTcpPacket(char*, int);
    void PrintData(char*, int);
    
    typedef struct ip_hdr
    {
        unsigned char ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also)
        unsigned char ip_version : 4; // 4-bit IPv4 version
        unsigned char ip_tos; // IP type of service
        unsigned short ip_total_length; // Total length
        unsigned short ip_id; // Unique identifier
    
        unsigned char ip_frag_offset : 5; // Fragment offset field
    
        unsigned char ip_more_fragment : 1;
        unsigned char ip_dont_fragment : 1;
        unsigned char ip_reserved_zero : 1;
    
        unsigned char ip_frag_offset1; //fragment offset
    
        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; // Source address
    } IPV4_HDR;
    
    typedef struct udp_hdr
    {
        unsigned short source_port; // Source port no.
        unsigned short dest_port; // Dest. port no.
        unsigned short udp_length; // Udp packet length
        unsigned short udp_checksum; // Udp checksum (optional)
    } UDP_HDR;
    
    // TCP header
    typedef struct tcp_header
    {
        unsigned short source_port; // source port
        unsigned short dest_port; // destination port
        unsigned int sequence; // sequence number - 32 bits
        unsigned int acknowledge; // acknowledgement number - 32 bits
    
        unsigned char ns : 1; //Nonce Sum Flag Added in RFC 3540.
        unsigned char reserved_part1 : 3; //according to rfc
        unsigned char data_offset : 4; /*The number of 32-bit words in the TCP header.
        This indicates where the data begins.
        The length of the TCP header is always a multiple
        of 32 bits.*/
    
        unsigned char fin : 1; //Finish Flag
        unsigned char syn : 1; //Synchronise Flag
        unsigned char rst : 1; //Reset Flag
        unsigned char psh : 1; //Push Flag
        unsigned char ack : 1; //Acknowledgement Flag
        unsigned char urg : 1; //Urgent Flag
    
        unsigned char ecn : 1; //ECN-Echo Flag
        unsigned char cwr : 1; //Congestion Window Reduced Flag
    
        ////////////////////////////////
    
        unsigned short window; // window
        unsigned short checksum; // checksum
        unsigned short urgent_pointer; // urgent pointer
    } TCP_HDR;
    
    
    FILE* logfile;
    int tcp = 0, udp = 0, icmp = 0, others = 0, igmp = 0, total = 0, i, j;
    struct sockaddr_in source, dest;
    char hex[2];
    
    //Its free!
    IPV4_HDR* iphdr;
    TCP_HDR* tcpheader;
    UDP_HDR* udpheader;
    
    int main()
    {
        SOCKET sniffer;
        struct in_addr addr;
        int in;
    
        char hostname[100];
        struct hostent* local;
        WSADATA wsa;
    
        logfile = fopen("log.txt", "w");
        if (logfile == NULL)
        {
            printf("Unable to create file.");
        }
    
        //Initialise Winsock
        printf("
    Initialising Winsock...");
        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
        {
            printf("WSAStartup() failed.
    ");
            return 1;
        }
        printf("Initialised");
    
        //Create a RAW Socket
        printf("
    Creating RAW Socket...");
        sniffer = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
        if (sniffer == INVALID_SOCKET)
        {
            printf("Failed to create raw socket.
    ");
            return 1;
        }
        printf("Created.");
    
        //Retrive the local hostname
        if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
        {
            printf("Error : %d", WSAGetLastError());
            return 1;
        }
        printf("
    Host name : %s 
    ", hostname);
    
        //Retrive the available IPs of the local host
        local = gethostbyname(hostname);
        printf("
    Available Network Interfaces : 
    ");
        if (local == NULL)
        {
            printf("Error : %d.
    ", WSAGetLastError());
            return 1;
        }
    
        for (i = 0; local->h_addr_list[i] != 0; ++i)
        {
            memcpy(&addr, local->h_addr_list[i], sizeof(struct in_addr));
            printf("Interface Number : %d Address : %s
    ", i, inet_ntoa(addr));
        }
    
        printf("Enter the interface number you would like to sniff : ");
        scanf("%d", &in);
    
        memset(&dest, 0, sizeof(dest));
        memcpy(&dest.sin_addr.s_addr, local->h_addr_list[in], sizeof(dest.sin_addr.s_addr));
        dest.sin_family = AF_INET;
        dest.sin_port = 0;
    
        printf("
    Binding socket to local system and port 0 ...");
        if (bind(sniffer, (struct sockaddr*) & dest, sizeof(dest)) == SOCKET_ERROR)
        {
            printf("bind(%s) failed.
    ", inet_ntoa(addr));
            return 1;
        }
        printf("Binding successful");
    
        //Enable this socket with the power to sniff : SIO_RCVALL is the key Receive ALL ;)
    
        j = 1;
        printf("
    Setting socket to sniff...");
        if (WSAIoctl(sniffer, SIO_RCVALL, &j, sizeof(j), 0, 0, (LPDWORD)&in, 0, 0) == SOCKET_ERROR)
        {
            printf("WSAIoctl() failed.
    ");
            return 1;
        }
        printf("Socket set.");
    
        //Begin
        printf("
    Started Sniffing
    ");
        printf("Packet Capture Statistics...
    ");
        StartSniffing(sniffer); //Happy Sniffing
    
        //End
        closesocket(sniffer);
        WSACleanup();
    
        return 0;
    }
    
    void StartSniffing(SOCKET sniffer)
    {
        char* Buffer = (char*)malloc(65536); //Its Big!
        int mangobyte;
    
        if (Buffer == NULL)
        {
            printf("malloc() failed.
    ");
            return;
        }
    
        do
        {
            mangobyte = recvfrom(sniffer, Buffer, 65536, 0, 0, 0); //Eat as much as u can
    
            if (mangobyte > 0)
            {
                ProcessPacket(Buffer, mangobyte);
            }
            else
            {
                printf("recvfrom() failed.
    ");
            }
        } while (mangobyte > 0);
    
        free(Buffer);
    }
    
    void ProcessPacket(char* Buffer, int Size)
    {
        iphdr = (IPV4_HDR*)Buffer;
        ++total;
    
        switch (iphdr->ip_protocol) //Check the Protocol and do accordingly...
        {
    
        case 6: //TCP Protocol
            ++tcp;
            PrintTcpPacket(Buffer, Size);
            break;
    
        case 17: //UDP Protocol
            ++udp;
            PrintUdpPacket(Buffer, Size);
            break;
    
        default: //Some Other Protocol like ARP etc.
            ++others;
            break;
        }
        printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d
    ", tcp, udp, icmp, igmp, others, total);
    }
    
    void PrintIpHeader(char* Buffer)
    {
        unsigned short iphdrlen;
    
        iphdr = (IPV4_HDR*)Buffer;
        iphdrlen = iphdr->ip_header_len * 4;
    
        memset(&source, 0, sizeof(source));
        source.sin_addr.s_addr = iphdr->ip_srcaddr;
    
        memset(&dest, 0, sizeof(dest));
        dest.sin_addr.s_addr = iphdr->ip_destaddr;
    
        fprintf(logfile, "
    ");
        fprintf(logfile, "IP Header
    ");
        fprintf(logfile, " |-IP Version : %d
    ", (unsigned int)iphdr->ip_version);
        fprintf(logfile, " |-IP Header Length : %d DWORDS or %d Bytes
    ", (unsigned int)iphdr->ip_header_len, ((unsigned int)(iphdr->ip_header_len)) * 4);
        fprintf(logfile, " |-Type Of Service : %d
    ", (unsigned int)iphdr->ip_tos);
        fprintf(logfile, " |-IP Total Length : %d Bytes(Size of Packet)
    ", ntohs(iphdr->ip_total_length));
        fprintf(logfile, " |-Identification : %d
    ", ntohs(iphdr->ip_id));
        fprintf(logfile, " |-Reserved ZERO Field : %d
    ", (unsigned int)iphdr->ip_reserved_zero);
        fprintf(logfile, " |-Dont Fragment Field : %d
    ", (unsigned int)iphdr->ip_dont_fragment);
        fprintf(logfile, " |-More Fragment Field : %d
    ", (unsigned int)iphdr->ip_more_fragment);
        fprintf(logfile, " |-TTL : %d
    ", (unsigned int)iphdr->ip_ttl);
        fprintf(logfile, " |-Protocol : %d
    ", (unsigned int)iphdr->ip_protocol);
        fprintf(logfile, " |-Checksum : %d
    ", ntohs(iphdr->ip_checksum));
        fprintf(logfile, " |-Source IP : %s
    ", inet_ntoa(source.sin_addr));
        fprintf(logfile, " |-Destination IP : %s
    ", inet_ntoa(dest.sin_addr));
    }
    
    void PrintTcpPacket(char* Buffer, int Size)
    {
        unsigned short iphdrlen;
    
        iphdr = (IPV4_HDR*)Buffer;
        iphdrlen = iphdr->ip_header_len * 4;
    
        tcpheader = (TCP_HDR*)(Buffer + iphdrlen);
    
        fprintf(logfile, "
    
    ***********************TCP Packet*************************
    ");
    
        PrintIpHeader(Buffer);
    
        fprintf(logfile, "
    ");
        fprintf(logfile, "TCP Header
    ");
        fprintf(logfile, " |-Source Port : %u
    ", ntohs(tcpheader->source_port));
        fprintf(logfile, " |-Destination Port : %u
    ", ntohs(tcpheader->dest_port));
        fprintf(logfile, " |-Sequence Number : %u
    ", ntohl(tcpheader->sequence));
        fprintf(logfile, " |-Acknowledge Number : %u
    ", ntohl(tcpheader->acknowledge));
        fprintf(logfile, " |-Header Length : %d DWORDS or %d BYTES
    "
            , (unsigned int)tcpheader->data_offset, (unsigned int)tcpheader->data_offset * 4);
        fprintf(logfile, " |-CWR Flag : %d
    ", (unsigned int)tcpheader->cwr);
        fprintf(logfile, " |-ECN Flag : %d
    ", (unsigned int)tcpheader->ecn);
        fprintf(logfile, " |-Urgent Flag : %d
    ", (unsigned int)tcpheader->urg);
        fprintf(logfile, " |-Acknowledgement Flag : %d
    ", (unsigned int)tcpheader->ack);
        fprintf(logfile, " |-Push Flag : %d
    ", (unsigned int)tcpheader->psh);
        fprintf(logfile, " |-Reset Flag : %d
    ", (unsigned int)tcpheader->rst);
        fprintf(logfile, " |-Synchronise Flag : %d
    ", (unsigned int)tcpheader->syn);
        fprintf(logfile, " |-Finish Flag : %d
    ", (unsigned int)tcpheader->fin);
        fprintf(logfile, " |-Window : %d
    ", ntohs(tcpheader->window));
        fprintf(logfile, " |-Checksum : %d
    ", ntohs(tcpheader->checksum));
        fprintf(logfile, " |-Urgent Pointer : %d
    ", tcpheader->urgent_pointer);
        fprintf(logfile, "
    ");
        fprintf(logfile, " DATA Dump ");
        fprintf(logfile, "
    ");
    
        fprintf(logfile, "IP Header
    ");
        PrintData(Buffer, iphdrlen);
    
        fprintf(logfile, "TCP Header
    ");
        PrintData(Buffer + iphdrlen, tcpheader->data_offset * 4);
    
        fprintf(logfile, "Data Payload
    ");
        PrintData(Buffer + iphdrlen + tcpheader->data_offset * 4
            , (Size - tcpheader->data_offset * 4 - iphdr->ip_header_len * 4));
    
        fprintf(logfile, "
    ###########################################################");
    }
    
    void PrintUdpPacket(char* Buffer, int Size)
    {
        unsigned short iphdrlen;
    
        iphdr = (IPV4_HDR*)Buffer;
        iphdrlen = iphdr->ip_header_len * 4;
    
        udpheader = (UDP_HDR*)(Buffer + iphdrlen);
    
        fprintf(logfile, "
    
    ***********************UDP Packet*************************
    ");
    
        PrintIpHeader(Buffer);
    
        fprintf(logfile, "
    UDP Header
    ");
        fprintf(logfile, " |-Source Port : %d
    ", ntohs(udpheader->source_port));
        fprintf(logfile, " |-Destination Port : %d
    ", ntohs(udpheader->dest_port));
        fprintf(logfile, " |-UDP Length : %d
    ", ntohs(udpheader->udp_length));
        fprintf(logfile, " |-UDP Checksum : %d
    ", ntohs(udpheader->udp_checksum));
    
        fprintf(logfile, "
    ");
        fprintf(logfile, "IP Header
    ");
    
        PrintData(Buffer, iphdrlen);
    
        fprintf(logfile, "UDP Header
    ");
    
        PrintData(Buffer + iphdrlen, sizeof(UDP_HDR));
    
        fprintf(logfile, "Data Payload
    ");
    
        PrintData(Buffer + iphdrlen + sizeof(UDP_HDR), (Size - sizeof(UDP_HDR) - iphdr->ip_header_len * 4));
    
        fprintf(logfile, "
    ###########################################################");
    }
    
    
    /*
        Print the hex values of the data
    */
    void PrintData(char* data, int Size)
    {
        char a, line[17], c;
        int j;
    
        //loop over each character and print
        for (i = 0; i < Size; i++)
        {
            c = data[i];
    
            //Print the hex value for every character , with a space. Important to make unsigned
            fprintf(logfile, " %.2x", (unsigned char)c);
    
            //Add the character to data line. Important to make unsigned
            a = (c >= 32 && c <= 128) ? (unsigned char)c : '.';
    
            line[i % 16] = a;
    
            //if last character of a line , then print the line - 16 characters in 1 line
            if ((i != 0 && (i + 1) % 16 == 0) || i == Size - 1)
            {
                line[i % 16 + 1] = '';
    
                //print a big gap of 10 characters between hex and characters
                fprintf(logfile, "          ");
    
                //Print additional spaces for last lines which might be less than 16 characters in length
                for (j = strlen(line); j < 16; j++)
                {
                    fprintf(logfile, "   ");
                }
    
                fprintf(logfile, "%s 
    ", line);
            }
        }
    
        fprintf(logfile, "
    ");
    }

    github链接

  • 相关阅读:
    数据分析 第五篇:离群点检测
    linux lsof命令详解
    ES基本查询语句教程
    Swagger详解(SpringBoot+Swagger集成)
    Elasticsearch5.0 安装问题集锦
    kafka auto.offset.reset latest earliest 详解
    干货 | Elasticsearch多表关联设计指南
    kafka auto.offset.reset latest earliest 详解
    linux sed命令
    Idea中如何使用debug操作
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14006016.html
Copyright © 2011-2022 走看看