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

作者:161720105实验题目实验题目:网络嗅探器实现实验目的:熟悉并实现网络监听的基本原理实验环境:linux/windows实验内容:用C/C++语言(必须用socket函数)编写一个监听网络流量的程序,并对截取的报文进行解析。实验环境Linux kali 4.19.0-kali1-686-pae #1 SMP Debian 4.19.13-1kali1 (2019-01-03...
摘要由CSDN通过智能技术生成

作者:shmily

实验题目

实验题目:网络嗅探器实现
实验目的:熟悉并实现网络监听的基本原理
实验环境:linux/windows
实验内容:用C/C++语言(必须用socket函数)编写一个监听网络流量的程序,并对截取的报文进行解析。

实验环境

Linux kali 4.19.0-kali1-686-pae #1 SMP Debian 4.19.13-1kali1 (2019-01-03) i686 GNU/Linux

程序运行方法

make

程序实现说明及源码分析

程序框架

在这里插入图片描述

如框图所示,程序可以获取到MAC帧、IP包以及传输层数据包。传输层的数据包中,只实现了对TCP, UPD, ICMP, IGMP报文的解析。

首先读取本主机和网卡的信息,在数据链路层接收经过本网卡的所有类型的数据包。在解析完MAC帧之后,将头部拆掉,并将payload继续解析,读出IP头部后,记下protocol类型,将头部拆掉,依据protocol 的类型进行分类解析。待三层都解析完毕后,重头解析下一个数据包,重复以上过程。

global.h

引用了程序可能用到的头文件,定义了数据链路层帧长度变量、必要的结构体、本机主机、网卡信息等内容。

#ifndef _NET_GLOBAL_H_
#define _NET_GLOBAL_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>  
#include <netinet/udp.h>   
#include <netinet/tcp.h>   
#include <netinet/ip.h>    
#include <net/ethernet.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <sys/types.h>
#include <asm/types.h>
#include <features.h>
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h> 
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h> 
#endif
#include <netinet/if_ether.h>
#include <net/if_arp.h>
/* 以太网帧首部长度 */
#define ETHER_HEADER_LEN sizeof(struct ether_header)
/* MAC地址长度 */
#define MAC_ADDR_LEN 6
/* IP地址长度 */
#define IP_ADDR_LEN 4
#define IP_CHAR_MAX_LEN 18
/* 广播地址 */
#define BROADCAST_ADDR	\
	{		\
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff\
	}		\
#define  err_exit(err_msg)  \
{                       	\
        perror(err_msg);    	\
        exit(EXIT_FAILURE); 	\
}			\
// 数据链路层
struct sockaddr_ll saddr_ll;
// 本地IP、子网掩码和本地MAC
struct in_addr local_ip, subnet_mask;
unsigned char local_mac_addr[MAC_ADDR_LEN];
// 网卡名称
char if_name[0x20];
#endif

获取本机信息

init_net.c文件与Scanner文件中的完全一样,主要通过socket函数和ioctl()获取相关信息。

接收数据包

为了实现直接从链路层收发数据帧,需要用到socket,为了手动实现解析,需要把type设置成SOCK_RAW,直接从网络硬件驱动程序接收没有任何处理的完整数据报文,包括物理帧的帧头。并且将protocol字段设置成ETH_P_ALL ,接收发往目的MAC是本机的所有类型的数据帧,同时还可以接收从本机发出去的所有数据帧。

由于可能收到UDP报文,所以这次使用recvfrom(),收到UDP这种无连接的报文时,可以很方便地进行回复。

为了防止收到过多数据包,设置一个较大缓冲区buffer,每次收到一个MAC帧就放进去,直到缓冲区满,每次从缓冲区中读数据进行解析。

void Getflow()
{
   
    int saddr_size, data_size;
    struct sockaddr saddr;
    struct in_addr in;
	
    /* 缓冲区 */
    unsigned char *buffer = (unsigned char *) malloc(65536); 
    /* 创建socket,接收所有类型数据包 */
    sock_raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sock_raw < 0) {
   
        printf("Socket Error: %s\n", strerror(errno));
        exit(0);
    }
    while (1) {
   //不停收数据直到缓冲区满
        saddr_size = sizeof saddr;
        /* 接收数据 */
        data_size = recvfrom(sock_raw, buffer, 2048, 0, &saddr, (socklen_t *) &saddr_size);
        if (data_size < 0) {
   
            printf("Recvfrom error , failed to get packets\n");
            exit(0);
        }
        /* 处理数据包 */
        ProcessPacket(buffer, data_size);
    }
    close(sock_raw
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值