コード例 #1
0
 def insertQuestions_Answers(self):
     db = Database()
     f = open("Preprocessing/Question_Answers.txt", 'r')
     i = 0
     while True:
         Question = Question = DataPreprocessing.removeSinqleQuotes(
             f.readline().rstrip())
         if Question == "":
             print("------Finished reading------")
             break
         A1 = DataPreprocessing.removeSinqleQuotes(f.readline().rstrip())
         A2 = DataPreprocessing.removeSinqleQuotes(f.readline().rstrip())
         A3 = DataPreprocessing.removeSinqleQuotes(f.readline().rstrip())
         CA_ID = f.readline().rstrip()
         cols = [
             "Question", "Answer_1", "Answer_2", "Answer_3",
             "Correct_AnswerID"
         ]
         values = [
             "'" + Question + "'", "'" + A1 + "'", "'" + A2 + "'",
             "'" + A3 + "'", "'" + str(CA_ID) + "'"
         ]
         conflict_fields = [
             "Question", "Answer_1", "Answer_2", "Answer_3",
             "Correct_AnswerID"
         ]
         i += 1
         print("-----Row " + (str)(i) + " -----")
         db.insert("Questions_Answers", cols, values, conflict_fields, '')
     print("Inserted Questions_Answers rows")
コード例 #2
0
ファイル: ExportManager.py プロジェクト: kevthehermit/FudgeC2
class CampaignExportManager:

    db = Database()

    def export_campaign_database(self, username, cid):
        # check user is admin
        # check campaign exists
        # check user has read access to campaign

        return

    def generate_database_(self):
        # get information (func)
        # check database export directory exists
        # check file doesn't exist
        # create campaign_name_unixtime
        # create database
        # encrypt
        # return file, return password
        return

    def get_information(self):
        return

    def database_file_storage_check(self):
        return
コード例 #3
0
class StagerGeneration:
    # TODO: This needs cleaned up to ensure expandability with database changes.

    db = Database()
    NetProfMan = NetworkProfileManager()


    def generate_static_stagers(self, cid, user):
        ret_data = {}
        if self.db.campaign.Verify_UserCanAccessCampaign(user, cid):
            implant_info = self.db.implant.Get_AllImplantBaseFromCid(cid)
            if implant_info is not False:
                for implant in implant_info:

                    ret_data[implant['title']] = {
                        "description": implant['description'],
                        "url": implant['callback_url'],
                        "kill_date":implant['kill_date'],
                        "encryption":implant['encryption'],
                        "powershell_stager": self._generate_powershell_stager_string(implant),
                        "docm_macro_stager": self._generate_docx_stager_string(implant),
                        "stager_key": implant['stager_key']}
            return ret_data
        else:
            return ret_data

    def GenerateSingleStagerFile(self, cid, user, stager_type):
        # TODO: Create docx file download from template.
        if self.db.campaign.Verify_UserCanAccessCampaign(user, cid):
            if stager_type == "docx":
                return self._generate_docx_stager_file()
            return
        else:
            return False

    def _generate_docx_stager_string(self, implant_data):
        stager_list = []
        if 'network_profiles' in implant_data:
            for element in implant_data['network_profiles']:
                raw = self.NetProfMan.get_docm_implant_stager(element, implant_data)
                if raw is not None:
                    stager_list.append(raw)
            return stager_list
        else:
            return stager_list

    def _generate_powershell_stager_string(self, implant_data):
        # Calls the Network Profile Manager to see if a powershell stager exists, if not the network profile will return
        #   a None value. Care should be taken to avoid comms which do not have any stager options to generate active
        #   payloads.
        stager_list = []
        if 'network_profiles' in implant_data:
            for element in implant_data['network_profiles']:
                raw = self.NetProfMan.get_powershell_implant_stager(element, implant_data)
                if raw is not None:
                    stager_list.append(raw)
            return stager_list
        else:
            return stager_list
コード例 #4
0
class AppManager:
    db = None

    def __init__(self):
        self.db = Database()

    @staticmethod
    def check_software_version():
        # Returns "True" if the software is behind GitHubs master version file.
        url = "https://raw.githubusercontent.com/Ziconius/FudgeC2/master/version.txt"
        try:
            request_result = requests.get(url, timeout=0.5)
            master = request_result.content.decode()
            with open("../version.txt", 'r') as v_file:
                local_version_number = str(v_file.read())
                if LooseVersion(master) > LooseVersion(local_version_number):
                    return True
                else:
                    return False
        except Exception as exception_text:
            print(exception_text)
            return False

    @staticmethod
    def get_software_verision_number():
        try:
            with open("../version.txt", 'r') as v_file:
                local_version_number = str(v_file.read())
                return local_version_number
        except Exception as exception_text:
            print(exception_text)
            return "0.0.0"

    def campaign_create_campaign(self, user, form):
        # Responsible for validating admin account, and campaign title exists.
        if self.db.user.User_IsUserAdminAccount(user) is True:
            if 'title' in form and 'description' in form:
                if form['title'].strip() != "":
                    if self.db.campaign.create_campaign(user, form['title'].strip(), form['description'].strip()) is True:
                        return True, "Campaign created successfully."
                    else:
                        return False, "Unknown error."
                else:
                    return False, "You must supply both title and description values."
            else:
                return False, "You must supply both title and description values."
        else:
            return False, "You do not have admin permissions to create a campaign."

    def campaign_get_campaign_name_from_cid(self, cid):
        return self.db.campaign.Get_CampaignNameFromCID(cid)

    # TODO: Implement returning app logs to web app.
    def get_application_logs(self, username):
        # is user admin if not return false.
        if self.db.user.User_IsUserAdminAccount(username):
            return self.db.get_application_logs()
        else:
            return []
コード例 #5
0
    def insertNotifications():
        db = Database()
        db_access = DataAccess()
        f = open("Preprocessing/Notifications.txt", 'r')
        i = 0
        while True:
            Notification = DataPreprocessing.removeSinqleQuotes(
                f.readline().rstrip())
            if Notification == "":
                print("------Finished reading------")
                break

            cols = []
            values = []
            noAttachment = True
            if "Attachment" in Notification:
                content = Notification.split(" Attachment: ")
                Notification = content[0]
                content = content[1].split("-")
                if content[1] == "GIF":
                    rows = db_access.select("Tag", ["Tag"], ["Tag"],
                                            ["'" + content[0] + "'"], "")
                    row = rows[0][0]
                    if row is not None:  # Check the existence of the tag used as an attachment.
                        cols = ["Message", "Attachment", "Type"]
                        values = [
                            "'" + Notification + "'", "'" + content[0] + "'",
                            "'GIF'"
                        ]
                        noAttachment = False
                elif content[1] == "Button":
                    cols = ["Message", "Attachment", "Type"]
                    values = [
                        "'" + Notification + "'", "'" + content[0] + "'",
                        "'Button'"
                    ]
                    noAttachment = False
            if noAttachment == True:
                cols = ["Message"]
                values = ["'" + Notification + "'"]
            conflict_fields = ["Message"]
            i += 1
            print("-----Notification number :: " + (str)(i) + " -----")
            db.insert("Notification", cols, values, conflict_fields, "")
        print("Inserted Notification messages")
コード例 #6
0
 def __run__(self):
     d = Database()
     d.__deleteTables__()
     d.__createTables__()
     self.insertAnswers_and_keywords()
     self.insertQuestions_Answers()
     self.insertGifs()
     self.insertNotifications()
     print("Data preprocessing done!")
コード例 #7
0
class ImplantResponseProcessor:
    db = Database()

    def _system_info(self, data):
        # Username: Kris
        # Hostname: DESKTOP - SUMPM3F
        # Domain: WORKGROUP
        # Local IP: 192.168.2.130
        return None

    def process_command_response(self, command_id, command_response):
        a = self.db.implant.get_registered_implant_commands_by_command_id(
            command_id)
        b = ast.literal_eval(a['log_entry'])

        return command_response, None
コード例 #8
0
    def process_command_response(self, command_entry, raw_command_result):
        # Takes a module type value, and the result and passes the raw result to the module process_implant_response
        db = Database()
        a = db.implant.get_registered_implant_commands_by_command_id(
            command_entry)
        command_entry = a['log_entry']
        host_data = None
        response_string = raw_command_result

        implant_module = self._get_module_object_by_type_(
            command_entry['type'])
        if implant_module is not None:
            response_string, host_data = implant_module.process_implant_response(
                raw_command_result, command_entry['args'])

        # failure checks required.
        return response_string, host_data
