def _(*args): parser = helpers.ArgumentParser( prog='logs', description='Get logs for a user or computer') parser.add_argument('-c', '--computer', help='Get logs for computer') parser.add_argument('-u', '--user', help='Get logs for user') parser.add_argument('out', help='Output file') try: args = parser.parse_args(args) except: return finds = 0 for frame in aggressor.data_query('beaconlog'): output_type = frame[0] bid = frame[1] if output_type == 'beacon_input': user = frame[2] data = frame[3] time = convert_time(frame[4]) else: data = frame[2] time = convert_time(frame[3]) user = aggressor.beacon_info(bid, 'user') computer = aggressor.beacon_info(bid, 'computer') if user == args.user or computer == args.computer: # it's a match! finds += 1 # -o/--out with open(args.out, 'a+') as fp: fp.write(data) engine.message('Wrote {} finds to {}'.format(finds, args.out))
def _(bid, text, when): global _triggers user = aggressor.beacon_info(bid, 'user') computer = aggressor.beacon_info(bid, 'computer') for trigger in _triggers: if trigger['type'] == 'output': _conditionally_run(bid, trigger)
def get_logs(out, bid=None, user=None, computer=None): """ Get logs for a bid, user, or computer :param out: Output file :param bid: Bid to match :param user: User to match :param computer: Computer to match """ finds = 0 for frame in aggressor.data_query('beaconlog'): log = parse_log(frame) if log['type'] == 'beacon_indicator': # skip indicators continue matched = False # check user if user: log_user = aggressor.beacon_info(log['bid'], 'user') if log_user == user: matched = True # check computer if computer: log_computer = aggressor.beacon_info(log['bid'], 'computer') if log_computer == computer: matched = True # check bid if bid and log['bid'] == bid: matched = True if matched: # it's a match! finds += 1 # -o/--out with open(out, 'a+') as fp: # fix line endings data = log['data'].replace('\r\n', '\n') # add user attribution if log['type'] == 'beacon_input': data = '{}> {}'.format(user, data) # write timestamp fp.write('----- {} -----\n'.format(log['time'])) fp.write(data + '\n\n') return finds
def _(*args): parser = helpers.ArgumentParser(prog='grep-logs', description='Grep beacon logs for a regex') parser.add_argument('-o', '--out', help='Output file') parser.add_argument('-w', '--whole', action='store_true', help='Show whole output') parser.add_argument('regex', action='append', help='Search for regex') try: args = parser.parse_args(args) except: return for regex in args.regex: finds = 0 engine.message("Searching beacon logs for '{}'".format(regex)) for frame in aggressor.data_query('beaconlog'): output_type = frame[0] bid = frame[1] if output_type == 'beacon_input': user = frame[2] data = frame[3] time = convert_time(frame[4]) else: data = frame[2] time = convert_time(frame[3]) for log in split_output(data): if re.search(regex, log, re.IGNORECASE): beacon = '{}@{}'.format(aggressor.beacon_info(bid, 'user'), aggressor.beacon_info(bid, 'computer')) # -w/--whole if args.whole: output = data else: output = log # -o/--out if args.out: with open(args.out, 'a+') as fp: fp.write(output) else: engine.message("Found beacon log matching '{}' from {} at {}:\n{}".format(regex, beacon, time, output)) finds += 1 if finds: if args.out: engine.message("Wrote {} finds containing '{}' to '{}'".format(finds, regex, args.out)) else: engine.message("Found {} logs containing '{}'".format(finds, regex)) else: engine.error("Didn't find any beacon logs containing '{}'".format(regex))
def _(regex): found = False engine.message("Searching keystrokes for '{}'".format(regex)) for frame in aggressor.data_query('keystrokes'): data = frame['data'] bid = frame['bid'] time = convert_time(frame['when']) beacon = '{}@{}'.format(aggressor.beacon_info(bid, 'user'), aggressor.beacon_info(bid, 'computer')) for line in data.splitlines(): if re.search(regex, line, re.IGNORECASE): engine.message("Found keystroke matching '{}' from {} at {}: {}".format(regex, beacon, time, line)) found = True if not found: engine.error("Didn't find any keystrokes containing '{}'".format(regex))
def make_tree(proc, indent=0, our_children=False): # are we in our beacon's process tree? if proc['pid'] == int(aggressor.beacon_info(bid, 'pid')): our_children = True # output proc info proc = copy.copy(proc) # add app description exe = proc['name'].lower() if exe in processes.process_descriptions: proc['description'] = processes.process_descriptions[exe] else: # write unknowns to a file if unknowns_file: if os.path.isfile(unknowns_file): with open(unknowns_file, 'r') as fp: names = set([line.strip() for line in fp]) else: names = set() names.add(proc['name']) with open(unknowns_file, 'w+') as fp: fp.write('\n'.join(sorted(names))) # clean up name if proc['name'].lower().endswith('.exe'): proc['clean_name'] = proc['name'][:-4] else: proc['clean_name'] = proc['name'] # indented name proc['indented'] = ' ' * indent + proc['clean_name'] if our_children: # child processes proc['indented'] = console.orange(proc['indented']) elif 'description' in proc and '!!!' in proc['description']: # dangerous processes proc['indented'] = console.red(proc['indented']) elif 'description' in proc and '+++' in proc['description']: # potentially dangerous processes proc['indented'] = console.red(proc['indented']) elif proc['name'].lower() in processes.browsers: # browser processes proc['indented'] = console.cyan(proc['indented']) # current proc is first one output_procs = [proc] # recurse children children = get_children(proc['pid']) for child in children: output_procs += make_tree(child, indent + 4, our_children=our_children) return output_procs
def guess_home(bid): """ Guess %userprofile% directory based on beacon user :param bid: Beacon to use :return: Possible %userprofile% (home) directory """ return r'c:\users\{}'.format(aggressor.beacon_info(bid)['user'])
def real_user(bid): """ Get just the username of a beacon. :param bid: Bid to check :return: Username of beacon """ return aggressor.beacon_info(bid)['user'].replace(' *', '')
def _conditionally_run(bid, trigger): """ Run a trigger if the conditions match :param bid: Bid to run on :param trigger: Trigger to match :return: Whether or not command was run """ user = aggressor.beacon_info(bid, 'user') computer = aggressor.beacon_info(bid, 'computer') if 'all' in trigger and trigger['all'] or \ 'bid' in trigger and bid == trigger['bid'] or \ 'user' in trigger and user == trigger['user'] or \ 'computer' in trigger and computer == trigger['computer']: engine.debug('running command: ' + str(trigger['command'])) _run_command(bid, trigger['command']) return True else: return False
def is_admin(bid): """ Check if beacon is admin (including SYSTEM) :param bid: Beacon to use :return: True if beacon is elevated (i.e. admin with UAC disabled or SYSTEM) """ if aggressor.isadmin(bid): return True user = aggressor.beacon_info(bid, 'user') if user.lower() == 'system': return True return False
def _(bid): out = "Beacon info:\n\n" for key, value in aggressor.beacon_info(bid).items(): out += ' - {}: {}\n'.format(key, value) aggressor.blog2(bid, out)