主页 PC知识 网管技术 黑客帝国 安全技术 开放系统 程序设计 搜索 技术论坛

 

相关联接
 
RHU本级分类

技术开发
桌面应用
嵌入技术
问答(FAQ)
基础知识
企业应用&技巧

 
RHU阅读排行
·手把手教你如何写Makefile
·Linux下PCI设备驱动程序开发基本框架
·VSFTP+MySQL虚拟用户配置过程讲解
·如何在Linux桌面上搭建C/C++IDE开发环境
·嵌入Linux基于MiniGUI信息终端软件开发
·Linux下动态链接库技术分析和移植技巧
·Linux网络编程几个必需的网络函数介绍
·一套的实用完整Makefile参考模板
·Sniff网络基础原理和软件实现技巧详解
·Linux系统和内核初始化过程简要介绍

 
 
RHU最新文章
·几个重要的Linux操作系统 内核文件介绍
·构筑Linux防火墙之为个人用户设置防火墙
·构筑防火墙之IPtables搭建防火墙的规则
·如何使用Linux LiveCD评估系统的安全性
·磨炼Gentoo的锋芒之只要敢想 就有Gentoo
·揭秘Linux内核调试器之内幕
·用SRP建立安全的Linux Telnet服务器
·构筑Linux防火墙之什么是Linux防火墙
·Fedora core 2服务器平台安全设置揭秘
·引黑客入瓮 给Linux系统蒙上Windows面纱

 
 
RHU相关搜索









 
 
RHU广而告之

 
 
>您的位置:首页 -> Linux/Unix-> 技术开发
Sniff网络基础原理和软件实现技巧详解

作者:RHU-TAC编辑员 来自:RHU网络采集 时间:2005-5-9 双击滚屏 收藏本页 字体:


点击 查看RHU2004全年文章


一、前言

SNIFF真是一个古老的话题,关于在网络上采用SNIFF来获取敏感信息已经不是什么新鲜事,也不乏很多成功的案例,那么,SNIFF究竟是什么呢? SNIFF就是嗅探器,就是窃听器,SNIFF静悄悄的工作在网络的底层,把你的秘密全部记录下来。看过威尔史密斯演的《全民公敌》吗?SNIFF就象里面精巧的窃听器一样,让你防不胜防。

SNIFF可以是软件,也可以是硬件,既然是软件那就要分平台,有WINDOWS下的、UNXI

下的等,硬件的SNIFF称为网络分析仪,反正不管硬件软件,目标只有一个,就是获取在网络上传输的各种信息。本文仅仅介绍软件的SNIFF。

当你舒适的坐在家里,惬意的享受网络给你带来的便利,收取你的EMAIL,购买你喜欢

的物品的时候,你是否会想到你的朋友给你的信件,你的信用卡帐号变成了一个又一个的信息包在网络上不停的传送着,你是否曾经这些信息包会通过网络流入别人的机器呢?你的担忧不是没有道理的,因为SNIFF可以让你的担忧变成实实在在的危险。就好象一个人躲在你身后偷看一样。

二、网络基础知识

"网络基础知识",是不是听起来有点跑题了?虽然听起来这和我们要谈的SNIFF没什么

关系,可是还是要说一说的,万丈高楼平地起,如果连地基都没打好,怎么盖楼?!如果你对网络还不是十分清楚的话,最好能静下心来好好看看,要知道,这是基础的基础,在这里我只是简单的说一下,免得到时候有人迷糊,详细的最好能够自己去找书看看。

(1)TCP/IP体系结构

开放系统互连(OSI)模型将网络划分为七层模型,分别用以在各层上实现不同的功能,

这七层分别为:应用层、表示层、会话层、传输层、网络层、数据链路层及物理层。而TCP/IP体系也同样遵循这七层标准,只不过在某些OSI功能上进行了压缩,将表示层及会话层合并入应用层中,所以实际上我们打交道的TCP/IP仅仅有5层而已,网络上的分层结构决定了在各层上的协议分布及功能实现,从而决定了各层上网络设备的使用。实际上很多成功的系统都是基于OSI模型的,如:如帧中继、ATM、ISDN等。

TCP/IP的网络体系结构

----------------------------------- 
| SMTP | DNS | HTTP | FTP | TELNET| 应用层 
----------------------------------- 
| TCP | UDP | 传输层 
----------------------------------- 
| IP | ICMP | ARP RARP | 网络层 
------------------------ 
| IEEE 802 以太网 SLIP/PPP PDN etc| 数据链路层 
----------------------------------- 
| 网卡 电缆 双绞线 etc | 物理层 
-----------------------------------



从上面的图中我们可以看出,第一层物理层和第二层数据链路层是TCP/IP的基础,而

TCP/IP本身并不十分关心低层,因为处在数据链路层的网络设备驱动程序将上层的协议和实际的物理接口隔离开来。网络设备驱动程序位于介质访问子层(MAC)。

(2)网络上的设备

中继器:中继器的主要功能是终结一个网段的信号并在另一个网段再生该信号,一句话,就是简单的放大而已,工作在物理层上。

网桥:网桥使用MAC物理地址实现中继功能,可以用来分隔网段或连接部分异种网络,工

作在数据链路层。

路由器:路由器使用网络层地址(IP,X.121,E.164等),主要负责资料包的路由寻径,也能处理物理层和数据链路层上的工作。

网关:主要工作在网络第四层以上,主要实现收敛功能及协议转换,不过很多时候网关都被用来描述任何网络互连设备。

(3)TCP/IP与以太网

以太网和TCP/IP可以说是相互相成的,可以说两者的关系几乎是密不可分,以太网在一二层提供物理上的联机,而TCP/IP工作在上层,使用32位的IP地址,以太网则使用48位的MAC地址,两者间使用ARP和RARP协议进行相互转换。从我们上面TCP/IP的模型图中可以清楚的看到两者的关系。

载波监听/冲突检测(CSMA/CD)技术被普遍的使用在以太网中,所谓载波监听是指在以

太网中的每个站点都具有同等的权利,在传输自己的资料时,首先监听信道是否空闲,如果空闲,就传输自己的数据,如果信道被占用,就等待信道空闲。而冲突检测则是为了防止发生两个站点同时监测到网络没有被使用时而产生冲突。以太网采用广播机制,所有与网络连接的工作站都可以看到网络上传递的资料。

为了加深你的理解,我们来看看下面的图,一个典型的在以太网中客户与服务器使用

TCP/IP协议的通信。



用户进程 FTP客户 <-------------------------> FTP服务器 应用层

| |

内核中的协议栈 TCP <-------------------------> TCP 传输层

| |

内核中的协议栈 IP <-------------------------> IP 网络层

| |

以太网驱动程序 <-------------------------> 以太网驱动程序 数据链路层

──────-------------------------------

说了这么多,有人烦了吧?相信我,这是基础的基础,可以说是说得是很简单拉,

如果需要,拿出个几十万字来说上面的内容,我想也不嫌多,好了,让我们进入下一节, sniff的原理。

三 SNIFF的原理

要知道在以太网中,所有的通讯都是广播的,也就是说通常在同一个网段的所有网络接口都可以访问在物理媒体上传输的所有资料,而每一个网络接口都有一个唯一的硬件地址,这个硬件地址也就是网卡的MAC地址,大多数系统使用48比特的地址,这个地址用来表示网络中的每一个设备,一般来说每一块网卡上的MFC地址都是不同的,每个网卡厂家得到一段地址,然后用这段地址分配给其生产的每个网卡一个地址。在硬件地址和IP地址间使用ARP和RARP协议进行相互转换。



在正常的情况下,一个网络接口应该只响应这样的两种资料帧:

1.与自己硬件地址相匹配的资料帧。

2.发向所有机器的广播资料帧。

在一个实际的系统中,资料的收发是由网卡来完成的,网卡接收到传输来的资料,网卡

内的单片程序接收资料帧的目的MAC地址,根据计算机上的网卡驱动程序设置的接收模式判断该不该接收,认为该接收就接收后产生中断信号通知CPU,认为不该接收就丢掉不管,所以不该接收的资料网卡就截断了,计算机根本就不知道。CPU得到中断信号产生中断,操作系统就根据网卡的驱动程序设置的网卡中断程序地址调用驱动程序接收资料,驱动程序接收资料后放入信号堆栈让操作系统处理。而对于网卡来说一般有四种接收模式:

广播方式:该模式下的网卡能够接收网络中的广播信息。

组播方式:设置在该模式下 的网卡能够接收组播资料。 直接方式:在这种模式下,只有目的网卡才能接收该数据。 混杂模式:在这种模式下的网卡能够接收一切通过它 的资料,而不管该资料是否是 传给它的。

好了,现在我们总结一下,首先,我们知道了在以太网中是基于广播方式传送资料的,也就是说,所有的物理信号都要经过我的机器,再次,网卡可以置于一种模式叫混杂模式(promiscuous),在这种模式下工作的网卡能够接收到一切通过它的资料,而不管实际上数据的目的地址是不是他。这实际上就是我们SNIFF工作的基本原理:让网卡接收一切他所能接收的数据。



我们来看一个简单的例子,机器A、B、C与集线器HUB相连接,集线器HUB通过路由器Router访问外部网络。这是一个很简单也很常见的情况,比如说在公司大楼里,我所在的网络部办公室里的几台机器通过集线器连接,而网络部、开发部、市场部也是同样如此,几个部门的集线器通过路由器连接。还是回到我们的图一上来,值得注意的一点是机器A、B、C使用一个普通的HUB连接的,不是用SWITCH,也不是用ROUTER,使用SWITCH和ROUTER的情况要比这复杂得多。

