zoukankan      html  css  js  c++  java
  • 网络嗅探器

    该项目相关知识点已经放到“网络嗅探器”标签中

    下面是相关头文件

    /*
    sniffer.h
    */
    #ifndef __SNIFFER_H__
    #define __SNIFFER_H__
    
    typedef struct s_protocol
    {
        int tcp;
        int udp;
        int icmp;
        int igmp;
        int others;
        int total;
    }t_protocol;
    
    typedef struct s_sinffer
    {
        FILE *logfile;
        t_protocol *prot;
    }t_sniffer;
    
    void ProcessPacket(unsigned char *, int, t_sniffer *);
    void print_ip_header(unsigned char *, int, t_sniffer *);
    void print_tcp_packet(unsigned char *, int, t_sniffer *);
    void print_udp_packet(unsigned char *, int, t_sniffer *);
    void print_icmp_packet(unsigned char *, int, t_sniffer *);
    void PrintData(unsigned char *, int, t_sniffer*);
    void display_time_and_data();
    void getting_started();
    void signal_white_now(int);
    
    #endif

    输出颜色定义

    /*
    tool.h
    */
    #ifndef __COLOR_H__
    #define __COLOR_H__
    
    #include<stdio.h>
    
    #define CLEARSCREEN() printf("33[H33[2J")
    #define INITCOLOR(color) printf("33[%sm",color)
    #define RED_COLOR    "31"
    #define GREEN_COLOR    "32"
    #define YELLOW_COLOR    "33"
    #define BLUE_COLOR    "34"
    #define ZERO_COLOR    "0"
    
    #endif

    暂停或退出的信号处理

    /*
    tool.c
    */
    #include<stdio.h>
    #include<signal.h>
    
    void signal_white_now(int signum)
    {
        printf("Bye Bye !
    ");
    }

    数据包 分解打印

    /*
    show_data.c
    */
    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<netinet/ip_icmp.h>
    #include<netinet/udp.h>
    #include<netinet/tcp.h>
    #include<netinet/ip.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    
    #include"sniffer.h"
    #include"tools.h"
    
    //将ip头部信息解析出来输出到文件中
    void print_ip_header(unsigned char *buf,int size, t_sniffer *sniffer)
    {
        unsigned short iphdrlen;
        struct iphdr *iph;
        struct sockaddr_in source;
        struct sockaddr_in dest;
        
        iph = (struct iphdr *)buf;
        iphdrlen = iph->ihl*4; //iph->ihl首部长度,乘以4是因为是以4字节为单位
        (void)iphdrlen;
        (void)size;
        memset(&source, 0, sizeof(source));
        source.sin_addr.s_addr = iph->saddr;
        
        memset(&dest, 0, sizeof(dest));
        dest.sin_addr.s_addr = iph->daddr;
        
        fprintf(sniffer->logfile,"
    ");
        fprintf(sniffer->logfile,"IP Header
    ");
        fprintf(sniffer->logfile,"    |-IP Version        :%d
    ",(unsigned int)iph->version);    
        fprintf(sniffer->logfile,"    |-IP Header Length    :%d DWORDS  or %d Bytes
    ",(unsigned int)iph->ihl,((unsigned int)(iph->ihl)) * 4);
        fprintf(sniffer->logfile,"    |-Type Of Service    :%d
    ",(unsigned int)iph->tos);    
        fprintf(sniffer->logfile,"    |-Identification    :%d
    ",ntohs(iph->id));
        fprintf(sniffer->logfile,"    |-TTL            :%d
    ",(unsigned int)iph->ttl);
        fprintf(sniffer->logfile,"    |-Protocol        :%d
    ",(unsigned int)iph->protocol);    
        fprintf(sniffer->logfile,"    |-Checksum        :%d
    ",ntohs(iph->check));    
        fprintf(sniffer->logfile,"    |-Source IP        :%s
    ",inet_ntoa(source.sin_addr));
        fprintf(sniffer->logfile,"    |-Destination IP    :%s
    ",inet_ntoa(dest.sin_addr));    
    }
    
    void print_tcp_packet(unsigned char *buf, int size , t_sniffer *sniffer)
    {
        unsigned short iphdrlen;
        struct iphdr *iph;
        struct tcphdr *tcph;
        
        iph = (struct iphdr *)buf;
        iphdrlen = iph->ihl * 4;
        tcph = (struct tcphdr*)(buf + iphdrlen); //跳过ip头部,就是tcp数据内存。buf里存储就是ip头部字节数
        print_ip_header(buf, size, sniffer);        //传过去的size是整个接收数据的长度,但是使用时都截取了相应的长度
        
        fprintf(sniffer->logfile,"
    ");
        fprintf(sniffer->logfile,"TCP Header
    ");
        fprintf(sniffer->logfile,"    |-Source Port    :%u
    ",ntohs(tcph->source));
        fprintf(sniffer->logfile,"    |-Destination Port    :%u
    ",ntohs(tcph->dest));
        fprintf(sniffer->logfile,"    |-Sequence Number    :%u
    ",ntohl(tcph->dest));
        fprintf(sniffer->logfile,"    |-Acknowledge Number    :%u
    ",ntohl(tcph->dest));
        fprintf(sniffer->logfile,"    |-Header Length    :%d DWORDS  or %d Bytes
    ",(unsigned int)tcph->doff,((unsigned int)(tcph->doff)) * 4);    
        fprintf(sniffer->logfile,"    |-Urgent Flag        :%d
    ",(unsigned int)tcph->urg);    
        fprintf(sniffer->logfile,"    |-Acknowledgement Flag        :%d
    ",(unsigned int)tcph->ack);
        fprintf(sniffer->logfile,"    |-Push Flag        :%d
    ",(unsigned int)tcph->psh);
        fprintf(sniffer->logfile,"    |-Reset Flag        :%d
    ",(unsigned int)tcph->rst);
        fprintf(sniffer->logfile,"    |-Synchronise Flag    :%d
    ",(unsigned int)tcph->syn);
        fprintf(sniffer->logfile,"    |-Finish Flag        :%d
    ",(unsigned int)tcph->fin);
        fprintf(sniffer->logfile,"    |-Window        :%d
    ",ntohs(tcph->window));    
        fprintf(sniffer->logfile,"    |-Checksum        :%d
    ",ntohs(tcph->check));
        fprintf(sniffer->logfile,"    |-Urgent Pointer    :%d
    ",(tcph->urg_ptr));    
        fprintf(sniffer->logfile,"
    ");
        fprintf(sniffer->logfile,"            DATA Dump            
    ");    
        
        fprintf(sniffer->logfile,"IP Header
    ");
        PrintData(buf, iphdrlen, sniffer);        //将ip头部信息按照16进制的方式输入到日志中
        
        fprintf(sniffer->logfile,"TCP Header
    ");
        PrintData(buf+iphdrlen, tcph->doff*4, sniffer);
        
        fprintf(sniffer->logfile,"Data Payload
    ");    //将tcp数据报中的存储的内容按16进制输出到日志中
        PrintData(buf+iphdrlen+tcph->doff*4, (size - tcph->doff*4 - iph->ihl*4),sniffer);
        fprintf(sniffer->logfile,"################################################
    ");
    }
    
    
    void print_udp_packet(unsigned char *buf, int size, t_sniffer * sniffer)
    {
        unsigned short iphdrlen;
        
        struct iphdr *iph;
        struct udphdr *udph;
        
        iph = (struct iphdr *)buf;
        iphdrlen = iph->ihl * 4;
        udph = (struct udphdr*)(buf + iphdrlen);
        fprintf(sniffer->logfile,"
    
    ************************UDP Packet********************
    ");
        
        print_ip_header(buf, size, sniffer);
        
        fprintf(sniffer->logfile,"
    UDP Header
    ");
        fprintf(sniffer->logfile,"    |-Source Port        :%d
    ",ntohs(udph->source));
        fprintf(sniffer->logfile,"    |-Destination Port    :%d
    ",ntohs(udph->dest));
        fprintf(sniffer->logfile,"    |-UDP Length        :%d
    ",ntohs(udph->len));
        fprintf(sniffer->logfile,"    |-UDP Checksum    :%d
    ",ntohs(udph->check));
        
        fprintf(sniffer->logfile,"
    ");
        fprintf(sniffer->logfile,"IP Header
    ");
        PrintData(buf, iphdrlen, sniffer);
        
        fprintf(sniffer->logfile,"UDP Header
    ");
        PrintData(buf+iphdrlen,sizeof(udph), sniffer);
        
        fprintf(sniffer->logfile,"Data Payload
    ");
        PrintData(buf+iphdrlen+sizeof(udph), (size - sizeof(udph) - iph->ihl*4),sniffer);
        fprintf(sniffer->logfile,"################################################
    ");
    }
    
    void print_icmp_packet(unsigned char * buf, int size, t_sniffer * sniffer)
    {
        unsigned short iphdrlen;
        struct iphdr *iph;
        struct icmphdr *icmph;
        
        iph = (struct iphdr *)buf;
        iphdrlen = iph->ihl * 4;
        icmph = (struct icmphdr *)(buf + iphdrlen);
        fprintf(sniffer->logfile,"
    
    ************************ICMP Packet********************
    ");
        print_ip_header(buf, size, sniffer);
        fprintf(sniffer->logfile,"
    ");
        fprintf(sniffer->logfile,"ICMP Header
    ");
        fprintf(sniffer->logfile,"    |-Type        :%d
    ",(unsigned int)icmph->type);
        
        if((unsigned int)(icmph->type) == 11)
        {
            fprintf(sniffer->logfile,"(TTL Expired)
    ");
        }
        else if((unsigned int)(icmph->type) == ICMP_ECHOREPLY)
        {
            fprintf(sniffer->logfile,"(ICMP Echo Reply)
    ");
        }
        fprintf(sniffer->logfile,"    |-Code        :%d
    ",(unsigned int)icmph->code);
        fprintf(sniffer->logfile,"    |-Checksum    :%d
    ",ntohs(icmph->checksum));
        fprintf(sniffer->logfile,"
    ");
        
        fprintf(sniffer->logfile,"IP Header
    ");
        PrintData(buf, iphdrlen, sniffer);
        
        fprintf(sniffer->logfile,"UDP Header
    ");
        PrintData(buf+iphdrlen,sizeof(icmph), sniffer);
        
        fprintf(sniffer->logfile,"Data Payload
    ");
        PrintData(buf+iphdrlen+sizeof(icmph), (size - sizeof(icmph) - iph->ihl*4),sniffer);
        fprintf(sniffer->logfile,"################################################
    ");
    }
    void PrintData(unsigned char * buf, int size, t_sniffer *sniffer)
    {
    #if 1
        int i;
        for(i = 0; i < size; i++)
        {
            if(i % 16 == 0)
            {
                fprintf(sniffer->logfile,"
    ");
            }
    
            
            fprintf(sniffer->logfile," %02X",(unsigned int)buf[i]);
            
            if(i == size - 1)
                fprintf(sniffer->logfile,"
    ");
        }
    #else
     int i;
    
      for(i = 0 ; i < size ; i++)
        {
            if(i % 16 == 0)
            fprintf(sniffer->logfile, "
    ");
            fprintf(sniffer->logfile, " %02X",(unsigned int)buf[i]);
          
            if( i == size - 1)
                fprintf(sniffer->logfile, "
    ");
        }
    #endif
    }

    主函数

    /*
    main.c
    */
    #include<signal.h>
    #include<unistd.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<netinet/ip.h>
    #include<sys/socket.h>
    #include<sys/select.h>
    #include<fcntl.h>
    #include<sys/types.h>
    #include<sys/time.h>
    #include<errno.h>
    
    #include"sniffer.h"
    #include"tools.h"
    #define ETH_P_IP 0x0800
    
     int exec_cmd(char *buffer, int len)
    {
        if(strncmp(buffer,"quit",4) == 0)
        {
            return 1;
        }
        return 0;
    }
    
    int command_interpreter(int sd)
    {
        int len;
        char buf[512];
    
        len = read(0,buf,512);
        if(len > 0)
        {
            if(exec_cmd(buf,len) == 1)
            {
                return 1;
            }
        }        
        return 0;
    }
    
    void display_time_and_data()
    {
        INITCOLOR(RED_COLOR);
        printf("[%s]",__DATE__);
        INITCOLOR(GREEN_COLOR);
        printf("[%s]  ", __TIME__);
        INITCOLOR(ZERO_COLOR);
    }
    
    void getting_started()
    {
        CLEARSCREEN();
        display_time_and_data();
        printf("Getting started of NetWork sniffer
    
    ");
    }    
    int main()
    {
        int sd;
        int res;
        int saddr_size;
        int data_size;
        struct sockaddr saddr;
        unsigned char *buffer;        //保存数据包中的数据
        t_sniffer sniffer;            //保存数据包的类型和日志文件等信息
        fd_set fd_read;
    
        buffer = malloc(sizeof(unsigned char *) * 65536);
    
        //创建日志文件
        sniffer.logfile = fopen("log.txt","w");
        fprintf(sniffer.logfile,"***LOGFILE(%s - %s)***
    ",__DATE__,__TIME__);
        if(sniffer.logfile == NULL)
        {
            perror("fopen(): ");
            return (EXIT_FAILURE);
        }
    
        sniffer.prot = malloc(sizeof(t_protocol *));
    
        //创建原始套接字,ETH_P_ALL表示侦听负载为IP数据报的以太网帧
        //返回一个int型数字作为文件描述符,用来表示创建成功的socket文件描述符
        sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
        if(sd < 0)
        {
            perror("socket() :");
            return (EXIT_FAILURE);
        }
        getting_started();
        signal(SIGINT, &signal_white_now);
        signal(SIGQUIT, &signal_white_now);
    
        while(1)
        {
            FD_ZERO(&fd_read);
            FD_SET(0,&fd_read);
            FD_SET(sd,&fd_read);
    
            //多路复用检测可读的套接字和标准输入
            res = select(sd+1,&fd_read,NULL,NULL,NULL);
            if(res < 0)
            {
                close(sd);
                if(errno != EINTR)
                {
                    perror("select() ");
                }
                return (EXIT_FAILURE);
            }
            else
            {
                //如果是标准输入可读,进入命令行处理程序
                if(FD_ISSET(0,&fd_read))
                {
                    if(command_interpreter(sd) == 1)    
                    {
                        break;
                    }
                }
                //如果是套接字可读,则读取以太网数据帧内容,并调用ProcessPacket函数解析数据包类型
                else if(FD_ISSET(sd,&fd_read))
                {
                    //读取以太网数据帧的内容
                    saddr_size = sizeof(saddr);
                    data_size = recvfrom(sd,buffer,65536,0,&saddr,(socklen_t*)&saddr_size);
                    if(data_size <= 0)
                    {
                        close(sd);
                        perror("rcvfrom(): ");
                        return (EXIT_FAILURE);
                    }
    
                    ProcessPacket(buffer, data_size, &sniffer);
                }
            }
        }        
        close(sd);
        return (EXIT_SUCCESS);
    }
    
    void ProcessPacket(unsigned char * buffer,int size, t_sniffer *sniffer)
    {
        //根据以太网帧结构,前6B是目的MAC地址,然后是6B的源MAC地址,接下来是2B的帧长度,然后是ip层数据作为负载
        buffer = buffer + 6 + 6 + 2;
        struct iphdr *iph = (struct iphdr*)buffer;
    
        ++sniffer->prot->total;
    
        //根据TCP/IP协议规定的IP数据包头部的protocol字段的值,判断上层数据包类型
        switch(iph->protocol)
        {
            //1 表示icmp协议
            case 1:
                ++sniffer->prot->icmp;
                print_icmp_packet(buffer,size,sniffer);
                break;
            //2表示igmp协议
            case 2:
                ++sniffer->prot->igmp;
                break;
            //6表示tcp协议
            case 6:
                ++sniffer->prot->tcp;
                print_tcp_packet(buffer,size,sniffer);
                break;
            //17表示udp协议
            case 17:
                ++sniffer->prot->udp;
                print_udp_packet(buffer,size,sniffer);
                break;
            default:
                ++sniffer->prot->others;
                break;
        }
    
        display_time_and_data();
        printf("TCP    :%d    UDP    :%d    ICMP  :%d    IGMP  :%d    others:%d    total:%d
    ",
                sniffer->prot->tcp,sniffer->prot->udp,
                sniffer->prot->icmp,sniffer->prot->igmp,
                sniffer->prot->others,sniffer->prot->total);
    
    }

    makefile

    NAME    =    network_sniffer
    SRCS    =    main.c    
                tools.c    
                show_data.c
    
    OBJS    =    $(SRCS:.c=.o)
    CC    =    gcc -o
    CFLAGS    =    -W    -Wall
    RM    =    rm -rf
    
    $(NAME)    :    $(OBJS)
                  $(CC)    $(NAME)    -I./    $(CFLAGS)    $(OBJS)
    
    all    :    $(NAME)
    
    clean    :
            $(RM)    $(OBJS)
    
    fclean    :    clean
            $(RM)    $(NAME)
    
    re    :    fclean all
  • 相关阅读:
    截取小数位数(准确四舍五入及直接截取)
    水印
    用心整理的 献丑啦 一些关于http url qs fs ...模块的方法
    html禁止清除input文本输入缓存的两种方法
    flink写入elasticsearch报错!OOM内存溢出!连接异常关闭!
    实现网格建造系统
    AcWing 1064. 小国王
    AcWing 1052. 设计密码
    KMP 模板
    AcWing 1058. 股票买卖 V
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11670528.html
Copyright © 2011-2022 走看看