要求的专业知识:
一: 精通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的数据报,关上正在建
立连接的三次握手。这是一种比较隐匿的扫描方式,因为很多主机不会记录没有完成三次握手的事件。
******待续******