我们假设一下机器A上的管理员为了维护机器C,使用了一个FTP命令向机器C进行远程登陆,那么在这个用HUB连接的网络里资料走向过程是这样的。首先机器A上的管理员输入的登陆机器C的FTP口令经过应用层FTP协议、传输层TCP协议、网络层IP协议、数据链路层上的以太网驱动程序一层一层的包裹,最后送到了物理层,我们的网线上。接下来资料帧送到了HUB上,现在由HUB向每一个接点广播由机器A发出的资料帧,机器B接收到由HUB广播发出的资料帧,并检查在资料帧中的地址是否和自己的地址相匹配,发现不是发向自己的后把这资料帧丢弃,不予理睬。而机器C也接收到了资料帧,并在比较之后发现是发现自己的,接下来他就对这数据帧进行分析处理。

在上面这个简单的例子中,机器B上的管理员如果很好奇,他很想知道究竟登陆机器C上FTP口令是什么?那么他要做的很简单,仅仅需要把自己机器上的网卡置于混杂模式,并对接收到的资料帧进行分析,从而找到包含在资料帧中的口令信息。
  

四 做一个自己的sniff

在上一节里,我们已经知道了SNIFF的基本原理是怎么一回事,这一节我们来亲自动手做一个自己的sniff,毕竟,用程序代码来说话比什么都要来得真实,也容易加深理解。

回头想一想我们上面说的原理,我们要做的事情有几件:

1. 把网卡置于混杂模式。 2. 捕获数据包。 3. 分析资料包。

注:下面的源代码取至Chad Renfro的<< Basic Packet-Sniffer Construction from the Ground Up>>一文中

/************************Tcp_sniff_2.c********************/ 
1.#include 
2.#include 
3.#include 
4.#include 
5.#include 
6.#include 
7.#include 
8.#include 
9.#include "headers.h" 
#define INTERFACE "eth0" 
/*Prototype area*/ 
10.int Open_Raw_Socket(void); 
11.int Set_Promisc(char *interface, int sock); 
12.int main() { 
13.int sock, bytes_recieved, fromlen; 
14.char buffer[65535]; 
15.struct sockaddr_in from; 
16.struct ip *ip; 
17.struct tcp *tcp; 
18.sock = Open_Raw_Socket(); 
19. Set_Promisc(INTERFACE, sock); 
20. while(1) 
22. { 
23. fromlen = sizeof from; 
24. bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen); 
25. printf("\nBytes received ::: %5d\n",bytes_recieved); 
26. printf("Source address ::: %s\n",inet_ntoa(from.sin_addr)); 
27. ip = (struct ip *)buffer; 
/*See if this is a TCP packet*/ 
28. if(ip->ip_protocol == 6) { 
29. printf("IP header length ::: %d\n",ip->ip_length); 
30. printf("Protocol ::: %d\n",ip->ip_protocol); 
31. tcp = (struct tcp *)(buffer + (4*ip->ip_length)); 
32. printf("Source port ::: %d\n",ntohs(tcp->tcp_source_port)); 
33. printf("Dest port ::: %d\n",ntohs(tcp->tcp_dest_port)); 
34. } 
35. } 
36.} 
37.int Open_Raw_Socket() { 
38. int sock; 
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { 
/*Then the socket was not created properly and must die*/ 
40. perror("The raw socket was not created"); 
41. exit(0); 
42. }; 
43. return(sock); 
44. } 
45.int Set_Promisc(char *interface, int sock ) { 
46. struct ifreq ifr; 
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); 
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { 
/*Could not retrieve flags for the interface*/ 
49. perror("Could not retrive flags for the interface"); 
50. exit(0); 
51. } 
52. printf("The interface is ::: %s\n", interface); 
53. perror("Retrieved flags from interface successfully"); 
54. ifr.ifr_flags |= IFF_PROMISC; 
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) { 
/*Could not set the flags on the interface */ 
56. perror("Could not set the PROMISC flag:"); 
57. exit(0); 
58. } 
59. printf("Setting interface ::: %s ::: to promisc", interface); 
60. return(0); 
61. } 
/***********************EOF**********************************/


上面这段程序中有很详细的注解,不过我想还是有必要说一说,首先

第10行--int Open_Raw_Socket(void); 是我们的自定义函数,具体内容如下:

37.int Open_Raw_Socket() { 
38. int sock; 
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { 
/*Then the socket was not created properly and must die*/ 
40. perror("The raw socket was not created"); 
41. exit(0); 
42. }; 
43. return(sock); 
44. }


