C语言实现Linux网络嗅探器

0x01 实验简介

网络嗅探器是拦截通过网络接口流入和流出的数据的程序。所以,如果你正在浏览的互联网,嗅探器以数据包的形式抓到它并且显示。在本实验中,我们用 C 语言实现了一个网络嗅探器。

0x02程序框架和功能描述

本程序使用c语言编程,实现linux环境下网络嗅探的功能,并实现对接收到的UDP数据报进行解析。

0x03程序代码

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_sniffer
{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_date();
void getting_started();
void signal_white_now(int);#endif

tools.h

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

tools.c

#include    <signal.h>
#include    <stdio.h>/* 信号处理函数 */
void signal_white_now(int signum)
{printf("Bye Bye !\n");
}

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; (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,"\n");fprintf(sniffer->logfile,"IP Header\n");fprintf(sniffer->logfile,"   |-IP Version        : %d\n",(unsigned int)iph->version);fprintf(sniffer->logfile,"   |-IP Header Length  : %d DWORDS or %d Bytes\n",(unsigned int)iph->ihl,((unsigned int)(iph->ihl))*4);fprintf(sniffer->logfile,"   |-Type Of Service   : %d\n",(unsigned int)iph->tos);fprintf(sniffer->logfile,"   |-IP Total Length   : %d  Bytes(size of Packet)\n",ntohs(iph->tot_len));fprintf(sniffer->logfile,"   |-Identification    : %d\n",ntohs(iph->id));fprintf(sniffer->logfile,"   |-TTL      : %d\n",(unsigned int)iph->ttl);fprintf(sniffer->logfile,"   |-Protocol : %d\n",(unsigned int)iph->protocol);fprintf(sniffer->logfile,"   |-Checksum : %d\n",ntohs(iph->check));fprintf(sniffer->logfile,"   |-Source IP        : %s\n",inet_ntoa(source.sin_addr));fprintf(sniffer->logfile,"   |-Destination IP   : %s\n",inet_ntoa(dest.sin_addr));
}/* 写 TCP 数据包到日志文件 */
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);print_ip_header(buf, size, sniffer);/* 把 tcp 头信息写入日志文件中 */fprintf(sniffer->logfile,"\n");fprintf(sniffer->logfile,"TCP Header\n");fprintf(sniffer->logfile,"   |-Source Port      : %u\n",ntohs(tcph->source));fprintf(sniffer->logfile,"   |-Destination Port : %u\n",ntohs(tcph->dest));fprintf(sniffer->logfile,"   |-Sequence Number    : %u\n",ntohl(tcph->seq));fprintf(sniffer->logfile,"   |-Acknowledge Number : %u\n",ntohl(tcph->ack_seq));fprintf(sniffer->logfile,"   |-Header Length      : %d DWORDS or %d BYTES\n" ,(unsigned int)tcph->doff,(unsigned int)tcph->doff*4);fprintf(sniffer->logfile,"   |-Urgent Flag          : %d\n",(unsigned int)tcph->urg);fprintf(sniffer->logfile,"   |-Acknowledgement Flag : %d\n",(unsigned int)tcph->ack);fprintf(sniffer->logfile,"   |-Push Flag            : %d\n",(unsigned int)tcph->psh);fprintf(sniffer->logfile,"   |-Reset Flag           : %d\n",(unsigned int)tcph->rst);fprintf(sniffer->logfile,"   |-Synchronise Flag     : %d\n",(unsigned int)tcph->syn);fprintf(sniffer->logfile,"   |-Finish Flag          : %d\n",(unsigned int)tcph->fin);fprintf(sniffer->logfile,"   |-Window         : %d\n",ntohs(tcph->window));fprintf(sniffer->logfile,"   |-Checksum       : %d\n",ntohs(tcph->check));fprintf(sniffer->logfile,"   |-Urgent Pointer : %d\n",tcph->urg_ptr);fprintf(sniffer->logfile,"\n");fprintf(sniffer->logfile,"                        DATA Dump                         ");fprintf(sniffer->logfile,"\n");fprintf(sniffer->logfile,"IP Header\n");PrintData(buf, iphdrlen, sniffer);fprintf(sniffer->logfile,"TCP Header\n");PrintData(buf+iphdrlen, tcph->doff*4, sniffer);fprintf(sniffer->logfile,"Data Payload\n");/* 把用户数据写入日志文件 */PrintData(buf + iphdrlen + tcph->doff*4,(size - tcph->doff*4-iph->ihl*4),sniffer );fprintf(sniffer->logfile,"\n###########################################################");
}/* 写 UDP 数据包到日志文件 */
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,"\n\n***********************UDP Packet*************************\n");print_ip_header(buf, size, sniffer);/* 把 udp 头信息写入日志文件中 */fprintf(sniffer->logfile,"\nUDP Header\n");fprintf(sniffer->logfile,"   |-Source Port      : %d\n" , ntohs(udph->source));fprintf(sniffer->logfile,"   |-Destination Port : %d\n" , ntohs(udph->dest));fprintf(sniffer->logfile,"   |-UDP Length       : %d\n" , ntohs(udph->len));fprintf(sniffer->logfile,"   |-UDP Checksum     : %d\n" , ntohs(udph->check));fprintf(sniffer->logfile,"\n");fprintf(sniffer->logfile,"IP Header\n");PrintData(buf , iphdrlen, sniffer);fprintf(sniffer->logfile,"UDP Header\n");PrintData(buf+iphdrlen, sizeof(udph), sniffer);fprintf(sniffer->logfile,"Data Payload\n");/* 把用户数据写入日志文件 */PrintData(buf + iphdrlen + sizeof udph,(size - sizeof udph - iph->ihl * 4),sniffer);fprintf(sniffer->logfile,"\n###########################################################");
}/* 写 ICMP 数据包到日志文件 */
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);/* 把 icmp 头信息写入日志文件中 */fprintf(sniffer->logfile,"\n\n***********************ICMP Packet*************************\n");  print_ip_header(buf , size, sniffer);fprintf(sniffer->logfile,"\n");fprintf(sniffer->logfile,"ICMP Header\n");fprintf(sniffer->logfile,"   |-Type : %d",(unsigned int)(icmph->type));  if((unsigned int)(icmph->type) == 11) fprintf(sniffer->logfile,"  (TTL Expired)\n");else if((unsigned int)(icmph->type) == ICMP_ECHOREPLY) fprintf(sniffer->logfile,"  (ICMP Echo Reply)\n");fprintf(sniffer->logfile,"   |-Code : %d\n",(unsigned int)(icmph->code));fprintf(sniffer->logfile,"   |-Checksum : %d\n",ntohs(icmph->checksum));fprintf(sniffer->logfile,"\n");fprintf(sniffer->logfile,"IP Header\n");PrintData(buf, iphdrlen, sniffer);fprintf(sniffer->logfile,"UDP Header\n");PrintData(buf + iphdrlen , sizeof(icmph), sniffer);fprintf(sniffer->logfile,"Data Payload\n");  /* 最后将用户数据写入日志文件中 */PrintData(buf + iphdrlen + sizeof(icmph),(size - sizeof(icmph) - iph->ihl * 4),sniffer);fprintf(sniffer->logfile,"\n###########################################################");
}/* 写用户数据到日志文件 */
void PrintData(unsigned char *buf, int size, t_sniffer *sniffer)
{int i;for(i = 0 ; i < size ; i++){if(i % 16 == 0)fprintf(sniffer->logfile, "\n");fprintf(sniffer->logfile, " %02X",(unsigned int)buf[i]);if( i == size - 1)fprintf(sniffer->logfile, "\n");}
}

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 0x0800int 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_date()
{INITCOLOR(RED_COLOR);printf("[%s]", __DATE__); /* 打印日期 */INITCOLOR(GREEN_COLOR);printf("[%s]  ", __TIME__); /* 打印时间 */INITCOLOR(ZERO_COLOR);
}void getting_started()
{CLEARSCREEN(); /* 清空屏幕 */display_time_and_date();printf("Getting started of Network sniffer\n\n");
}/* 主函数入口 */
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)***\n", __DATE__, __TIME__);if (sniffer.logfile == NULL){perror("fopen(): ");return (EXIT_FAILURE);}sniffer.prot = malloc(sizeof(t_protocol *));  /* 创建原始套接字,ETH_P_ALL 表示侦听负载为 IP 数据报的以太网帧 */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);/* 循环侦听以太网帧,并调用 ProcessPacket 函数解析 */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{/* 如果是标准输入可读,进入命令行处理程序 command_interpreter,暂时只支持 'quit' 命令 */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("recvfrom(): ");return (EXIT_FAILURE);}ProcessPacket(buffer, data_size, &sniffer); /* 调用 ProcessPacket 函数解析出数据包的类型 */}}}close(sd);return (EXIT_SUCCESS);
}void ProcessPacket(unsigned char* buffer, int size, t_sniffer *sniffer)
{buffer = buffer + 6 + 6 + 2; /* 根据太网帧结构,前 6B 是目的 MAC 地址,接下来的是源 MAC 地址,接下来 2B 是帧长度,其余的是负载(上层的 IP 数据报) */struct iphdr *iph = (struct iphdr*)buffer;++sniffer->prot->total; /* 数据包总数加 1 *//* 根据 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_date(); /* 显示时间 *//* 打印 sniffer 中的信息 */printf("TCP : %d   UDP : %d   ICMP : %d   IGMP : %d   Others : %d Total : %d\n",sniffer->prot->tcp, sniffer->prot->udp,sniffer->prot->icmp, sniffer->prot->igmp,sniffer->prot->others, sniffer->prot->total);
}

