当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]在Linux下如何利用C语言来实现一个Sniffer

Sniffer技术是网络安全领域里一项非常重要的技术!对于“Hacker”来说,他们可以以非常隐蔽的方式得到网络中传输的大量的敏感信息,如 Telnet,ftp帐号和密码等等明文传送的信息!与主动扫描相比,嗅探的行为更加难以被察觉,操作起来也不是很复杂!对于网络管理人员来说,可以利用嗅探技术对网络活动进行监控,并及时发现各种攻击行为!

  在这篇文章里,我们主要探讨在Linux下如何利用C语言来实现一个Sniffer!我们将假设所有的主机在一个局域网内。

  首先,我们将简短的回顾一下一个普通的以太网卡是怎么工作的!(如果你对这方面的知识早已熟悉,那么你可以直接跳到下一段)来源于应用程序的IP报文被封装成以太网帧(这是在以太网上传播的数据报文的名称),它是底层链路层报文上面的一层报文,包含有源地址报文和一些需要用来传送至目标主机的信息。通常情况下,目的IP地址对应着一个6字节的目的以太网址(经常叫做MAC地址),它们之间通过ARP协议进行映射!就这样,包含着以太网帧的报文从源主机传输到目的主机,中间经过一些网络设备,如交换机,路由器等等,当然,因为我们的前提是主机在同一网内,所以我们的讨论不涉及以上这些网络设备!

  在链路层中并不存在路线的概念,换句话说,源主机发出的帧不会直接指向目的主机,而是基于广播方式传播,网络中的所有网卡都能看到它的传输。每个网卡会检查帧开始的6个字节(目的主机的MAC地址),但是只有一个网卡会发现自己的地址和其相符合,然后它接收这个帧,这个帧会被网络驱动程序分解,原来的IP 报文将通过网络协议栈传送至接收的应用程序!

  更准确的说,网络驱动程序会检查帧中报文头部的协议标识,以确定接收数据的上层协议!大多数情况下,上层是IP协议,所以接收机制将去掉IP报文头部,然后把剩下的传送至UDP或者TCP接收机制!这些协议,将把报文送到SOCKET-handling机制,它将最后把报文数据变成应用程序可接收的方式发送出去。在这个过程中,报文将失去所有的和其有关的网络信息,比如源地址(IP和MAC),端口号,IP选择,TCP参数等等!所以如果目的主机没有一个包含正确参数的打开端口,那么这个报文将被丢弃而且永远不会被送到应用层去!

  因此我们在进行网络嗅探的时候有两个不同的问题:一个和以太网址有关,我们不能抓到不是发给自己主机的包,另一个和协议栈的运行过程有关,我们需要一个socket去*每个端口,得到那些没有被丢弃的报文!

  第一个问题不是最根本的,因为我们可能不会对发往其他主机的报文有兴趣而只想嗅探所有发往自己主机的报文。第二个问题是必须要解决的,下面我们将看到这个问题是怎么样一步一步解决的!

  当你打开一个标准的SOCKET套接字时,你需要指明你将使用哪个协议簇,大多数情况下我们一般用PF_UNIX在本地机器间进行通信,PF_INET在基于IPv4协议簇基础之上进行通信,你还需要指明所用的协议类型及与协议簇相关的确切数值,,在PF_INET协议簇中,常用的有 SOCK_STREAM(与TCP相关),SOCK_DGRAM(与UDP相关)。在把报文发送到应用程序前内核对其的处理与SOCKET类型有关,你指定的协议将处理报文在SOCKET的传输!(具体细节问题你可以man socket(3))

  在LINUX内核版本中(2.0 releases),一个名为PF_PACKET的协议簇被加了进来!这个簇允许应用程序直接利用网络驱动程序发送和接收报文,避免了原来的协议栈处理过程,在这种情况下,所有SOCKET发出的报文直接送到以太网卡接口,而接口收到的任何报文将直接送到应用程序The PF_PACKET协议簇支持两个稍微有点不同的SOCKET类型,SOCK_DGRAM和SOCK_RAW。

  前者让内核处理添加或者去除以太网报文头部工作,而后者则让应用程序对以太网报文头部有完全的控制!在SOCKET调用中的协议类型必须符合/usr /include/linux/if_ether.h中定义的以太网IDs中的一个,除非遇到特别声明的协议,一般你可以用ETH_P_IP来处理IP的一组协议(TCP,UDP,ICMP,raw IP等等)因为它们容易受到一些很严重的安全问题的牵连(比如你可以伪造一个MAC地址),所以只有具有root权限才可以使用PF_PACKET- familysocket.这也就是为什么只有具有root权限后才能运行嗅探器的原因!

  PF_PACKET-family 协议簇可以很容易解决协议栈处理嗅探来的数据报文时候遇到的问题!我们一起来看看程序1,我们打开一个属于PF_PACKET-family 协议簇的SOCKET,指定一个SOCK_RAW socket类型和IP相关协议类型。这时我们开始从SOCKET抓包,在一些相关检查后.我们开始得到从链路层和IP层抓来的头部信息,。通过阅读程序一,你将会发现让应用程序从网络层抓包其实并不难!

  Example 1.

  #include

  #include

  #include

  #include

  #include

  #include

  #include

  int main(int argc, char **argv) {

  int sock, n;

  char buffer[2048];

  unsigned char *iphead, *ethhead;

  if ( (sock=socket(PF_PACKET, SOCK_RAW,

  htons(ETH_P_IP)))<0) {

  perror("socket");

  exit(1);

  }

  while (1) {

  printf("----------n");

  n = recvfrom(sock,buffer,2048,0,NULL,NULL);

  printf("%d bytes readn",n);

  /* Check to see if the packet contains at least

  * complete Ethernet (14), IP (20) and TCP/UDP

  * (8) headers.

  */[!--empirenews.page--]

  if (n<42) {

  perror("recvfrom():");

  printf("Incomplete packet (errno is %d)n",

  errno);

  close(sock);

  exit(0);

  }

  ethhead = buffer;

  printf("Source MAC address: "

  "%02x:%02x:%02x:%02x:%02x:%02xn",

  ethhead[0],ethhead[1],ethhead[2],

  ethhead[3],ethhead[4],ethhead[5]);

  printf("Destination MAC address: "

  "%02x:%02x:%02x:%02x:%02x:%02xn",

  ethhead[6],ethhead[7],ethhead[8],

  ethhead[9],ethhead[10],ethhead[11]);

  iphead = buffer+14; /* Skip Ethernet header */

  if (*iphead==0x45) { /* Double check for IPv4

  * and no options present */

  printf("Source host %d.%d.%d.%dn",

  iphead[12],iphead[13],

  iphead[14],iphead[15]);

  printf("Dest host %d.%d.%d.%dn",

  iphead[16],iphead[17],

  iphead[18],iphead[19]);

  printf("Source,Dest ports %d,%dn",

  (iphead[20]<<8)+iphead[21],

  (iphead[22]<<8)+iphead[23]);

  printf("Layer-4 protocol %dn",iphead[9]);

  }

  }

  }

  PF_PACKET协议簇可以让一个应用程序把数据包变成似乎从网络层接收的样子,但是没有办法抓到那些不是发向自己主机的包。正如我们前面看到的,网卡丢弃所有不含有主机MAC地址的数据包,这是因为网卡处于非混杂模式,即每个网卡只处理源地址是它自己的帧!

  只有三个例外:如果一个帧的目的MAC地址是一个受限的广播地址(255.255.255.255)那么它将被所有的网卡接收:如果一个帧的目的地址是组播地址,那么它将被那些打开组播接收功能的网卡所接收;网卡如被设置成混杂模式,那么它将接收所有流经它的数据包最后一种情况当然是我们最感兴趣的了,把网卡设置成混杂模式,我们只需要发出一个特殊的ioctl()调用在那个网卡上打开一个socket,因为这是一个具有危险性的操作,所以这个调用只有具有root权限的用户才可完成,假设那个“sock”包含一个已经打开的socket。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

