自己做吧,给个帖子给你,扫描CGI漏洞的
漏洞扫描器一般都不难做的.
CGI扫描器的原理和实现过程
(Windows )------------------------------------------------------------------------------------      
 
 
        有很多网站为了安全起见,在WEB Server前面架了防火墙,或者做了TCP/IP过滤,对外只开放TCP 80 端口。从入侵者角度来看,要入侵那么从80上跑的CGI入手是比较可行的,当然也可以用别的办法,例如旁敲侧击,呵呵。从网管角度来看,一是要保证CGI的安全性,另外网络的整体安全性也是很重要的。针对基于80端口入侵、防范而出的CGI扫描器数不胜数,但基本上原理都一样    CGI扫描器原理说起来其实非常简单,可以用四句话来概括:<1>连接目标WEB SERVER;<2>发送一个特殊的请求;<3>接收目标服务器返回数据;<4>根据返回数据判断目标服务器是否有此CGI漏洞。   当管理的服务器达到一定数量的时候,手工检测自己的服务器是否存在各种各样的CGI漏洞,那就太消耗时间和精力了,所以一个网管手上有个比较好用的CGI漏洞扫描器还是必要的。OK!今天我们就自己来动手用C写一个简单的CGI扫描器,帮助自己在日常工作中检测服务器:))
   源代码如下,很多地方我都加了注释,别嫌我烦哦:))编译好的程序可以从http://eyas.3322.net/program/cgicheck.exe下载。/*************************************************************************
Module:CGICheck.cpp
Author:ey4s<[email protected]>
Date:2001/5/16
说明:这是一个Console下多线程,带有进度显示的CGI扫描器的模板,更改一下szSign和SendBuff就可以扫描其他CGI漏洞,设置了连接、发送、接收超时,速度还可以哦。希望可以帮助到admins检测自己的服务器:))
*************************************************************************/
#include <stdio.h>
#include <winsock2.h>
#include <time.h>  #define iPort 80//目标Web Server端口
#define szSign "500 13\r\nServer: Microsoft-IIS/5.0"//根据此标志来检查目标是否有 
#pragma comment(lib,"ws2_32.lib")/////////////////////////////////////////////////////////////////////////////file://定义&初始化全局/char *SendBuff="GET /NULL.printer\n",//发送的请求buff 
    CurrentTarget[52]={0},//存放最后一个线程将扫描的目标 
    turn[4][2]={"-","\\","|","/"};//显示进度时的字符 
int SendBuffLen=strlen(SendBuff),//发送的buff长度    iConnTimeout,//TCP Connect TimeOut
    ii=0,//扫描进度
    iTotal;//服务器总数
HANDLE hSemaphore=NULL,//信标内核对象句柄,用来控制线程数量
       hStdout;//console标准输出句柄,做进度显示的时候用的
struct timeval timeout;//连接、发送和接收的超时值
DWORD SleepTime;//每个一个线程后等待的时间
    /*
    SleepTime值根据用户输入的线程数量[ThreadNum]和TCP ConnectTimeOut[CONNTIMEO]来计算。确保在CONNTIMEO时间左右开    ThreadNum个线程。这样在CONNTIMEO时间后,所开的线程开始陆续超时退出,可以继续稳定的开线程,可以有效的保证同时有    ThreadNum个线程在运行。
    */