0x04程序运行

本程序运行界面如下:

实现的功能之一就是解析UDP数据报,其扫描解析结果存放在log.txt中。这里从log.txt中以一个UDP数据包的解析为例

***LOGFILE(Dec 14 2017 - 21:41:38)**************************UDP Packet*************************IP Header|-IP Version        : 4|-IP Header Length  : 5 DWORDS or 20 Bytes|-Type Of Service   : 0|-IP Total Length   : 213  Bytes(size of Packet)|-Identification    : 6639|-TTL      : 64|-Protocol : 17|-Checksum : 31927|-Source IP        : 172.16.69.82|-Destination IP   : 172.16.69.255UDP Header|-Source Port      : 138|-Destination Port : 138|-UDP Length       : 193|-UDP Checksum     : 26258IP Header保护隐私,这部分我删除了AC 10 45 FF
UDP Header保护隐私,这部分我删除了
Data Payload
保护隐私,这部分我删除了###########################################################

0x05附

我认为本实验的亮点在于使用脚本控制,有必要好好学习下脚本编程
launcher.sh

#!/bin/shsigint()
{printf '\nQUIT !\n'exit 1
}main()
{clearprintf "\t\t\t\t\tWelcome to Sniffer Project r\n\n"while [ 1 ]; doprintf "Select option: \n\n"printf "1 : Build Project\n"printf "2 : Launch Project\n"printf "3 : Remove Object files\n"printf "4 : Rebuild\n"printf "0 : Exit\n"printf "\nYou choose: "read optionif [ $option = 0 ]thenexitfiif [ $option -ge 1 ] && [ $option -le 4 ]thenif [ $option = 1 ]thenmake "network_sniffer"fiif [ $option = 2 ]then"./network_sniffer"fiif [ $option = 3 ]thenmake cleanfiif [ $option = 4 ]thenmake refi      elseprintf "This option does not exist\n"fidone
}trap 'sigint' 2main

