Solved

portscanner, works slow in windows

Posted on 2003-11-26
10
589 Views
Last Modified: 2008-03-10
hi !!
i had made a small utility sometime back that did a portscan on a given ip. i was using it in linux, and it worked fine .. i.e, it was fast enough. the basic thing that i was doing was a connect, and then checking the return code to determine whether the port was open or not. scanning all ports from 1 to 65536 took abt 10 seconds
i then tried using the same code, with minor changes, e.g, had to add WSAStartup(), .. etc, to make it work on windows so that i could integrate it into another program. the problem is, it works really slow on windows ... scanning ports 22 to 30 (i.e, only 9 ports) takes over 5 seconds ..
anyone know what culd be the problem ??
////////////////////////////////////////////////////////////////
//Code

WSADATA wsad;
WSAStartup(MAKEWORD(2,0),&wsad);

struct sockaddr_in thePC;
memset(&thePC,0,sizeof(thePC));
thePC.sin_family=AF_INET;

///Getting the IPAddress from the IPAddress control
DWORD IPAddress;
SendMessage(IPToPortScan,IPM_GETADDRESS,0,(LPARAM)(LPDWORD)&IPAddress);
IPAddress = ntohl(IPAddress);
memcpy((void*)&thePC.sin_addr.S_un,&IPAddress,sizeof(IPAddress));

unsigned int theP;
char thePort[8];
for (theP=22;theP<=30;theP++)
{
     SOCKET SockFDS = socket(AF_INET,SOCK_STREAM,0);
     thePC.sin_port=htons(theP);
     int n = connect(SockFDS,(sockaddr*)&thePC,sizeof(thePC));
     if (n>=0)
     {
          itoa(theP,thePort,10);
          SendMessage(ListOfOpenPorts,LB_ADDSTRING,0,(LPARAM)thePort);
          UpdateWindow(ListOfOpenPorts);
     }
     closesocket(SockFDS);
}

WSACleanup();
///////////////////////////////////

Thanks :-)
muskad202
0
Comment
Question by:muskad202
  • 7
  • 3
10 Comments
 
LVL 17

Expert Comment

by:rstaveley
ID: 9830873
I suspect that it is related to SendMessage/UpdateWindow and the fact that your message pump isn't pumped. Is it faster if you use PostMessage instead of SendMessage and finish up with a PostMessage to update the window? Sorry, I'm not much of a Windows programmer... this is pure guess-work!
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9830879
> finish up with a PostMessage to update the window

i.e. don't call UpdateWindow(ListOfOpenPorts) locally, but do that in a message handler
0
 
LVL 2

Author Comment

by:muskad202
ID: 9831447
its nothing to do with UpdateWindow/SendMessage ... etc.. its a problem in winsock. Even if i rewrite the code as below..its equally slow
---------------------------------------------------------------------------
#include <stdio.h>
#include <winsock2.h>

void main()
{
      WSADATA wsad;
      WSAStartup(MAKEWORD(2,0),&wsad);

      struct sockaddr_in thePC;
      memset(&thePC,0,sizeof(thePC));
      thePC.sin_family=AF_INET;
      thePC.sin_addr.S_un.S_addr=inet_addr("10.108.7.52");

      unsigned int theP;
      char thePort[8];
      for (theP=20;theP<=30;theP++)
      {
            SOCKET SockFDS = socket(AF_INET,SOCK_STREAM,0);
            thePC.sin_port=htons(theP);
            int n = connect(SockFDS,(sockaddr*)&thePC,sizeof(thePC));
            if (n>=0)
            {
                   itoa(theP,thePort,10);
                  printf("%s\n",thePort);
            }
                 closesocket(SockFDS);
      }

      WSACleanup();
}
------------------------------------------------------
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9831968
I've just tried this myself, and it looks like the Berkley sockets implementation in Winsock doesn't detect connect failure quickly as you surmised. Sorry for the bum steer.

