基于Linux环境下的Sniffer设计与实现

转载 2005年05月20日 18:56:00

come from http://www.cnpaf.net

一、Sniffer原理分析

在实现嗅探器之前,我们先需要掌握TCP/IP协议。TCP协议和IP协议指两个用在Internet上的网络协议(或数据传输的方法)。它们分别是传输控制协议和互连网协议。这两个协议属于众多的TCP/IP 协议组中的一部分。

TCP/IP协议组中的协议保证Internet上数据的传输,提供了几乎现在上网所用到的所有服务。这些服务包括:电子邮件的传输、文件传输、新闻组的发布和访问万维网。

TCP协议在IP协议之上。与IP协议提供不可靠传输服务不同的是,TCP协议为其上的应用层提供了一种可靠传输服务。这种服务的特点是:可靠、全双工、流式和无结构传输。TCP传输原理:

TCP协议使 用了一个叫积极确认和重发送(positive acknowledgement with retransmission)的技术来实现可靠传输。接收者在收到发送者发送的数据后,必须发送一个相应的确认(ACK)消息,表示它已经收到了数据。 发送者保存发送的数据的记录,在发送下一个数据之前,等待这个数据的确认消息。在它发送这个数据的同时,还启动了一个记时器。如果在一定时间之内,没有接 收到确认消息,就认为是这个数据在传送时丢失了,接着,就会重新发送这个数据。

这种方法还产生了一个问题,就是包的重复。如果网络传 输速度比较低,等到等待时间结束后,确认消息才返回到发送者,那么,由于发送者采用的发送方法,就会出现重复的数据了。解决的一个办法是给每个数据一个序 列号,并需要发送者记住哪个序列号的数据已经确认了。为了防止由于延时或重复确认,规定确认消息里也要包含确认序列号。从而发送者就能知道哪个包已经确认 了.

有 前面的描述可见,发送者在发送完一个数据包之后,要等待确认。在它收到确认消息之前的这段时间是空闲的。如果网络延时比较长,这个问题会相当明显。滑动窗 口方法是在它收到确认消息以前,发送多个数据包。可以想象成有一个窗口在一个序列上移动。如果一个包发送出去之后还没有确认,叫做未确认包。通常未确认的 包的个数就是窗口的大小。在接收端,也有一个滑动窗口接收和确认一个包。

使用TCP传输就是建立一个连接。在TCP传输中一个连接有 两个端点组成。其实,一个连接代表的是发送和接收两端应用程序的之间的一个通信。可以把他们想象成建立了一个电路。通常一个连接用下面的公式表示: (host,port),host是主机,port是端口。TCP端口能被几个应用程序共享。对于程序员来讲,可以这样理解:一个应用程序可以为不同的连 接提供服务。TCP传输的单位是段,在建立连接,传送数据,确认消息和告之窗口大小时均要进行段的交换。

TCP协议使 用一个三次握手来建立一个TCP连接的。握手过程的第一个段的代码位设置为SYN,序列号为x,表示开始一次握手。接收方收到这个段后,向发送者回发一个 段。代码位设置为SYN和ACK,序列号设置为y,确认序列号设置为x+1。发送者在受到这个段后,知道就可以进行TCP数据发送了,于是,它又向接收者 发送一个ACK段,表示,双方的连接已经建立。在完成握手之后,就开始正式的数据传输了。上面握手段中的序列号都是随机产生的。

了解了TCP/IP协议后, 还要掌握网络编程。在LINUX网络编程中,我们可以认为套接字是将Unix系统的文件操作推广到提供点对点的通信。如果要操作文件,应用程序会根据应用 程序的需要为之创建一个套接字。操作系统返回一个整数。应用程序通过引用这个正数来使用这个套接字。文件描述符和套接字描述符的不同点在于,在程序调用 open()时,操作系统将一个文件描述符绑定到一个文件或设备,但在创建一个套接字时,可以不将它绑定到一个目标地址。程序可以在任何想要用这个套接字 的时候指定目标地址。在点对点的通信程序中,我们将请求服务或数据的程序叫做客户端程序,提供数据或服务的软件叫做服务器程序。下面解释一下一个基本的套 接字系统调用函数,也是该嗅探器中要用到的函数:



socket()
#include < sys/types.h>
#include < sys/socket.h>
int socket(int family, int type, int protocol);
int family参数指定所要使用的通信协议,取以下几个值:

AF_UNIX Unix内部协议
AF_INET Internet协议
AF_NS Xerox NS协议
AF_IMPLINK IMP 连接层
int type 指定套接字的类型,取以下几个值 :
SOCK_STREAM 流套接字
SOCK_DGRAM 数据报套接字
SOCK_RAW 未加工套接字
SOCK_SEQPACKET 顺序包套接字
int protocol 参数通常设置为0。


socket()系统调用返回一个整数值,叫做套接字描述字sockfd,它的原理与文件描述符一样。网络I/O的第一步通常就是调用这个函数。

二、Sniffer具体实现

现在具体介绍一下该嗅探器的实现。该嗅探器是在Red Hat LINUX6.2版本中,用C语言编写的,以调试并编译通过。

Sniffer是一种常用的收集有用数据方法,这些数据可以是用户的帐号和密码,可以是一些商用机密数据等等。Sniffer是一种常用的收集有用数据的方法,这些数据可以是用户的帐号和密码,可以是一些商用机密数据等等。

以 太网sniffing 是指对以太网设备上传送的数据包进行侦听,发现感兴趣的包。如果发现符合条件的包,就把它存到一个log文件中去。通常设置的这些条件是包含字 "username"或"password"的包。它的目的是将网络层放到promiscuous模式,从而能干些事情。Promiscuous模式是指 网络上的所有设备都对总线上传送的数据进行侦听,并不仅仅是它们自己的数据。根据以太网的工作原理,可以知道:一个设备要向某一目标发送数据时,它是对以 太网进行广播的。一个连到以太网总线上的设备在任何时间里都在接受数据。不过只是将属于自己的数据传给该计算机上的应用程序。利用这一点,可以将一台计算 机的网络连接设置为接受所有以太网总线上的数据,从而实现sniffer。

sniffer通常运行在路由器,或有路由器功能的主机 上。这样就能对大量的数据进行监控。sniffer属第二层次的攻击。通常是攻击者已经进入了目标系统,然后使用sniffer这种攻击手段,以便得到更 多的信息。sniffer除了能得到口令或用户名外,还能得到更多的其他信息,比如一个其他重要的信息,在网上传送的金融信息等等。sniffer几乎能 得到任何以太网上的传送的数据包。通常sniffer程序只看一个数据包的前200-300个字节的数据,就能发现想口令和用户名这样的信息。

下面对该程序的实现作一个介绍。结构etherpacket定义了一个数据包。其中的ethhdr,iphdr,和tcphdr分别是三个结构,用来定义以太网帧,IP数据包头和TCP数据包头的格式。

它们在头文件中的定义如下:



struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int8_t ihl:4;
u_int8_t version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int8_t version:4;
u_int8_t ihl:4;
#else
#error "Please fix < bytesex.h>"
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/*The options start here. */
};
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
u_int16_t ack:1;
u_int16_t urg:1;
u_int16_t res2:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff:4;
u_int16_t res1:4;
u_int16_t res2:2;
u_int16_t urg:1;
u_int16_t ack:1;
u_int16_t psh:1;
u_int16_t rst:1;
u_int16_t syn:1;
u_int16_t fin:1;
#else
#error "Adjust your < bits/endian.h > defines"
#endif
u_int16_t window;
u_int16_t check;
u_int16_t urg_ptr;
};


接下来,定义了一个结构变量victim。随后,看一下函数int openintf(char *d),它的作用是打开一个网络接口。在main中是将eth0作为参数来调用这个函数。在这个函数中,用到了下面的结构:



struct ifreq
{
#define IFHWADDRLEN 6
#define IFNAMSIZ 16
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
__caddr_t ifru_data;
} ifr_ifru;
};



这个结构叫接口请求结构,用来调用在I/O输入输出时使用。所有的接口I/O输出必须有一个参数,这个参数以ifr_name开头,后面的参数根据使用不同的网络接口而不同。

如 果你要看看你的计算机有哪些网络接口,使用命令ifconfig即可。一般会看到两个接口lo0和eth0。在ifreq结构中的各个域的含义与 ifconfig的输出是一一对应的。在这里,程序将eth0作为ifr_name来使用的。接着,该函数将这个网络接口设置成promiscuous模 式。请记住,sniffer是工作在这种模式下的。

再看一下函数read_tcp,它的作用是读取TCP数据包,传给filter处 理。Filter函数是对上述读取的数据包进行处理。接下来的程序是将数据输出到文件中去。函数clearup是在程序退出等事件时,在文件中作个记录, 并关闭文件。否则,你刚才做的记录都没了。