コード例 #9
0
    def insertGifs():
        db = Database()
        file = open("Preprocessing/gifs.txt", "r")

        while True:
            line = file.readline()
            if (line == ''):
                print("EOF!")
                break
            arr = line.split(" ")
            name = "'" + arr[0].strip("\n") + "'"
            url = "'" + arr[1].strip("\n") + "'"
            tag = "'" + arr[2].strip("\n") + "'"
            db.insert("Tag", ["tag"], [tag], ["tag"], "")
            db.insert("Gifs", ["name", "url", "gif_tag"], [name, url, tag], "",
                      "")
        print("Inserted Tags & Gifs")
コード例 #10
0
class CampaignExportManager:
    export_db = None
    db = Database()
    file_dir = "Storage/ExportedCampaigns/"

    def test(self, filename, file_dir):
        # check file name for uniqueness.
        self.export_db = DbCreator(filename)
        a = self.export_db.Session.query(ExportedCampaign).all()
        return a

    def test_put(self, a, b, c, d):
        logs = ExportedCampaign(user=str(a),
                                time=str(b),
                                log_type=str(c),
                                entry=str(d))
        self.export_db.Session.add(logs)
        self.export_db.Session.commit()

    def _validate_user_(self, username, cid):
        if self.db.user.User_IsUserAdminAccount(username) is not False:
            if self.db.campaign.Verify_UserCanReadCampaign(username,
                                                           cid) is not False:
                return True
        return False

    def get_encrypted_file(self, username, cid, filename):
        if self._validate_user_(username, cid) is False:
            return False

        a = os.listdir(self.file_dir)
        if filename in a:
            return filename
        else:
            return False

    def export_campaign_database(self, username, cid):
        if self._validate_user_(username, cid) is False:
            return False

        db = self._generate_database_(cid)
        if db is False:
            return False

        # db contains(filename, file_path, password)
        result = self.encrypt_file(db[0], db[1], db[2])
        if result is False:
            return
        return result[0], result[1]

    def _generate_database_(self, cid):
        # DONE  get information (func)
        # check database export directory exists
        # DONE check file doesn't exist
        # DONE create campaign_name_unixtime
        # DONE create database
        # DONE encrypt
        # DONE return file, return password

        password = str(''.join(
            random.choices(string.ascii_lowercase + string.ascii_uppercase +
                           string.digits,
                           k=12)))
        raw_logs = self.db.Log_GetCampaignActions(cid)

        campaign_name = self.db.campaign.Get_CampaignNameFromCID(cid)
        file_name = "{}_{}".format(campaign_name.replace(" ", "_"),
                                   int(time.time()))
        file_dir = "Storage/ExportedCampaigns/"
        a = os.listdir(file_dir)
        database = file_dir + file_name
        if file_name in a:
            return False

        b = self.test(file_name, file_dir)
        for x in raw_logs:
            self.test_put(raw_logs[x]['user'], raw_logs[x]['time'],
                          raw_logs[x]['log_type'], raw_logs[x]['entry'])

        return file_name, file_dir, password

    def get_information(self):
        return

    def database_file_storage_check(self):
        return

    def encrypt_file(self, filename, file_path, password):

        password_provided = password  # This is input in the form of a string
        password = password_provided.encode()  # Convert to type bytes
        salt = b'salt_'  # CHANGE THIS - recommend using a key from os.urandom(16), must be of type bytes
        kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
                         length=32,
                         salt=salt,
                         iterations=100000,
                         backend=default_backend())
        key = base64.urlsafe_b64encode(kdf.derive(password))

        from cryptography.fernet import Fernet
        # key = b''  # Use one of the methods to get a key (it must be the same when decrypting)
        input_file = file_path + filename
        output_file = file_path + filename + ".encrypted"

        with open(input_file, 'rb') as f:

            data = f.read()

        fernet = Fernet(key)
        encrypted = fernet.encrypt(data)

        with open(output_file, 'wb') as f:
            f.write(encrypted)

        return filename + ".encrypted", password
コード例 #11
0
class UserManagementController:
    db = Database()
    def add_new_user(self, formdata=None, submitting_user=None):
        # -- Refacteror/Clean Add failure checks
        # -- Check for the keys in formdata, if none then return an error.
        # -- UserName/is_admin

        Result_Dict = {
            "action":"Add New User",
            "result":None,
            "reason":None }
        # TODO: Review if minimum lenght usernames should be permitted.
        if len(formdata['UserName']) < 3:
            Result_Dict['result'] = False
            Result_Dict['reason'] = "Username too short"
            return Result_Dict
        U = self.db.user.Get_UserObject(submitting_user)
        if U.admin == 1:
            G = self.db.user.Get_UserObject(formdata['UserName'])
            admin = False
            if 'is_admin' in formdata:
                admin = True
            if G == None:
                N=8
                pw=''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
                self.db.user.add_new_user(formdata['UserName'],pw,admin)
                Result_Dict['result']=True
                Result_Dict['reason']=str(formdata['UserName']+" now created. Password is: "+pw+" <br> Take note of this, it will not be visable again.")
            else:
                Result_Dict['result'] = False
                Result_Dict['reason'] = "User already exists."
            # -- Validate

        return Result_Dict

    def AddUserToCampaign(self, submitter, Users, Campaign, Rights=0):
        # -- Refactor with Try/Catch validating the Rights values.
        '''
        :param submitter: string
        :param Users: Request.form (dict)
        :param Campaign: int
        :param Rights: int
        :return: bool
        '''
        # Remove Right kawgs.
        # Improve variable names
        # --

        current_user_settings = self.db.campaign.get_campaign_user_settings(Campaign)

        if len(Users) < 1:
            return False
        S = self.db.user.Get_UserObject(submitter)
        if S.admin:
            for user in Users:
                for current_user in current_user_settings:
                    if user == current_user['user']:
                        if int(Users[user]) != int(current_user['permissions']):
                            self.db.campaign.User_SetCampaignAccessRights(user,
                                                                          current_user['uid'],
                                                                          Campaign,
                                                                          Users[user])
            return True
        else:
            return False

# -- New methods added in Tauren Herbalist to abstract functionality from the web application.
# --    This improves maintainability between frontend <-> Database changes.
    def user_login(self, user, password):
        # Returns False or user database object.
        return self.db.user.user_login(user, password)

    def get_first_logon_guid(self, user):
        return self.db.user.Get_UserFirstLogonGuid(user)

    def get_user_object(self, user):
        return self.db.user.Get_UserObject(user)

    def change_password_first_logon(self, form):
        pw_1 = form['password_one']
        pw_2 = form['password_two']
        pw_c = form['current_password']
        guid = form['id']
        if pw_1 == pw_2:
            user_object = self.db.user.User_ChangePasswordOnFirstLogon(guid, pw_c, pw_1)
            return user_object
        else:
            return False

    def get_current_campaign_users_settings_list(self, user, cid):
        # Returns a list of user dictionaries. Remove the current user so that a user cannot attempt to
        #   update, or remove their own configurations.
        list_of_user_settings = self.db.campaign.get_campaign_user_settings(cid)
        for x in list_of_user_settings:
            if x['user'] == user:
                list_of_user_settings.remove(x)
        return list_of_user_settings

    def campaign_get_user_access_right_cid(self, user, cid):
        # Return a boolean.
        return self.db.campaign.Verify_UserCanAccessCampaign(user, cid)

    def campaign_get_user_campaign_list(self, user):
        return self.db.campaign.get_all_user_campaigns(user)

    def campaign_get_all_implant_base_from_cid(self, user, cid):
        if self.db.campaign.Verify_UserCanReadCampaign(user, cid) is True:
            return self.db.campaign.get_all_campaign_implant_templates_from_cid(cid)
        return False
