Sockets and socket behavior has been around since
before the start of network programming.
Sockets allow communication to flow between processes
running on the same or different machines.
For this to work, we have to bind the socket to a specific port.
When the socket is bound to a port receiving packets,
the TCP layer knows which application is listening for that data.
We will be covering quite a few functions in this section.
The full writeup on all of them can be found on the
python.org site as a socket module comes standard and
there is no need to pip install it.
The lessons learned here are nothing new,
but how can we take these things and use them in security?
Well,
I have developed many scripts over the years that conduct
very specific tasks for pen testing, such as port scanning,
various wireless access point attacks, and on the flipside of that,
when a new server is spun up,
a server hardening script is kicked off to audit the machine
and verify things like what ports are open,
are default accounts disabled,
and some other basic reviews so a human doesn't have to waste time on it.
Looking at the functions, and there are a lot we want to cover,
so let's run through these quickly.
The socket function is what actually creates the new socket.
The provided parameters allow you to define the type of socket it is.
Bind then runs on the server side and takes that newly formed socket
and connects it to an IP and port on the server.
Listen does exactly what you would think.
You now have a socket and a port assigned to a server.
We can now listen for traffic on the bind and port.
Once packets are received on the new socket,
the accept function formally accepts the connection and tells your code
who the IP address talking to it on the other end is.
Speaking on the other end,
the connect function sits on the client side and tells the socket to make a
TCP connection with the remote server via host and port.
With different parameters, this can be a UDP port as well.
Send and sendall is the command to send a packet.
Send is limited in size,
whereas sendall can handle larger packet sizes by basically breaking
down the packet into chunks and using the send command over and over
until all the bytes have been sent.
On the other end of those sends will be the function receive that will
handle the data packets by processing them as they come in.
Once your communications are complete,
it is customary to close the socket and free up resources.
Sockets are going to be a rather complicated demo
as there are many moving parts.
I'll try to explain everything going on,
and for some,
I will just only cover the code and what's different inside of it
versus previous ones as to not confuse you.
The socket library comes standard with Python,
so you simply have to import socket to begin.
The first task is to set up a server.
In this server script,
we are simply echoing on the page everything that is sent in,
so I'll start by assigning the variables for the
loopback IP and port I want to listen on,
in this case port 12345.
The socket function will then be called with two parameters,
the first to tell the system what network protocol and the
second parameter what type of socket, in this case SOCK_STREAM,
which will send and receive TCP packets.
With the Socket class created,
I can now bind it to a specific host and port set above and
open the listener waiting for traffic.
This puts me into the ready state.
I then start an infinite loop so that the connection doesn't close
after the first communication from the client.
This loop will keep the listener open and ready.
Inside that loop, I will wait for a message using the accept function,
which will accept a key piece of information,
who sent the message.
Once the message starts coming in,
the receive function is called with a message size boundary.
This loop will keep cycling back and call the receive over and
over until the full message is pulled in.
In my demo, if the messages disconnect,
I display a disconnect message and break out of this loop; otherwise,
I tell a client I received their message and print it on the screen.
Once the loop is broken, it will move and close the connection.
On the client side,
we are setting up what host and port we want to communicate with,
which is where the server script will be sitting,
then opening a socket and connecting to the remote server and port.
For this script,
I will be dropping a message in the arguments so I can control what is sent.
Messages are in bytes with UTF‑8 encoding.
Once sent,
I then listen to see if the server sends anything back to relay to
the client a successful connection was made,
and I print that out.
So looking at this in action, on the top here I have my server script,
I'm going to set that to start running.
You'll see that it kicked off and I'm in a Ready state.
And now I'm going to send off on the client side a Hello There message
to which the server received it and sent back to say,
hey, I received your Hello message.
I'm going to try that one more time just to show it
in action that it's still looping.
I'm now going to go through and send over a disconnect message to break out.
So now I'm broken out of my listener.
Another demo I want to get into is the port scanning.
So the port scanning basically instead of sending one message,
it looks at all the different ports and sends a different message over
the different ports and says, hey, are you listening?
If it comes back with a result of 0,
it means that it's open and that it will print out to say this port is
open; otherwise, it will just simply print the port name.
So looking at this,
again I'm going to open that server up to begin listening, so I'm
showing it in a Ready state, and now when I run my port scan script,
it's going to ask me for what IP address I want to scan, so I'm just
going to loop back here, and I have it set to scan all the ports
around that 12345.
I simply wanted to show that port 12345 was opening and listening, and
you'll see a message came through that was the communication from that port
scan. I'm now going to disconnect that port, so now I'm not listening
anymore, and when I rerun my port scan on that same IP address, I'm now
going to show that that port is closed.
Okay, so two more scripts I kind of want to go through. First the UDP.
So with the UDP, instead of sending a TCP which makes a connection,
UDP makes a connection list.
I'm going to be using the SOCK_DGRAM connection type and basically sending a
message to that port and listening in for any callback.
Another one, another script that I want to talk through is
another use case for this socket connection.
So in our last lesson, we talked a little bit about YARA rules and
we talked about when it finds a hit that, hey,
you have a potential malware here,
you have a potential problem. Instead of just displaying on the screen to say,
hey, you have a problem, what if we were to open up a socket,
relay that back to a central server that's listening for these types of
things, and this way a SOC analyst who may have a dashboard up with all
these different sockets coming in can be alerted when a match of a
possible infected file comes in.