要求的專業知識:
一: 精通OSI參考模型,精通網絡五層:物理層,數據鏈路層,網絡層,傳輸層,應用層。
精通每一層的協議,數據報格式。精通網絡拓撲結構,第一層,第二層,第三層的網
絡互聯,數據的轉發和路由等。
二: 精通C語言程序設計,UNIX/LINUX程序設計,網絡程序設計。熟悉UNIX/LINUX系
統操作,熟悉著名服務的基本配置,特性及使用的端口號。熟悉經典網絡命令的使用,
如:netstat,ping,traceroute,netcat,arp等。
三: 精通標準SQL語言,熟悉流行的數據庫使用,如:Oracle,Mysql等。掌握數據庫與
WEB語言的結合使用。
掃描通常是查看目標主機是否開機,對外開放了哪些服務及端口,服務的版本號,使用的是什么操作系
統及版本號。
更進一步的掃描通常是獲得目標主機的系統漏洞,各種開放的服務漏洞,而這種漏洞掃描通常都是用程
序從一個已知的漏洞數據庫里依次嘗試。這里就跳過而不給出示例代碼了。用于這類掃描的常用工具有:
whisker(www.wiretrip.net),nikto(www.cirt.net)等,有興趣的讀者可以自行下載其源碼閱
讀。不過建議要有一點perl語言的基礎。
現在來講通常的端口掃描。使用傳輸層協議(TCP and UDP)的應用,都會開一個端口號來listen,如
web通常開放80,ftp用21,telnet用23(現在幾近不用了),ssh用22等。最簡單的思想就是嘗試去連
接目標主機的端口,如果可以建立連接,可推測某端口開放,如果是著名端口,則相應的服務是打開的。
我所要講的是如何寫程序去試圖連接目標主機的目標端口。主要的方式有TCP和UDP。
1:例如我們給目標主機上的某個端口發送一個UDP數據報,如果目標端口沒有開放,則目標主機會回應
一個端口不可達ICMP報文,當我們的程序收到了這個ICMP報文,則可認為此端口沒有開放。這樣依次
連接每個端口,則可判斷目標主機開放了哪些端口了。
2:單純的TCP方式掃描大概是最簡單的了。建一個socket,然后調用connect去連接目標主機上的端口,
成功返回,則可判斷端口開放。
下面是一個TCP方式掃描的示例程序代碼,代碼在linux下測試成功。編譯命令:clearcase/" target="_blank" >cc -pthread scan.c。
/*
A very beautiful port scan program
Copyright (C) 2005 by kf_701
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached as follows:
E_mail: kf_701@21cn.com
Address: hefei of china
Phone: 0551-2150103
*/
/*
* 本程序是一個簡單的端口掃描程序,使用TCP SOCKET
* 依次試連接目標主機的端口,以此判斷端口開放與否。
* 程序設計上使用了線程池,共100個線程。每個線程
* 用mutex方式來得到一個端口號用來測試,并將端口
* 號變量port_num加 1,當port_num增至 MAX_PORT,線程
* 將thread_num減 1并結束自身,當99個線程都結束后,
* thread_num變為 0,最后一個線調用exit結束程序。
*/
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<netdb.h>
#include<netinet/in.h>
#include<unistd.h>
#include<errno.h>
#include<signal.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<pthread.h>
#include<thread_db.h>
#include<arpa/inet.h>
#define MAX_PORT 4000
#define MAX_THREAD 100
/* basename(argv[0]). netBSD,linux and gnu libc all define it. */
extern char *__progname;
/* globals */
int port_num,thread_num=100;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main(int argc,char **argv)
{
void *thread_main(void *);
pthread_t tid;
#ifndef HAVE__PROGNAME
__progname = argv[0];
#endif
printf("----kf_701 scan tool---------\n");
if(argc != 2){
fprintf(stderr,"* Usage: %s host\n",__progname);
exit(0);
}
/* create threads */
int i;
for(i=0;i<MAX_THREAD;i++)
pthread_create(&tid,NULL,&thread_main,argv[1]);
/* main pause */
for( ; ; )
pause();
}
void *thread_main(void *arg)
{
struct sockaddr_in sa;
struct hostent *host;
int i,sockfd;
pthread_detach(pthread_self());
/* init sockaddr_in struct */
bzero(&sa,sizeof(struct sockaddr));
sa.sin_family = AF_INET;
if(inet_aton((char *)arg,&sa.sin_addr) == 0){
host = gethostbyname((char *)arg);
if(host == NULL){
fprintf(stderr,"Hostname Error: %s \n",hstrerror(h_errno));
exit(1);
}
sa.sin_addr = *(struct in_addr *)(host->h_addr_list[0]);
}
while(1){
/* get a port number */
if(pthread_mutex_lock(&mutex) != 0) exit(1);
if(++port_num > MAX_PORT){
if(pthread_mutex_unlock(&mutex) != 0) exit(1);
if(--thread_num == 0){
printf("-----------------------------\n");
exit(0);
}
pthread_exit(NULL);
}
i=port_num;
if(pthread_mutex_unlock(&mutex) != 0) exit(1);
/* try to connect */
sa.sin_port=htons(i);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0)
perror("Create socket error"),exit(1);
if(connect(sockfd,(struct sockaddr *)&sa,sizeof(sa)) == 0)
printf("* port %d is open \n",i);
if(close(sockfd) < 0)
perror("shutdown error"),exit(1);
}/*end while*/
}
如果你深入學習過TCP/IP協議的話,就會知道建立TCP連接的三次握手(SYN-->SYN/ACK-->ACK),
下面的文章,我們將學習半開式的掃描。如發送一個SYN位設置為1的數據報,當收到目標主機的ACK
回應,則可判斷某端口是開放的。然后我們立即給目標主機發送一個RST位置1的數據報,關上正在建
立連接的三次握手。這是一種比較隱匿的掃描方式,因為很多主機不會記錄沒有完成三次握手的事件。
******待續******