要求的专业知识:
一: 精通OSI参考模型,精通网络五层:物理层,数据链路层,网络层,传输层,应用层。
精通每一层的协议,数据报格式。精通网络拓扑结构,第一层,第二层,第三层的网
络互联,数据的转发和路由等。
二: 精通C语言程序设计,UNIX/LINUX程序设计,网络程序设计。熟悉UNIX/LINUX系
统操作,熟悉著名服务的基本配置,特性及使用的端口号。熟悉经典网络命令的使用,
如:netstat,ping,traceroute,netcat,arp等。
三: 精通标准SQL语言,熟悉流行的数据库使用,如:Oracle,Mysql等。掌握数据库与
WEB语言的结合使用。
有的时候可能要确定一个局域网内有多少台机器是开机的,那么就要依次扫描这个网段内的所有IP。通
常的端口扫描或漏洞扫描的前提是目标主机是开机的,否则所有的扫描都是白费时间。最简单的办法是先
ping一下目标主机。大部分的扫描软件都会在扫描开始前进行和ping类似的测试。
我们要成为真正的黑客,所以我们不会满足于使用别人的程序,我们要理解这里面全部的网络原理,我
们要写自己的程序。
其实这样的程序并不难,我们只要向目标主机发送一个ICMP ECHO请求报文,如果目标主机回应了一
个ICMP ECHOREPLY报文,则目标主机一定是开机的。那么我们就可以进行后面的扫描工作了。
ICMP是第三层(网络层)的协议,虽然它和IP协议都在网络层,但ICMP数据报依然使用IP报头封装
其报文内容。ICMP ECHO的类型值是8(ICMP_ECHO),代码值是0。我们用程序来完成一个简单的ping。
读到这里,我假想你是完全知道ICMP报文的格式的,如果你不知道,那么请你离开,去打点基础再来阅
读,否则纯属浪费时间。
先建一个原始socket,再自已构造一个ICMP报文,通过这个原始socket把ICMP报文发送出去,然后
用这个原始socket接收目标主机的回应ICMP,收到回应,那么进行后面的扫描吧。要说明的是系统内核
会把收到的所有ICMP消息给每个ICMP原始socket复制一份,也就是说我们程序里创建的ICMP RAW
socket会收到所有的ICMP消息,但我们只想等待我们程序里指定的目标主机的ICMP ECHOREPLY消息,
较好的办法是使用ICMP ECHO报头的标识字段,在构造ICMP请求报文的时候,把标识字段(icmp_id)设
为进程号(process id)。然后检查收到的每个ICMP消息的标识字段,和process id相同的则是我们
等待的报文。
raw socket只有superuser可以创建,务必在superuser权限下运行。下面是一段简单的代码,不
过也是完整呈现了ping程序。
send_icmp()构造ICMP报头并使用raw socket发送。main循环接收ICMP消息,交给proc_icmp
判断处理。代码是linux系统上测试通过。
本程序只对一个IP地址进行,如果要对一段IP进行测试,简单修改程序即可。可将发送放在单独的进程
里(使用fork()),send_icmp里做成循环,每次重新初始化struct sockaddr_in。那么对接收到的数据
进行分析的proc_icmp()将多一道对IP报头ip->src字段的判断。具体的修改,留给读者自己完成。
1 /*
2 A simply ping program for unix
3 Copyright (C) 2005 by kf_701
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 The author can be reached as follows:
20 E_mail: kf_701@21cn.com
21 Address: hefei of china
22 Phone: 0551-2150103
23 */
24
25 #include <netinet/ip.h>
26 #include <stdio.h>
27 #include <netinet/ip_icmp.h>
28 #include <netinet/in_systm.h>
29 #include <netdb.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <unistd.h>
35 #include <sys/time.h>
36 #include <errno.h>
37 #include <signal.h>
38 #include <string.h>
39 #include <stdlib.h>
40
41 #define BUFSIZE 1024
42
43 /* global vars */
44 char recvbuf[BUFSIZE];
45 char sendbuf[BUFSIZE];
46 int datalen = 56; /* bytes of data,following ICMP header*/
47 pid_t pid; /* the pid use as icmp_id*/
48 unsigned short seqno; /* icmp_seq number*/
49 int timeerr; /* test gettimeofday if error*/
50 int sockfd = -1;
51 struct sockaddr_in destaddr;
52 socklen_t len = sizeof(struct sockaddr);
53
54 /* function prototypes */
55 static unsigned short check_sum(unsigned short *,int);
56 static void send_icmp(void);
57 static void proc_icmp(char *,ssize_t,struct timeval *);
58 static void tv_sub(struct timeval *,struct timeval *);
59 static void sig_alrm(int);
60 static void sig_int(int);
61
62 int
63 main(int argc,char **argv)
64 {
65 int size = 60*1024; /* set SO_RCVBUF */
66 struct timeval timeval; /* recvfrom time */
67 struct hostent *host;
68
69 if(argc != 2)
70 puts("-----usage:ping host------"),exit(1);
71
72 bzero(&destaddr,sizeof(destaddr));
73 destaddr.sin_family = AF_INET;
74 if(inet_aton(argv[1],&destaddr.sin_addr) == 0){
75 host = gethostbyname(argv[1]);
76 if(host == NULL){
77 fprintf(stderr,"Hostname Error: %s \n",hstrerror(h_errno));
78 exit(1);
79 }
80 destaddr.sin_addr = *(struct in_addr *)(host->h_addr_list[0]);
81 }
82 /*struct addrinfo hints,*res;
83 hints.ai_flags = AI_CANONNAME;
84 hints.ai_family = AF_INET;
85 hints.ai_socktype = 0;
86 if(getaddrinfo(argv[1],NULL,&hints,&res) != 0)
87 perror("getaddrinfo error"),exit(1);*/
88
89 sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
90 if(sockfd == -1)
91 perror("socket error"),exit(1);
92 setuid(getuid()); /* not need super permission any more*/
93 setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
94
95 signal(SIGINT,sig_int);
96 signal(SIGALRM,sig_alrm);
97 pid = getpid();
98 printf("------------ping %s 56 bytes packet------------\n",argv[1]);
99 sig_alrm(SIGALRM); /* send first packet*/
100
101 while(1){ /* receive packet */
102 int n = -1;
103 n = recvfrom(sockfd,recvbuf,sizeof(recvbuf),0,(struct sockaddr *)NULL,NULL);
104 if(n < 0){
105 if(errno == EINTR)
106 continue;
107 else
108 perror("recvfrom error"),exit(1);
109 }
110 /*printf("received : ");*/
111 if(gettimeofday(&timeval,NULL) == -1)
112 perror("gettimeofday error"),timeerr++;
113 proc_icmp(recvbuf,n,&timeval);
114 }
115 }
116
117 static void
118 send_icmp(void)
119 {
120 int len;
121 struct icmp *icmp;
122
123 icmp = (struct icmp *)sendbuf;
124 icmp->icmp_type = ICMP_ECHO;
125 icmp->icmp_code = 0;
126 icmp->icmp_id = pid;
127 icmp->icmp_seq = seqno;
128 if(gettimeofday((struct timeval *)icmp->icmp_data,NULL) == -1)
129 puts("set icmp_data error"),timeerr++;
130 len = 8 + datalen;
131 icmp->icmp_cksum = 0;
132 icmp->icmp_cksum = check_sum((u_short *)icmp,len);
133 if(sendto(sockfd,sendbuf,len,0,(struct sockaddr *)&destaddr,len) == -1)
134 perror("sendto error"),exit(1);
135 printf("send one packet and wait for answer ......\n");
136 fflush(NULL);
137 }
138
139 static void
140 sig_alrm(int signo)
141 {
142 send_icmp();
143 seqno = seqno + 1;
144 alarm(1);
145 return;
146 }
147
148 static void
149 proc_icmp(char *ptr,ssize_t len,struct timeval *tvrecv)
150 {
151 int iphdlen,icmplen;
152 struct ip *ip;
153 struct icmp *icmp;
154 struct timeval *tvsend;
155 double rtt;
156
157 ip = (struct ip *)ptr; /* start of IP header */
158 iphdlen = ip->ip_hl<<2; /* length of IP header */
159 icmp = (struct icmp *)(ptr+iphdlen); /* start of ICMP header */
160 if( (icmplen = len - iphdlen) < 8){ /* test icmp header len */
161 puts("icmplen error");
162 return;
163 }
164 if((icmp->icmp_type == ICMP_ECHOREPLY)&&(icmp->icmp_id == pid)){
165 printf("*receive: icmp_seq=%d ",icmp->icmp_seq);
166 if(icmplen < 16)
167 puts("icmplen < 16"),exit(1);
168 tvsend = (struct timeval *)icmp->icmp_data;
169 if(!timeerr){
170 tv_sub(tvrecv,tvsend);
171 rtt = tvrecv->tv_sec*1000.0 + tvrecv->tv_usec/1000.0;
172 printf(" rtt=%.3f ms\n",rtt);
173 }
174 }
175 return;
176 }
177
178 static void
179 tv_sub(struct timeval *out,struct timeval *in)
180 {
181 if( (out->tv_usec -= in->tv_usec) < 0 ){
182 --out->tv_sec;
183 out->tv_usec += 1000000;
184 }
185 out->tv_sec -= in->tv_sec;
186 }
187
188 static void sig_int(int sig)
189 {
190 printf("-------------------------------------------------------\n");
191 exit(0);
192 }
193
194 static unsigned short
195 check_sum(unsigned short *addr,int len)
196 {
197 register int nleft = len;
198 register int sum = 0;
199 register short *w = addr;
200 short answer = 0;
201
202 while(nleft>1)
203 {
204 sum += *w++;
205 nleft -= 2;
206 }
207 if(nleft ==1)
208 {
209 *(unsigned char *)(&answer) = *(unsigned char *)w;
210
211 sum += answer;
212 }
213 sum = (sum>>16)+(sum&0xffff);
214 sum += (sum>>16);
215 answer = ~sum;
216 return(answer);
217 }
check_sum函数是大家都使用的函数,这里就不作详细介绍了。作用是计算校验和。
看完后,你是否觉得原来是如些简单的事情呢,有问题请给我mail,谢谢。
******待续******