|
![]() | 作者: kf701 [kf701]
![]() |
登录 |
黑客(hacker)成长的代码之路:扫描(1) 作者:kf_701 写作时间:2005/4 Email:kf_701@21cn.com 转载请保留原作者信息,谢谢。 更多内容:blog.chinaunix.net/index.php?blogId=3063 要求的专业知识: 一: 精通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下测试成功。编译命令:cc -pthread scan.c。 /* writed by kf_701 * kf_701@21cn.com * 合肥大学生公寓 * * 本程序是一个简单的端口扫描程序,使用TCP SOCKET * 依次试连接目标主机的端口,以此判断端口开放与否。 * 程序设计上使用了线程池,共100个线程。每个线程 * 用mutex方式来得到一个端口号用来测试,并将端口 * 号变量port_num加 1,当port_num增至 MAX_PORT,线程 * 将thread_num减 1并结束自身,当99个线程都结束后, * thread_num变为 0,最后一个线调用exit结束程序。 * ******scan.c****** */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<errno.h> #include<signal.h> #include<netdb.h> #include<sys/types.h> #include<netinet/in.h> #include<sys/socket.h> #include<arpa/inet.h> #include<pthread.h> #include<thread_db.h> #define MAX_PORT 1023 #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的数据报,关上正在建 立连接的三次握手。这是一种比较隐匿的扫描方式,因为很多主机不会记录没有完成三次握手的事件。 ******待续****** |
地主 发表时间: 05-04-15 21:10 |
![]() | 回复: xiaoshi [xiaoshi] ![]() |
登录 |
不错,收藏起来仔细瞧瞧1 |
B1层 发表时间: 05-04-15 22:40 |
|
20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon
粤ICP备05087286号