//////////////////////////////////////////////////////////
//PortScan.cpp
#include < winsock2.h >
#include < windows.h >
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#pragma comment( lib, "WS2_32.lib" )
//-----------------by Chrython Chou 200532530012 ----------------------
//////////////////////////////////////////////////////////
//函數原型
//歡迎界面
void psTitle( char * );
//默認掃描方式
void ps1( char *, char * );
//自定義掃描方式
void ps2( char *, char *, char *, char * );
//獲得主機信息
void GetLocalDate( void );
//線程函數
DWORD WINAPI psProc(
LPVOID lpParameter // thread data
);
//////////////////////////////////////////////////////////
//全局變量
//目標地址和目標端口
char g_szTargetIP[20];
int g_nTargetPort;
//默認常用探測端口
int g_nPorts[23] = {
21,22,23,25,53,79,80,110,111,119,135,139,143,
443,445,512,554,1080,1433,1521,2401,3306,3389
};
//端口開放數量
int g_nOpenPorts;
//////////////////////////////////////////////////////////
//類
//載入和釋放Winsock2庫的類
class CInitSock
{
public:
CInitSock( BYTE minorVer = 2, BYTE majorVer = 2)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( minorVer, majorVer );
err = ::WSAStartup( wVersionRequested, &wsaData );
if( err != 0 )
{
return;
}
if ( LOBYTE( wsaData.wVersion ) != minorVer || HIBYTE( wsaData.wVersion ) != majorVer )
{
::WSACleanup();
return;
}
}
~CInitSock()
{
::WSACleanup();
}
};
//參數輸入錯誤類
class CGetError
{
public:
void PortError( int nStartPort, int nEndPort )
{
if ( nStartPort < 0 || nStartPort > 65535 || nEndPort < 0 || nEndPort > 65535 )
{
printf("錯誤: 端口輸入/n");
exit(1);
}
if ( nStartPort >= nEndPort )
{
printf("錯誤: 端口輸入/n");
exit(1);
}
}
void IPError( void )
{
DWORD IPmax = inet_addr( "255.255.255.255" );
DWORD IPmin = inet_addr( "0.0.0.0" );
DWORD nowIP = inet_addr( g_szTargetIP );
if ( nowIP >= IPmax || nowIP <= IPmin )
{
printf("錯誤: IP地址輸入/n");
exit(1);
}
}
void DelayTimeError( int nDelayTime )
{
if ( nDelayTime < 0 || nDelayTime > 65535 )
{
printf("錯誤: 等待時間輸入/n");
exit(1);
}
}
};
//////////////////////////////////////////////////////////
//主函數用於命令行參數輸入
void main(int argc,char *argv[])
{
if( argc == 1 )
{
psTitle( argv[0] );
exit( 1 );
}
else if(argc == 3)
{
ps1( argv[1] , argv[2] );
}
else if( argc == 5 )
{
ps2( argv[1], argv[2], argv[3], argv[4] );
}
else
{
printf( "錯誤: 參數輸入/n" );
exit( 1 );
}
}
//歡迎界面
void psTitle(char *help)
{
printf ("--------------------------------------------------------------------/n");
printf ("Portscan端口掃描器/n");
printf ("------------------------------本機信息------------------------------/n");
GetLocalDate();
printf ("------------------------------功能說明------------------------------/n");
printf ("常用端口掃描:/n");
printf ("/tPortscan <目標IP> [等待時間(毫秒)]/n");
printf ("自定義端口掃描:/n");
printf ("/tPortscan <目標IP> [開始端口] [結束端口] [等待時間(毫秒)]/n");
printf ("舉例:/n");
printf ("/tPortscan 127.0.0.1 1/n");
printf ("/tPortscan 127.0.0.1 0 65535 1/n");
printf ("--------------------------------------------------------------------/n");
}
//默認掃描方式
void ps1( char *target, char *delay )
{
//初始化CGetError
CGetError psError;
int nDelayTime = atoi( delay );
//初始化Winsock庫
CInitSock initSock;
HANDLE hThread1;
strcpy( g_szTargetIP , target );
//輸入錯誤處理
psError.IPError();
psError.DelayTimeError( nDelayTime );
printf ("/n--------------------------------------------------------------------/n");
printf( "目標地址: ");
puts( target );
printf( "目標端口: 默認常用端口" );
printf("/n------------------------------掃描報告------------------------------");
for ( int i = 0; i < 23; i++ )
{
g_nTargetPort = g_nPorts[i];
//NULL 使用缺省的安全性
//0 採用調用線程一樣的大小
//psProc 指定線程入口函數的地址
//NULL 傳遞給線程的一個參數
//0 創建的標記爲0 一旦創建立即運行
//NULL 線程的ID 不需要使用
hThread1 = CreateThread( NULL, 0, psProc, NULL, NULL, NULL );
CloseHandle( hThread1 );
Sleep( nDelayTime );
}
printf( "/n/n共掃描到%d個端口開放" , g_nOpenPorts );
printf ("/n--------------------------------------------------------------------/n");
printf( "/n/n端口掃描完畢/n" );
}
//自定義掃描方式
void ps2( char *target, char *start, char *end, char *delay )
{
//初始化CGetError
CGetError psError;
int nStartPort = atoi( start );
int nEndPort = atoi( end );
int nDelayTime = atol( delay );
//初始化Winsock庫
CInitSock initSock;
HANDLE hThread2;
strcpy( g_szTargetIP , target );
//輸入錯誤處理
psError.PortError( nStartPort, nEndPort );
psError.IPError();
psError.DelayTimeError( nDelayTime );
printf ("/n--------------------------------------------------------------------/n");
printf( "目標地址: ");
puts( target );
printf( "目標端口: %d -- %d:", nStartPort, nEndPort );
printf ("/n------------------------------掃描報告------------------------------");
for ( int port = nStartPort; port <= nEndPort; port++ )
{
g_nTargetPort = port;
//NULL 使用缺省的安全性
//0 採用調用線程一樣的大小
//psProc 指定線程入口函數的地址
//NULL 傳遞給線程的一個參數
//0 創建的標記爲0 一旦創建立即運行
//NULL 線程的ID 不需要使用
hThread2 = CreateThread( NULL, 0, psProc, NULL, NULL, NULL );
CloseHandle( hThread2 );
Sleep( nDelayTime );
}
printf( "/n/n共掃描到%d個端口開放" , g_nOpenPorts );
printf ("/n--------------------------------------------------------------------/n");
printf( "/n/n端口掃描完畢/n" );
}
//獲得主機信息
void GetLocalDate( void )
{
//初始化Winsock庫
CInitSock initSock;
char szHost[256];
//獲取本地主機名
::gethostname( szHost, 256 );
//通過主機名獲取主機信息
hostent *pHost = ::gethostbyname( szHost );
//打印出所有IP
in_addr addr;
for( int i = 0;; i++ )
{
char *p;
char *szlp;
p = pHost->h_addr_list[i];
if ( p == NULL )
break;
memcpy( &addr.S_un.S_addr, p, pHost->h_length );
szlp = ::inet_ntoa( addr );
printf("本地主機名: %s /n", szHost);
printf("本地主機IP: %s /n", szlp);
}
}
//調用輔線程來循環掃描每個端口
DWORD WINAPI psProc(
LPVOID lpParameter // thread data
)
{
//創建套接字
SOCKET psSock = ::socket ( AF_INET, SOCK_STREAM, 0 );
//sockaddr_in結構
struct sockaddr_in psAddr;
if( psSock == INVALID_SOCKET )
{
printf( "Error: socket /n" );
exit(1);
}
//將psAddr中的前sizeof( psAddr )個字符都替換成0
memset( &psAddr, 0, sizeof( psAddr ) );
//填充sockaddr結構
psAddr.sin_family = AF_INET;
psAddr.sin_addr.S_un.S_addr = inet_addr( g_szTargetIP );
psAddr.sin_port = htons( g_nTargetPort );
if( ::connect( psSock, ( sockaddr* )&psAddr, sizeof( psAddr ) ) != SOCKET_ERROR )
{
printf( "/n端口 %d 開放", ntohs( psAddr.sin_port) );
g_nOpenPorts++;
}
//關閉監聽套接字
::closesocket( psSock );
return 0;
}