要求的專業知識:
一: 精通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進行測試,簡單修改程序即可??蓪l送放在單獨的進程
里(使用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,謝謝。
******待續******