You get good results, if you make sockets non-blocking for the connect and select looking for exceptions or writable descriptors:
--------8<--------
#include <iostream>
#include <winsock2.h>

bool missing_result(bool [],int);

int main()
{
      WSADATA wsad;
      WSAStartup(MAKEWORD(2,0),&wsad);

      struct sockaddr_in addr;
      memset(&addr,0,sizeof(addr));
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = inet_addr("10.108.7.52");

      const unsigned short first_port = 20;
      const int ports = 10;
      SOCKET sock[ports];
      bool result[ports];
      bool listening[ports];
      unsigned long now_nonblocking = 1;

      for (int i = 0;i < ports;i++) {
            sock[i] = socket(AF_INET,SOCK_STREAM,0);
            ioctlsocket(sock[i],FIONBIO,&now_nonblocking); // Make it a non-blocking
            addr.sin_port=htons(first_port+i);
            if (connect(sock[i],(sockaddr*)&addr,sizeof(addr)) != -1) // Non-blocking connect attempt
                  listening[i] = result[i] = true; // Immediate success is unlikely, but possible
            else
                  result[i] = false; // More likely to have to wait for a result
      }

      while (missing_result(result,ports)) { // While we are waiting for results
            fd_set wdesc,edesc;
            FD_ZERO(&wdesc); // This picks up on connection successes
            FD_ZERO(&edesc); // This picks up on connection failures
            for (int i = 0;i < ports;i++)
                  if (!result[i]) {
                        FD_SET(sock[i],&wdesc);
                        FD_SET(sock[i],&edesc);
                  }
            select(sock[ports-1]+1,(fd_set*)0,&wdesc,&edesc,0);
            for (int i = 0;i < ports;i++)
                  if (FD_ISSET(sock[i],&wdesc)) {
                        listening[i] = result[i] = true;
                        //std::cout << "Listening on port " << first_port+i << '\n';
                  }
                      else if (FD_ISSET(sock[i],&edesc)) {
                        listening[i] = false;
                        result[i] = true;
                        //std::cout << "Not listening on port " << first_port+i << '\n';
                      }
      }
      WSACleanup();

      for (int i = 0;i < ports;i++)
            if (listening[i])
                  std::cout << "Listening on port " << first_port+i << '\n';
}

bool missing_result(bool result[],int ports)
{
      for (int i = 0;i < ports;i++)
            if (result[i] == false)
                  return true;
      return false;
}
--------8<--------
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9831984
Tabulation was horrible then, I'll post that code again:
--------8<--------
#include <iostream>
#include <winsock2.h>

bool missing_result(bool [],int);

int main()
{
      WSADATA wsad;
      WSAStartup(MAKEWORD(2,0),&wsad);

      struct sockaddr_in addr;
      memset(&addr,0,sizeof(addr));
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = inet_addr("192.168.51.87");

      const unsigned short first_port = 20;
      const int ports = 10;
      SOCKET sock[ports];
      bool result[ports];
      bool listening[ports];
      unsigned long now_nonblocking = 1;

      for (int i = 0;i < ports;i++) {
            sock[i] = socket(AF_INET,SOCK_STREAM,0);
            ioctlsocket(sock[i],FIONBIO,&now_nonblocking);
            addr.sin_port=htons(first_port+i);
            if (connect(sock[i],(sockaddr*)&addr,sizeof(addr)) != -1)
                  listening[i] = result[i] = true;
            else
                  result[i] = false;
      }

      while (missing_result(result,ports)) {
            fd_set wdesc,edesc;
            FD_ZERO(&wdesc);
            FD_ZERO(&edesc);
            for (int i = 0;i < ports;i++)
                  if (!result[i]) {
                        FD_SET(sock[i],&wdesc);
                        FD_SET(sock[i],&edesc);
                  }
            select(sock[ports-1]+1,(fd_set*)0,&wdesc,&edesc,0);
            for (int i = 0;i < ports;i++)
                  if (FD_ISSET(sock[i],&wdesc)) {
                        listening[i] = result[i] = true;
                        //std::cout << "Listening on port " << first_port+i << '\n';
                  }
                  else if (FD_ISSET(sock[i],&edesc)) {
                        listening[i] = false;
                        result[i] = true;
                        //std::cout << "Not listening on port " << first_port+i << '\n';
                  }
      }
      WSACleanup();

      for (int i = 0;i < ports;i++)
            if (listening[i])
                  std::cout << "Listening on port " << first_port+i << '\n';
}

