天津理工大学
计算机与通信工程学院
实验报告
2015 至 2016 学年 第 一 学期
实验目的:了解网络攻防中软件开发的一般方法。
实验方式:采用某种高级语言进行网络攻防软件的设计。
实验要求:以下题目选一个或多个并编程实现。
(1)网络扫描器的设计。(主机扫描、端口扫描、操作系统探测、漏洞扫描)
(2)网络嗅探器的设计。
(3)远程控制软件的设计与实现。
(4)防火墙的设计与实现。
报告中包括程序原理、功能模块图及文字介绍、流程图、源代码(带注释),运行过程。
实验设备:PC机
实验分组:2人/组
完成时间:2学时
实验内容:
网络嗅探器的设计
嗅探器的设计原理:
嗅探器作为一种网络通讯程序,也是通过对网卡的编程来实现网络通讯的,对网卡的编程也是使用通常的套接字(socket)方式来进行。但是,通常的套接字程序只能响应与自己硬件地址相匹配的或是以广播形式发出的数据帧,对于其他形式的数据帧比如已到达网络接口但却不是发给此地址的数据帧,网络接口在验证投递地址并非自身地址之后将不引起响应,也就是说应用程序无法收取到达的数据包。而网络嗅探器的目的恰恰在于从网卡接收所有经过它的数据包,这些数据包即可以是发给它的也可以是发往别处的。显然,要达到此目的就不能再让网卡按通常的正常模式工作,而必须将其设置为混杂模式。
网络技术与设备简介及监听原理:
数据在网络上是以很小的称为帧(Frame)的单位传输的,帧由几部分组成,不同的部分执行不同的功能。帧通过特定的称为网络驱动程序的软件进行成型,然后通过网卡发送到网线上,通过网线到达它们的目的机器,在目的机器的一端执行相反的过程。接收端机器的以太网卡捕获到这些帧,并告诉操作系统帧已到达,然后对其进行存储。就是在这个传输和接收的过程中,存在安全方面的问题。
每一个在局域网(LAN)上的工作站都有其硬件地址,这些地址惟一地表示了网络上的机器。当用户发送一个数据包时,这些数据包就会发送到LAN上所有可用的机器。在一般情况下,网络上所有的机器都可以“听”到通过的流量,但对不属于自己的数据包则不予响应(如果某个工作站的网络接口处于混杂模式,那么它就可以捕获网络上所有的数据包和帧。
Sniffor程序是一种利用以太网的特性把网络适配卡(NIC,一般为以太网卡)置为(promiscuous)模式状态的工具,一旦网卡设置为这种模式,它就能接收传输在网络上的每一个信息包。普通的情况下,网卡只接收和自己的地址有关的信息包,即传输到本地主机的信息包。要使Sniffer
能接收并处理这种方式的信息,系统需要支持BPF,Linux下需要支持SOCKET-PACKET。但一般情况下,网络硬件和TCP/IP堆栈不支持接收或者发送与本地计算机无关的数据包,所以,为了绕过标准的TCP/IP堆栈,网卡就必须设置为混杂模式。一般情况下,要激活这种方式,内核必须支持这种伪设备BPFilter,而且需要root权限来运行这种程序,所以Sniffer需要root身份安装,如果只是以本地用户的身份进入了系统,那么不可能嗅探到root的密码,因为不能运行Sniffer。基于Sniffer这样的模式,可以分析各种信息包并描述出网络的结构和使用的机器,由于它接收任何一个在同一网段上传输的数据包,所以也就存在着捕获密码、各种信息、秘密文档等一些没有加密的信息的可能性。这成为黑客们常用的扩大战果的方法,用来夺取其他主机的控制权。
网络嗅探器源代码及其说明:
#include <winsock2.h>
/*windows socket
的头文件,系统
定义的
*/
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib,"ws2_32.lib")
/*
链接API相关连的Ws2_32.lib静态库
*/
#define MAX_HOSTNAME_LAN 255
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define MAX_ADDR_LEN 16
struct ipheader {
unsigned char ip_hl:4; /*header length(报头长度)*/
unsigned char ip_v:4; /*version(版本)*/
unsigned char ip_tos; /*type os service服务类型*/
unsigned short int ip_len; /*total length (总长度)*/
unsigned short int ip_id; /*identification (标识符)*/
unsigned short int ip_off; /*fragment offset field(段移位 域)*/
unsigned char ip_ttl; /*time to live (生存时间)*/
unsigned char ip_p; /*protocol(协议)*/
unsigned short int ip_sum; /*checksum(校验和)*/
unsigned int ip_src; /*source address(源地址)*/
unsigned int ip_dst; /*destination address(目的地址)*/
};
/* total ip header length: 20 bytes (=160 bits) */
typedef struct tcpheader {
unsigned short int sport;/*source port (源端口号)*/
unsigned short int dport; /*destination port(目的端口号)*/
unsigned int th_seq; /*sequence number(包的序列号)*/
unsigned int th_ack; /*acknowledgement number(确认应答号)*/
unsigned char th_x:4; /*unused(未使用)*/
unsigned char th_off:4; /*data offset(数据偏移量)*/
unsigned char Flags; /*标志全*/
unsigned short int th_win; /*windows(窗口)*/
unsigned short int th_sum; /*checksum(校验和)*/
unsigned short int th_urp; /*urgent pointer紧急指针)*/
}TCP_HDR;
typedef struct udphdr {
unsigned short sport; /*source port(源端口号)*/
unsigned short dport; /*destination port(目的端口号)*/
unsigned short len; /*udp length(udp长度)*/
unsigned short cksum; /*udp checksum(udp校验和)*/
}UDP_HDR;
void main(){
SOCKET sock;
WSADATA wsd;
DWORD dwBytesRet;
unsigned int optval = 1;
unsigned char *dataudp,*datatcp;
int i,pCount=0,lentcp, lenudp;
SOCKADDR_IN sa,saSource, saDest;
struct hostent FAR * pHostent;
char FAR name[MAX_HOSTNAME_LAN];
char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN],RecvBuf[65535] = {0};
struct udphdr *pUdpheader;
struct ipheader *pIpheader;
struct tcpheader *pTcpheader;
WSAStartup(MAKEWORD(2,1),&wsd);
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP))==SOCKET_ERROR)
exit(1);
gethostname(name, MAX_HOSTNAME_LAN);
pHostent = gethostbyname(name);
sa.sin_family = AF_INET;
sa.sin_port = htons(6000);
memcpy(&sa.sin_addr.S_un.S_addr,
pHostent->h_addr_list[0],
pHostent->h_length);
bind(sock, (SOCKADDR *)&sa, sizeof(sa)); /*bind()设定自己主机的IP地址和端口号*/
if ((WSAGetLastError())==10013)
exit(1);
WSAIoctl(sock, SIO_RCVALL, &optval, sizeof(optval), NULL, 0, &dwBytesRet, NULL,NULL); pIpheader = (struct ipheader *)RecvBuf;
pTcpheader = (struct tcpheader *)(RecvBuf+ sizeof(struct ipheader ));
pUdpheader = (struct udphdr *) (RecvBuf+ sizeof(struct ipheader ));
while (1){
memset(RecvBuf, 0, sizeof(RecvBuf));
recv(sock, RecvBuf, sizeof(RecvBuf), 0);
saSource.sin_addr.s_addr = pIpheader->ip_src;
strncpy(szSourceIP,
inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);
saDest.sin_addr.s_addr = pIpheader->ip_dst;
strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);
lentcp =(ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(structtcpheader))); lenudp =(ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct udphdr)));
if((pIpheader->ip_p)==IPPROTO_TCP&&lentcp!=0){
printf("*******************************************\n");
pCount++;
datatcp=(unsigned char*) RecvBuf+sizeof(struct ipheader)+sizeof(struct tcpheader);
printf("-TCP-\n");
printf("\n目的IP地址:%s\n",szDestIP); printf("\n目的端口:%i\n",ntohs(pTcpheader>dport));
printf("datatcp address->%x\n",datatcp);
printf("size of ipheader->%i\n",sizeof(struct ipheader));
printf("size of tcpheader->%i\n",sizeof(struct tcpheader));
printf("size of the hole packet->%i\n",ntohs(pIpheader->ip_len));
printf("\nchar Packet%i [%i]=\"",pCount,lentcp-1);
for (i=0;i<lentcp;i++){
printf("\\x%.2x",*(datatcp+i));
if (i%10==0)
printf("\"\n\"");
}
printf("\";\n\n\n");
for (i=0;i<lentcp;i++){
if( *(datatcp+i)<=127&&*(datatcp+i)>=20)
printf("%c",*(datatcp+i));
else
printf(".");
}
printf("\n\n*******************************************\n");
}
if((pIpheader->ip_p)==IPPROTO_UDP&&lentcp!=0){
pCount++;
dataudp=(unsigned char *) RecvBuf+sizeof(struct ipheader)+sizeof(struct udphdr);
printf("-UDP-\n");
printf("\n目的IP地址:%s\n",szDestIP);
printf("\n目的端口:%d\n",ntohs(pTcpheader->dport));
printf("UDP数据地址:%x\n",dataudp);
printf("IP头部长度:%i\n",sizeof(struct ipheader));
printf("UDP头部长度:%i\n",sizeof(struct udphdr));
printf("包的大小:%i\n",ntohs(pIpheader->ip_len));
printf("\nchar Packet%i [%i]=\"",pCount,lenudp-1);
for (i=0;i<lenudp;i++){
printf("\\x%.2x",*(dataudp+i));
if (i%10==0)
printf("\"\n\"");
}
printf("\";\n\n\n");
for (i=0;i<lenudp;i++){
if( *(dataudp+i)<=127&&*(dataudp+i)>=20)
printf("%c",*(dataudp+i));
else
printf(".");
}
printf("\n\n*******************************************\n");
}
}
}
嗅探器运行状况分析:
嗅探器抓包包括目的IP地址、目的端口、数据地址、头部长度和包的大小,以及包内的具体信息!大致情况如下图:
实验二是嗅探工具的使用,编程部分参考了网络资料。实验过程比较简单,理解并掌握了嗅探工具的原理。