This post is the first in a series that will serve as an introduction to Python scripting for Cyber. This series does assume the reader has a basic understanding of Python and networking.
A recommended pre-requisite pathway before beginning this series is getting familiar with the basics of programming and knowing the Python fundamentals; which can be achieved by doing WYWM’s awesome Software Development Pathway. Go check it out!
This will teach you the basics of programming and Python fundamentals. Furthermore, an understanding of networking terminology is also recommended. You guessed it… WYWM has got you covered with their Networking Fundamentals Course. Go check that one too !
For those who will continue on ahead, each part of the series will build upon the previous part. These are presented in a step-by-step fashion and can easily be recreated by anyone; however, as the series progresses it might become more difficult for an individual who has no knowledge of programming.
Who is this series useful for ?
This series will benefit python enthusiasts, cyber security analysts, penetration testers and anyone who wants to familiarize themselves with exploit writing. During the series we will explore how to program client-server networks, program our own exploits, create our own attack tools and much more. I believe those interested in pentesting will greatly benefit from writing their own code.
This first entry into the series will focus on demonstrating how we can create a simple TCP client. It is very simple to do and is the first step towards writing some awesome tools and exploits in Python. For those aspiring or junior pentesters, the TCP client is what you will be using to interact and exploit basic buffer overflows.
Our TCP client can have many usages, but for simplicity we will do a simple client that connects to www.google.com on port 80.
First we are going to create a file called “tcp_client.py” using a text editor. Feel free to use nano, VIM or any text editor. For our first TCP client our script starts with the importing of the socket module. This module provides us with the necessary functions to create a client.
The socket module provides many useful functions and methods when it comes to networking. For our TCP client we will use the below: :
For those who are interested in investigating the module more in-depth they can find the full documentation of the socket module here: https://docs.python.org/3/library/socket.html
The next step will be to add two variables to our script which will be named “host” and “port”. The “host” variable will hold the name of the host/server we want to connect to. The “port” variable will hold the port number for our client to connect to. In this example we are using a domain name; however, an IP address can also be used.
This next step creates a socket object called “client” and specifies a socket type of protocols we want to use. Our next line will be the following:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Our next line of code will use the connect() method from the socket module. This method is what initiates the connection to a host/server. Since we are building a TCP client, this initiates the 3-way handshake from the client to a host/server.
Great ! Now we can connect to a host and a port. Now what we need to do is either send or receive data. For our use, we will use our TCP client to connect to www.google.com; therefore, we will use the HTTP GET request. In order to receive information we need to request it, so we will send data first.
Now that we know we will send data in the form of a HTTP GET request we need to use the send() function. Our next line will be the following:
client.send(b”GET / HTTP/1.1\r\n\r\n”)
Sending data is great. Now we need to tell our client to receive data from our target host. For this we will use the recv() function to receive the information from the server. We will also save that data to a variable. Our next line of code will be this:
response = client.recv(1024)
Now that we have our response from the server saved in a variable. Lets print that variable and since this TCP client was only a one time use let's close our connection to the server.
this closes our connection with the server.
In a few lines of code we have built a TCP client! Let's test our client and make sure everything works. For myself, I choose to run this in the CLI of my Linux OS.
There we have it. Our TCP client sent a HTTP request to www.google.com and the response received was outputted to the screen through our print() function. In the above picture we can observe the HTTP header from google.com.
The target host and port have been hardcoded into the script. Oftentimes this can suffice; however, for those who want a little more versatility we can make minor changes to our code so it accepts command line arguments. For example, the following python command runs our script and then has two arguments that are passed to it.
Python3 tcp_client.py www.google.com 80
In order to do this we start by importing the sys module:
Then we replace the data we hardcoded in the “host” and “port” variables with the following :
Now when the arguments are passed the data will be stored in both our variables. The numbers in the square brackets refer to the arguments passed at the command line in the order they are passed. If we passed a third argument we could add a third variable and have it store “ sys.argv”.
Our script now accepts command line arguments passed to it.
The TCP Client is working and we can have it connect to a server and port successfully; however, what happens if we share our script with others. They might not understand at first glance how to use our script. Let's improve the user experience by telling a user how exactly to run our TCP client.
There is a python module that will help us do exactly that. That module is the argparse module. Importing the argparse module is done the same way as the previous modules we imported.
The argparse module is really useful as it automatically generates help and usage messages, and issues errors when users give the program invalid arguments.
Adding the 4 lines of code below is all that is necessary for our TCP client. Of note, are the two lines where we specify arguments. These two lines instruct the module and the parser function to expect two arguments - host and port - and if a user does not pass two arguments an error message is generated instructing the user on how to use the client.
With No Arguments:
With the --help Argument:
Although adding argparse is not necessary for scripts meant to be written quickly when pentesting inside a network or writing an exploit meant for a one time use. It is very handy when wanting to share a tool or exploit and provide guidance to the user.
For more information on this module please refer to: https://docs.python.org/3/howto/argparse.html#id1
I used Python 3 to write the script; However, for those who are wondering what this would look like in python 2...
Here is what the code would be in python 2:
The differences between the two are very little. Line 10 does not have the ‘b’ prefix and line 14 has a pair of parentheses removed. Running the code would result in the following error.
Running it with python 2 we get no errors :
This happens because in Python 2 default strings were bytes whereas in Python 3 default strings are Unicode. With the ‘b’ prefix we are changing the string from unicode to bytes.
In addition sometimes python 2 scripts are written with no parentheses for the print() function. This will cause an error in python 3.
In python 2:
In python 3:
Knowing these two differences can go a long way in changing python2 scripts/exploits to python3. There are still many python2 scripts/exploits outhere that have not been updated to python3. Knowing some of these differences will benefit anyone wanting to stick to python3 and not having to juggle between both versions.
This marks the end of part 1 of the Python for Cyber series. Our very simple TCP client can be applied in a variety of ways. For those aspiring pentesters, the TCP client will certainly be how you will send payloads when exploiting buffer overflow vulnerabilities. As this series progresses, we will use this first part as a building block for many interesting scripts we will build.
In part 2, we will build a server and have our client and server communicate with each other.
Feel free to reach out for any questions/comments/suggestions.