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;
}