C implementation of the non blocking mode command line port scanner source code

  • 2020-04-02 02:25:11
  • OfStack

This example is a C implemented port scan code based on command line mode and is implemented in a non-blocking manner to test the connection between IP and port. Comments have been added in as many places as possible in the code for your convenience and to help you understand C port scanning.

The specific function code is as follows:


#include <afxext.h>
#include <winsock.h>
//Libraries to use at compile time
#pragma comment(lib,"wsock32.lib")
//Select () member definition
#define ZERO (fd_set *)0
//Variable definitions
int maxth, scanok, scannum;
int portip, hoststart, hoststop, startport, endport; //Defines the start I and end P addresses, start and end ports
long searchnum, searched;
void usage(char *); //Defines the display usage method function
void playx(int); //Define the status prompt
void setip2(char *); //Define the set IP function
void customport(char *, char *, char *); //Define the custom scan port function
void portscannow(int); //Define a port scan scan
int main(int argc, char *argv[])
{
WSADATA wsadata;
//Clear the screen
system("cls.exe");
//Display version information
printf("rn==============  Command line port scanner  PortScanner V1.0 ==============");
//Check the input
if ((argc < 3) || (argc > 4))
{
//Show help tips
usage(argv[0]);
return -1;
}
//Detect whether it is a port scan
if(!(stricmp(strlwr(argv[1]), "-p") == 0))
{
usage(argv[0]);
return -1;
}
//Program initialization
if (WSAStartup(MAKEWORD(1,1), &wsadata) != 0) //If the initialization is wrong
{
printf("rnWsatartup error");      //An error message
return -1;
}
//Port scan parameter conversion
//If the argument is three
if (argc == 3)
{
//Set IP directly
setip2(argv[2]);
}
//If the parameter is four
else
if (argc == 4)
{
//Enter custom port scan processing
customport(argv[0], argv[2], argv[3]);
}
//Parameter overload shows help
else
{
usage(argv[0]);
return -1;
}
//Scan port start
portscannow(argc);
WSACleanup();
return 0;
}
//Help prompt function
void usage(char * prog)
{
printf("Usage: %s <Option>", prog);
printf("rnn <Option>:");
printf("rn -p [ Port|StartPort-EndPort ] < HostName|IP|StartIP-EndIP >");
printf("rnn Example: ");
printf("rn %s -p 192.168.0.1", prog);
printf("rn %s -p 192.168.0.1-192.168.0.254", prog);
printf("rn %s -p 21-80 192.168.0.1", prog);
printf("rn %s -p 21-80 192.168.0.1-192.168.0.254rn", prog);
return;
}
//Progress indication
void playx(int play = 0)
{
//The progress bar
char *plays[12]=
{
" | ",
" / ",
" - ",
" \ ",
" | ",
" / ",
" - ",
" \ ",
" | ",
" / ",
" - ",
" \ ",
};
if (searchnum != 0)
{
for (int i = 0 ; i <= 3; i ++)
{
 printf(" =%s= %d%s Completed. r", plays , searched * 100 / (searchnum + 1), "%");
 Sleep(5);
}
}
else
{
 printf(" =%s=r", plays[play]); //According to schedule
 Sleep(10);
}
}
//Set the IP
void setip2(char *cp)
{
int host;
struct hostent *testhost;
char *startip = "", *endip = "";
//Determine whether the input is in the form of 192.168.0.1-192.168.0.254
if (strstr(cp, "-") && strlen(cp) > 15 && strlen(cp) < 32)
{
//Extract the end IP
endip = strchr(cp, '-') + 1;
//Extract the start IP
strncpy(startip, cp, strlen(cp) - strlen(strchr(cp, '-')));
//Assign a value to the variable that controls the IP segment to be scanned
hoststart = ntohl(inet_addr(startip));
hoststop = ntohl(inet_addr(endip));
}
else
{
//Gets the input host address
testhost = gethostbyname(startip);

//If the address doesn't exist
if(!testhost)
{
 WSACleanup( );
 printf("rnCan't get ip of: %s", cp);
 exit(-1);
}
//Assign a value to the variable that controls the IP segment to be scanned
memcpy(&host, testhost->h_addr, 4);
hoststop = hoststart = ntohl(host);
}
}
//Tests if the thread is full
void TestThread(int thread = 200)
{
for (;;)
{
playx();
//Tests if the thread is full
if (maxth > thread)
 Sleep(100);
else break;
}
return;
}
//Wait for thread end function
void WaitThreadEnd()
{
//Time delay
Sleep(6000);
//Display wait prompt
printf("r   rn");
printf(" Wait ( %d )Thread end...rn", maxth);
for(;;)
{
//Determines whether all threads have ended
if (maxth > 0)
{
 //Time delay The wait line program is over 
 Sleep(100);
 playx();
 continue;
}
else break;
}
printf("rn");
return;
}
//Customize port scan parameters
void customport(char *cp, char *cp2, char *cp3)
{
int intport;
char *checker;
//Handles the port to be scanned
//Scan start port variable assignment
startport = atoi(cp2);
//Scan end port variable assignment
endport = atoi(cp2);
//Determine if it's a 21-80 form
if (strstr(cp2,"-"))
{
intport = atoi(checker = strchr(cp2, '-') + 1);
if (intport > 0 && intport < 65536)
 //Scan end port variable assignment
 endport = intport;
}
//Port size determination
if (startport < 0 || startport > 65536 || endport < 0 || endport > 65535)
{
usage(cp);
exit(-1);
}
//Processing IP addresses
setip2(cp3);
}
//Port scan function
UINT portscan(LPVOID port)
{
int addr = portip; //Gets the address to be scanned
int sock;
struct fd_set mask;
struct timeval timeout;
struct sockaddr_in server;
unsigned long flag = 1;
//Create a sock
sock = socket(AF_INET, SOCK_STREAM, 0);
//Create sock failed processing
if (sock == INVALID_SOCKET)
{
printf("rnSock Error:%s", WSAGetLastError());
maxth --;
return -1;
}
//Assign a value to the sock member
server.sin_family=AF_INET;
server.sin_addr.s_addr = htonl(addr); //The address to be scanned
server.sin_port = htons(short(port)); //Port to be scanned
// According to schedule
playx();
//The ioctlsocket() call sets the socket to non-blocking mode
if (ioctlsocket(sock, FIONBIO, &flag) != 0)
{
//Set failure handling
printf("rnSock Error:%s", WSAGetLastError());
closesocket(sock);
maxth --;
return -1;
}
//Call connect() to connect to the remote host port
connect(sock, (struct sockaddr*)&server, sizeof(server));
timeout.tv_sec = 18; //The timeout is limited to 18 seconds
timeout.tv_usec = 0;
FD_ZERO(&mask); //Clear the collection mask
FD_SET(sock, &mask); //Put sock in the collection mask

//Select () is used to process the scan results
switch(select(sock + 1, ZERO, &mask, ZERO, &timeout))
{
case -1:
{
 printf("rnSelect() error");
 maxth --;
 return -1;
}
//Sock timeout handling
case 0:
{
 maxth --;
 closesocket(sock);
 return -1;
}
default:
if(FD_ISSET(sock, &mask))
{
 //Sock is not allowed to send and receive data
 shutdown(sock, 0);
 //Format the output
 printf(" [Found:] %s Port: %d open.rn", inet_ntoa(server.sin_addr), ntohs(server.sin_port));
 //Close the sock
 closesocket(sock);
 scanok ++;
 maxth --;
 return 1;
}
}
return 0;
}
//The scan starts the main function
void portscannow(int xp)
{
int sport;
char *timenow, timebuf[32];
//The default scanned port
char *ports[32]={
"21",
"22",
"23",
"25",
"53",
"79",
"80",
"110",
"111",
"113",
"123",
"135",
"139",
"143",
"443",
"512",
"513",
"514",
"515",
"540",
"1080",
"1433",
"1521",
"1524",
"3306",
"3389",
"5631",
"6000",
"6112",
"8000",
"8080",
"12345"//Here you can also scan the port yourself
};
//Displays the time when the scan started
timenow = _strtime(timebuf);
printf("rnPortScan Start Time: %srnn",timenow);
//Counter initialization.
maxth = 0;
scanok = 0;
scannum = 0;
searched = 0;
//Calculate the number of ports to scan
searchnum = hoststop - hoststart +1;
if(xp == 3)
searchnum = searchnum * 32;
if(xp == 4)
searchnum = searchnum * (endport - startport +1);
//Port scan start
for (portip = hoststart; portip <= hoststop; portip ++, scannum ++)
{
//*.*.*.0 and *.*.*.255 address processing
if ((portip % 256) == 0 || (portip % 256) == 255)
{
 if(xp == 3)
 searchnum = searchnum - 32;
 if(xp == 4)
 searchnum = searchnum - (endport - startport +1);
 scannum --;
 playx();
 continue;
}
if(i > 11) i = 0;
//Default port scan
// scan 192.168.0.1
// scan 192.168.0.1-192.168.0.254
if (xp == 3)
{
 for (sport = 0; sport < 32; sport ++, maxth ++, searched ++)
 {
 //Tests whether the current thread is greater than 180
 TestThread(180);
 //Generates a new thread processing port scan
 CWinThread * pthread = AfxBeginThread(portscan,LPVOID(atoi((char*)ports[sport])));
 //Time delay
 Sleep(120);
 }
}
//Self port scanning
// scan -p 21 192.168.0.1
// scan -p 21-80 192.168.0.1-192.168.0.254
if (xp == 4)
{ //Calculate the port to scan
 sport = endport - startport;
 if(sport > 500 )
 {
 //Scan from the port
 for(sport = startport; sport <= endport; sport ++, maxth ++, searched ++)
 {
  TestThread(2000);
  //Generates a new thread processing port scan
  CWinThread * pthread = AfxBeginThread(portscan, LPVOID(sport));
  //Time delay
  Sleep(10);
 }
 }
 else
 {
 //Scan from the port
 for(sport = startport; sport <= endport; sport ++, maxth ++, searched ++)
 {
  //Tests whether the current thread is greater than 250
  TestThread(250);
  //Generates a new thread processing port scan
  CWinThread * pthread = AfxBeginThread(portscan, LPVOID(sport));
  //Time delay
  Sleep(100);
  playx();
 }
 }
}
}
//Wait for all threads to finish
WaitThreadEnd();
//Displays the end time of the port scan
timenow = _strtime(timebuf);
printf("rnPortScan End Time: %s", timenow);
printf("rnScan %d Hosts completed. Open %d Ports!rn", scannum, scanok);
}

