def print_tool(self, opts): """ print tool and a description of it """ tools = [] m = Module(MOD_PATH) m.get_docstrings() if 'all' in opts.keys(): for tool in m.docstrings.keys(): tools.append(tool) else: for moddir, module in opts.items(): if module: for mod in module: for tool in m.docstrings: if m.docstrings[tool]['moddir'] == moddir and \ m.docstrings[tool]['module'] == mod: tools.append(tool) else: for k, v in m.docstrings.items(): if moddir in v['moddir']: tools.append(k) tools = sorted(list(set(tools))) for tool in tools: self.log(m.docstrings[tool]['moddir'] + '/' + m.docstrings[tool]['module'] + '/' + tool + ' - ' + m.docstrings[tool]['descr'], end='\n', _type='vmsg') return
def check_tools(self): """ check for missing tools on the system (-C) """ tools = [] missing_tools = [] found_files = [] suffixes = ('', '.py', '.pl', '.rb', '.php', '.jar', '.sh', '.bin', '.exe') # get docstrings m = Module(MOD_PATH) m.get_docstrings() # get paths from PATH to search for tools paths = list(filter(None, os.environ.get('PATH').split(':'))) paths.extend(['/opt', '/usr/share']) # search for files in given paths and unique+append them for rootdir in paths: for root, dirs, files in os.walk(rootdir): if 'nmap/scripts/vulscan' in root: files.append('vulscan') found_files.append(files) found_files = list(set(itertools.chain.from_iterable(found_files))) # get defined tools list out of doscstrings for key in m.docstrings.keys(): for tool in m.docstrings[key]['tools']: if tool not in tools: tools.append(tool) # message if not found for tool in tools: for suffix in suffixes: if '.' in tool: tool = tool.split('.')[0] if tool + suffix in found_files: break else: self.log(f'{tool} not found\n', _type='vmsg') missing_tools.append(tool) # one-liner for parsing if len(missing_tools) > 0: self.log('\n') self.log('One-liner for parsing\n\n', _type='msg') self.log(f" {' '.join(missing_tools)}\n") else: self.log('All tools are available\n', _type='msg') return
def __init__(self): # set status to none for exception handling self.__status = None try: super(Core, self).__init__() self.__state = StatusModule.StatusType.booting # set configurable variables self.__encoded = self.config().get("encode_measurements") Logger().level = self.config().get("log_level") Logger().use_timestamps = self.config().get("log_timestamps") # load platform module self.__platform = Module.load_module("platform", self.config().get("platform")) # load status modules self.__status = Module.load_modules(self.config(), "status") # set status indicators to booting self.__set_status(StatusModule.StatusType.booting) # add status modules as log observers for s in self.__status: Logger().add(s) # load input modules self.__input = Module.load_modules(self.config(), "input") if len(self.__input) == 0: log_warning("No input module loaded.") # load output modules self.__output = Module.load_modules(self.config(), "output") if len(self.__output) == 0: log_warning("No output module loaded.") # load sleep module self.__sleep = Module.load_module("sleep", self.config().get("sleep")) except Exception as e: self.__fatal(e)
def test_modules(): # load all module classes to check for import and syntax errors for i in ("platform", "input", "output", "sleep", "status"): log_info("Test loading " + i + " module classes.") for j in Module.list_modules(i): Module.load_class(i, j) # check if input device id's are unique log_info("Testing for unique input module ids.") ids = [] for i in range(0, 256): ids.append("") for i in Module.list_modules("input"): klass = Module.load_class("input", i) if len(ids[klass.get_id()]) == 0: ids[klass.get_id()] = i else: raise Exception("Id " + str(klass.get_id()) + " should be unique but is used by input modules '" + ids[klass.get_id()] + "' and '" + i + "'.")
def __init__(self): """ constructor """ # options and modules self.opt = None self.mod = Module(MOD_PATH) # logger self.logger = Logger() self.log = self.logger.log # rest we need self.file = File() self.check = Check() self.misc = Misc() self.parser = None # nullscan working dir self.nullscan_dir = None return
def landing(role): ''' 老师和学生认证装饰器 :param func: :return: ''' n = 0 while True: account = input('输入账号>>:').strip() file_path = Module.check_file(role, account) if file_path: # 账号校验 massage = Module.get_data(role, account) else: print('用户未注册!') continue if massage['state'] == 0: # 检查用户状态 r_password = input('输入密码>>:').strip() password = Module.encrypt(r_password) else: print('账号被冻结,请联系管理员解除锁定!') exit() # 账号冻结退出程序 if password == massage['password']: # 密码校验 print('登录成功!') landing_log = 'role:%s account:%s operation:landing info:登录成功!' % ( role, account) loggers = Logger.logs(role) loggers.info(landing_log) return account else: print('密码错误,请重新输入!') n += 1 if n >= 3: print('密码输入错误次数过多,账号被冻结!') massage['state'] = 1 Module.save_file(role, account, massage) landing_error = 'role:%s account:%s operation:landing info:账号被冻结!' % ( role, account) loggers = Logger.logs(role) loggers.error(landing_error) return
def default_config(): # create core config Module.create_config(Core.get_config_definition()) # iterate over module types for i in ("input", "output", "platform", "sleep", "status"): # list module folder for j in Module.list_modules(i): # load module class klass = Module.load_class(i, j) # skip unloadable classes if klass == None: continue # get config definition cd = klass.get_config_definition() # skip if module has no configuration if cd == None: continue # create configuration file Module.create_config(cd)
class Controller: """ program controller class """ def __init__(self): """ constructor """ # options and modules self.opt = None self.mod = Module(MOD_PATH) # logger self.logger = Logger() self.log = self.logger.log # rest we need self.file = File() self.check = Check() self.misc = Misc() self.parser = None # nullscan working dir self.nullscan_dir = None return def prepare(self): """ preparation/initialization of opts and env: parsing & checks """ # declare nullscan options self.opt = Option(sys.argv) # check argc and argc (usage) self.check.check_argc(len(sys.argv)) self.check.check_argv(sys.argv) # check for missing libraries / deps / python modules self.check.check_deps(self.file.read_file(PYDEPS)) # parse cmdline and config options, update final options dictionary try: self.parser = Parser(self.opt.opts) self.parser.parse_cmdline() self.parser.parse_config() self.opt.opts = self.parser.opts except: self.log('usage', _type='err', end='\n') # update final options dictionary self.opt.update_opts() # further checks for usage, options, env, etc. self.check.check_opts(self.opt.opts) # collect all py-files and grep the tools out of the py-files tools = [] py_files = self.misc.find_py_files(MOD_PATH) for py in py_files: tools.append(self.misc.grep_tools(py)) tools = [x for sublist in tools for x in sublist] # create the locks for each tool except for excluded ones with ThreadPoolExecutor(50) as exe: for tool in tools: if tool not in self.opt.opts['tools']['ex_tools']: exe.submit(self.file.create_lock, tool) # copy debug flag to target_opts (for nullscan tools) self.opt.opts['targets_opts']['debug'] = self.opt.opts['debug'] return def run_misc(self): """ run chosen misc options """ if self.opt.opts['check_tools']: self.log('Checking for missing tools\n\n', _type='msg') self.check.check_tools() os._exit(SUCCESS) if self.opt.opts['print_tools']: self.log('Printing tools and information\n\n', _type='msg') self.misc.print_tool(self.opt.opts['print_tools']) os._exit(SUCCESS) if self.opt.opts['add_module']: self.log('Adding new module\n', _type='msg') self.misc.add_mod_tool('mod', self.opt.opts['add_module']) os._exit(SUCCESS) if self.opt.opts['add_tool']: self.log('Adding new tool\n', _type='msg') self.misc.add_mod_tool('tool', self.opt.opts['add_tool']) os._exit(SUCCESS) return def prepare_modules(self): """ filter in-/excluded mods + return a unique list """ self.mod.filter_modules(self.opt.opts) self.mod.mods = list(set(self.mod.mods)) return def run_nmap_mode(self): """ run nmap scan mode """ nmap = Nmap(self.opt.opts['targets']['nmap']) # create nmap logdir based on scan type requested logpath = f'{self.nullscan_dir}/logs/nmap/{nmap.get_protocol()}' logfile = f'{logpath}/results' self.file.make_dir(logpath) nmap.set_logfile(logfile) # build nmap command line nmap.build_cmd() # start scans self.log('NMAP mode activated\n', _type='msg', color='blue') self.log('Targets added: {}\n'.format( len(self.opt.opts['targets']['nmap']['hosts'])), _type='msg') if self.opt.opts['verbose']: self.log('\n') for target in self.opt.opts['targets']['nmap']['hosts']: self.log(f'{target}\n', _type='msg') nmap.scan(debug=self.opt.opts['debug']) return f'{logfile}.xml' def run_social_mode(self, target): """ run social mode """ if '.social.' in str(self.mod.mods): # availabel social modules to import and load mods = [i for i in self.mod.mods if '.social.' in i] with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for key in target.keys(): if target[key]: for t in target[key]: # default module rdir = f'{self.nullscan_dir}/logs/targets/' wdir = f"{rdir}{t}/social/{key}/default" exe.submit(self.mod.run_module, 'modules.social.default', t, self.opt.opts, wdir) # non-default modules for m in mods: if 'default' not in m: splitted = m.split('.') moddir = splitted[1] modname = splitted[2] wdir = f"{rdir}{t}/{moddir}/{key}/{modname}" exe.submit(self.mod.run_module, m, t, self.opt.opts, wdir) return def run_wifi_mode(self, target): """ run wifi mode """ if '.wifi.' in str(self.mod.mods): # available wifi modules to import and load mods = [i for i in self.mod.mods if '.wifi.' in i] # default module first rdir = f'{self.nullscan_dir}/logs/targets/' wdir = f'{rdir}{target}/wifi/default' self.mod.run_module('modules.wifi.default', target, self.opt.opts, wdir) # non-default modules with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for m in mods: if 'default' not in m: splitted = m.split('.') moddir = splitted[1] modname = splitted[2] wdir = f'{rdir}{target}/{moddir}/{modname}' exe.submit(self.mod.run_module, m, target, self.opt.opts, wdir) return def run_lan_mode(self, target): """ run lan mode """ if '.lan.' in str(self.mod.mods): # available lan modules to import and load mods = [i for i in self.mod.mods if '.lan.' in i] # default module first rdir = f'{self.nullscan_dir}/logs/targets/' wdir = f'{rdir}{target}/lan/default' self.mod.run_module('modules.lan.default', target, self.opt.opts, wdir) # non-default modules with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for m in mods: if 'default' not in m: splitted = m.split('.') moddir = splitted[1] modname = splitted[2] wdir = f'{rdir}{target}/{moddir}/{modname}' exe.submit(self.mod.run_module, m, target, self.opt.opts, wdir) return def run_web_mode(self, target): """ run web mode """ if '.web.' in str(self.mod.mods): # available web modules to import and load mods = [i for i in self.mod.mods if '.web.' in i] # we need host name for working directory host = requests.utils.urlparse(target).netloc # default module first rdir = f'{self.nullscan_dir}/logs/targets/' wdir = f'{rdir}{host}/web/default' self.mod.run_module('modules.web.default', target, self.opt.opts, wdir) # non-default modules with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for m in mods: if 'default' not in m: splitted = m.split('.') moddir = splitted[1] modname = splitted[2] wdir = f'{rdir}{host}/{moddir}/{modname}' exe.submit(self.mod.run_module, m, target, self.opt.opts, wdir) return def run_udp_mode(self, target): """ run udp mode """ # we need to run host modules before tcp and we need to run default # tool first self.run_host_mode(target) # now tcp modules if '.udp.' in str(self.mod.mods): with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for p in target['ports']: exe.submit(self.run_tcp_udp_mode, target, p, 'udp') return def run_tcp_mode(self, target): """ run tcp mode """ # we need to run host modules before tcp and we need to run default # module first self.run_host_mode(target) # now tcp modules if '.tcp.' in str(self.mod.mods): with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for p in target['ports']: exe.submit(self.run_tcp_udp_mode, target, p, 'tcp') return def run_tcp_udp_mode(self, host, port, proto): """ wrapper for tcp/udp mode """ # available modules mod = f'modules.{proto}.{port[1]}' # force default module for given port if module does not exist if mod not in self.mod.mods: mod = f'modules.{proto}.default' # new target dict as we only need the corresponding port t = {'host': host['host'], 'port': port[0]} # default module first rdir = f'{self.nullscan_dir}/logs/targets/' wdir = f"{rdir}{t['host']}/{proto}/{port[0]}/default" self.mod.run_module(f'modules.{proto}.default', t, self.opt.opts, wdir) # now non-default module if '.default' not in mod: wdir = f"{rdir}{t['host']}/{proto}/{port[0]}/{port[1]}" self.mod.run_module(mod, t, self.opt.opts, wdir) return def run_host_mode(self, target): """ run host mode """ # available host modules to import and load mods = [i for i in self.mod.mods if '.host.' in i] # default module rdir = f'{self.nullscan_dir}/logs/targets/' wdir = f"{rdir}{target['host']}/host/default" self.mod.run_module('modules.host.default', target, self.opt.opts, wdir) # non-default modules with ProcessPoolExecutor(self.opt.opts['m_workers']) as exe: for m in mods: if 'default' not in m: splitted = m.split('.') moddir = splitted[1] modname = splitted[2] wdir = f"{rdir}{target['host']}/{moddir}/{modname}" exe.submit(self.mod.run_module, m, target, self.opt.opts, wdir) return def run_modes(self): """ run chosen modes """ scans = [] modes = { 'tcp': self.run_tcp_mode, 'udp': self.run_udp_mode, 'wifi': self.run_wifi_mode, 'web': self.run_web_mode, 'social': self.run_social_mode, 'http': self.run_web_mode, 'https': self.run_web_mode, } # run lan mode first if requested if self.opt.opts['targets']['lan']: ifaces = [] self.log('LAN mode activated\n', color='blue', _type='msg') self.log( f"Targets added: {len(self.opt.opts['targets']['lan'])}\n\n", _type='msg') for iface in self.opt.opts['targets']['lan']: if self.opt.opts['verbose']: self.log(f'{iface}\n', _type='vmsg') ifaces.append((self.run_lan_mode, iface)) if self.opt.opts['verbose']: self.log('\n') with ProcessPoolExecutor(self.opt.opts['t_workers']) as exe: self.log('Shooting tools\n\n', color='green', _type='msg') for iface in ifaces: exe.submit(iface[0], iface[1]) self.log('\n') if not self.opt.opts['verbose']: self.log('\n') self.log('Tools done\n\n', color='green', _type='msg') for log in glob.glob('**/lan/portscan/*.xml', recursive=True): if log: self.parser.parse_nmap_logfile(log, lan=True) # collect scan modes for each target for k, v in self.opt.opts['targets'].items(): if self.opt.opts['targets'][k]: if k == 'lan': continue else: self.log(f'{k.upper()} mode activated\n', color='blue', _type='msg') self.log(f'Targets added: {len(v)}\n\n', _type='msg') if k == 'social': if self.opt.opts['verbose']: for targets in v.values(): for target in targets: self.log(f'{target}\n', _type='vmsg') self.log('\n') scans.append((modes[k], v)) else: for target in v: scans.append((modes[k], target)) if self.opt.opts['verbose']: if 'host' in target: target_head = target['host'] else: target_head = target self.log(f'{target_head}\n', _type='vmsg') if self.opt.opts['verbose']: self.log('\n') # start mode for each target with ProcessPoolExecutor(self.opt.opts['t_workers']) as exe: if scans: self.log('Shooting tools\n\n', color='green', _type='msg') for scan in scans: exe.submit(scan[0], scan[1]) if scans: self.log('\n') if not self.opt.opts['verbose']: self.log('\n') self.log('Tools done\n\n', _type='msg', color='green') return def start(self): """ nullscan starts here with actions """ self.check.check_uid() self.log('Game Started\n\n', _type='msg') # create nullscan working, targets and log dir self.nullscan_dir = self.file.make_dir(self.opt.opts['nullscan_dir'], incr=True) self.file.make_dir(f'{self.nullscan_dir}/logs/targets') self.opt.opts['targets_opts']['nullscan_logdir'] = \ f'{self.nullscan_dir}/logs/targets/' # run nmap mode first if requested if 'hosts' in self.opt.opts['targets']['nmap']: self.parser.parse_nmap_logfile(self.run_nmap_mode()) self.log('\n') # delete nmap key del self.opt.opts['targets']['nmap'] # prepare modules for other modes self.prepare_modules() # run the nullscan modes now self.run_modes() return def end(self): """ program ends here. clean-ups, reporting, etc. """ # go back to root dir os.chdir(ROOT_PATH) # clean up empty directories and empty (log-)files or logfiles containing # a singl ebyte (newline) (failed tools) self.misc.remove_empty_files_dirs(f'{self.nullscan_dir}/logs/targets/') # just to be safe - delete all locks, in case tools didn't self.file.del_file('/tmp/nullscan', _dir=True) # create report if self.opt.opts['report']: self.log('Creating report\n', _type='msg') tmpl_dir = f'{ROOT_PATH}/src/report/template' rep_dir = f'{self.nullscan_dir}/report' logs_dir = f'{self.nullscan_dir}/logs' self.report = HTML(TODAY, self.opt.opts, tmpl_dir, rep_dir, logs_dir) self.report.make_report() self.log('Report done\n\n', _type='msg') self.log('Game Over\n', _type='msg') # reset terminal to original state. sometimes f**k up occurs because of # color and other escape codes. self.misc.reset_terminal() return
def __decode(array): # create an array of all the input modules modules = [None] * 256 for i in Module.list_modules("input"): klass = Module.load_class("input", i) if modules[klass.get_id()] != None: Exception( "Input module id " + str(klass.get_id()) + " is used by multiple classes, run tests for more information." ) modules[klass.get_id()] = klass # first check if we have a valid measurement array by adding together # the lengths and checking if it fits the size l = len(array) if l < 2: raise Exception("invalid measurement string - too small") s = 0 while s < l: if modules[array[s]] == None: raise Exception( "invalid measurement string - unknown input module id") if array[s + 1] == 0: raise Exception( "invalid measurement string - length cannot be zero") s += array[s + 1] if l != s: raise Exception( "invalid measurement string - lenght does not add up") # decoded string s = "" # read counter c = 0 while c < l: # input module id id = array[c] # measurement length ml = array[c + 1] # measurement array ma = bytearray(ml) for i in range(0, ml): ma[i] = array[c + 2 + i] # set read counter c = c + 2 + ml # add to decoded string if len(s) != 0: s += ",\n" s += modules[id].decode(ma) return "{\n" + s + "\n}"