コード例 #12
0
ファイル: UserManagement.py プロジェクト: Ziconius/FudgeC2
class UserManagementController:
    db = Database()
    def process_new_user_account(self, formdata=None, submitting_user=None):
        # -- Refactor/Clean Add failure checks
        # -- Check for the keys in formdata, if none then return an error.
        # -- UserName/is_admin

        # Process - authorise user; Return False, "Insufficient permissions"
        # Parse input; Return False; "Input error"
        # Submit form; Return False; "Entry already exists"
        # Submit form; Check email; Send email; Return True; "User created, email notification"
        # Submit form; Check email; Send email; Return True; "User created, password is X"

        # Configuration vars
        generated_password_lenght = 12

        if self.db.user.User_IsUserAdminAccount(submitting_user) is not True:
            return False, "Insufficient permissions"

        name = formdata.get("name", None)
        username = formdata.get("username", None)
        user_email = formdata.get("user_email", None)
        # DEV: This will be refactored when granular permissions are implemented.
        admin = formdata.get("admin", False)
        password = ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits,
                                          k=generated_password_lenght))

        # Check if the input matches minimum:
        if len(username) < 3:
            return False, "Minimum username is 3 characters."

        # Assuming all checks passed, attempt to create the user in the database:
        state, msg = self.db.user.add_new_user(name, username, user_email, password, admin)
        if state is False:
            return False, msg
        else:
            if email_notification.email_notification_configuration():
                if email_notification.send_email_new_user_account(name, user_email, password):
                    return True, f"{username} account created. Login information has been emailed to: {user_email}"
                else:
                    return False, f"SMTP failed. New user account email notification failed. The temporary password for this account is: {password}<br>" \
                             f"Please take note of this as it will not be visible again."
            else:
                return True, f"{username} account created. The temporary password for this account is: {password}<br>" \
                             f"Please take note of this as it will not be visible again."

    def AddUserToCampaign(self, submitter, Users, Campaign, Rights=0):
        # -- Refactor with Try/Catch validating the Rights values.
        '''
        :param submitter: string
        :param Users: Request.form (dict)
        :param Campaign: int
        :param Rights: int
        :return: bool
        '''
        # Remove Right kawgs.
        # Improve variable names
        # --

        current_user_settings = self.db.campaign.get_campaign_user_settings(Campaign)

        if len(Users) < 1:
            return False
        S = self.db.user.Get_UserObject(submitter)
        if S.admin:
            for user in Users:
                for current_user in current_user_settings:
                    if user == current_user['user']:
                        if int(Users[user]) != int(current_user['permissions']):
                            self.db.campaign.User_SetCampaignAccessRights(user,
                                                                          current_user['uid'],
                                                                          Campaign,
                                                                          Users[user])
            return True
        else:
            return False

# -- New methods added in Tauren Herbalist to abstract functionality from the web application.
# --    This improves maintainability between frontend <-> Database changes.
    def user_login(self, user, password):
        # Returns False or user database object.
        return self.db.user.user_login(user, password)

    def get_first_logon_guid(self, user):
        return self.db.user.Get_UserFirstLogonGuid(user)

    def get_user_object(self, user):
        return self.db.user.Get_UserObject(user)

    def get_users_state(self, user):
        if self.db.user.User_IsUserAdminAccount(user):
            return self.db.user.get_user_state_list()
        return []
    def update_active_account_state(self, user, form):
        if self.db.user.User_IsUserAdminAccount(user):
            target_user = form['user']
            target_state = form['to_state']
            if self.db.user.change_account_active_state(target_user, target_state):
                return True
            return False
        else:
            return False
    def change_password_first_logon(self, form):
        pw_1 = form['password_one']
        pw_2 = form['password_two']
        pw_c = form['current_password']
        guid = form['id']
        if pw_1 == pw_2:
            user_object = self.db.user.User_ChangePasswordOnFirstLogon(guid, pw_c, pw_1)
            return user_object
        else:
            return False

    def get_current_campaign_users_settings_list(self, user, cid):
        # Returns a list of user dictionaries. Remove the current user so that a user cannot attempt to
        #   update, or remove their own configurations.
        list_of_user_settings = self.db.campaign.get_campaign_user_settings(cid)
        for x in list_of_user_settings:
            if x['user'] == user:
                list_of_user_settings.remove(x)
        return list_of_user_settings

    def campaign_get_user_access_right_cid(self, user, cid):
        # Return a boolean.
        return self.db.campaign.Verify_UserCanAccessCampaign(user, cid)

    def campaign_get_user_campaign_list(self, user):
        return self.db.campaign.get_all_user_campaigns(user)

    def campaign_get_all_implant_base_from_cid(self, user, cid):
        if self.db.campaign.Verify_UserCanReadCampaign(user, cid) is True:
            return self.db.campaign.get_all_campaign_implant_templates_from_cid(cid)
        return False
コード例 #13
0
class UserManagementController():
    db = Database()

    def AddUser(self, formdata=None, submitting_user=None):
        # -- Refacteror/Clean Add failure checks
        # -- Check for the keys in formdata, if none then return an error.
        # -- UserName/is_admin

        Result_Dict = {
            "action": "Add New User",
            "result": None,
            "reason": None
        }
        # TODO: Review if minimum lenght usernames should be permitted.
        if len(formdata['UserName']) < 3:
            Result_Dict['result'] = False
            Result_Dict['reason'] = "Username too short"
            return Result_Dict
        U = self.db.Get_UserObject(submitting_user)
        if U.admin:
            G = self.db.Get_UserObject(formdata['UserName'])
            admin = False
            if 'is_admin' in formdata:
                admin = True
            if G == None:
                N = 8
                pw = ''.join(
                    random.choices(string.ascii_uppercase + string.digits,
                                   k=N))
                self.db.Add_User(formdata['UserName'], pw, admin)
                Result_Dict['result'] = True
                Result_Dict['reason'] = str(
                    formdata['UserName'] + " now created. Password is: " + pw +
                    " <br> Take note of this, it will not be visable again.")
            else:
                Result_Dict['result'] = False
                Result_Dict['reason'] = "User already exists."
            # -- Validate

        return Result_Dict

    def AddUserToCampaign(self, Submitter, Users, Campaign, Rights=0):
        # -- Refactor with Try/Catch validating the Rights values.
        '''
        :param Submitter: string
        :param Users: Request.form (dict)
        :param Campaign: int
        :param Rights: int
        :return: bool
        '''
        # Remove Right kawgs.
        # Improve variable names
        # --
        if len(Users) < 1:
            return False
        if Users:
            for User in Users:
                S = self.db.Get_UserObject(Submitter)
                if S.admin:
                    U = self.db.Get_UserObject(User)
                    if U:
                        C = self.db.Verify_UserCanAccessCampaign(
                            S.user_email, Campaign)
                        if C:
                            self.db.User_SetCampaignAccessRights(
                                U.uid, Campaign, Users[User])
                else:
                    return False
            return True
コード例 #14
0
    def insertAnswers_and_keywords():
        db = Database()
        db_access = DataAccess()
        parser = TextParser()
        recognizer = WordRecognizer()
        file = open("Preprocessing/essay_questions.txt", "r")

        while True:
            line = file.readline()
            if (line == ''):
                print("no question!")
                break
            question = DataPreprocessing.removeSinqleQuotes(line.strip('-'))
            line = file.readline()
            if (line == ''):
                print("no answer!")
                break
            answer = DataPreprocessing.removeSinqleQuotes(line.strip('\n'))
            cols = ["answer"]
            values = ["'" + answer + "'"]
            db.insert("Answers", cols, values, "", "")

            cols = ["id"]
            parameters = ["answer"]
            values = ["'" + answer + "'"]
            answer_id = db_access.select("Answers", cols, parameters, values,
                                         "")

            tokens = parser.tokenize(question)
            keywords = parser.removeStopWords(tokens)
            keywords_id = []
            for k in keywords:

                cols = ["id"]
                parameters = ["keyword"]
                values = ["'" + k + "'"]
                keyword_id = db_access.select("Keywords", cols, parameters,
                                              values, "")
                if len(keyword_id) == 0:
                    cols = ["keyword"]
                    values = ["'" + k + "'"]
                    conflict_fields = ["keyword"]
                    db.insert("Keywords", cols, values, conflict_fields, "")

                    cols = ["id"]
                    parameters = ["keyword"]
                    values = ["'" + k + "'"]
                    id = db_access.select("Keywords", cols, parameters, values,
                                          "")
                    keywords_id.append(id[0][0])
                    synonyms = recognizer.getSynonym(k)
                    for s in synonyms:
                        cols = ["key_id", "synonym"]
                        values = [str(id[0][0]) + ", '" + s + "'"]
                        db.insert("Synonyms", cols, values, "", "")
                else:
                    keywords_id.append(keyword_id[0][0])
            for i in keywords_id:
                cols = ["answer_id", "keyword_id"]
                values = [str(answer_id[0][0]) + "," + str(i)]
                conflict_fields = ["answer_id", "keyword_id"]
                db.insert("Answers_Keywords", cols, values, conflict_fields,
                          "")
        print("Inserted Answers_Keywords rows")