第39行 if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {

这里我们调用了socket函数,使创建了了一个原始套接口,使之收到TCP/IP信息包。

接下来第11行-int Set_Promisc(char *interface, int sock),这也是我们的自定义函数,目的是把网卡置于混杂模式,具体内容如下:

45.int Set_Promisc(char *interface, int sock ) { 
46. struct ifreq ifr; 
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); 
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { 
/*Could not retrieve flags for the interface*/ 
49. perror("Could not retrive flags for the interface"); 
50. exit(0); 
51. } 
52. printf("The interface is ::: %s\n", interface); 
53. perror("Retrieved flags from interface successfully"); 
54. ifr.ifr_flags |= IFF_PROMISC; 
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) { 
/*Could not set the flags on the interface */ 
56. perror("Could not set the PROMISC flag:"); 
57. exit(0); 
58. } 
59. printf("Setting interface ::: %s ::: to promisc", interface); 
60. return(0); 
61. }


首先 struct ifreq ifr;定一了一个ifrreg的结构ifr,接下来strncpy(ifr.ifr_name, interface,strnlen(interface)+1);,就是把我们网络设备的名字填充到ifr结构中,在这里 #define INTERFACE "eth0" ,让我们再往下看,

ioctl(sock, SIOCGIFFLAGS, &ifr),SIOCGIFFLAGS请求表示需要获取接口标志,现在到了第54行,在我们成功的获取接口标志后把他设置成混杂模式,

ifr.ifr_flags |= IFF_PROMISC;ioctl (sock, SIOCSIFFLAGS, &ifr)。OK,现在我们所说的第一步已经完成--------把网卡置于混杂模式。

现在进入第二步,捕获资料包。从第20行开始,我们进入了一个死循环,while(1),在

第24行,recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen),这个函数要做的就是接收数据,冰把接收到的资料放入buffer中。就是这么简单,已经完成了我 们要捕获资料包的任务。

到了第三步,分析资料包。27行,ip = (struct ip *)buffer,使我们在头档中的IP结构对应于所接收到的资料,接下来判断在网络层中是否使用的是TCP协议,if(ip->ip_protocol == 6) ,如果答案是,tcp信息包从整个IP/TCP包 buffer + (4*ip->ip_length) 地址处开始,所以31行 tcp = (struct tcp *)(buffer + (4*ip->ip_length)),然后对应结构把你所需要的信息输出。

/*************************headers.h**************************/ 
/*structure of an ip header*/ 
struct ip { 
unsigned int ip_length:4; /*little-endian*/ 
unsigned int ip_version:4; 
unsigned char ip_tos; 
unsigned short ip_total_length; 
unsigned short ip_id; 
unsigned short ip_flags; 
unsigned char ip_ttl; 
unsigned char ip_protocol; 
unsigned short ip_cksum; 
unsigned int ip_source; unsigned int ip_dest; 
}; 
/* Structure of a TCP header */ 
struct tcp { 
unsigned short tcp_source_port; 
unsigned short tcp_dest_port; 
unsigned int tcp_seqno; 
unsigned int tcp_ackno; 
unsigned int tcp_res1:4, /*little-endian*/ 
tcp_hlen:4, 
tcp_fin:1, 
tcp_syn:1, 
tcp_rst:1, 
tcp_psh:1, 
tcp_ack:1, 
tcp_urg:1, 
tcp_res2:2; 
unsigned short tcp_winsize; 
unsigned short tcp_cksum; 
unsigned short tcp_urgent; 
};


/*********************EOF***********************************/

从上面的分析我们可以清楚的认识到,认识一个SNIFF需要对TCP/IP协议有着详细的了解,否则你根本无法找到你需要的信息。有了上面的基础,你可以自己来做一个你需要的SNIFF了。

[本文共有 2 页,当前是第 1 页] <<上一页 下一页>>

OVER

[1] [2] 页 RedHyphone.Union 投稿邮箱
[特别声明]:
本站文章大多搜索转载自网络中,如果侵犯了您的权利,请告之我们。本站将立即删除。
本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
查看评论】【向上滚屏】【关闭窗口】【 打印
-相关文章
  • 认知盲区 解惑双网卡双线路DNS解析
  • FlashFXP 简体中文版 3.7.5 Build 1303 Beta[烈火]
  • 确认:番茄花园作者洪磊被检察院批准逮捕
  • 1983年的今天 DNS诞生
  • Windows 2003 IIS 6.0搭建asp+.net+php+jsp+mysql+mssql
  • -文章评论 (关闭)
    ·还没有相关的评论!

    网上大名:
    红旋风网络技术联盟 RHUTech.Union
     
    Copyright © 2000-2007 RedHyphone.Union All Rights Reserved. 红旋风联盟版权所有.皖ICP备05011033号
    中国红旋风网络技术联盟 | www.RedHyphone.net
    Mailto:Redhyphone@gamil.com