三、运行结果及结论

运行这个程序的结果,计算机是 处于一个由三十台以上主机组成的局域网环境中,这个局域网中的所有主机通过代理网关可以上Internet。经测试,在晚上上网高峰期,可以在几分钟之内 探测到5以上个不同IP地址的邮箱用户名及密码,当然,还可以探测到别的信息,如用户用Web浏览器浏览的网页内容、telnet登录名及密码等有用信 息。预计如果该程序运行于网关,会截取更多的信息。

Linux下sniffer的编写(新手上路)

Sniffer程序是把NIC(网络适配卡,一般如以太网卡)置为一种叫promiscuous杂乱模式的状态,一旦网卡设置为这种模式,它就能是 sniffer程序能接受传输在网络上的每一个信息包。普通的情...
  • bat603
  • bat603
  • 2006年09月01日 19:05
  • 3778

基于linux的TCP网络聊天室设计与实现

利用Linux实现基于TCP模式的网络聊天程序 主要完成的两大组成部分为:服务器和客户端。 服务器程序主要负责监听客户端发来的消息。 客户端需要登录到服务器端才可以实现正常的聊天功能。该程序是利用进...
  • qq_35260622
  • qq_35260622
  • 2016年06月12日 09:12
  • 5201

搭建sip环境

第一步软件准备:   服务器软件 ndoSip Server 下载地址:http://www.brekeke.com/    这个软件是用java写的,因此在安装前先装jdk   sip客户端...
  • shuangyidehudie
  • shuangyidehudie
  • 2012年09月06日 14:06
  • 720

毕业论文——基于Android的网上订餐系统的设计与实现

本系统主要分析了中小型餐饮店管理与发展的现状所面临的问题,发现传统的服务模式已经不能适应市场发展的需求,方便、快捷、个性化的网上订餐服务正在进入人们的生活。针对这类问题,结合当代科技发展的新成果,本文...
  • guai25qiaokn
  • guai25qiaokn
  • 2014年08月06日 12:09
  • 1679

初识OGC规范

OpenGIS是什么OGC为分布式环境下访问地理数据和地理信资源制定的一套全面的规范。它包括抽象规范和实现规范。各厂商按照OpenGIS制定的规范开发GIS软件,而且些软件之间能够实现互操作。OGIS...
  • angeltimes
  • angeltimes
  • 2007年03月05日 21:18
  • 3705

简易的sniffer程序

真的很简易,这个程序仅仅是抓一些发送到本机的数据包,然后显示出来它们的一些信息罢了!      程序非常简单!      #include #include #include #include ...
  • lishuhuakai
  • lishuhuakai
  • 2014年06月05日 17:27
  • 2164

[毕业设计]手写数字识别系统设计与实现

内容摘要:本文论述并设计实现了一个自由手写体数字识别系统。文中首先对待识别数字的预处理进行了介绍,包括二值化、噪声处理、图像分割、归一化、细化等图像处理方法;其次,探讨了数字字符特征向量的提取;最后采...
  • szydwy
  • szydwy
  • 2016年03月20日 20:30
  • 4967

linux 线程--内核线程、用户线程实现方法

Linux上进程分3种,内核线程(或者叫核心进程)、用户进程、用户线程 内核线程拥有 进程描述符、PID、进程正文段、核心堆栈 当和用户进程拥有相同的static_prio 时,内核线程有机会...
  • sdulibh
  • sdulibh
  • 2016年01月12日 10:31
  • 1588

基于SSM的博客网的设计与实现

每年的11月都要开始整理毕设题目,今年涉及的班级和学生人数时去年的2倍,这次准备出一个博客的毕设,所有来亲身体验一下博客的功能(原谅我之前没有用过博客)...
  • u011756320
  • u011756320
  • 2017年11月29日 10:57
  • 123

【Linux内核设计与实现】Linux内核简介

之前在读《APUE》的时候,更多的是从上层去了解如何使用Linux系统的API,那个时候就十分喜欢Linux的设计,觉得一切都很奇妙。最近有些迷茫,不知道自己以后更加具体的技术方向在哪,所以最近广泛阅...
  • jiange_zh
  • jiange_zh
  • 2016年09月22日 11:22
  • 1309
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于Linux环境下的Sniffer设计与实现
举报原因:
原因补充:

(最多只允许输入30个字)