コード例 #15
0
class ImplantManagement:
    # -- The implant management class is responsible for performing pre-checks and validation before sending data
    # --    to the Implant class
    db = Database()
    Imp = ImplantSingleton.instance
    ImpFunc = ImplantFunctionality()
    NetProMan = NetworkProfileManager()

    def _form_validated_obfucation_level_(self, form):
        # Checking if obfuscation if an integer between 0-4, if not return None to raise an error.
        try:
            obfuscation_value = int(form['obfuscation'])

            if obfuscation_value < 0:
                obfuscation_value = 0
            elif obfuscation_value > 4:
                obfuscation_value = 4
            return obfuscation_value
        except:
            return None

    def _validate_command(self, command):
        # Validate the command is one of 2 thing either a Powershell direct execution or a
        # builtin command using :: notation.
        # Once validate this processes the command into a "type" and "arg", both strings.

        command_listing = self.ImpFunc.command_listing()
        # Process command output into:
        # :: load_module powerup
        if command.lstrip()[0:2] == "::":
            preprocessed_command = command.lstrip()[2:].lower().strip()
            for x in command_listing:
                if x['input'] in preprocessed_command:
                    a = preprocessed_command.partition(x['input'])
                    r_command = {"type": x['type'], "args": a[2].strip()}
                    return r_command, True
            return command, "Unknown inbuilt command (::). See help page for more info."
        elif command.lstrip()[0:1] == ":":
            preprocessed_command = command.lstrip()[1:].lower().strip()
            for x in command_listing:
                if x['input'] in preprocessed_command:
                    return command, (
                        f"Potential typo found in command. A single colon was found, did you mean :"
                        f"{command}. If not please raise a GitHub ticket with the submitted command."
                    )

        else:
            r_command = {"type": "CM", "args": command}
            return r_command, True

    def _validate_template_kill_date(self, form):
        if 'kill_date' in form:
            try:
                # Checking to ensure a the time is not before current time.
                #  This time must match the webapp submission format.
                user_time = datetime.datetime.strptime(form['kill_date'],
                                                       '%d/%m/%Y, %H:%M')
                current_time = datetime.datetime.now()
                if user_time < current_time:
                    return None
                else:
                    # Reformatting the datetime to match implant datetime format string
                    return datetime.datetime.strftime(user_time,
                                                      '%Y-%m-%d %H:%M:%S')
            except Exception as E:
                return None

    def get_network_profile_options(self):
        return self.NetProMan.get_implant_template_code()

    def implant_command_registration(self, cid, username, form):
        result_msg = "Unknown error."
        try:
            User = self.db.campaign.Verify_UserCanWriteCampaign(username, cid)
            if User is False:
                result_msg = "You are not authorised to register commands in this campaign."
                raise ValueError

            if "cmd" not in form and "ImplantSelect" not in form:
                result_msg = f"Malformed request: {form}"
                raise ValueError

            if len(form['cmd']) == 0:
                result_msg = "No command submitted."
                raise ValueError

            processed_command, validated_command = self._validate_command(
                form['cmd'])
            if validated_command is not True:
                result_msg = validated_command
                raise ValueError

            result = self.ImpFunc.validate_pre_registered_command(
                processed_command)
            if result is not True:
                result_msg = result
                raise ValueError

            if form['ImplantSelect'] == "ALL":
                list_of_implants = self.db.implant.Get_AllGeneratedImplantsFromCID(
                    cid)
            else:
                list_of_implants = self.db.implant.Get_AllImplantIDFromTitle(
                    form['ImplantSelect'])

            # Check if any implants have been returned against the user submitted values.
            if len(list_of_implants) == 0:
                result_msg = "No implants listed."
                raise ValueError

            # Assuming all checks have passed no Exceptions will have been raised and we can register commands.
            for implant in list_of_implants:
                self.Imp.add_implant_command_to_server(
                    username, cid, implant['unique_implant_id'],
                    processed_command)
            return {"result": True, "reason": "Command registered"}
        except:
            return {"result": False, "reason": result_msg}

    def _verify_network_profile_(self, form):
        network_protocols = {}
        for key in form:
            a = self.NetProMan.validate_web_form(key, form[key])
            if a is not None:
                if a != False:
                    network_protocols.update(a)
        return network_protocols

    def create_new_implant(self, cid, form, user):
        # TODO: Create checks for conflicting ports.
        implant_configuration = {
            "title": None,
            "description": None,
            "url": None,
            "beacon": None,
            "inital_delay": None,
            "obfuscation_level": None,
            "protocol": {},
            "kill_date": None
        }
        try:
            User = self.db.user.Get_UserObject(user)
            if User.admin == 0:
                return False, "Insufficient privileges."
            campaign_priv = self.db.campaign.Verify_UserCanWriteCampaign(
                user, cid)
            if campaign_priv is False:
                raise ValueError('User cannot write to this campaign.')

            if "CreateImplant" in form:
                obfuscation_level = self._form_validated_obfucation_level_(
                    form)
                implant_configuration[
                    'kill_date'] = self._validate_template_kill_date(form)

                if obfuscation_level is None:
                    raise ValueError('Missing, or invalid obfuscation level.')
                else:
                    implant_configuration[
                        'obfuscation_level'] = obfuscation_level

                # -- Test for initial callback delay
                if 'initial_delay' in form:
                    if int(form['initial_delay']) and int(
                            form['initial_delay']) >= 0:
                        implant_configuration['initial_delay'] = form[
                            'initial_delay']
                    else:
                        raise ValueError(
                            "Initial delay must be positive integer.")
                else:
                    raise ValueError("Initial delay not submitted.")
                # -- Test for beacon delay
                if 'beacon_delay' in form:
                    if int(form['beacon_delay']) >= 1:
                        implant_configuration['beacon'] = form['beacon_delay']
                    else:
                        raise ValueError(
                            "Beacon delay must an integer greater than 1 second."
                        )
                else:
                    raise ValueError("No beacon delay submitted.")

                if form['title'] == "" or form['url'] == "" or form[
                        'description'] == "":
                    raise ValueError('Mandatory values left blank')
                else:
                    implant_configuration['title'] = form['title']
                    implant_configuration['url'] = form['url']
                    implant_configuration['description'] = form['description']
                    implant_configuration['beacon'] = form['beacon_delay']

                # Verify the input against all loaded network profiles.
                validated_network_protocols = self._verify_network_profile_(
                    form)
                if len(validated_network_protocols) != 0:
                    implant_configuration['protocol'].update(
                        validated_network_protocols)
                else:
                    raise ValueError(
                        "Error: No valid network profiles submitted.")

                implant_creation = self.db.implant.create_new_implant_template(
                    user, cid, implant_configuration)
                if implant_creation is True:
                    return True, "Implant created."
                else:
                    raise ValueError(f"Error: {implant_creation}")

        except Exception as E:
            print(E)
            return False, E

    def Get_RegisteredImplantCommands(self, username, cid=0):
        # -- Return list of dictionaries, not SQLAlchemy Objects.
        if self.db.campaign.Verify_UserCanAccessCampaign(username, cid):
            commands = self.db.implant.Get_RegisteredImplantCommandsFromCID(
                cid)
            to_dict = []
            for x in commands:
                a = x.__dict__
                if '_sa_instance_state' in a:
                    del a['_sa_instance_state']
                to_dict.append(a)
            return to_dict
        else:
            return False

    def Get_CampaignLogs(self, username, cid):
        User = self.db.campaign.Verify_UserCanReadCampaign(username, cid)
        if User is False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to view commands in this campaign."
                }
            }
        return self.db.Log_GetCampaignActions(cid)

    def get_active_campaign_implants(self, user, campaign_id):
        if self.db.campaign.Verify_UserCanAccessCampaign(user, campaign_id):
            raw = self.db.implant.Get_AllGeneratedImplantsFromCID(campaign_id)
            # Removing the SQLAlchemy object.
            tr = []
            for num, item in enumerate(raw):
                del item['_sa_instance_state']
                tr.append(item)
            return tr
        else:
            return False