///////////////////////////////////////////////////////////////////////////
void ShowError(char *);//显示出错信息函数,可以写完善一些,偶偷懒了:)
BOOL ResetCursor(void);//重置光标位置,线程输出的时候调用的
DWORD WINAPI ShowProInfo(LPVOID);//显示进度信息
DWORD WINAPI scan(LPVOID);//扫描函数
void usage(char *);//帮助函数
///////////////////////////////////////////////////////////////////////////
int main(int argc,char **argv)
{
    HANDLE hThread=NULL;//线程句柄
    DWORD dwThreadID;//线程ID
    struct sockaddr_in sa;
    int i,
       MaxThread;//最大线程数量
    WSADATA    wsd;
    long PreviousCount;
    clock_t start,end;//程序运行的起始和结束时间
    double duration;      file://检查用户输入参数
    if(argc!=5)
    {
       usage(argv[0]);
        return 1;
    }
    file://get target range
    int StartNet=inet_addr(argv[1]);
    int StopNet=inet_addr(argv[2]);
    int StartHost=ntohl(StartNet);
    int StopHost=ntohl(StopNet);
    file://取得线程数量
    MaxThread=atoi(argv[3]);
    file://取得conn超时时间
    iConnTimeout=atoi(argv[4]);
    file://检查参数合法性
    if((iConnTimeout>6) || (iConnTimeout<2) || (MaxThread<1) || (MaxThread>500) || (StopHost<StartHost))
    {
       usage(argv[0]);
        return 1;
    }
    file://计算时间
    SleepTime=1000*iConnTimeout/MaxThread;
    file://设置连接超时值
    timeout.tv_sec = iConnTimeout;
    timeout.tv_usec =0;
    __try
    {
        file://开始计时
       start=clock();
        file://加载winsock库
        if (WSAStartup(MAKEWORD(1,1), &wsd) != 0)
        {
            ShowError("WSAStartup");
            __leave;
        }
        file://创建信标内核对象句柄
       hSemaphore=CreateSemaphore(NULL,MaxThread,MaxThread,NULL);
       if(hSemaphore==NULL)
        {
            ShowError("CreateSemaphore");
            __leave;
        }
        file://取得console标准输出句柄
       hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
       if(hStdout==INVALID_HANDLE_VALUE)
        {
            ShowError("GetStdHandle");
            __leave;
        }
        file://设置目标总数
       iTotal=StopHost-StartHost;
        file://创建进度显示线程
       hThread=CreateThread(NULL,0,ShowProInfo,NULL,0,&dwThreadID);
       if(hThread==NULL)
        {
            ShowError("1 CreateThread");
            __leave;
        }
file://关闭句柄
       CloseHandle(hThread);
        file://循环创建扫描线程
       for(i=StartHost;i<=StopHost;i++)
        {
           file://等待信标内核对象通知
            WaitForSingleObject(hSemaphore,INFINITE);
            file://create thread to scan
            hThread=CreateThread(NULL,0,scan,(LPVOID)i,0,&dwThreadID);
            if(hThread==NULL)
           {
               ShowError("2 CreateThread");
              break;
           }
           file://进度自加1
            ii++;
           file://重设最后一个线程扫描的目标
            sa.sin_addr.s_addr=htonl(i);
            strncpy(CurrentTarget,inet_ntoa(sa.sin_addr),sizeof(CurrentTarget));
           file://休息一会儿:))
            Sleep(SleepTime);
           file://关闭线程句柄
            CloseHandle(hThread);
        }
        file://等待所有线程结束
       while(1)
        {
            WaitForSingleObject(hSemaphore,INFINITE);
            if(!ReleaseSemaphore(hSemaphore,1,&PreviousCount))
           {
              ShowError("main() ReleaseSemaphore");
              Sleep(5000);
              break;
           }
            if(PreviousCount==(MaxThread-1))
            {
              printf("\nAll done.");
              break;
           }
            Sleep(500);
        }
    }//end of try
    file://搞定,清场,收工
    __finally
    {
        file://计时结束
       end=clock();
        file://转换时间格式
       duration = (double)(end - start) / CLOCKS_PER_SEC;
        file://显示所用时间
       printf("\n\nComplete.Scan %d targets use %2.1f seconds.Speed %0.3g/s\n",iTotal,duration,iTotal/duration);
        file://关闭句柄
       CloseHandle(hStdout);
       CloseHandle(hSemaphore);
       WSACleanup();
    }
    return 0;
}
///////////////////////////////////////////////////////////////////////////
//
file://回显错误信息函数
//
void ShowError(char *msg)
{
    MessageBox(NULL,msg,"ERROR",0);
    file://printf("\n%s failed:%d",GetLastError());
}
//////////////////////////////////////////////////////////////////////////
//
file://重置光标位置函数,以便扫描线程输出结果
//
BOOL ResetCursor()
{
    CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
    file://取得当前光标位置
    if(!GetConsoleScreenBufferInfo(hStdout,&ConsoleScreenBufferInfo))
    {
       ShowError("GetConsoleScreenBufferInfo");
        return FALSE;
    }
    file://设置光标X坐标为0
    ConsoleScreenBufferInfo.dwCursorPosition.X=0;
    file://设置当前光标位置
    SetConsoleCursorPosition(hStdout,ConsoleScreenBufferInfo.dwCursorPosition);
    return TRUE;
}
///////////////////////////////////////////////////////////////////////////
//
file://显示进度信息函数
//
DWORD WINAPI ShowProInfo(LPVOID lp)
{  
    int j,k;
    CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
    float m;
    for(j=0;ii<iTotal;j++)
    {
        file://休息一会儿:)))
       Sleep(SleepTime);
        file://取得当前光标位置
       if(!GetConsoleScreenBufferInfo(hStdout,&ConsoleScreenBufferInfo))
        {
            ShowError("GetConsoleScreenBufferInfo");
            return 1;
        }
        file://设置百分比进度显示的X坐标
       ConsoleScreenBufferInfo.dwCursorPosition.X=0;
        file://设置当前光标位置
       SetConsoleCursorPosition(hStdout,ConsoleScreenBufferInfo.dwCursorPosition);
        file://已经完成的百分比
       m=(ii+1)*100.00/iTotal;
        file://显示进度
       if(ii==iTotal)
        {
            printf("******** 100%% Wait %d seconds to exit ********        \n",iConnTimeout);
            break;
        }
        else
        {
            k=j%4;
            printf("%-15s %s [%d/%d] %s %%%0.3g",CurrentTarget,turn[k],ii,iTotal,turn[k],m);
        }
    }//end of for
    return 0;
}
///////////////////////////////////////////////////////////////////////////
//
file://扫描函数
//
DWORD WINAPI scan(LPVOID lp)
{
    int i=(int)lp,iErr;
    struct sockaddr_in server;
    SOCKET s=INVALID_SOCKET;
    char RecvBuff[1024]={0},*ptr;
    int RecvBuffLen=sizeof(RecvBuff);
    u_long ul=1;//初始化为为非0值
  fd_set r,w;      file://create socket
    s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(s==INVALID_SOCKET)
    {
       printf("\nCreate socket failed:%d",GetLastError());
       ExitProcess(1);
    }
    file://fill the addr struct
    server.sin_family=AF_INET;
    server.sin_port=htons(iPort);
    server.sin_addr.S_un.S_addr=htonl(i);
    __try
    {
        file://设置socket为非锁定模式,ul为0值的话,那么soocket将被设置为锁定模式
       iErr=ioctlsocket(s,FIONBIO,(unsigned long*)&ul);
       if(iErr==SOCKET_ERROR )
        {
            ResetCursor();
            ShowError("ioctlsocket");
            ExitProcess(1);
        }
       file://printf("\n%X ioctl ok.strat conn",i);
       file://connect to target
       connect(s,(struct sockaddr *)&server,sizeof(server));
       file://printf("\n%X conn return,start select w",i);
        file://设置select参数
       FD_ZERO(&w);
       FD_SET(s, &w);
        file://等待connect成功&socket可写
       iErr=select(0, 0, &w, 0, &timeout);
       file://printf("\n%X select w return %d",i,iErr);
        file://等待返回后,socket仍不可写则退出
       if((iErr==SOCKET_ERROR) || (iErr==0))
        {
            file://printf("\n%X select return w err,exit",i);
            __leave;
        }
       file://socket可写则继续
        else
        {
            file://send buff to target
            file://printf("\n%X send",i);
            iErr=send(s,SendBuff,SendBuffLen,0);
            file://printf("\n%X send return",i);
            if(iErr==SOCKET_ERROR)
              __leave;
        }
        file://等待socket可读
       FD_ZERO(&r);
       FD_SET(s, &r);
       file://printf("\n%X start select r",i);
       iErr=select(0, &r, 0, 0, &timeout);
       file://printf("\n%X select r return %d",i,iErr);
       if((iErr==SOCKET_ERROR) || (iErr==0))
        {
            file://printf("\n%X select r err,exit",i);
            __leave;
        }
        else
        {
            file://recv buff from target
            file://printf("\n%X start recv",i);
            iErr=recv(s,RecvBuff,RecvBuffLen,0);
            file://printf("\n%X recv ret",i);
            if(iErr==SOCKET_ERROR)
              __leave;
        }
       file://verify buff
       ptr=strstr(RecvBuff,szSign);
       if(ptr!=NULL)
        {
           file://线程输出前要先调用ResetCursor函数
            ResetCursor();
           file://输出信息后务必加一个以上换行符号,输出前请别加换行符号,以免显示混乱
            printf("[%-15s] has .printer mapped.         \n",inet_ntoa(server.sin_addr));
        }
    }
    __finally
    {
       if(!ReleaseSemaphore(hSemaphore,1,NULL))
            ShowError("thread ReleaseSemaphore failed");
       closesocket(s);
    }
    return 0;
}
///////////////////////////////////////////////////////////////////////////
void usage(char *proname)
{
    printf("\n%s v0.1 only can find IIS5 .Printer mapped"
       "\nPower by ey4s<[email protected]> 2001.5.20"
       "\nhttp://www.patching.net"
       "\n\nUsage:%s <StartIP> <EndIP> <ThreadNum> <CONNTIMEO>"
       "\n\nNotice"
        "\n    StartIP StopIP ==>Don‘t forgot StopIP must large than StartIP "
        "\n    ThreadNum ==>Thread number,please input between 1-500"
        "\n    CONNTIMEO ==>TCP connect timeout,please input between 2-6"
       "\n\nExample"
        "\n    %s 192.168.0.0 192.168.255.255 200 2",proname,proname,proname);
}   程序在VC++6.0上编译通过,在windows2000上运行良好:)
出处:eyas 
 ------------------------------------------------------------------------------------
