1 引题
这里提出一个概念:什么是主机扫描?主机扫描顾名思义就是扫描
网络中存在的主机。那怎么扫描特定的主机是否存在呢?答案就是通过发送ICMP协议包来确定。那什么是ICMP包呢?
我打个不恰当的比方,ICMP包就好比邮局的快递,你要扫描一个主机是否存在,就向这个主机的地址(IP)发一个快递,不管是否投递成功,邮局都会通知
你。那么你就知道该网络地址是否存在了。那么邮局的回单,我要如何分析才能知道对方的信息呢?那么我们就要来分析ICMP这个‘快递’包的投送回单。
具体的结构解释我就不多说了,网上很多,可以自己查阅
在Linux中ICMP
数据结构()定义如下:
struct icmp
{
u_int8_t icmp_type; /* type of message, see below */
u_int8_t icmp_code; /* type sub code */
u_int16_t icmp_cksum; /* ones complement checksum of struct */
union
{
u_char ih_
pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* gateway address */
struct ih_idseq /* echo datagram */
{
u_int16_t icd_id;
u_int16_t icd_seq;
} ih_idseq;
u_int32_t ih_void;
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu
{
u_int16_t ipm_void;
u_int16_t ipm_nextmtu;
} ih_pmtu;
struct ih_rtradv
{
u_int8_t irt_num_addrs;
u_int8_t irt_wpa;
u_int16_t irt_lifetime;
} ih_rtradv;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
union
{
struct
{
u_int32_t its_otime;
u_int32_t its_rtime;
u_int32_t its_ttime;
} id_ts;
struct
{
struct ip idi_ip;
/* options and then 64 bits of data */
} id_ip;
struct icmp_ra_addr id_radv;
u_int32_t id_mask;
u_int8_t id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
};
那么现在的问题我们怎么自己组装ICMP包,也就是我们的包裹呢?答案在下面
void make_icmp_packet(struct icmp *icmp,int len,int n)
{
memset((char *)icmp,0,len);
gettimeofday((struct timeval*)(icmp->icmp_data),(struct timezone*)0 );
//生成ICMP报头
icmp->icmp_type=ICMP_ECHO;
icmp->icmp_code=0;
icmp->icmp_id=getpid();
icmp->icmp_seq=n;
//icmp->icmp_cksum=0;//进行检查和,要或不要均可
icmp->icmp_cksum=checksum((u_short*)icmp,len);
}
这里有一个校验和的程序,我在网上down了一个,大家就这么用好了
u_short checksum(u_short *data,int len)
{
u_long sum=0;
for(;len>1;len-=2)
{
sum+=*data++;
if(sum & 0x80000000)
sum=(sum & 0xffff)+(sum>>16);
}
if(len==1)
{
u_short i=0;
*(u_char*)(&i)=*(u_char*)data;
sum+=i;
}
while(sum>>16)
{
sum=(sum & 0xffff)+(sum>>16);
}
return (sum==0xffff)?sum:~sum;
}
需要扫描,那么自然需要一个定时器,做超时控制
void tvsub(struct timeval* out,struct timeval *in)
{
out->tv_sec-=in->tv_sec;
}
好了,一切就绪,我们现在可以开始我们的主机扫描之旅了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PACK_LEN 72
#define BUFSIZE 4096
int main(int argc, char *argv[])
{
struct sockaddr_in send_sa;
//struct s;
int i=0,j=0;
int scan_icmp_socket;
char send_buff[PACK_LEN];
char recv_buff[BUFSIZE];
struct in_addr start_addr,end_addr;
struct timeval tv;
fd_set readfd_set;
struct ip *ip;
struct icmp *icmp;
int hlen; //报头 长度
send_sa.sin_family=AF_INET;
scan_icmp_socket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if (scan_icmp_socketip_hlip_src.s_addr==send_sa.sin_addr.s_addr)
{
icmp=(struct icmp*)(recv_buff+hlen);
//解析icmp包内容信息
if (icmp->icmp_type==ICMP_ECHOREPLY)
{
printf("%-15s",inet_ntoa( *(struct in_addr*)
&(ip->ip_src.s_addr)));
//获得当前
系统时间后与ICMP包内的数据内容对比
gettimeofday(&tv,NULL);
tvsub(&tv,(struct timeval*) (icmp->icmp_data));
printf(":RTT=%8.4f ms\n",tv.tv_sec+tv.tv_usec/1000.0);
break;
}
else
{
printf("ICMP STATE:%d\n",icmp->icmp_type);
}
}
}
}
}
close(scan_icmp_socket);
return 0;
}
至此,我们主机扫描的原理和实现已经讲完了,那么主机扫描有什么用?
没错,主机是否可到达是网络安全测试的第一步内容。而且,每次有人发送ICMP包,你的电脑都
要应答。如果很多人同时发送ICMP包达到你的电脑,也就是说邮局同时送来了1000个包裹,你可能就有些应付不了了吧。这时候的状态就是你的电脑上网很
卡很卡,或者根本上不了。那么我们怎么防范ICMP攻击呢,或者我不想别人知道我的电脑到底在不在上网?很简单,装个防火墙,将拒绝ICMP勾选上就可以
了。
其实说了半天,ICMP多半用来DOS攻击,这种攻击多半基于单机,带宽小,效率低,对于被扫描者不会造成很大的危害。然后,目前的网络攻击多半是类似
云计算的形式,当成千上万的肉鸡向你发动攻击的时候,那可不是好玩的。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103065/showart_2021565.html网络数据包监控程序IpMon_2k源码如下:
|
文件: | ipMon_zw_2K.zip |
大小: | 127KB |
下载: | 下载 |
|