bool missing_result(bool result[],int ports)
{
      for (int i = 0;i < ports;i++)
            if (result[i] == false)
                  return true;
      return false;
}
--------8<--------
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 17

Expert Comment

by:rstaveley
ID: 9832010
Sorry I just realised that was C++... do you want a C version or is that OK?
0
 
LVL 17

Accepted Solution

by:
rstaveley earned 50 total points
ID: 9832050
...well here it is in C anyhow :-)

--------8<--------
#include <stdio.h>
#include <winsock2.h>

BOOL missing_result(BOOL [],int);

int main()
{
WSADATA wsad;
struct sockaddr_in addr;
#define      first_port 20
#define      ports 10
SOCKET sock[ports];
BOOL result[ports];
BOOL listening[ports];
unsigned long now_nonblocking = 1;
int i;

      WSAStartup(MAKEWORD(2,0),&wsad);

      memset(&addr,0,sizeof(addr));
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = inet_addr("192.168.51.87");

      for (i = 0;i < ports;i++) {
            sock[i] = socket(AF_INET,SOCK_STREAM,0);
            ioctlsocket(sock[i],FIONBIO,&now_nonblocking);
            addr.sin_port=htons(first_port+i);
            if (connect(sock[i],(struct sockaddr*)&addr,sizeof(addr)) != -1)
                  listening[i] = result[i] = TRUE;
            else
                  result[i] = FALSE;
      }

      while (missing_result(result,ports)) {
      fd_set wdesc,edesc;

            FD_ZERO(&wdesc);
            FD_ZERO(&edesc);
            for (i = 0;i < ports;i++)
                  if (!result[i]) {
                        FD_SET(sock[i],&wdesc);
                        FD_SET(sock[i],&edesc);
                  }
            select(sock[ports-1]+1,(fd_set*)0,&wdesc,&edesc,0);
            for (i = 0;i < ports;i++)
                  if (FD_ISSET(sock[i],&wdesc)) {
                        listening[i] = result[i] = TRUE;
                  }
                  else if (FD_ISSET(sock[i],&edesc)) {
                        listening[i] = FALSE;
                        result[i] = TRUE;
                  }
      }
      WSACleanup();

      for (i = 0;i < ports;i++)
            if (listening[i])
                  printf("Listening on port %d\n",first_port+i);;
}

BOOL missing_result(BOOL result[],int _ports)
{
int i;

      for (i = 0;i < _ports;i++)
            if (result[i] == FALSE)
                  return TRUE;
      return FALSE;
}
--------8<--------
0
 
LVL 2

Author Comment

by:muskad202
ID: 9832306
works like a charm !!! :)

one thing .. i thought linux and windows both used berkley sockets .. then how come it works different on both ??

thanks  :)
muskad202
0
 
LVL 2

Author Comment

by:muskad202
ID: 9832321
also .. is there any way to set a timeout for a connect ??
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 9832528
The Berkley sockets API was evolved for UNIX. I think Microsoft implemented the Berkley API for Windows on top of its own Winsock API, which is more tightly bound to the Winsock TCP/IP protocol stack. If you want to write relatively portable code, it is best to go with the Berkley API, but if you want to specialise for Windows, you'll probably get better performace if you get into the intestines of Winsock API programming.

If you look at the ConnectEx spiel at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connectex_2.asp?frame=true you'll see that you can use getsockopt with SO_CONNECT_TIME to see if a connection is established and you could abort the connection by doing DisconnectEx. I've not played around with this stuff, but I'm sure you'll find experts on EE who have.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now