为了满足日益增长的数据处理需求,铁威马NAS推出了全新的性能巅峰2024年旗舰之作F4-424 Pro,并搭载了最新的操作系统--TOS 6。这款高效办公神器的问世,无疑将为企业和专业人士带来前所未有的便捷与效率。

关键字: 存储 Linux 服务器

嵌入式开发作为信息技术领域的重要分支,其涉及的语言种类繁多,各具特色。这些语言的选择取决于目标平台的特性、性能需求、开发者的熟练程度以及项目的具体要求。本文将详细介绍几种常见的嵌入式开发语言,包括C语言、C++、汇编语言...

关键字: 嵌入式开发 C语言

双系统将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对双系统的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 双系统 Windows Linux

安装Linux操作系统并不复杂,下面是一个大致的步骤指南,以帮助您完成安装。1. 下载Linux发行版:首先,您需要从Linux发行版官方网站下载最新的ISO镜像文件。

关键字: Linux 操作系统 ISO镜像

计算机是由一堆硬件组成的,为了有限的控制这些硬件资源,于是就有了操作系统的产生,操作系统是软件子系统的一部分,是硬件基础上的第一层软件。

关键字: Linux 操作系统 计算机

Linux操作系统是一套免费使用和自由传播的类Unix操作系统,通常被称为GNU/Linux。它是由林纳斯·托瓦兹在1991年首次发布的,并基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Lin...

关键字: Linux 操作系统

所谓进程间通信就是在不同进程之间传播或交换信息,它是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息;还可以让一个程序能够在同一时间里处理许多用户的需求。

关键字: Linux 进程通信 编程接口

串口通信作为一种最传统的通信方式,在工业自动化、通讯、控制等领域得到广泛使用。

关键字: Linux 串口通信 通讯

2023年11月16日: MikroElektronika(MIKROE) ,作为一家通过提供基于成熟标准的创新式硬软件产品来大幅缩短开发时间的嵌入式解决方案公司,今天宣布推出一款基于单线设备的软硬件开源解决方案Cli...

关键字: 嵌入式 Linux 操作系统

Linux是一种免费使用和自由传播的类Unix操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布。它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CP...

关键字: Linux 操作系统
关闭
关闭