コード例 #16
0
class ListenerManagement():
    active_listener = 0
    listeners = {}
    db = Database()

    def create_listener(self,
                        listener_name,
                        listener_type,
                        port=None,
                        auto_start=False,
                        url=None):
        # Listener States:
        # 0 : Stopped
        # 1 : Running
        # 2 : Awaiting Stop
        # 3 : Awaiting Start
        supported_listeners = ["http", "https"]
        a = self.__check_for_listener_duplicate_element(
            listener_name, "common_name")
        if a == False:
            return (False, "Existing listener name found.")
        a = self.__check_for_listener_duplicate_element(port, "port")
        if a == False:
            return (False, "Existing port found.")

        if listener_type in supported_listeners:
            if int(port):
                #print("Creating: ", listener_type, port)
                # TODO: Likely to contain bugs if deletion is implemented?
                id = "0000" + str(len(self.listeners))
                id = id[-4:]

                # --
                listener = {
                    "type": listener_type,
                    "port": port,
                    "state": int(0),
                    "id": id,
                    "common_name": listener_name
                }
                if auto_start == True:
                    listener["state"] = int(3)

                self.__validate_listener(listener)

                self.listeners[id] = listener
                if auto_start == True:
                    self.__review_listeners()
            else:
                return (False, "Please submit the port as an integer.")
            return (False, "Invalid listener configuration.")

        return (True, "Success")

    def listener_form_submission(self, user, form):
        # This will process the values submitted and decided what to call next
        #   these will require further management
        if not self.db.User_IsUserAdminAccount(user):
            return (False, "Insufficient privileges")
        # else:
        #     return (True, "Temp success value.")
        if 'state_change' in form:
            print("State change requested")
            if self.listeners[form['state_change']]['state'] == 0:
                print(form['state_change'])
                self.update_listener(form['state_change'], "start")
            elif self.listeners[form['state_change']]['state'] == 1:
                print(form['state_change'])
                self.update_listener(form['state_change'], "stop")

        elif 'listener_name' in form and 'listener_protocol' in form and 'listener_port' in form:
            # print("Adding new listener")
            if 'auto_start' in form:
                auto_start = True
            else:
                auto_start = False
            a = self.create_listener(form['listener_name'],
                                     form['listener_protocol'].lower(),
                                     form['listener_port'], auto_start)
            return a

        return (True, "Placeholder content")

    # User action
    def update_listener(self, id, action):
        print(id, action)
        if action == "stop":
            self.listeners[id]["state"] = 2
        if action == "start":
            self.listeners[id]["state"] = 3
        self.__review_listeners()
        return

    # Review Data
    def get_active_listeners(self, type=None):
        return self.listeners

    def __check_for_listener_duplicate_element(self, value, key):
        for x in self.listeners.keys():
            #print(self.listeners[x][key], "==",value)
            if self.listeners[x][key] == value:
                print(value, key)
                return False
        return True

    def __review_listeners(self):
        for l in self.listeners.keys():
            #print("+",self.listeners[l])
            if int(self.listeners[l]['state']) == 2:
                #print("state 2 found for ID:",l)
                self.__stop_listener(l)
            if int(self.listeners[l]['state']) == 3:
                self.__start_listener(l)

    def __start_listener(self, id):

        #print("Starting: ", id)
        self.listeners[id]['state'] = 1

        if self.listeners[id]['type'] == "http":
            self.__start_http_listener(self.listeners[id])
        elif self.listeners[id]['type'] == "https":
            self.__start_https_listener(self.listeners[id])
        elif self.listeners[id]['type'] == "dns":
            self.__start_dns_listener(self.listeners[id])

        return

    def __stop_listener(self, id):
        #print("Stopping: ", id)
        self.listeners[id]['state'] = 0
        return

    def __validate_listener(self, listener):
        # This will check for any conflicting arguments i.e. conflicting ports.
        return True

    # TODO: Refactor this code to remove as much code duplication.
    def __start_http_listener(self, obj):
        #print("Pre-Thread",obj)
        self.listeners[
            obj['id']]['listener_thread'] = _thread.start_new_thread(
                self.start_http_listener_thread, (obj, ))

    def __start_https_listener(self, obj):
        #print("Pre-Thread",obj)
        _thread.start_new_thread(self.start_https_listener_thread, (obj, ))

    def __start_dns_listener(self, obj):
        # -- This listener is not implemented yet.
        return

    def __start_binary_listener(self, obj):
        # -- This listener is not implemented yet.
        return

    def start_http_listener_thread(self, obj):
        App = HttpListener.app
        App.config['listener_type'] = "http"
        App.run(debug=False,
                use_reloader=False,
                host='0.0.0.0',
                port=obj['port'],
                threaded=True)

    def start_https_listener_thread(self, obj):
        AppSsl = HttpListener.app
        AppSsl.config['listener_type'] = "https"
        path = os.getcwd() + "/Storage/"
        #print(path)
        AppSsl.run(debug=False,
                   use_reloader=False,
                   host='0.0.0.0',
                   port=obj['port'],
                   threaded=True,
                   ssl_context=(path + 'server.crt', path + 'server.key'))
