Exemple #1
0
def main():
    print('pyEWFmount by Florian Wahl, 03.08.2020')
    print()

    parser = argparse.ArgumentParser()
    parser.add_argument('-i',
                        '--input',
                        type=str,
                        help="path to a EWF file which should be mounted")
    parser.add_argument(
        '-o',
        '--output',
        type=str,
        help=
        "Specify the name of the mounted directory (default: /mnt/YYYY.MM.DD_hh.mm)",
        default=__get_default_name_of_mounting_directory())
    arguments = parser.parse_args()

    if arguments.input is None or len(arguments.input) == 0:
        parser.print_help()
        exit()

    input_path = os.path.abspath(arguments.input)
    mounting_path = os.path.abspath(arguments.output)

    if not __is_root():
        error(message='The script needs sudo rights. Exiting.')
        exit()

    try:
        program(input_path=input_path, mounting_path=mounting_path)
    except KeyboardInterrupt:
        error(message='Keyboard Interrupt. Exiting.')
Exemple #2
0
def extract_attachment(parsed_eml: Message, attachment_number: int,
                       output_path: str or None):
    print_headline_banner('Attachment Extracting')
    attachment = None
    counter = 1
    for child in parsed_eml.walk():
        if child.get_filename() is not None:
            if counter == attachment_number:
                attachment = child
                break
            counter += 1

    # Check if attachment was found
    if attachment is None:
        error('Attachment {} could not be found'.format(attachment_number))
        return

    attachment_filename = _get_printable_attachment_filename(
        attachment=attachment)

    info('Found attachment [{}] "{}"'.format(attachment_number,
                                             attachment_filename))

    if output_path is None:
        output_path = attachment.get_filename()
    elif os.path.isdir(output_path):
        output_path = os.path.join(output_path, attachment_filename)

    payload = attachment.get_payload(decode=True)
    output_file = open(output_path, mode='wb')
    output_file.write(payload)
    info('Attachment extracted to {}'.format(output_path))
Exemple #3
0
def __try_to_decode(content: bytes, parsed_eml: Message) -> str or None:
    list_of_possible_encodings = __create_list_of_possible_encodings(parsed_eml=parsed_eml)

    for encoding_format in list_of_possible_encodings:
        try:
            return content.decode(encoding_format)
        except ValueError:
            continue
    error('Payload could not be decoded')
    return None
Exemple #4
0
 def start_scanning(self):
     try:
         device = parted.getDevice(self.path_to_input_device)
     except Exception as exception:
         error('Input Device could not be read: {}'.format(exception))
         self.is_running = False
         exit()
     else:
         self.is_running = True
         t = Thread(target=self.__start_scanning,
                    args=(device, ),
                    daemon=True)
         t.start()
Exemple #5
0
    def __read_data(self, device):
        self.number_of_sectors = device.length
        self.size_of_a_sector = device.sectorSize
        info('Model of input device: {}'.format(device.model))
        info('Number of sectors: {}'.format(self.number_of_sectors))
        info('Bytes per sector: {}'.format(self.size_of_a_sector))

        try:
            with open(self.path_to_input_device, mode='rb') as input_file:
                input_file.seek(0)
                for sector_i in range(self.number_of_sectors + 1):
                    data_of_new_sector = input_file.read(self.size_of_a_sector)
                    self.buffer.put(data_of_new_sector, block=True)
        except IsADirectoryError:
            error('The Input has to be a drive not an directory')
            self.is_running = False
            exit()
