设为首页 收藏本站 English

当前位置: 海南体育网 >> 电竞

基于Linux环境下的Sniffer设计

发布时间:2020-06-15 04:59:32

一、Sniffer原理分析 aOhoAAWd

yr#SaG

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

gi;Iya~D

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

%8=e Y}g

TCP协议在IP协议之上如果一个站全部是采集或复制别人的内容。与IP协议提供不可靠传输服务不同的是,TCP协议为其上的应用层提供了一种可靠传输服务。这种服务的特点是:可靠、全双工、流式和无结构传输。TCP传输原理: J;,mSBZ=

@t(G*Srg

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

$\~WF$.

这种方法还产生了一个问题,就是包的重复。如果络传输速度比较低,等到等待时间结束后,确认消息才返回到发送者,那么,由于发送者采用的发送方法,就会出现重复的数据了。解决的一个办法是给每个数据一个序列号,并需要发送者记住哪个序列号的数据已经确认了。为了防止由于延时或重复确认,规定确认消息里也要包含确认序列号。从而发送者就能知道哪个包已经确认了。TCP协议中还有一个重要的概念:滑动窗口。这一方法的使用,使得传输更加高效。 $^0eiW

;+ }d'O

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

k ]E1@q

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

sRVXe+

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

2FO,io _

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

Mx_w'xk7

o9)6V3

_]|gw.j9

socket() 6TXu0Ip

#include sys/types.h } n_Zz6R

#include sys/socket.h o\:u7W?

int socket(int family, int type, int protocol); H t Y[

int family参数指定所要使用的通信协议,取以下几个值: o;93oO_f

pE#N2 

AF_UNIX Unix内部协议 mN10jT(

AF_INET Internet协议 /*":J\C*

AF_NS Xerox NS协议 k:FjwYK

AF_IMPLINK IMP 连接层 =O@=. /

int type 指定套接字的类型,取以下几个值 : jLe)\5%

SOCK_STREAM 流套接字 7  4O 

SOCK_DGRAM 数据报套接字 LpVA8'

SOCK_RAW 未加工套接字 uu1z:{]~E

SOCK_SEQPACKET 顺序包套接字 S]3,$MC

int protocol 参数通常设置为0。 h =u5n5V

m9v0# j

a {=~Eve

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

^x(0rhA~f

二、Sniffer具体实现 :7?6Hd]i:T

;-|hg-

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

#nPR)MuP

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

z*V@_`

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

e-q3FE 

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

d3RIGp[$

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

wj.w7W

它们在头文件中的定义如下: M-Dpl=_

Ta2CI|043

JgmrV [K

u(S .kC

FtcI{ zp

struct ethhdr "@9TkS:SB@

{ jpvKt]Y

unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ 6UyF:Y*

unsigned char h_source[ETH_ALEN]; /* source ether addr */ /8A79HC

unsigned short h_proto; /* packet type ID field */ $b @N:}

}; 'rG O2X

struct iphdr M;ObN|('

{ kz 0 N6/

#if __BYTE_ORDER == __LITTLE_ENDIAN Z3n5C,j

u_int8_t ihl:4; @N|JY"Nq?a

u_int8_t version:4; d3-]fT~

#elif __BYTE_ORDER == __BIG_ENDIAN FqGW9x,

u_int8_t version:4; bQh$\m l*

u_int8_t ihl:4; jqV}'|Snz

#else PulyCb*

#error "Please fix bytesex.h" Cc5Xp K'?

#endif a1sBN"u

u_int8_t tos; +7}w-5`

u_int16_t tot_len; )SINu_/8

u_int16_t id; bA!mS.t4

u_int16_t frag_off; X$^ j

u_int8_t ttl; sjVsZe$

u_int8_t protocol; lK|U9 T^

u_int16_t check; Y|z3v

u_int32_t saddr; %gXJGN;2F-

u_int32_t daddr; :y+/~FL

/*The options start here. */  ah]LHM`

}; 6yFYVKf

struct tcphdr ajzk{c;

{ FU.2Rxd

u_int16_t source; 'OP6O**0

u_int16_t dest; /B|NRO3'

u_int32_t seq; Td M+8tgnu

u_int32_t ack_seq; k5V@t,w3l

#if __BYTE_ORDER == __LITTLE_ENDIAN C|g1$U "5

u_int16_t res1:4; GmaKp ~|

u_int16_t doff:4; $8hK2W?uP

u_int16_t fin:1; #!TrPP BW

u_int16_t syn:1; 8t*b4#u"

u_int16_t rst:1; iI="(T

u_int16_t psh:1; @]Ev\k

u_int16_t ack:1; E~=nDH;U

u_int16_t urg:1; ZEd_+a%

u_int16_t res2:2; C5aj^u^31

#elif __BYTE_ORDER == __BIG_ENDIAN **cD w*

u_int16_t doff:4; ^$pX{ .W

u_int16_t res1:4; 9z [FIQ

u_int16_t res2:2; BEoP~mQ

u_int16_t urg:1; _Q(,Yo\4M]

u_int16_t ack:1; | lWP7tEc

u_int16_t psh:1; o-w?bFOKCF

u_int16_t rst:1; l1Na9x/`

u_int16_t syn:1; =Krx

u_int16_t fin:1; )ae`=eY23

#else _d$Ca l%xQ

#error "Adjust your bits/endian.h defines" Rp}+6g!

#endif B,.r!$X.;A

u_int16_t window; h '1Yel

u_int16_t check; X_m7O=vI

u_int16_t urg_ptr; k%E-0@7

}; " \40-WX

M|Y@s/:N

Ht[fPj("

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

B)@E[rOV

~LjI*pG

_f\#' D

struct ifreq @e=2DR.{I

{ vL\MqAg32

#define IFHWADDRLEN 6 juV@a S-xM

#define IFNAMSIZ 16 !=ddcQe)

union OFA\*'g}

{ -SRFU

char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ B{*1n gz'

} ifr_ifrn; .vw*l}lH

union ITU~F`k

{ \* 6hiZt

struct sockaddr ifru_addr; {o/ n

struct sockaddr ifru_dstaddr; O%Z j^mH

struct sockaddr ifru_broadaddr; qVtFh8

struct sockaddr ifru_netmask; 7Frp9'U.

struct sockaddr ifru_hwaddr; ]7Z[jD?l

short int ifru_flags; ~WNO/5

int ifru_ivalue; 5(x\s3 

int ifru_mtu; 0\/^TasVi}

struct ifmap ifru_map; hz NdsP+

char ifru_slave[IFNAMSIZ]; /* Just fits the size */ c[G?K\ iA

__caddr_t ifru_data; t"#r9(Z

} ifr_ifru; Y\XIBIAW

}; *{tb80iW

6mG1 `0

Q" )f-`H

[7ve4gKZ

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

nW {fHnCQa

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

1jC^w8

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

NFWsX9A

三、运行结果及结论 /kQX7iP8

|E+ kz\;

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

瘦身成功后如何保持
小孩不爱吃饭原因
呼和浩特哪家医院治疗白癜风
友情链接