コード例 #17
0
class ImplantManagement:
    # -- The implant management class is responsible for performing pre-checks and validation before sending data
    # --    to the Implant class
    db = Database()
    Imp = ImplantSingleton.instance

    def _form_validated_obfucation_level_(self, form):
        if "obfuscation" in form:
            try:
                obfuscation_value = int(form['obfuscation'])

                if obfuscation_value < 0:
                    return 0
                elif obfuscation_value > 3:
                    return 3
                else:
                    return obfuscation_value
            except:
                print("None integer submitted.")
                return None
        return None

    def _validate_command(self, command):
        # -- TODO: Check if type needs to be enforced.
        special_cmd = ["sys_info", "enable_persistence"]
        if command[0:2] == "::":
            preprocessed_command = command[2:].lower().strip()
            if preprocessed_command in special_cmd:
                postprocessed_command = ":: " + preprocessed_command
                return postprocessed_command, True
            return command, {
                "cmd_reg": {
                    "result": False,
                    "reason": "Unknown inbuilt command, i.e. '::'"
                }
            }
        return command, True

    def ImplantCommandRegistration(self, cid, username, form):
        # -- This should be refactored at a later date to support read/write changes to
        # --    granular controls on templates, and later specific implants
        # print("CID: ",cid,"\nUSR: "******"\nCMD: ",form)
        User = self.db.campaign.Verify_UserCanWriteCampaign(username, cid)
        if User is False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to register commands in this campaign."
                }
            }

        # -- Get All implants or implants by name then send to 'implant.py'
        # -- email, unique implant key, cmd
        if "cmd" in form and "ImplantSelect" in form:
            # -- before checking the database assess the cmd that was input.
            if len(form['cmd']) == 0:
                return {
                    "cmd_reg": {
                        "result": False,
                        "reason": "No command submitted."
                    }
                }
            processed_command, validated_command = self._validate_command(
                form['cmd'])
            if validated_command is not True:
                return validated_command

            # -- If validated_command is True then continue as it IS a valid command. N.b it may not be a legitimate command, but it is considered valid here.
            if form['ImplantSelect'] == "ALL":
                list_of_implants = self.db.implant.Get_AllGeneratedImplantsFromCID(
                    cid)
            else:
                list_of_implants = self.db.implant.Get_AllImplantIDFromTitle(
                    form['ImplantSelect'])
            # -- Access if this can fail. If empty return error.
            if len(list_of_implants) == 0:
                return {
                    "cmd_reg": {
                        "result": False,
                        "reason": "No implants listed."
                    }
                }
            for implant in list_of_implants:
                # -- Create return from the Implant.AddCommand() method.
                self.Imp.AddCommand(username, cid,
                                    implant['unique_implant_id'],
                                    processed_command)
            return {
                "cmd_reg": {
                    "result": True,
                    "reason": "Command registered"
                }
            }
        return {
            "cmd_reg": {
                "result":
                False,
                "reason":
                "Incorrect implant given, or non-existent active implant."
            }
        }

    def CreateNewImplant(self, cid, form, user):
        # TODO: Create checks for conflicting ports.
        implant_configuration = {
            "title": None,
            "description": None,
            "url": None,
            "beacon": None,
            "inital_delay": None,
            "obfuscation_level": None,
            "protocol": {
                "comms_http": None,
                "comms_https": None,
                "comms_binary": None,
                "comms_dns": None
            }
        }
        print(form)
        User = self.db.user.Get_UserObject(user)
        if User.admin == 0:
            return False, "Insufficient privileges."
        CampPriv = self.db.campaign.Verify_UserCanWriteCampaign(user, cid)
        if CampPriv is False:
            return False, "User cannot write to this campaign."

        try:
            if "CreateImplant" in form:
                obfuscation_level = self._form_validated_obfucation_level_(
                    form)
                if obfuscation_level is None:
                    raise ValueError('Missing, or invalid obfuscation level.')
                else:
                    implant_configuration[
                        'obfuscation_level'] = obfuscation_level

                # -- Test for initial callback delay
                if 'initial_delay' in form:
                    if int(form['initial_delay']) and int(
                            form['initial_delay']) >= 0:
                        implant_configuration['initial_delay'] = form[
                            'initial_delay']
                    else:
                        raise ValueError(
                            "Initial delay must be positive integer.")
                else:
                    raise ValueError("Initial delay not submitted.")
                # -- Test for beacon delay
                if 'beacon_delay' in form:
                    if int(form['beacon_delay']) >= 1:
                        implant_configuration['beacon'] = form['beacon_delay']
                    else:
                        raise ValueError(
                            "Beacon delay must an integer greater than 1 second."
                        )
                else:
                    raise ValueError("No beacon delay submitted.")

                if form['title'] == "" or form['url'] == "" or form[
                        'description'] == "":
                    raise ValueError('Mandatory values left blank')
                else:
                    implant_configuration['title'] = form['title']
                    implant_configuration['url'] = form['url']
                    implant_configuration['description'] = form['description']
                    implant_configuration['beacon'] = form['beacon_delay']

                a = {
                    "comms_http": "http-port",
                    "comms_https": "https-port",
                    "comms_dns": "dns-port",
                    "comms_binary": "binary-port"
                }
                for element in a.keys():
                    print("::", element)
                    if element in form:
                        # print("@@", form[a[element]])
                        if int(form[a[element]]):
                            if int(form[a[element]]) > 0 or int(
                                    form[a[element]]) < 65536:
                                # print(int(form[a[element]]))
                                implant_configuration["protocol"][
                                    element] = int(form[a[element]])
                            else:
                                raise ValueError(
                                    "Submitted port for {} is out of range".
                                    format(a[element]))
                        else:
                            # print(form[element])
                            raise ValueError(
                                "Ports must be submitted as an integer")

                protocol_set = False
                for proto in implant_configuration['protocol'].keys():
                    if implant_configuration['protocol'][proto] is None:
                        protocol_set = True
                if protocol_set is False:
                    raise ValueError(
                        'No protocol selected, ensure a protocol and port are selected.'
                    )

                # print("Final configuration:")
                # for element in implant_configuration.keys():
                #     print(element,": ",implant_configuration[element])

                a = self.db.implant.create_new_implant_template(
                    user, cid, implant_configuration)
                if a is True:
                    return True, "Implant created."
                else:
                    raise ValueError(
                        "Error creating entry. Ensure implant title is unique."
                    )

        except Exception as E:
            return False, E

        return

    def Get_RegisteredImplantCommands(self, username, cid=0):
        # -- Return list of dictionaries, not SQLAlchemy Objects.
        if self.db.campaign.Verify_UserCanAccessCampaign(username, cid):
            Commands = self.db.implant.Get_RegisteredImplantCommandsFromCID(
                cid)
            toDict = []
            for x in Commands:
                a = x.__dict__
                if '_sa_instance_state' in a:
                    del a['_sa_instance_state']
                toDict.append(a)
            return toDict
        else:
            return False

    def Get_CampaignLogs(self, username, cid):
        User = self.db.campaign.Verify_UserCanReadCampaign(username, cid)
        if User is False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to view commands in this campaign."
                }
            }
        return self.db.Log_GetCampaignActions(cid)

    def get_active_campaign_implants(self, user, campaign_id):
        if self.db.campaign.Verify_UserCanAccessCampaign(user, campaign_id):
            return self.db.implant.Get_AllGeneratedImplantsFromCID(campaign_id)
        else:
            return False
コード例 #18
0
class ImplantManagement():
    # -- The implant management class is responsible for performing pre-checks and validation before sending data
    # --    to the Implant class
    db = Database()
    Imp = ImplantSingleton.instance

    def _form_validated_obfucation_level_(self, form):
        for x in form:
            if "obfus" in x:
                a = x.split("-")
                # -- returning first value, we should only receive a single entry.
                try:
                    return int(a[1])
                except:
                    return None
        return None

    def _validate_command(self, command):
        # -- TODO: Check if type needs to be enforced.
        special_cmd = ["sys_info"]
        if command[0:2] == "::":
            preprocessed_command = command[2:].lower().strip()
            if preprocessed_command in special_cmd:
                postprocessed_command = ":: " + preprocessed_command
                return postprocessed_command, True
            return command, {
                "cmd_reg": {
                    "result": False,
                    "reason": "Unknown inbuilt command, i.e. '::'"
                }
            }
        return command, True

    def ImplantCommandRegistration(self, cid, username, form):
        # -- This should be refactored at a later date to support read/write changes to
        # --    granular controls on templates, and later specific implants
        #print("CID: ",cid,"\nUSR: "******"\nCMD: ",form)
        User = self.db.Verify_UserCanWriteCampaign(username, cid)
        if User == False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to register commands in this campaign."
                }
            }

        # -- Get All implants or implants by name then send to 'implant.py'
        # -- email, unique implant key, cmd
        if "cmd" in form and "ImplantSelect" in form:
            # -- before checking the database assess the cmd that was input.
            processed_command, validated_command = self._validate_command(
                form['cmd'])
            if validated_command != True:
                return validated_command

            # -- If validated_command is True then continue as it IS a valid command. N.b it may not be a legitimate command, but it is considered valid here.
            if form['ImplantSelect'] == "ALL":
                ListOfImplants = self.db.Get_AllGeneratedImplantsFromCID(cid)
            else:
                ListOfImplants = self.db.Get_AllImplantIDFromTitle(
                    form['ImplantSelect'])
            # -- Access if this can fail. If empty return error.
            if len(ListOfImplants) == 0:
                return {
                    "cmd_reg": {
                        "result": False,
                        "reason": "No implants listed."
                    }
                }
            for implant in ListOfImplants:
                # -- Create return from the Implant.AddCommand() method.
                self.Imp.AddCommand(username, cid,
                                    implant['unique_implant_id'],
                                    processed_command)
            return {
                "cmd_reg": {
                    "result": True,
                    "reason": "Command registered"
                }
            }
        return {
            "cmd_reg": {
                "result":
                False,
                "reason":
                "Incorrect implant given, or non-existant active implant."
            }
        }

    def CreateNewImplant(self, cid, form, user):
        # -- This is creating a new Implant Template
        User = self.db.Get_UserObject(user)
        if User.admin == 0:
            return False, "Insufficient Priviledges"
        CampPriv = self.db.Verify_UserCanWriteCampaign(user, cid)
        if CampPriv == False:
            return False, "User cannot write to this campaign"
        # -- From here we know the user is able to write to the Campaign and an admin.

        try:
            if "CreateImplant" in form:
                obfuscation_level = self._form_validated_obfucation_level_(
                    form)
                if obfuscation_level == None:
                    print("OL", obfuscation_level)
                    raise ValueError('Missing, or invalid obfuscation levels')
                if form['title'] == "" or form['url'] == "" or form[
                        'description'] == "":
                    raise ValueError('Mandatory values left blank')
                title = form['title']
                url = form['url']
                port = form['port']
                description = form['description']
                beacon = form['beacon_delay']
                initial_delay = form['initial_delay']
                comms_http = 0
                comms_https = 0
                comms_dns = 0
                comms_binary = 0
                try:
                    port = int(port)
                except:
                    if type(port) != int:
                        raise ValueError('Port is required as integer')
                # -- Comms check --#
                if "comms_http" in form:
                    comms_http = 1
                if "comms_https" in form:
                    comms_https = 1
                if "comms_dns" in form:
                    comms_dns = 1
                if "comms_binary" in form:
                    comms_binary = 1
                if comms_binary == 0 and comms_dns == 0 and comms_http == 0 and comms_https == 0:
                    raise ValueError('No communication channel selected.')
                if comms_http == 1 and comms_https == 1:
                    raise ValueError(
                        "Please select either HTTP or HTTPS. Multi-protocol is not yet supported."
                    )
                a = self.db.Add_Implant(cid, title, url, port, beacon,
                                        initial_delay, comms_http, comms_https,
                                        comms_dns, comms_binary, description,
                                        obfuscation_level)
                if a == True:
                    return True, "Implant created."
                else:
                    raise ValueError(
                        "Error creating entry. Ensure implant title is unique")
        except Exception as e:
            # --  returning page with generic Error --#
            return False, e

    def Get_RegisteredImplantCommands(self, username, cid=0):
        # -- Return list of dictionaries, not SQLAlchemy Objects.
        if self.db.Verify_UserCanAccessCampaign(username, cid):
            Commands = self.db.Get_RegisteredImplantCommandsFromCID(cid)
            toDict = []
            for x in Commands:
                a = x.__dict__
                if '_sa_instance_state' in a:
                    del a['_sa_instance_state']
                toDict.append(a)
            return toDict
        else:
            return False

    def Get_CampaignLogs(self, username, cid):
        User = self.db.Verify_UserCanReadCampaign(username, cid)
        if User == False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to view commands in this campaign."
                }
            }
        return self.db.Log_GetCampaignActions(cid)
