def test_quits_with_help(): captured_output = io.StringIO() sys.stdout = captured_output with pytest.raises(SystemExit): ArgHandler.parse_arguments(["--help"]) sys.stdout = sys.__stdout__ assert "Lancer - system vulnerability scanner" in captured_output.getvalue()
def test_quits_with_version(): captured_output = io.StringIO() sys.stdout = captured_output with pytest.raises(SystemExit): ArgHandler.parse_arguments(["--version"]) sys.stdout = sys.__stdout__ assert config.__version__ in captured_output.getvalue()
def get_logger(name: str) -> logging.Logger: """ Get a logger for the current module/class :param name: The name of the logger - this appears in the logs :return: Logger instance to store """ logger = logging.getLogger(name) console_logger = logging.StreamHandler() console_logger.setFormatter(LogFormatter()) console_logger.setLevel(logging.WARNING) if ArgHandler.get_verbose(): console_logger.setLevel(logging.INFO) elif ArgHandler.get_very_verbose(): console_logger.setLevel(logging.DEBUG) logger.addHandler(console_logger) logger.debug("New logger created: {NAME}".format(NAME=name)) return logger
def scan_targets() -> None: """ Open the target file, Nmap file or get the target to scan """ # Detect if we have a target list or just a single target if ArgHandler.get_target_file() is not None: # Target list targets = ArgHandler.get_target_file().read().splitlines() for target in targets: if len(target.strip()) == 0: continue # Comments start with a hashtag if len(target.strip()) > 0 and target[0] == "#": continue scan_target(target) elif ArgHandler.get_nmap_file() is not None: print(utils.normal_message(), "Loading nmap file") raise NotImplementedError("Loading from an Nmap file with -TF is not yet implemented") # nmap.parse_nmap_scan(ArgHandler.get_nmap_file()) else: scan_target(ArgHandler.get_target())
def __execute_modules(target: Target): """ Run Modules against the Target :param target: Target object to scan """ global LOADED_MODULES global logger # Order according to priority LOADED_MODULES = sorted(LOADED_MODULES, key=operator.attrgetter('priority'), reverse=True) # Add null service and port to ensure that the Hostname/Geo modules always run # TODO: Convert to InitModules EventQueue.push("", 0) # Get the current event from the Queue while EventQueue.events_in_queue(): current_event = EventQueue.pop() logger.info("Processing {SERVICE}:{PORT}".format( SERVICE=current_event.service, PORT=current_event.port)) if current_event.port not in ArgHandler.get_skip_ports(): # Iterate through every single instance of our modules for module in LOADED_MODULES: # Check if we can run it run_state = module.can_execute_module() if run_state is ModuleExecuteState.CanExecute: ip = str(target.ip) if module.should_execute(current_event.service, current_event.port): print( utils.normal_message(), "Executing {PROGRAM}".format(PROGRAM=module.name)) module.execute(ip, current_event.port)
def test_get_target_none(): ArgHandler.parse_arguments(["-TF", "targets.lan"]) assert ArgHandler.get_target() is None
def test_get_target(): ArgHandler.parse_arguments(["-T", "127.0.0.1"]) assert ArgHandler.get_target() is not None
def test_quits_with_no_parameters(): with pytest.raises(SystemExit): ArgHandler.parse_arguments([])
def init(): """ Initialise all of the needed prerequisites for Lancer. This should: - Register the signal handler for Ctrl+C - Load the config file - Parse command line arguments - Show the header - Check that we're on a supported Python version - Show an option to update the VirtualTerminal registry key if on Win 10 - Show a warning that localisation support is not yet implemented if there is a non-default -l parameter - Display a legal disclaimer about using Lancer for illegal use - Warn if the cache is over 500mb in size - Clear the cache if we want to """ # Register the signal handler for a more graceful Ctrl+C signal.signal(signal.SIGINT, utils.signal_handler) # Load the config file config.load_config() # Parse the arguments ArgHandler.parse_arguments(sys.argv[1:]) # Display the header utils.display_header() time.sleep(1.25) # Check we're on a supported Python version utils.python_version() # Update the Windows virtual terminal if necessary # If we're on Windows 10, import winutils if platform.system().lower() == "windows" and platform.release() == "10": from core.winutils import update_windows_virtual_terminal update_windows_virtual_terminal() # Language warning - not yet implemented if ArgHandler.get_language_code() != 'en': print(utils.error_message(), "Multi-language support is not yet implemented...") # Show a legal disclaimer disclaimer = utils.terminal_width_string( "Legal Disclaimer: Usage of Lancer for attacking targets without prior mutual" " authorisation is illegal. It is the end user's responsibility to adhere to all local" " and international laws. The developers of this tool assume no liability and are not" " responsible for any misuse or damage caused by the use of this program." ) print(utils.error_message(), disclaimer) print() # Cache warning # If it is more than 1GB, we display an error-style warning root_directory = Path(config.get_cache_path()) size = sum(f.stat().st_size for f in root_directory.glob('**/*') if f.is_file()) / 1048576 # Bytes -> MB if size >= 2048: print(utils.error_message(), "Cache is {SIZE}gb in size. It is recommended to clear it with --clear-cache." .format(SIZE="{:.1f}".format(size/1024))) # If it is more than 500, we display a warning elif size >= 512: print(utils.warning_message(), "Cache is {SIZE}mb in size. You can clear it with --clear-cache." .format(SIZE="{:.1f}".format(size))) # Clear the cache if ArgHandler.get_clear_cache(): files = os.listdir(config.get_cache_path()) for filename in files: file_path = os.path.join(config.get_cache_path(), filename) if os.path.isfile(file_path) or os.path.islink(file_path): os.unlink(file_path) elif os.path.isdir(file_path) and file_path != config.get_current_cache_path(): shutil.rmtree(file_path) print(utils.normal_message(), "Removed {NUM} items from the cache".format(NUM=len(files))) # Check if we are admin, display a relevant message if utils.is_user_admin(): print(utils.normal_message(), "Lancer running with elevated permissions") else: non_admin_warning = utils.terminal_width_string("Lancer doesn't appear to being run with elevated" " permissions. Some functionality may not work" " correctly") print(utils.warning_message(), non_admin_warning) # Display warning about your IP address ip_address = utils.terminal_width_string( "Your IP Address has been detected as {IP}. This can be changed with -a [IP]" ) print(utils.normal_message(), ip_address.format(IP=get_ip())) print() # Preload all of the modules ModuleProvider.load()
def test_get_verbose_none(): ArgHandler.parse_arguments(["-T", "127.0.0.1"]) assert ArgHandler.get_verbose() is False
def test_get_skip_ports_empty(): ArgHandler.parse_arguments(["-T", "127.0.0.1"]) assert not ArgHandler.get_skip_ports()
def test_get_clear_cache_none(): ArgHandler.parse_arguments(["-T", "127.0.0.1"]) assert ArgHandler.get_clear_cache() is False
def test_get_clear_cache(): ArgHandler.parse_arguments(["-T", "127.0.0.1", "--clear-cache"]) assert ArgHandler.get_clear_cache()
def test_get_language_code_none(): ArgHandler.parse_arguments(["-T", "127.0.0.1"]) assert ArgHandler.get_language_code() == "en"
def test_get_very_verbose(): ArgHandler.parse_arguments(["-T", "127.0.0.1", "-vv"]) assert ArgHandler.get_very_verbose()
def test_get_nmap_file(): ArgHandler.parse_arguments(["-TN", "targets.lan"]) assert ArgHandler.get_nmap_file() is not None
def test_get_nmap_file_none(): ArgHandler.parse_arguments(["-T", "127.0.0.1"]) assert ArgHandler.get_nmap_file() is None
def test_get_multiple_skip_ports(): ArgHandler.parse_arguments(["-T", "127.0.0.1", "--skip-ports", "80", "8080"]) assert 80 in ArgHandler.get_skip_ports() assert 8080 in ArgHandler.get_skip_ports()
def test_get_logger_verbose(): ArgHandler.parse_arguments(["-T", "::1", "-v"]) logger = config.get_logger("TestVerbose") assert logger.handlers[0].level is logging.INFO
def test_create_parser(): parser = ArgHandler.create_parser() assert parser is not None