Exemple #6
0
def main():
    flags_to_parse, path_to_file = __parse_cli_arguments()

    argument_parser = argparse.ArgumentParser(
        usage='zipAnalyzer FILE [OPTIONS]',
        description='A cli script to analyze zip archive.')
    argument_parser.add_argument(
        '-c',
        '--crack',
        help=
        "Tries to crack the encryption by enumeration over a password list. Extracts the zip archive if the password was found.",
        action='store_true',
        default=False)
    argument_parser.add_argument('--passlist',
                                 type=str,
                                 help="Path to custom password list",
                                 default=None)

    parsed_arguments = argument_parser.parse_args(flags_to_parse)

    if path_to_file is None:
        argument_parser.print_help()
        exit()

    path_to_archive = os.path.abspath(path_to_file)

    try:
        zip_archive = zipfile.ZipFile(path_to_archive)
    except Exception as exception:
        error('Zip file could not be read: {}'.format(exception))
        exit()
    else:
        if parsed_arguments.crack:
            password_list = __read_password_list(
                path_to_custom_password_list=parsed_arguments.passlist)
            crack_zip_archive(password_list=password_list,
                              zip_archive=zip_archive)
        else:
            analyse_zip_archive(zip_archive=zip_archive)
Exemple #7
0
def __final_mount_procedure(source_path: str, target_path: str,
                            partition_number: int):
    if not os.path.exists(target_path):
        os.makedirs(target_path)

    mount_options = list()

    while True:
        user_input = input('Mount in readonly mode (y/n) [y]: ')
        if len(user_input) == 0 or user_input == 'y':
            mount_options.append('ro')
            break
        elif user_input == 'n':
            break
        else:
            error(message='input not valid.')
            print()

    mount_options.append('show_sys_files')

    while True:
        user_input = input('Mount as NTFS filesystem (y/n) [y]: ')
        if len(user_input) == 0 or user_input == 'y':
            mount_options.append('streams_interface=windows')
            break
        elif user_input == 'n':
            break
        else:
            error(message='input not valid.')
            print()

    # generate mount command
    mount_options_string = ','.join(mount_options)

    mount_command = 'mount -o {} "{}" "{}" >/dev/null 2>&1'.format(
        mount_options_string, __escape_path(source_path),
        __escape_path(target_path))

    if int(os.system(mount_command)) == 0:
        info(message='Partition {} was mounted under "{}"'.format(
            partition_number, __escape_path(target_path)))
    else:
        error('An Error occurred. Partition could not be mounted')
Exemple #8
0
def main():
    argument_parser = argparse.ArgumentParser(
        usage='emlAnalyzer [OPTION]... -i FILE',
        description=
        'A cli script to analyze an E-Mail in the eml format for viewing the header, extracting attachments etc.'
    )
    argument_parser.add_argument('-i',
                                 '--input',
                                 help="path to the eml-file (is required)",
                                 type=str)
    argument_parser.add_argument('--header',
                                 action='store_true',
                                 default=False,
                                 help="Shows the headers")
    argument_parser.add_argument(
        '-x',
        '--tracking',
        action='store_true',
        default=False,
        help=
        "Shows content which is reloaded from external resources in the HTML part"
    )
    argument_parser.add_argument('-a',
                                 '--attachments',
                                 action='store_true',
                                 default=False,
                                 help="Lists attachments")
    argument_parser.add_argument('--text',
                                 action='store_true',
                                 default=False,
                                 help="Shows plaintext")
    argument_parser.add_argument('--html',
                                 action='store_true',
                                 default=False,
                                 help="Shows HTML")
    argument_parser.add_argument('-s',
                                 '--structure',
                                 action='store_true',
                                 default=False,
                                 help="Shows structure of the E-Mail")
    argument_parser.add_argument(
        '-u',
        '--url',
        action='store_true',
        default=False,
        help="Shows embedded links and urls in the html part")
    argument_parser.add_argument('-ea',
                                 '--extract',
                                 type=int,
                                 default=None,
                                 help="Extracts the x-th attachment")
    argument_parser.add_argument('--extract-all',
                                 action='store_true',
                                 default=None,
                                 help="Extracts all attachments")
    argument_parser.add_argument(
        '-o',
        '--output',
        type=str,
        default=None,
        help=
        "Path for the extracted attachment (default is filename in working directory)"
    )
    arguments = argument_parser.parse_args()

    if arguments.input is None or len(arguments.input) == 0:
        warning('No Input specified')
        argument_parser.print_help()
        exit()

    # get the absolute path to the input file
    path_to_input = os.path.abspath(arguments.input)

    # read the eml file
    try:
        with open(path_to_input, mode='r') as input_file:
            eml_content = input_file.read()
    except Exception as e:
        error('Error: {}'.format(e))
        error('File could not be loaded')
        info('Existing')
        exit()

    # parse the eml file
    try:
        parsed_eml = message_from_string(eml_content)
    except Exception as e:
        error('Error: {}'.format(e))
        error('File could not be parsed. Sure it is a eml-file?')
        info('Existing')
        exit()

    # use default functionality if no options are specified
    is_default_functionality = not (arguments.header or arguments.tracking
                                    or arguments.attachments or arguments.text
                                    or arguments.html or arguments.structure
                                    or arguments.url
                                    or arguments.extract is not None)

    if is_default_functionality:
        arguments.structure = True
        arguments.url = True
        arguments.tracking = True
        arguments.attachments = True

    if arguments.header:
        show_header(parsed_eml=parsed_eml)
    if arguments.structure:
        show_structure(parsed_eml=parsed_eml)
    if arguments.url:
        show_urls(parsed_eml=parsed_eml)
    if arguments.tracking:
        check_tracking(parsed_eml=parsed_eml)
    if arguments.attachments:
        show_attachments(parsed_eml=parsed_eml)
    if arguments.text:
        show_text(parsed_eml=parsed_eml)
    if arguments.html:
        show_html(parsed_eml=parsed_eml)

    if arguments.extract is not None:
        extract_attachment(parsed_eml=parsed_eml,
                           attachment_number=arguments.extract,
                           output_path=arguments.output)
    if arguments.extract_all is not None:
        extract_all_attachments(parsed_eml=parsed_eml, path=arguments.output)
Exemple #9
0
def main():
    flags_to_parse, path = __parse_cli_arguments()

    parser = argparse.ArgumentParser(
        usage='lad [OPTION]... [FILE]...',
        description=
        'Lists information about the FILEs (the current directory by default) including Alternate Data Streams.',
        add_help=False)
    parser.add_argument('-h',
                        '--human-readable',
                        dest="human_readable",
                        help="print sizes like 1K 234M 2G etc.",
                        action='store_true',
                        default=False)
    parser.add_argument('--help',
                        dest='help',
                        help="prints the help text",
                        action='store_true',
                        default=False)
    parser.add_argument('-R',
                        '--recursive',
                        dest="recursive",
                        help="list subdirectories recursively",
                        action='store_true',
                        default=False)
    parser.add_argument('--full-time',
                        dest="full_time",
                        help="Shows the complete timestamp",
                        action='store_true',
                        default=False)
    parser.add_argument('-n',
                        '--numeric-uid-gid',
                        dest="numeric_uid_gid",
                        help="list numeric user and group IDs",
                        action='store_true',
                        default=False)
    parser.add_argument(
        '-F',
        dest="filter_files_with_ads",
        help="Show only files which include Alternate Data Streams",
        action='store_true',
        default=False)
    parser.add_argument(
        '--no-warning',
        dest="no_warning",
        help="Suppress warnings (e.g. if the filesystem is not NTFS)",
        action='store_true',
        default=False)

    parsed_arguments = parser.parse_args(flags_to_parse)

    if parsed_arguments.help:
        parser.print_help()
        exit()

    base_path = os.path.abspath(path)
    if not os.path.exists(base_path):
        error('Path "{}" does not exist'.format(path))
        exit()

    output = list()

    if os.path.isfile(path):  # the path points to a file
        # check the filesystem and collect the alternate data streams
        if path_is_an_ntfs_filesystem(path=base_path):
            alternate_data_streams = get_alternate_data_streams_of_file(
                path_to_file=base_path)
        else:
            alternate_data_streams = list()
            if not parsed_arguments.no_warning:
                warning(WARNING_TEXT_WRONG_FILE_SYSTEM_PATH)

        output.extend(
            __generate_output_single_file(
                arguments=parsed_arguments,
                path_to_file=base_path,
                file_name=path,
                file_info=os.stat(base_path),
                alternate_data_streams=alternate_data_streams))

    elif not parsed_arguments.recursive:  # the path points to a directory (recursive flag is not set)
        if path_is_an_ntfs_filesystem(path=base_path):
            search_alternate_data_streams = True
        else:
            search_alternate_data_streams = False
            if not parsed_arguments.no_warning:
                warning(WARNING_TEXT_WRONG_FILE_SYSTEM_PATH)

        for x in os.scandir(base_path):
            file_name = x.path.replace(base_path, '')
            file_info = x.stat()
            if search_alternate_data_streams and x.is_file():
                alternate_data_streams = get_alternate_data_streams_of_file(
                    path_to_file=x.path)
            else:
                alternate_data_streams = list()

            generated_output = __generate_output_single_file(
                arguments=parsed_arguments,
                path_to_file=x.path,
                file_name=file_name,
                file_info=file_info,
                alternate_data_streams=alternate_data_streams)
            output.extend(generated_output)

    else:  # the path points to a directory (recursive flag is set)
        # to faster the scan apply getfattr recursively on the directory and parse the complete output

        if not parsed_arguments.no_warning and not path_is_an_ntfs_filesystem(
                base_path):
            warning(WARNING_TEXT_WRONG_FILE_SYSTEM_BASE_PATH)

        alternate_data_streams_dict = get_alternate_data_streams_recursively(
            path_to_directory=base_path)

        def scan_directory(path_to_dir):
            for x in os.scandir(path_to_dir):
                file_name = x.path.replace(base_path, '')
                try:
                    file_info = x.stat()
                except OSError:
                    warning(message='File {} could not be analyzed'.format(
                        file_name))
                    continue

                alternate_data_streams = alternate_data_streams_dict.get(
                    x.path, list())
                generated_output = __generate_output_single_file(
                    arguments=parsed_arguments,
                    path_to_file=x.path,
                    file_name=file_name,
                    file_info=file_info,
                    alternate_data_streams=alternate_data_streams)
                output.extend(generated_output)

                if parsed_arguments.recursive and x.is_dir():
                    scan_directory(path_to_dir=x.path)

        scan_directory(path_to_dir=base_path)

    # Find maximum width of each column to print the table nicely
    max_width_for_each_column = defaultdict(int)
    for line in output:
        for i, cell in enumerate(line):
            max_width_for_each_column[i] = max(max_width_for_each_column[i],
                                               len(cell))

    for line in output:
        for i, cell in enumerate(line):
            if i == len(line) - 1:
                print(cell.ljust(max_width_for_each_column[i]), end='\n')
            elif i == 3:  # the file size has to be aligned to the right
                print(cell.rjust(max_width_for_each_column[i]), end=' ')
            else:
                print(cell.ljust(max_width_for_each_column[i]), end=' ')
Exemple #10
0
def program(input_path: str, mounting_path: str):
    # create directory which contains all mounting endpoints
    if not os.path.exists(mounting_path):
        try:
            os.makedirs(mounting_path)
        except PermissionError:
            error('Permission denied for creating directory "{}"'.format(
                mounting_path))
            exit()

    # mount the ewf file
    mounting_path_ewf_dir = os.path.join(mounting_path, '.ewf')
    if not os.path.exists(mounting_path_ewf_dir):
        try:
            os.makedirs(mounting_path_ewf_dir, exist_ok=True)
        except PermissionError:
            error('Permission denied for creating directory "{}"'.format(
                mounting_path_ewf_dir))
            exit()

    if int(
            os.system('ewfmount "{}" "{}" >/dev/null 2>&1'.format(
                __escape_path(input_path),
                __escape_path(mounting_path_ewf_dir)))) != 0:
        error(message=
              'An error occurred while mounting ewf file to "{}". Exiting.'.
              format(mounting_path_ewf_dir))
        exit()
    else:
        info(message='ewf file mounted to "{}"'.format(mounting_path_ewf_dir))

    # get the path to the ewf file
    path_to_the_mounted_ewf_file = None
    for file_path in os.listdir(mounting_path_ewf_dir):
        path_to_the_mounted_ewf_file = os.path.join(mounting_path_ewf_dir,
                                                    file_path)
    if path_to_the_mounted_ewf_file is None:
        info(message='Could not find mounted ewf file. Exiting.')
        exit()

    # Mount ewf tile to unused loop device
    path_to_loop_device = __get_first_unused_loop_device()
    if int(
            os.system('losetup -Pv "{}" "{}" >/dev/null 2>&1'.format(
                __escape_path(path_to_loop_device),
                __escape_path(path_to_the_mounted_ewf_file)))) != 0:
        info(
            message=
            'An error occurred while mounting ewf file to loop back device. Exiting.'
        )
        exit()

    while True:
        info(message='Select Partition to mount:')
        os.system('fdisk -l "{}"'.format(__escape_path(path_to_loop_device)))
        print()
        selected_partition_number = input(
            'select number of partition (0 for complete disk) [1] > ')

        if len(selected_partition_number) == 0:  # Default value
            selected_partition_number = 1
        else:
            # check if partition number is an integer
            try:
                selected_partition_number = int(selected_partition_number)
            except ValueError:
                error('The partition number must be an integer')
                print()
                continue

        if selected_partition_number == 0:
            selected_partition_path = path_to_loop_device
            info(message='selected the complete disk "{}"'.format(
                __escape_path(selected_partition_path)))
        else:
            selected_partition_path = '{}p{}'.format(
                path_to_loop_device, selected_partition_number)
            info(message='selected partition "{}"'.format(
                __escape_path(selected_partition_path)))

        bitlocker_key = input(
            'Bitlocker Recovery Key (if encrypted otherwise empty) > ')

        if len(bitlocker_key) > 0:

            # check if provided key is valid
            if re.fullmatch(r'((\d){6}-){7}(\d{6})', bitlocker_key) is None:
                error(
                    'The format of the recovery key you typed in is invalid.')
                info(
                    'The key must be in the format: DDDDDD-DDDDDD-DDDDDD-DDDDDD-DDDDDD-DDDDDD-DDDDDD'
                )
                print()
                continue

            mounting_path_dislocker = os.path.join(
                mounting_path,
                '.partition_{}_encrypted'.format(selected_partition_number))
            if not os.path.exists(mounting_path_dislocker):
                os.makedirs(mounting_path_dislocker)
            if int(
                    os.system(
                        'dislocker -v -V "{}" -p{} "{}" >/dev/null 2>&1'.
                        format(__escape_path(selected_partition_path),
                               bitlocker_key,
                               __escape_path(mounting_path_dislocker)))) != 0:
                info(message=
                     'An Error occurred. Partition could not be decrypted')
            else:
                mounting_path_dislocker_file = os.path.join(
                    mounting_path_dislocker, 'dislocker-file')
                mounting_path_decrypted = os.path.join(
                    mounting_path,
                    'partition_{}_decrypted'.format(selected_partition_number))
                __final_mount_procedure(
                    source_path=mounting_path_dislocker_file,
                    target_path=mounting_path_decrypted,
                    partition_number=selected_partition_number)
        else:
            mounting_path_partition = os.path.join(
                mounting_path,
                'partition_{}'.format(selected_partition_number))
            __final_mount_procedure(source_path=selected_partition_path,
                                    target_path=mounting_path_partition,
                                    partition_number=selected_partition_number)
        print()
        input('Press ENTER to mount another partition')