Showing posts with label tcp. Show all posts
Showing posts with label tcp. Show all posts

Building a TCP-Connect Port Scanner using C

The first step in any hacking methodology is reconnaissance. In this step, the hacker enumerates information related to their target. This includes IP addresses, DNS information (through Whois lookup), open ports and services, OS type and version, and really anything else that helps the hacker choose an appropriate exploit.



In this post, I'll focus on fundamentals required to build a simple program in C which scans a target and reports the open ports on it.

Disclaimer: Scanning remote networks without permission is a crime. Be very careful with the knowledge that you learn from this post. I'll not be held responsible for any malicious activities that you may be involved in.

What exactly are we trying to build?

Nmap is the de-facto tool for scanning networks for open ports and services. Here's an example of nmap scanning the top 100 ports using TCP Connect:

nikhilh@ubuntu:~/projects/hades_scanner/src$ nmap -sT -F scanme.nmap.org

Starting Nmap 7.01 ( https://nmap.org ) at 2018-07-14 12:02 PDT
Nmap scan report for scanme.nmap.org (45.33.32.156)
Host is up (0.26s latency).
Other addresses for scanme.nmap.org (not scanned): 2600:3c01::f03c:91ff:fe18:bb2f
Not shown: 99 filtered ports
PORT   STATE SERVICE
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 21.04 seconds

The program that we're coding tries to determine port states like nmap did above.


What is TCP Connect?

TCP Connect is one of the techniques used to identify a port state. When two systems connect to each other using TCP they go through what is called a three-way handshake process.

Say, we have two systems Sys-A and Sys-B and Sys-A is trying to connect to Sys-B using TCP. The following are the steps involved in a three-way handshake process:
  1. Sys-A sends a SYN packet to Sys-B.
  2. On receipt of the SYN packet, Sys-B sends a SYN+ACK packet to Sys-A.
  3. On receipt of the SYN+ACK packet, Sys-A sends an ACK packet to Sys-B.

This is the connection methodology used by the TCP Connect technique. If our program is able to successfully connect to a port on the target, that port is deemed open, else it is closed. (There is also a technique called TCP Stealth which does not execute step 3 of the three-way handshake process but that is for another post.)

Let the coding begin!


Parsing command line options

Our program will use two required options - host and scan_type - and one flag - verbose (for debugging). We'll be using GNU long options through getopt.h to parse the passed options.

#include <getopt.h>
struct option cmdline_options[] = {
        {"host", required_argument, 0, 'h'},
        {"scan_type", required_argument, 0, 's'},
        {"verbose", no_argument, &VERBOSE,1},
        {0, 0, 0, 0}

};
opt = getopt_long(argc, argv, "h:s:", cmdline_options, &long_index);

opt contains the ASCII value of the option it is parsing. optarg variable contains the value of the parsed option. A switch-case block can be used to execute code based on the value of opt. For more information on getopt_long, refer to https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html#Getopt-Long-Options


Resolving the hostname into an IP address (if required)

The host can be specified as a hostname or an IP address. If we have a hostname on our hands, we would need to resolve it to a network address in network byte order (most significant byte first) to make it compatible with socket creation/connection.

For hostname resolution we'll use gethostbyname() defined in netdb.h

#include <netdb.h>
struct hostent *he;
struct in_addr **addr_list;
he = gethostbyname(*HOST);
addr_list = (struct in_addr **) he->h_addr_list;

addr_list is of type char **. To store the IP address in *HOST as a string, we'll use inet_ntoa()which is defined in arpa/inet.h

strcpy(*HOST, inet_ntoa(*addr_list[index]))

Creating the structure for storing target information

We'll be storing the target information in a sockaddr_in structure. AF_INET determines the domain of the socket and is being used since we're communicating over an internet socket.

struct sockaddr_in server_address;
server_address.sin_family = AF_INET;

Since the sin_addr member of sockaddr_in structure is of type of struct in_addr, we'll use a cast to get the IP address from HOST in the correct manner. We'll use inet_aton() which is defined in arpa/inet.h as well.

inet_aton(*HOST, (struct in_addr*) &server_address.sin_addr.s_addr);

Creating a socket

Socket creation is very simple and uses socket() from sys/socket.h
The first argument to socket() is the domain of the socket. In this case, since we're using an internet socket, we'll use AF_INET. The second argument is SOCK_STREAM which is the type of socket being created and is being used since we're creating a TCP type socket.

int net_socket = socket(AF_INET, SOCK_STREAM, 0);

socket() returns -1 if socket creation is unsuccessful.

Creating a connection using the socket

Since we're scanning all the ports of the target, we'll use a for loop as a port number counter. Each time we create a connection, we'll set the port number in the server_address structure. htons() ensures that the port numbers are stored in memory in network byte order. If you're working on a big-endian machine, there would be no need for using htons(). Many devices, however, store numbers in little endian format (LSB first).

server_address.sin_port = htons(port);

We'll then use connect() from sys/socket.h to create a connection to the target.

int conn_status = connect(net_socket, (struct sockaddr *)&server_address, sizeof server_address);

connect() returns -1 if the connection wasn't established.

Demo

That's it! We've gone through the fundamentals of building a simple port scanner. You can find the code for this program in my GitHub repo: https://github.com/nikhilh-20/Hades-Scanner. The repo is an ongoing work and I'll be writing more posts as and when more features are developed.

Here's a 1:44 minute demo to show how the program works (I'm scanning only ports 1-9 to keep the video short and sweet):


Popular posts