In order to test the port scanner, you can use the following connection test code to test, the source code is as follows:


 
BOOL ConnectTest(char * m_server,int m_port) 
{ 
    struct hostent* host = NULL; 
    struct sockaddr_in saddr; 
    unsigned int s = 0; 
    BOOL ret; 
    time_t start; 
    int error; 
    host = gethostbyname (m_server); 
    if (host==NULL)return FALSE; 

    saddr.sin_family = AF_INET; 
    saddr.sin_port = htons(m_port); 
    saddr.sin_addr = *((struct in_addr*)host->h_addr); 
    if( (s=socket(AF_INET, SOCK_STREAM, 0))<0){ 
        return FALSE; 
    } 
    fcntl(s,F_SETFL, O_NONBLOCK); 

    if(connect(s,(struct sockaddr*)&saddr, sizeof(saddr)) == -1) { 
        if (errno == EINPROGRESS){// it is in the connect process 
            struct timeval tv; 
            fd_set writefds; 
            tv.tv_sec = m_nTimeOut; 
            tv.tv_usec = 0; 
            FD_ZERO(&writefds); 
            FD_SET(s, &writefds); 
            if(select(s+1,NULL,&writefds,NULL,&tv)>0){ 
                int len=sizeof(int); 
                //The following sentence must be, mainly for the firewall
                getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len); 
                if(error==0) ret=TRUE; 
                else ret=FALSE; 
            }else  ret=FALSE;//timeout or error happen 
        }else ret=FALSE; 
    } 
    else  ret=TRUE; 
    close(s); 
    return ret; 
}

Related articles: