网络ping源代码注有详细注释Word格式文档下载.doc
《网络ping源代码注有详细注释Word格式文档下载.doc》由会员分享,可在线阅读,更多相关《网络ping源代码注有详细注释Word格式文档下载.doc(6页珍藏版)》请在冰点文库上搜索。
//3位标志位
unsignedcharttl;
//8位生存时间TTL
unsignedcharproto;
//8位协议(TCP,UDP或其他)
unsignedshortchecksum;
//16位IP首部校验和
unsignedintsourceIP;
//32位源IP地址
unsignedintdestIP;
//32位目的IP地址
}IpHeader;
//定义ICMP首位
/************************************************
//主程序入口
************************************************/
typedefstruct_ihdr{
BYTEi_type;
//8位类型
BYTEi_code;
//8位代码
USHORTi_cksum;
//16位校验和
USHORTi_id;
//识别号(一般用进程号作为识别号)
USHORTi_seq;
//报文序列号
ULONGtimestamp;
//时间戳
}IcmpHeader;
#defineSTATUS_FAILED0xFFFF
#defineDEF_PACKET_SIZE32//包的大小
#defineMAX_PACKET1024//最大ICMP包长度
#definexmalloc(s)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
#definexfree(p)HeapFree(GetProcessHeap(),0,(p))
voidfill_icmp_data(char*,int);
//填补数据
USHORTchecksum(USHORT*,int);
//校验数据
voiddecode_resp(char*,int,structsockaddr_in*);
voidUsage(char*progname){
fprintf(stderr,"
Usage:
\n"
);
//传送格式化数据
fprintf(stderr,"
%s<
host>
[data_size]\n"
progname);
datasizecanbeupto1Kb\n"
ExitProcess(STATUS_FAILED);
}
intmain(intargc,char**argv){//初始化套接字
WSADATAwsaData;
SOCKETsockRaw;
structsockaddr_indest,from;
structhostent*hp;
intbread,datasize;
//定义bread,datasize
intfromlen=sizeof(from);
inttimeout=1000;
//等待每次回复的超时时间,默认1秒
char*dest_ip;
//发送IP地址
char*icmp_data;
char*recvbuf;
unsignedintaddr=0;
//初始化地址
USHORTseq_no=0;
//序列号初始化
if(WSAStartup(MAKEWORD(2,1),&
wsaData)!
=0){//初始化函数
fprintf(stderr,"
WSAStartupfailed:
%d\n"
GetLastError());
//设置显示
ExitProcess(STATUS_FAILED);
//退出
}
if(argc<
2){//残数个数小于2,即执行
Usage(argv[0]);
//调用函数argv
sockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,0);
//创建数据库
if(sockRaw==INVALID_SOCKET){//检查套接是否合法
WSASocket()failed:
WSAGetLastError());
//退出
bread=setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&
timeout,sizeof(timeout));
//设置超时时间
if(bread==SOCKET_ERROR)//检查设置选项是否失败
{
failedtosetrecvtimeout:
timeout=1000;
//时间输出为1000
memset(&
dest,0,sizeof(dest));
//给最大内存清零
hp=gethostbyname(argv[1]);
//函数调用
if(!
hp)//域名解析
addr=inet_addr(argv[1]);
//得到域名的数值地址
if((!
hp)&
&
(addr==INADDR_NONE))//域名储出错,比如不能获取、域名不对
{
Unabletoresolve%s\n"
argv[1]);
//输出
//退出
}
if(hp!
=NULL)//判断是否有IP地址
memcpy(&
(dest.sin_addr),hp->
h_addr,hp->
h_length);
else
dest.sin_addr.s_addr=addr;
//给目标地址
if(hp)
dest.sin_family=hp->
h_addrtype;
//目标地址赋值
dest.sin_family=AF_INET;
//目标地址赋值
dest_ip=inet_ntoa(dest.sin_addr);
//传送IP地址
if(argc>
2){//判断argc是否大于2
datasize=atoi(argv[2]);
if(datasize==0)//判断datasize
datasize=DEF_PACKET_SIZE;
//赋值
datasize=DEF_PACKET_SIZE;
datasize+=sizeof(IcmpHeader);
icmp_data=(char*)malloc(MAX_PACKET);
//调用最大内存char型强制转换
recvbuf=(char*)malloc(MAX_PACKET);
if(!
icmp_data){//检查指针是否有效
HeapAllocfailed%d\n"
ExitProcess(STATUS_FAILED);
}
memset(icmp_data,0,MAX_PACKET);
fill_icmp_data(icmp_data,datasize);
while
(1){//ICMP打包
intbwrote;
//定义bwrote
((IcmpHeader*)icmp_data)->
i_cksum=0;
//校验盒
((IcmpHeader*)icmp_data)->
timestamp=GetTickCount();
//时间戳
i_seq=seq_no++;
//序列号
i_cksum=checksum((USHORT*)icmp_data,datasize);
//校验盒
bwrote=sendto(sockRaw,icmp_data,datasize,0,(structsockaddr*)&
dest,sizeof(dest));
//发送
if(bwrote==SOCKET_ERROR){//判断发送是不是失败了
if(WSAGetLastError()==WSAETIMEDOUT){//判断失败的是不是WSAETIMEDOUT
printf("
timedout\n"
//输出timedout\n
continue;
//结束这个判断
}
fprintf(stderr,"
sendtofailed:
//输出,WSAGetLastError()是获取错误的代码
ExitProcess(STATUS_FAILED);
}
if(bwrote<
datasize){//判断发送缓冲区的大小
fprintf(stdout,"
Wrote%dbytes\n"
bwrote);
//输出大小
bread=recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(structsockaddr*)&
from,&
fromlen);
//接送报文的大小
if(bread==SOCKET_ERROR){//判断报文的是不是带有SOCKET_ERROR
if(WSAGetLastError()==WSAETIMEDOUT){//判断WSAETIMEDOUT
//输出timedout\n
//结束if
recvfromfailed:
//输出
//退出
decode_resp(recvbuf,bread,&
from);
//recvbuf为8位
Sleep(1000);
}
return0;
//返回
voiddecode_resp(char*buf,intbytes,structsockaddr_in*from){//定义报头及各个含义
IpHeader*iphdr;
//定义IP报头
IcmpHeader*icmphdr;
//定义ICMP报头
unsignedshortiphdrlen;
iphdr=(IpHeader*)buf;
//IP首部的地址就等于buf的地址
iphdrlen=iphdr->
h_len*4;
//因为h_len是32位word,要转换成bytes必须*
if(bytes<
iphdrlen+ICMP_MIN){//判断iphdrlen+ICMP_MIN相加后的大小与bytes
printf("
Toofewbytesfrom%s\n"
inet_ntoa(from->
sin_addr));
//取出源地址
icmphdr=(IcmpHeader*)(buf+iphdrlen);
//ICMP首部的地址等于IP首部长加buf
if(icmphdr->
i_type!
=ICMP_ECHOREPLY){
non-echotype%drecvd\n"
icmphdr->
i_type);
//设置接收超时
return;
//结束,返回
if(icmphdr->
i_id!
=(USHORT)GetCurrentProcessId()){
fprintf(stderr,"
someoneelse'
spacket!
//设置发送超时
return;
/*printf("
%dbytesfrom%s:
"
bytes,inet_ntoa(from->
//取出源地址
printf("
icmp_id=%d."
icmp_seq=%d."
i_seq);
//取出序列号
time:
%dms"
GetTickCount()-icmphdr->
timestamp);
printf("
*/
%dbytesfrom%s:
"
bytes,inet_ntoa(from->
sin_addr));
icmp_id=%d."
i_id);
//取出进程号
icmp_seq=%d."
i_seq);
//取出序列号
icmp_type=%d"
i_type);
//取出类型
icmp_code=%d"
i_code);
//取出代码
USHORTchecksum(USHORT*buffer,intsize){//ICMP数组的构建
unsignedlongcksum=0;
while(size>
1){//判断大小
cksum+=*buffer++;
//两位校验盒相加
size-=sizeof(USHORT);
}
if(size)//如果是奇数值,那么再加上,不是,就不执行
cksum+=*(UCHAR*)buffer;
//如果是奇数值,那么再加上,不是,就不执行
cksum=(cksum&
16)+(cksum&
0xffff);
//高4位和低四位相加
cksum+=(cksum&
16);
//跟自己高4位相加
return(USHORT)(~cksum);
//返回cksum校验盒的数据
//在ICMP的要求下,使用函数填写
voidfill_icmp_data(char*icmp_data,intdatasize)
{
IcmpHeader*icmp_hdr;
char*datapart;
//定义datapart型指针
icmp_hdr=(IcmpHeader*)icmp_data;
icmp_hdr->
i_type=ICMP_ECHO;
//类型为ICMP_ECHOREPLY
i_code=0;
i_id=(USHORT)GetCurrentProcessId();
//识别号为进程号
//校验和初始化
i_seq=0;
//序列号初始化
datapart=icmp_data+sizeof(IcmpHeader);
//数据端的地址为icmp报文地址加上ICMP的首部长度
memset(datapart,'
E'
datasize-sizeof(IcmpHeader));
//这里我填充的数据全部为"
A"
,你能填充所有代码和数据,实际上木马和控制端之间就是通过数据段传递数据的
}