• 网络嗅探器


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

    下面是相关头文件

    /*
    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
  • 相关阅读:
    Vue路由机制
    谷歌浏览器打不开应用商店的解决方法
    Vue报错——Component template should contain exactly one root element. If you are using vif on multiple elements, use velseif to chain them instead.
    Vue.js学习之——安装
    Vue使用axios无法读取data的解决办法
    关于localstorage存储JSON对象的问题
    2013年整体计划
    个人喜欢的警语收集
    Linux防火墙的关闭和开启
    Flex修改title 转载
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11670528.html
Copyright © 2020-2023  润新知