一個包含詳細註釋的掃描器C源代碼

 
一個包含詳細註釋的掃描器C源代碼
 
 

#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")
///////////////////////////////////////////////////////////////////////////
//
//定義&初始化全局變量
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;
    //檢查用戶輸入參數
    if(argc!=5)
    {
       usage(argv[0]);
       return 1;
    }
    //get target range
    int StartNet=inet_addr(argv[1]);
    int StopNet=inet_addr(argv[2]);
    int StartHost=ntohl(StartNet);
    int StopHost=ntohl(StopNet);
    //取得線程數量
    MaxThread=atoi(argv[3]);
    //取得conn超時時間
    iConnTimeout=atoi(argv[4]);
    //檢查參數合法性
    if((iConnTimeout>6) || (iConnTimeout<2) || (MaxThread<1) || (MaxThread>500) || (StopHost<StartHost))
    {
       usage(argv[0]);
       return 1;
    }
    //計算時間
    SleepTime=1000*iConnTimeout/MaxThread;
    //設置連接超時值
    timeout.tv_sec = iConnTimeout;
    timeout.tv_usec =0;
    __try
    {
       //開始計時
       start=clock();
       //加載winsock庫
       if (WSAStartup(MAKEWORD(1,1), &wsd) != 0)
       {
           ShowError("WSAStartup");
           __leave;
       }
       //創建信標內核對象句柄
       hSemaphore=CreateSemaphore(NULL,MaxThread,MaxThread,NULL);
       if(hSemaphore==NULL)
       {
           ShowError("CreateSemaphore");
           __leave;
       }
       //取得console標準輸出句柄
       hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
       if(hStdout==INVALID_HANDLE_VALUE)
       {
           ShowError("GetStdHandle");
           __leave;
       }
       //設置目標總數
       iTotal=StopHost-StartHost;
       //創建進度顯示線程
       hThread=CreateThread(NULL,0,ShowProInfo,NULL,0,&dwThreadID);
       if(hThread==NULL)
       {
           ShowError("1 CreateThread");
           __leave;
       }
//關閉句柄
       CloseHandle(hThread);
       //循環創建掃描線程
       for(i=StartHost;i<=StopHost;i++)
       {
           //等待信標內核對象通知
           WaitForSingleObject(hSemaphore,INFINITE);
           //create thread to scan
           hThread=CreateThread(NULL,0,scan,(LPVOID)i,0,&dwThreadID);
           if(hThread==NULL)
           {
              ShowError("2 CreateThread");
              break;
           }
           //進度自加1
           ii++;
           //重設最後一個線程掃描的目標
           sa.sin_addr.s_addr=htonl(i);
           strncpy(CurrentTarget,inet_ntoa(sa.sin_addr),sizeof(CurrentTarget));
          //休息一會兒 )
           Sleep(SleepTime);
           //關閉線程句柄
           CloseHandle(hThread);
       }
       //等待所有線程結束
       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
    //搞定,清場,收工
    __finally
    {
       //計時結束
       end=clock();
       //轉換時間格式
       duration = (double)(end - start) / CLOCKS_PER_SEC;
       //顯示所用時間
       printf("/n/nComplete.Scan %d targets use %2.1f seconds.Speed %0.3g/s/n",iTotal,duration,iTotal/duration);
       //關閉句柄
       CloseHandle(hStdout);
       CloseHandle(hSemaphore);
       WSACleanup();
    }
    return 0;
}
///////////////////////////////////////////////////////////////////////////
//
//回顯錯誤信息函數
//
void ShowError(char *msg)
{
    MessageBox(NULL,msg,"ERROR",0);
    //printf("/n%s failed:%d",GetLastError());
}
//////////////////////////////////////////////////////////////////////////
//
//重置光標位置函數,以便掃描線程輸出結果
//
BOOL ResetCursor()
{
    CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
    //取得當前光標位置
    if(!GetConsoleScreenBufferInfo(hStdout,&ConsoleScreenBufferInfo))
    {
       ShowError("GetConsoleScreenBufferInfo");
       return FALSE;
    }
    //設置光標X座標爲0
    ConsoleScreenBufferInfo.dwCursorPosition.X=0;
    //設置當前光標位置
    SetConsoleCursorPosition(hStdout,ConsoleScreenBufferInfo.dwCursorPosition);
    return TRUE;
}
///////////////////////////////////////////////////////////////////////////
//
//顯示進度信息函數
//
DWORD WINAPI ShowProInfo(LPVOID lp)
{  
    int j,k;
    CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
    float m;
    for(j=0;ii<iTotal;j++)
    {
       //休息一會兒 ))
       Sleep(SleepTime);
       //取得當前光標位置
       if(!GetConsoleScreenBufferInfo(hStdout,&ConsoleScreenBufferInfo))
       {
           ShowError("GetConsoleScreenBufferInfo");
           return 1;
       }
       //設置百分比進度顯示的X座標
       ConsoleScreenBufferInfo.dwCursorPosition.X=0;
       //設置當前光標位置
       SetConsoleCursorPosition(hStdout,ConsoleScreenBufferInfo.dwCursorPosition);
       //已經完成的百分比
       m=(ii+1)*100.00/iTotal;
       //顯示進度
       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;
}
///////////////////////////////////////////////////////////////////////////
//
//掃描函數
//
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;
    //create socket
    s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(s==INVALID_SOCKET)
    {
       printf("/nCreate socket failed:%d",GetLastError());
       ExitProcess(1);
    }
    //fill the addr struct
    server.sin_family=AF_INET;
    server.sin_port=htons(iPort);
    server.sin_addr.S_un.S_addr=htonl(i);
    __try
    {
       //設置socket爲非鎖定模式,ul爲0值的話,那麼soocket將被設置爲鎖定模式
       iErr=ioctlsocket(s,FIONBIO,(unsigned long*)&ul);
       if(iErr==SOCKET_ERROR )
       {
           ResetCursor();
           ShowError("ioctlsocket");
           ExitProcess(1);
       }
       //printf("/n%X ioctl ok.strat conn",i);
       //connect to target
       connect(s,(struct sockaddr *)&server,sizeof(server));
       //printf("/n%X conn return,start select w",i);
       //設置select參數
       FD_ZERO(&w);
       FD_SET(s, &w);
       //等待connect成功&socket可寫
       iErr=select(0, 0, &w, 0, &timeout);
       //printf("/n%X select w return %d",i,iErr);
       //等待返回後,socket仍不可寫則退出
       if((iErr==SOCKET_ERROR) || (iErr==0))
       {
           //printf("/n%X select return w err,exit",i);
           __leave;
       }
       //socket可寫則繼續
       else
       {
           //send buff to target
           //printf("/n%X send",i);
           iErr=send(s,SendBuff,SendBuffLen,0);
           //printf("/n%X send return",i);
           if(iErr==SOCKET_ERROR)
              __leave;
       }
       //等待socket可讀
       FD_ZERO(&r);
       FD_SET(s, &r);
       //printf("/n%X start select r",i);
       iErr=select(0, &r, 0, 0, &timeout);
       //printf("/n%X select r return %d",i,iErr);
       if((iErr==SOCKET_ERROR) || (iErr==0))
       {
           //printf("/n%X select r err,exit",i);
           __leave;
       }
       else
       {
           //recv buff from target
           //printf("/n%X start recv",i);
           iErr=recv(s,RecvBuff,RecvBuffLen,0);
           //printf("/n%X recv ret",i);
           if(iErr==SOCKET_ERROR)
              __leave;
       }
       //verify buff
       ptr=strstr(RecvBuff,szSign);
       if(ptr!=NULL)
       {
           //線程輸出前要先調用ResetCursor函數
           ResetCursor();
           //輸出信息後務必加一個以上換行符號,輸出前請別加換行符號,以免顯示混亂
           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"  

       "/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);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章