コード例 #19
0
    class __OnlyOne:
        # Dev Work:
        #   Improve logging on listener events
        #   Improve race-condition checks

        listeners = []
        db = Database()
        npm = NetworkProfileManager()

        def create_new_listener(self, username, common_name, profile_tag, args,
                                auto_start):
            # First check the profile tag is valid, and then ensure adding the listener to the DB is successful
            #   before taking action.
            if self.db.user.User_IsUserAdminAccount(username):
                listener_class = self.npm.get_listener_object(profile_tag)
                listener_interface = self.npm.get_listener_interface(
                    profile_tag)
                if listener_class is not None and listener_interface is not None:

                    if self.db.listener.create_new_listener_record(
                            common_name, args, profile_tag, auto_start):
                        listener = self.db.listener.get_listener_by_common_name(
                            common_name)
                        if listener is not False:
                            # already instantiated interface
                            listener['interface'] = listener_interface
                            listener['interface'].configure(
                                listener_class, args)
                            self.listeners.append(listener)
                            self.listener_state_change(username,
                                                       listener['name'],
                                                       listener['auto_run'])
                            return True
            return False

        def get_all_listeners(self):
            # Create copys of listeners to avoid the interface being removed.
            to_return = []
            for listener in self.listeners:
                to_return.append(copy.copy(listener))
            return to_return

        def get_listener_state(self, common_name):
            for listener in self.listeners:
                if listener['common_name'] == common_name:
                    return listener['object'].query_state()

        def startup_auto_run_listeners(self):
            tmp_listeners = self.db.listener.get_all_listeners()
            for listener in tmp_listeners:
                listener_class = self.npm.get_listener_object(
                    listener['protocol'])
                listener_interface = self.npm.get_listener_interface(
                    listener['protocol'])
                if listener_class is not None and listener_interface is not None:
                    # Already instantiated interface
                    listener['interface'] = listener_interface
                    listener['interface'].configure(listener_class,
                                                    listener['port'])
                    self.listeners.append(listener)
                    self.listener_state_change(True, listener['name'],
                                               listener['auto_run'])

        def listener_state_change(self, username, common_name, state):
            state_change_message = "Insufficient privileges"
            if self.db.user.User_IsUserAdminAccount(
                    username) or username is True:
                for listener in self.listeners:
                    if listener['name'] == common_name:
                        if state == 0 and listener['state'] == 1:
                            listener['state'] = 0
                            listener['interface'].stop_listener()
                            state_change_message = f"Successfully stopped {common_name}"
                        elif state == 1:
                            listener['state'] = 1
                            listener['interface'].start_listener()
                            state_change_message = f"Successfully started {common_name}"
            return state_change_message

        # Undecided if I want to check for server certificates at a global level - this should be down to
        #   specific network profiles?
        # Note: This is still called when the C2 server starts for now so automatically return True.
        @staticmethod
        def check_tls_certificates():
            return True
コード例 #20
0
class ListenerManagement:
    listeners = {}
    db = Database()

    def __init__(self, a, b):
        pass

    def _check_if_listener_is_unique(self, name, port, protocol, reboot):
        # Bypass the unique check when rebooting.
        if reboot:
            return True
        a = self.db.listener.get_all_listeners()
        for x in a:
            if x.name == name:
                return False
        return True

    def _create_listener(self,
                         name,
                         raw_protocol,
                         port,
                         auto_start=False,
                         reboot=False):
        protocol = raw_protocol.lower()
        if self._check_if_listener_is_unique(name, port, protocol, reboot):
            if protocol.lower() == "http" or protocol.lower() == "https":
                self.listeners[name] = HttpListener(name, port, protocol)
            elif protocol == "binary":
                self.listeners['name'] = BinaryListener(name, port, protocol)
            else:
                return False

            if reboot is not True:
                if self.db.listener.create_new_listener_record(
                        name, port, protocol, auto_start) is False:
                    return False

            if auto_start is True or auto_start == 1:
                self.listeners[name].start_listener()
        else:
            return False

        return True

    def _update_listener_state(self, listener, state):
        if listener in self.listeners.keys():
            if state == "off":
                self.listeners[listener].stop_listener()
            elif state == "on":
                self.listeners[listener].start_listener()
        return

    def check_tls_certificates(self):
        return True

    def get_active_listeners(self):
        blah = {}
        for listener in self.listeners:
            blah[self.listeners[listener].name] = {
                "type": self.listeners[listener].type,
                "port": self.listeners[listener].port,
                "state": self.listeners[listener].query_state(),
                "id": "who knows",
                "common_name": self.listeners[listener].name
            }
        return blah

    def update_listener_state(self, username, form):
        if self.db.user.User_IsUserAdminAccount(username) is False:
            return False, "You are not an admin."

        if "state_change" in form:

            if form['state_change'] in self.listeners.keys():
                current_state = self.listeners[
                    form['state_change']].query_state()
                if current_state is True:
                    self._update_listener_state(form['state_change'], "off")
                else:
                    self._update_listener_state(form['state_change'], "on")
                return True, ""

        else:
            return False, ""

    def create_new_listener(self, username, form):
        if self.db.user.User_IsUserAdminAccount(username) is False:
            return False, "You are not an admin."

        if "listener_name" in form:
            auto_start = False
            if "auto_start" in form:
                auto_start = True
            listener_created = self._create_listener(form['listener_name'],
                                                     form['listener_protocol'],
                                                     form['listener_port'],
                                                     auto_start)
            if listener_created is True:
                return True, "Listener created"
            else:
                return False, "Error in _create_listener()"
        else:
            return False, ""

    def start_auto_run_listeners_at_boot(self):
        auto_run_listeners = self.db.listener.get_all_listeners()
        for listener in auto_run_listeners:
            self._create_listener(listener.name, listener.protocol,
                                  listener.port, listener.auto_run, True)
コード例 #21
0
 def __init__(self):
     self.db = Database()
コード例 #22
0
ファイル: Implant.py プロジェクト: cyberhunter00/FudgeC2
            # --    May need to move authentication to this level.
            return db.implant.Get_CampaignImplantResponses(cid)

        # -- Used by Implant stagers to create a suitable implant based on implant template configuration
        def GeneratePayload(self, NewSplicedImplantData):
            # -- Refactor code: variable names + checks on types.
            ImpGen = ImplantGenerator()
            if len(NewSplicedImplantData) == 1:
                NewSplicedImplantData = NewSplicedImplantData[0]
            rendered_implant = ImpGen.generate_implant_from_template(NewSplicedImplantData)
            db.implant.Set_GeneratedImplantCopy(NewSplicedImplantData, rendered_implant)
            return rendered_implant

        # TODO:
        # create functions for all listener/webapp/stager actions to avoid direct DB queries from ImplantManager, HttpListener/HttpsListener etc

        # Register implant submit stager key ( implant template returns a unique implant id aka unique implant key )
        # Implant check in: UII/UIK + protocol checkin occured over



    instance = None
    def __init__(self):
        if not ImplantSingleton.instance:
            ImplantSingleton.instance = ImplantSingleton.__OnlyOne()
        else:
            ImplantSingleton.instance.val = arg

