Example #1
0
  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
Example #2
0
    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
Example #3
0
    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)
Example #4
0
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 + "'.")
Example #5
0
    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
Example #6
0
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
Example #7
0
    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)
Example #8
0
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
Example #9
0
    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}"