转载于:https://www.cnblogs.com/ghost00011011/p/8040468.html

C语言实现Linux网络嗅探器相关推荐

  1. Linux网络嗅探器实验报告,分析网络嗅探器实验报告

    网络攻击与防御技术实验报告 实验目的 本实验通过研究Winp c ap中常用的库函数的使用方式来实现了一个小型的网络数据包抓包器并通过对原始包文的分析来展示当前网络的运行状况. 实验内容 1. ...

  2. 基于C语言实现的网络嗅探器设计课程设计

    资源下载地址:https://download.csdn.net/download/sheziqiong/86805873 资源下载地址:https://download.csdn.net/downl ...

  3. c语言实现 网络嗅探程序代码,一个简易网络嗅探器的实现源代码.doc

    一个简易网络嗅探器的实现源代码 摘要:本文介绍一个用C语言和网络数据包分析开发工具实现的简易网络Sniffer. 要害词:网络:数据包:Sniffer 引言 目前,已经有不少的Sniff工具软件,如W ...

  4. Linux 网络基础 C语言常用API 快速翻阅笔记 (字节序篇)

    Linux 网络基础(字节序篇) 一.字节序大小端 1.大小端简介 2.C语言判断大小端 二.大小端 C语言函数 1.将十进制数字转成网络字节序 2.将网络字节序转成十进制数字 三.IP字符串与网络字 ...

  5. C语言实现网络嗅探器

    这里介绍一个用C语言和网络数据包和分析开发工具libpcap及winpcap实现的简易网络Sniffer. 2网络嗅探器程序实现 在c环境下编程,源码如下: #include #include //必 ...

  6. Linux网络编程:用C语言实现的聊天程序(同步通信)

    通过TCP协议,用C语言实现的同步聊天程序,注释写的比较详细,个人觉得对字符串处理比较充分,能够正常编译运行,拿出来和大家分享一下! 1.客户端源代码: [cpp] view plaincopypri ...

  7. 计算机网络安全之网络嗅探器

    作者:shmily 实验题目 实验题目:网络嗅探器实现 实验目的:熟悉并实现网络监听的基本原理 实验环境:linux/windows 实验内容:用C/C++语言(必须用socket函数)编写一个监听网 ...

  8. 基于Python实现的网络嗅探器【100010784】

    基于C语言的网络嗅探器 一.引言 1.1 编写目的 通过编写网络嗅探器,可以提高编程能力,加深对网络协议的理解,培养团队协作能力,完成课程项目 二.功能概述 2.1 节 功能模块命名原则 使用英文进行 ...

  9. Linux网络编程实例分析

    最近由于工作原因需要温习一下Linux网络编程的部分基础知识,因此对之前写的Socket网络通信的代码进行了进一步优化和拓展,在不关闭一次Socket连接的基础上,对服务端加入循环读写的功能,同时加入 ...