db = Database()
ImplantSingleton() # Create Singleton
コード例 #23
0
class ImplantManagement:
    # -- The implant management class is responsible for performing pre-checks and validation before sending data
    # --    to the Implant class
    db = Database()
    Imp = ImplantSingleton.instance

    def _form_validated_obfucation_level_(self, form):
        if "obfuscation" in form:
            try:
                obfuscation_value = int(form['obfuscation'])

                if obfuscation_value < 0:
                    return 0
                elif obfuscation_value > 3:
                    return 3
                else:
                    return obfuscation_value
            except:
                return None
        return None

    def _validate_command(self, command):
        command_listing = [{
            "type": "FU",
            "args": "base64-file::filelocation",
            "input": "upload_file"
        }, {
            "type": "FD",
            "args": "base64 target file",
            "input": "download_file"
        }, {
            "type": "PS",
            "args": "sound file location (on Fudge)",
            "input": "play_audio"
        }, {
            "type": "EP",
            "args": None,
            "input": "enable_persistence"
        }, {
            "type": "SI",
            "args": None,
            "input": "sys_info"
        }, {
            "type": "EC",
            "args": None,
            "input": "export_clipboard"
        }, {
            "type": "LM",
            "args": None,
            "input": "load_module"
        }, {
            "type": "IM",
            "args": None,
            "input": "exec_module"
        }, {
            "type": "ML",
            "args": None,
            "input": "list_modules"
        }]

        # Process command output into:
        if command.lstrip()[0:2] == "::":
            preprocessed_command = command.lstrip()[2:].lower().strip()
            for x in command_listing:
                if x['input'] in preprocessed_command:
                    a = preprocessed_command.partition(x['input'])
                    r_command = {"type": x['type'], "args": a[2].strip()}
                    return r_command, True
            return command, {
                "cmd_reg": {
                    "result": False,
                    "reason": "Unknown inbuilt command, i.e. '::'"
                }
            }
        elif command.lstrip()[0:1] == ":":
            preprocessed_command = command.lstrip()[1:].lower().strip()
            for x in command_listing:
                if x['input'] in preprocessed_command:
                    return command, {
                        "cmd_reg": {
                            "result":
                            False,
                            "reason":
                            f"Potential typo found in \
command.A single colon was found, did you mean: :{command}. If not please submit a GitHub ticket with the \
submitted command."
                        }
                    }

        else:
            r_command = {"type": "CM", "args": command}
            return r_command, True

    def ImplantCommandRegistration(self, cid, username, form):
        # -- This should be refactored at a later date to support read/write changes to
        # --    granular controls on templates, and later specific implants
        User = self.db.campaign.Verify_UserCanWriteCampaign(username, cid)
        if User is False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to register commands in this campaign."
                }
            }

        # -- Get All implants or implants by name then send to 'implant.py'
        # -- email, unique implant key, cmd
        if "cmd" in form and "ImplantSelect" in form:
            # -- before checking the database assess the cmd that was input.
            if len(form['cmd']) == 0:
                return {
                    "cmd_reg": {
                        "result": False,
                        "reason": "No command submitted."
                    }
                }

            processed_command, validated_command = self._validate_command(
                form['cmd'])
            if validated_command is not True:
                return validated_command

            # -- If validated_command is True then continue as it IS a valid command. N.b it may not be a legitimate command, but it is considered valid here.
            if form['ImplantSelect'] == "ALL":
                list_of_implants = self.db.implant.Get_AllGeneratedImplantsFromCID(
                    cid)
            else:
                list_of_implants = self.db.implant.Get_AllImplantIDFromTitle(
                    form['ImplantSelect'])

            # -- Access if this can fail. If empty return error.
            if len(list_of_implants) == 0:
                return {
                    "cmd_reg": {
                        "result": False,
                        "reason": "No implants listed."
                    }
                }

            for implant in list_of_implants:
                # -- Create return from the Implant.AddCommand() method.
                self.Imp.AddCommand(username, cid,
                                    implant['unique_implant_id'],
                                    processed_command)
            return {
                "cmd_reg": {
                    "result": True,
                    "reason": "Command registered"
                }
            }
        return {
            "cmd_reg": {
                "result":
                False,
                "reason":
                "Incorrect implant given, or non-existent active implant."
            }
        }

    def CreateNewImplant(self, cid, form, user):
        # TODO: Create checks for conflicting ports.
        implant_configuration = {
            "title": None,
            "description": None,
            "url": None,
            "beacon": None,
            "inital_delay": None,
            "obfuscation_level": None,
            "protocol": {
                "comms_http": None,
                "comms_https": None,
                "comms_binary": None,
                "comms_dns": None
            }
        }
        try:
            User = self.db.user.Get_UserObject(user)
            if User.admin == 0:
                return False, "Insufficient privileges."
            campaign_priv = self.db.campaign.Verify_UserCanWriteCampaign(
                user, cid)
            if campaign_priv is False:
                raise ValueError('User cannot write to this campaign.')

            if "CreateImplant" in form:
                obfuscation_level = self._form_validated_obfucation_level_(
                    form)
                if obfuscation_level is None:
                    raise ValueError('Missing, or invalid obfuscation level.')
                else:
                    implant_configuration[
                        'obfuscation_level'] = obfuscation_level

                # -- Test for initial callback delay
                if 'initial_delay' in form:
                    if int(form['initial_delay']) and int(
                            form['initial_delay']) >= 0:
                        implant_configuration['initial_delay'] = form[
                            'initial_delay']
                    else:
                        raise ValueError(
                            "Initial delay must be positive integer.")
                else:
                    raise ValueError("Initial delay not submitted.")
                # -- Test for beacon delay
                if 'beacon_delay' in form:
                    if int(form['beacon_delay']) >= 1:
                        implant_configuration['beacon'] = form['beacon_delay']
                    else:
                        raise ValueError(
                            "Beacon delay must an integer greater than 1 second."
                        )
                else:
                    raise ValueError("No beacon delay submitted.")

                if form['title'] == "" or form['url'] == "" or form[
                        'description'] == "":
                    raise ValueError('Mandatory values left blank')
                else:
                    implant_configuration['title'] = form['title']
                    implant_configuration['url'] = form['url']
                    implant_configuration['description'] = form['description']
                    implant_configuration['beacon'] = form['beacon_delay']

                a = {
                    "comms_http": "http-port",
                    "comms_https": "https-port",
                    "comms_dns": "dns-port",
                    "comms_binary": "binary-port"
                }
                for element in a.keys():
                    if element in form:
                        if int(form[a[element]]):
                            if int(form[a[element]]) > 0 or int(
                                    form[a[element]]) < 65536:
                                implant_configuration["protocol"][
                                    element] = int(form[a[element]])
                            else:
                                raise ValueError(
                                    f"Submitted port for {a[element]} is out of range"
                                )
                        else:
                            raise ValueError(
                                "Ports must be submitted as an integer")

                protocol_set = False
                for proto in implant_configuration['protocol'].keys():
                    if implant_configuration['protocol'][proto] is None:
                        protocol_set = True
                if protocol_set is False:
                    raise ValueError(
                        'No protocol selected, ensure a protocol and port are selected.'
                    )

                a = self.db.implant.create_new_implant_template(
                    user, cid, implant_configuration)
                if a is True:
                    return True, "Implant created."
                else:
                    raise ValueError(
                        "Error creating entry. Ensure implant title is unique."
                    )

        except Exception as E:
            return False, E

    def Get_RegisteredImplantCommands(self, username, cid=0):
        # -- Return list of dictionaries, not SQLAlchemy Objects.
        if self.db.campaign.Verify_UserCanAccessCampaign(username, cid):
            commands = self.db.implant.Get_RegisteredImplantCommandsFromCID(
                cid)
            to_dict = []
            for x in commands:
                a = x.__dict__
                if '_sa_instance_state' in a:
                    del a['_sa_instance_state']
                to_dict.append(a)
            return to_dict
        else:
            return False

    def Get_CampaignLogs(self, username, cid):
        User = self.db.campaign.Verify_UserCanReadCampaign(username, cid)
        if User is False:
            return {
                "cmd_reg": {
                    "result":
                    False,
                    "reason":
                    "You are not authorised to view commands in this campaign."
                }
            }
        return self.db.Log_GetCampaignActions(cid)

    def get_active_campaign_implants(self, user, campaign_id):
        if self.db.campaign.Verify_UserCanAccessCampaign(user, campaign_id):
            raw = self.db.implant.Get_AllGeneratedImplantsFromCID(campaign_id)
            # Removing the SQLAlchemy object.
            tr = []
            for num, item in enumerate(raw):
                del item['_sa_instance_state']
                tr.append(item)
            return tr
        else:
            return False