Qt – Making a Port Scanner

Whenever I start a new language, or framework, I like to attempt a port scanner.  Making a port scanner is a simple enough concept (keeping it simple that is.)  It involves looping, data handling and potentially data type conversion.  If there’s a UI, then some UI display issues as well, and potentially threading to increase performance or to add some more responsiveness of the scanner.

To date, I’ve built port scanners in Python, Ruby, and Golang, as I started to learn more about Qt, I began a scanner project as well.

Qt – C++

Qt is a C++ framework.  It makes C++ app generation quite a bit easier than raw coding C++, and it has a “Creator” UI that allows for visual representation of the application.  Beyond that, Qt can output deployments to Windows, OSX, and mobile devices.

Simple Port Scanner

To start, I built out the UI itself using the Qt Creator’s built in forms.  Forms are the traditional UI components of Qt.  Developers can also use a QT Markup language called QML to generate the responsive layouts.  For my first Qt app I decided to keep it simple.

The Qt Creator forms interface looks like this:

It’s quite intuitive and simple – I drag out labels for text labels, drag out QLineEdit boxes for fields and a QPushButton for the submit button.  For the output window, I used a QTextEdit box and dragged it out.

Color Controls

Colors are easily set via the widget’s “Palette” controller which is found in the property window:

Double clicking the value field next to “palette” it loads a color wheel UI with various slots for different elements.  Text, base, link, etc.  These are each configurable by double clicking on the element and then choosing a color.

Widget Attributes

Widgets can also be have various functions set, such as read only or the focus aspect.  This is all accessible via the Widget details.

Tool tips can also be added under the Widget details, or by right clicking the element and choosing “change Tool Tip.”

The tool tips can use plain or rich text, so you can go a bit crazy with some styling in there.

Port Scanner Logic

In the UI view, right clicking a button (like my submit button), there’s an option to “Go To Slot.”  This brings up a window for different actions.  In this case I want to select “clicked().”

When you select the signal (action), it will create some boilerplate code for you in the mainwindow.cpp (or whatever file corresponds to your UI.)

Code

Below is the code that I supplied in the clicked function:

void MainWindow::on_pushButton_clicked()
{
//     ui->running->setText("RUNNING...");
    ui->results->setText("");
    QString host = ui ->lineEditHost->text();
    QString startPort = ui ->lineEditStartPort->text();
    quint16 startPortInt = startPort.toUShort();
    QString endPort = ui ->lineEditEndPort->text();
    quint16 endPortInt = endPort.toUShort();
    QString timeout = ui ->lineEditTimeout->text();
    quint16 timeoutInt = timeout.toUShort();
    qInfo() << host;
    QTcpSocket socket;


    for(quint16 i = startPortInt; i < endPortInt; i++){

            socket.connectToHost(host, i);
            if(socket.waitForConnected(timeoutInt)){
                qInfo() << "Open Port: " << i;
                QString openPort = QString::number(i);
                ui->results->append("Port: " + openPort);
                socket.disconnectFromHost();
            }
    }
    ui->results->append("Scan Complete");
   qInfo() << "Scan Complete";
}
Qt Code

The code is probably pretty self explanatory, but I’ll go through a bit of the highlights:

ui->results->setText("");

The above UI object is pointing to an instance of the results widget (this is the QTextEdit / text box that displays results) and that is pointing to a function to clear out any output that might be there from a previous run.  Basically I’m clearing the screen.

After that, I’m setting up a series of variables that point to the UI elements / widgets.  For example:

QString host = ui ->lineEditHost->text();

The above simply takes the value input in the text field and assigns it to variable “host.”

In some cases, data types had to be changed.  Input fields come through as strings, and in the case of the “connectToHost” method, I had to convert the ports to 16 bit integers.  I did this using the toUShort() method.

The Socket creation itself is done outside the loop, and the socket is updated each time we loop through – special thanks to my friend Austin for helping me debug that.

Loop wise, it’s a simple for loop.  The only oddities would be the transforming of the 16bit integer back to a string:

QString openPort = QString::number(i);

“i” above is the port as an integer and I’m converting it back to a string using the above syntax.

Then the open ports found in that embedded if statement, are passed back to the UI

                ui->results->append("Port: " + openPort);

Socket is disconnected on each loop and outside the loop I append back to the ui a message that the scan has completed.

That’s pretty much it.

Leave a Reply

Your email address will not be published. Required fields are marked *