&copy; Copyright 2000-2001 HackerUnion Group
黑客联盟版权所有 

解决方案 »

  1.   

    用Nessus吧,它是Open Source的。
      

  2.   

    linux下的源码很多
    随便找把,都是源代码开放
      

  3.   

    我们要求的是WIN下的服务器扫描,
    还请各位费心。
      

  4.   

    价格如何?我的信箱[email protected]
      

  5.   

    我们有一个做好的成品
    [email protected]
    VC开发的,大约代码4万行
      

  6.   

    为什么到现在也没有一个真正的回应呢?
    我觉得这个东西一定有人自己就能做呀!
    如果你有产品,请寄你的DEMO来,
    我们寻求的是长期合作、长期维护升级!
    [email protected]
      

  7.   

    WIN平台网络漏洞扫描器
    代码7万行
    能否说你们可接受价格?
    不知你所说的长期合作、长期维护升级是何意?
      

  8.   

    XDL:
    价格在我们看了你的DEMO后双方议定。
    长期合作包括,对这个扫描器的维护(有BUG和技术支持);或者你有其它安全的东东,我们也感兴趣。
    升级的意思是,漏洞是不断出现的,特征码得数据是要不断更新的,希望你一直维护下去。
    我们寻求的并不是一次“买卖”,而是真正找到一个有能力的人,来做这个东西!
    希望得到各位进一步回复,可直接写到我的邮箱。
    我的QQ是:
    256141
    ICQ是:
    86177757