def diff_file(file_path, source, destination, results): if source.is_dir(file_path) and destination.is_dir(file_path): diff_directory(file_path, source, destination, results) try: EVENTS['differ.pre_open'](file_path, source, destination, results, DIFF_NAME) except Exception as e: logger.error("File '{}' not found in destination".format(file_path)) # Store difference in existence if EVENTS['differ.with_open']: try: with source.open( file_path ) as fd: # TODO: When it returns I will stuff it in the right place EVENTS['differ.with_open']( file_path, file_type, source, destination, results, DIFF_NAME, fd, ) EVENTS['differ.post_close'](file_path, file_type, source, destination, results, DIFF_NAME) except IOError: logger.warn( "'open()' System Call not supported on {}".format(file_path))
def _clone(args, image, context=os): entrypoints = [] for entrypoint in args.entrypoints: if context.path.isdir(entrypoint): entrypoints.append(entrypoint) else: logger.error( "Entrypoint '{}' is not a Directory".format(entrypoint)) if not entrypoints: logger.critical("No valid Entrypoints Found!") logger.critical("Exiting...") sys.exit(-1) crawler = BaseCrawler(entrypoints, args.excluded_dirs, image=context) load_extension_list(args.load_extensions) pool = Pool(args.threads) pool.starmap( # image, (filename, filetype), context file_worker, zip(itertools.repeat(image), crawler(), itertools.repeat(context))) pool.close() pool.join() logger.info("Processed {} files".format(PROCESSED_FILES)) logger.info("Image Generated!") image_serializer = SatoriJsoner() # image_serializer = SatoriPickler() image_serializer.write(image, args.image_file) logger.warn("Stored to file '{}'".format(image_serializer.last_file))
def diff_directory(file_path, source, destination, results): try: s_cont = set(source.listdir(file_path)) d_cont = set(destination.listdir(file_path)) except PermissionError: logger.warn("Permission Denied for listing '{}'. Skipping...".format( file_path)) return source_only = s_cont - d_cont dest_only = d_cont - s_cont for diff_only in ( (source_only, "src_only"), (dest_only, "dst_only"), ): if diff_only[0]: try: diff_dict = results.get_attribute(file_path, DIFF_NAME) except FileNotFoundError: diff_dict = {} results.set_attribute( file_path, diff_dict, DIFF_NAME, force_create=True, ) diff_dict[diff_only[1]] = list(diff_only[0]) # print (s_cont, d_cont) common_files = s_cont & d_cont # print(common_files) for f in common_files: # Use thread map? new_file_path = file_path + '/' + f diff_file(new_file_path, source, destination, results)
def load_extension_list(extension_list): """ extension_list: list of filenames """ for i, extension in enumerate(extension_list): try: ext_module = imp.load_source('extension_{}'.format(i), extension) logger.warn("Extension '{}' loaded".format(ext_module.__name__)) except Exception as e: logger.error("[{}] - Extension {} could not be loaded".format( e, extension))
def main(): global ENCODING parser = argparse.ArgumentParser() parser.add_argument("SatoriFile", help="The SatoriImage file to mount") parser.add_argument("--mountpoint", help="The directory to use as mount target") parser.add_argument( "--encoding", help="""The Text Encoding to use for 'open("..","r")' System calls """, default=ENCODING, ) parser.add_argument( '-l', '--load-extensions', help='Load the following extensions', action='append', default=[], ) args = parser.parse_args() logging.basicConfig(level=logging.DEBUG) ENCODING = args.encoding load_extension_list(args.load_extensions) mountpoint = args.mountpoint use_temp_dir = False if mountpoint is None: mountpoint = tempfile.mkdtemp(prefix='satori_mnt_') use_temp_dir = True filename = args.SatoriFile image = load_image(filename) # print (type(image)) logger.warn("Mounting Image at: '{}'".format(mountpoint)) try: main_fuse(mountpoint, image) finally: if use_temp_dir: logger.warn("[!] Cleaning up '{}'".format(mountpoint)) os.rmdir(mountpoint)
def get_image_context_from_arg(arg, allow_local=True): from satoricore.file import load_image if arg == '.': return dummy_context(os) if allow_local: try: os.stat(arg) logger.info("Found to '{}'".format(arg)) image_path = arg source = load_image(image_path) if source != None: return dummy_context(source) except FileNotFoundError: logger.error("File '{}' could not be found".format(arg)) pass try: import satoriremote logger.info("Connecting to '{}'".format(arg)) conn_context_source, conn_dict = satoriremote.connect(arg) logger.warn("Connected to {}".format(conn_dict['host'])) return conn_context_source # with conn_context_source as context: # return context except ImportError: logger.critical( "'satori-remote' package not available, remote paths can't be used" ) sys.exit(-1) except ValueError: # If can't be parsed as regular expression logger.critical("'{}' can't be parsed as URI".format(arg)) sys.exit(-1) except ConnectionError: logger.critical("Connection failed for path '{}'".format(arg)) sys.exit(-1)
def main(): parser = _setup_argument_parser() args = parser.parse_args() source_context = get_image_context_from_arg(args.original_image) logger.warn("Loaded image '{}'".format(args.original_image)) destination_context = get_image_context_from_arg(args.tested_image) logger.warn("Loaded image '{}'".format(args.tested_image)) # if not args.output: try: results = load_image(args.output) logger.warn("SatoriImage '{}' loaded to archive results".format( args.output)) except TypeError as te: logger.warn("No output image selected") logger.info("Using an Empty SatoriImage to store results") results = SatoriImage() except ValueError: logger.error("Output image file '{}' is not a SatoriImage".format( args.output)) logger.warn("Using an Empty SatoriImage to store results".format( args.output)) results = SatoriImage() assert (results is not None) try: logger.info("Adding DIFF section in SatoriImage") results.add_section(_DIFFS_SECTION) except KeyError: logger.warn("DIFF Section in SatoriImage already exists") existing_diffs = results.get_classes(_DIFFS_SECTION) if existing_diffs: logger.info("Existing DIFFs in SatoriImage: {}".format( str(existing_diffs))) name = get_diff_name(existing_diffs) global DIFF_NAME DIFF_NAME = name logger.warn("New DIFF name is '{}'".format(name)) with source_context as source: with destination_context as destination: if not args.entrypoints: # s_entrypoints try: s_epoints = source.get_entrypoints() logger.info( "Original Image entrypoints: {}".format(s_epoints)) except: logger.warn("Entrypoints for source cannot be specified.") d_epoints = set('/') try: d_epoints = destination.get_entrypoints() logger.info( "Tested Image entrypoints: {}".format(d_epoints)) except: logger.warn( "Entrypoints for destination cannot be specified.") d_epoints = set('/') common_entrypoints = s_epoints & d_epoints if not common_entrypoints: logger.critical("No common entrypoints found. Exiting...") sys.exit(-1) else: logger.info("Common Entrypoints are {}".format( str(common_entrypoints))) args.entrypoints = common_entrypoints logger.warn("Operating for entrypoints: {}".format( str(args.entrypoints))) EVENTS['differ.on_start'](parser=parser, args=args, source=source, destination=destination, results=results, diff_name=DIFF_NAME) logger.warn("Diff Process Started...") diff_images(source, destination, args.entrypoints, results) logger.warn("Diff Process Finished!") if not args.output: args.output = DIFF_NAME image_serializer = SatoriJsoner() # image_serializer = SatoriPickler() if args.output.endswith(image_serializer.suffix): image_serializer.suffix = '' image_serializer.write(results, args.output) logger.warn("Stored to file '{}'".format(image_serializer.last_file)) # print(diff_obj) # print(results) # if args.output: # pass EVENTS['differ.on_end'](results)