论坛: 编程破解 标题: 黑客(hacker)成长的代码之路:扫描(1) 复制本贴地址    
作者: 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号