def test_mount(self): volumes = [] self.filename = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.filename) parser = ImageParser([self.filename], None, False) for v in parser.init(): volumes.append(v) parser.clean() self.validate_count(volumes) self.validate_types(volumes)
def test_mount(self): volumes = [] self.filename = os.path.join( os.path.dirname(os.path.realpath(__file__)), self.filename) parser = ImageParser([self.filename], None, False) for v in parser.init(): volumes.append(v) parser.clean() self.validate_count(volumes) self.validate_types(volumes)
def _mount_dd_img(self): """ Mounts a dd image and all of its volumes and returns a list of directory paths to each volume, as well as the mount path for the disk image itself. :return: path_to_mountpoint, list of paths to mounted volumes """ parser = ImageParser([self.img_path], pretty=True, mountdir=self.mount_parent, casename=self.mount_stub, disk_mounter="xmount") volume_mount_paths = [] for volume in parser.init(single=True, swallow_exceptions=True): # parser.init() loops over all volumes and mounts them if volume.mountpoint: # If the mountpoint is set, we have successfully mounted it logger.info( f"Mounted volume {volume.get_description()} on {volume.mountpoint}" ) volume_mount_paths.append((volume.mountpoint)) elif volume.exception and volume.size is not None and volume.size <= 1048576: # If an exception occurred, but the volume is small, this is just a warning logger.info( f"Exception while mounting small volume {volume.get_description()}" ) elif volume.exception: # Other exceptions are a bit troubling. Should never happen, actually. logger.debug( f"Exception while mounting {volume.get_description()}") return parser.disks[0].mountpoint, volume_mount_paths
def main(): # We use argparse to parse arguments from the command line. parser = argparse.ArgumentParser(description='Simple CLI to mount disk images.') parser.add_argument('--version', action='version', version=__version__, help='display version and exit') parser.add_argument("-i", "--in", action='append', required=True, metavar='IN', help="path(s) to the files you want to mount", dest='images') parser.add_argument("-o", "--out", help="directory to mount the volumes in", dest="mountdir") parser.add_argument("-c", "--casename", help="the name of the case (this is appended to the output dir)") parser.add_argument("-r", "--restore", action="store_true", help="carve unallocated space", dest="carve") parser.add_argument("-s", "--shadow", action="store_true", help="mount volume shadow copies", dest="vshadow") parser.add_argument("-v", "--verbose", action="store_true", help="enable verbose output") args = parser.parse_args() # This sets up the logger. This is somewhat huge part of this example class ImageMounterFormatter(logging.Formatter): def format(self, record): msg = record.getMessage() if args.verbose and record.exc_info: if not record.exc_text: record.exc_text = self.formatException(record.exc_info) if msg[-1:] != "\n": msg += "\n" msg += record.exc_text if record.levelno >= logging.WARNING: return colored("[-] " + msg, 'cyan') elif record.levelno == logging.INFO: return colored("[+] " + msg, 'cyan') elif msg.startswith('$'): return colored(" " + msg, 'cyan') else: return colored(" " + msg, 'cyan') # Set logging level for internal Python handler = logging.StreamHandler() handler.setFormatter(ImageMounterFormatter()) logger = logging.getLogger("imagemounter") logger.setLevel(logging.WARNING if not args.verbose else logging.DEBUG) logger.addHandler(handler) # This is the basic parser. parser = ImageParser(args.images, pretty=True, **vars(args)) for volume in parser.init(): # parser.init() loops over all volumes and mounts them if volume.mountpoint: # If the mountpoint is set, we have successfully mounted it print('[+] Mounted volume {0} on {1}.'.format(colored(volume.get_description(), attrs=['bold']), colored(volume.mountpoint, 'green', attrs=['bold']))) elif volume.loopback: # If the mountpoint is not set, but a loopback is used, this is probably something like an LVM that did # not work properly. print('[+] Mounted volume {0} as loopback on {1}.'.format(colored(volume.get_description(), attrs=['bold']), colored(volume.loopback, 'green', attrs=['bold']))) print(colored('[-] Could not detect further volumes in the loopback device.', 'red')) elif volume.exception and volume.size is not None and volume.size <= 1048576: # If an exception occurred, but the volume is small, this is just a warning print(colored('[-] Exception while mounting small volume {0}'.format(volume.get_description()), 'yellow')) elif volume.exception: # Other exceptions are a bit troubling. Should never happen, actually. print(colored('[-] Exception while mounting {0}'.format(volume.get_description()), 'red')) elif volume.flag != 'meta' or args.verbose: # Meta volumes are not interesting enough to always show a warning about # Other volumes, we just print a warning that we couldn't mount it. print(colored('[-] Could not mount volume {0}'.format(volume.get_description()), 'yellow')) if args.carve and volume.flag != 'meta': # Carving is not neccesary on meta volumes, other volumes are carved for their unallocated space # or their entire space, depending on whether we could mount it. sys.stdout.write("[+] Carving volume...\r") sys.stdout.flush() try: path = volume.carve(freespace=not volume.mountpoint) except ImageMounterError: print(colored('[-] Carving failed.', 'red')) else: print('[+] Carved data is available at {0}.'.format(colored(path, 'green', attrs=['bold']))) if args.vshadow and volume.fstype == 'ntfs': sys.stdout.write("[+] Mounting volume shadow copies...\r") sys.stdout.flush() try: volumes = volume.detect_volume_shadow_copies() except ImageMounterError: print(colored('[-] Volume shadow copies could not be mounted.', 'red')) else: for v in volumes: try: v.init_volume() except ImageMounterError: print(colored('[-] Volume shadow copy {} not mounted'.format(v), 'red')) else: print('[+] Volume shadow copy available at {0}.'.format(colored(v.mountpoint, 'green', attrs=['bold']))) else: continue # we do not need the unmounting sequence
def main(): # We use argparse to parse arguments from the command line. parser = argparse.ArgumentParser( description='Simple CLI to mount disk images.') parser.add_argument('--version', action='version', version=__version__, help='display version and exit') parser.add_argument("-i", "--in", action='append', required=True, metavar='IN', help="path(s) to the files you want to mount", dest='images') parser.add_argument("-o", "--out", help="directory to mount the volumes in", dest="mountdir") parser.add_argument( "-c", "--casename", help="the name of the case (this is appended to the output dir)") parser.add_argument("-r", "--restore", action="store_true", help="carve unallocated space", dest="carve") parser.add_argument("-s", "--shadow", action="store_true", help="mount volume shadow copies", dest="vshadow") parser.add_argument("-v", "--verbose", action="store_true", help="enable verbose output") args = parser.parse_args() # This sets up the logger. This is somewhat huge part of this example class ImageMounterFormatter(logging.Formatter): def format(self, record): msg = record.getMessage() if args.verbose and record.exc_info: if not record.exc_text: record.exc_text = self.formatException(record.exc_info) if msg[-1:] != "\n": msg += "\n" msg += record.exc_text if record.levelno >= logging.WARNING: return colored("[-] " + msg, 'cyan') elif record.levelno == logging.INFO: return colored("[+] " + msg, 'cyan') elif msg.startswith('$'): return colored(" " + msg, 'cyan') else: return colored(" " + msg, 'cyan') # Set logging level for internal Python handler = logging.StreamHandler() handler.setFormatter(ImageMounterFormatter()) logger = logging.getLogger("imagemounter") logger.setLevel(logging.WARNING if not args.verbose else logging.DEBUG) logger.addHandler(handler) # This is the basic parser. parser = ImageParser(args.images, pretty=True, **vars(args)) for volume in parser.init(): # parser.init() loops over all volumes and mounts them if volume.mountpoint: # If the mountpoint is set, we have successfully mounted it print('[+] Mounted volume {0} on {1}.'.format( colored(volume.get_description(), attrs=['bold']), colored(volume.mountpoint, 'green', attrs=['bold']))) elif volume.loopback: # If the mountpoint is not set, but a loopback is used, this is probably something like an LVM that did # not work properly. print('[+] Mounted volume {0} as loopback on {1}.'.format( colored(volume.get_description(), attrs=['bold']), colored(volume.loopback, 'green', attrs=['bold']))) print( colored( '[-] Could not detect further volumes in the loopback device.', 'red')) elif volume.exception and volume.size is not None and volume.size <= 1048576: # If an exception occurred, but the volume is small, this is just a warning print( colored( '[-] Exception while mounting small volume {0}'.format( volume.get_description()), 'yellow')) elif volume.exception: # Other exceptions are a bit troubling. Should never happen, actually. print( colored( '[-] Exception while mounting {0}'.format( volume.get_description()), 'red')) elif volume.flag != 'meta' or args.verbose: # Meta volumes are not interesting enough to always show a warning about # Other volumes, we just print a warning that we couldn't mount it. print( colored( '[-] Could not mount volume {0}'.format( volume.get_description()), 'yellow')) if args.carve and volume.flag != 'meta': # Carving is not neccesary on meta volumes, other volumes are carved for their unallocated space # or their entire space, depending on whether we could mount it. sys.stdout.write("[+] Carving volume...\r") sys.stdout.flush() try: path = volume.carve(freespace=not volume.mountpoint) except ImageMounterError: print(colored('[-] Carving failed.', 'red')) else: print('[+] Carved data is available at {0}.'.format( colored(path, 'green', attrs=['bold']))) if args.vshadow and volume.fstype == 'ntfs': sys.stdout.write("[+] Mounting volume shadow copies...\r") sys.stdout.flush() try: volumes = volume.detect_volume_shadow_copies() except ImageMounterError: print( colored('[-] Volume shadow copies could not be mounted.', 'red')) else: for v in volumes: try: v.init_volume() except ImageMounterError: print( colored( '[-] Volume shadow copy {} not mounted'.format( v), 'red')) else: print( '[+] Volume shadow copy available at {0}.'.format( colored(v.mountpoint, 'green', attrs=['bold']))) else: continue # we do not need the unmounting sequence