最新文章

  1. poj2723详解(二分 + 2-SAT)( 两种方法求解 )
  2. php算出文件相对路径,php计算两个文件相对路径的方法
  3. Matlab练习:timer(定时器)
  4. Qt Creator与调试器进行交互
  5. robot连接mysql_robot连接mysql - autocar - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  6. 2018 上海.NET职位围观报告
  7. hdu 1231 最大连续子序列 ,1003 Max Sum;
  8. Asp.net Mvc使用PagedList分页
  9. java商城管理系统_基于SSM框架的JAVA商场管理系统
  10. 在TextView中插入图片
  11. 互联的情怀 凝成一股绳共同成长
  12. oracle alter命令大全
  13. 精通JavaScript+jQuery:100%动态网页设计密码 中文PDF扫描版
  14. adb 黑域app_黑域使用教程 进入黑域app详细教程
  15. 一共81个,开源大数据处理工具汇总(上)
  16. 电容的材质资料/什么cog,x5r y5v等知识
  17. 神经网络(六)循环神经网络
  18. AltiumDesigner如何绘制PCB封装
  19. 手机访问计算机FTP服务器
  20. 和平精英灵敏度分享码服务器没有响应,和平精英灵敏度分享码

热门文章

  1. 利尔达受邀出席天翼物联开发者大赛创新成果发布会暨颁奖典礼
  2. 电子商务平台的API集成接口的意义
  3. 传说中的100句英语可以帮你背7000单词
  4. 论2019年EI会议全球化的内在逻辑意蕴
  5. 从源码的角度看Go语言flag库如何解析命令行参数!
  6. Win7下配置MySql定时自动备份
  7. Vue常用指令 [vue框架][web前端]
  8. CentOS7.5平台下的vsftpd运维脚本(个人练习版)
  9. 多台以太网交换机怎么连接?
  10. python zipfile 处理压缩文件并读取包里面的所有内容