Example #1
0
    def error_handler(self, exc):
        """
        Error callback handler for thread related issues
        :param exc: Exception
        :return: None
        """
        error(
            f'Unhandled exception in cracker thread. Please report this issue '
            f'on the official bug tracker: "{__url__}/issues" and don\'t forget '
            f'to include the following traceback:')

        print(type(exc).__name__ + ': ' + str(exc), file=sys.stderr)
        print_tb(exc.__traceback__, file=sys.stderr)
        self.has_error = True
        self.pool.terminate()
Example #2
0
def main():
    """Main entry point of the application"""

    if any(i in sys.argv for i in ('-q', '--quiet', '--stfu')):
        if any(i in sys.argv for i in ('-V', '--verbose')):
            return error(
                "Arguments 'verbose' and 'quiet', are mutually exclusive. "
                "You have to choose either one of them, not both.")

        sys.stderr = DevNull()

    if any(i in sys.argv for i in ('-v', '--version')):
        return print(__version__)

    log(f'StegCracker {__version__} - ({__url__})', )
    log(f'Copyright (c) {datetime.now().year} - Luke Paris (Paradoxis)')
    log('')

    args = ArgumentParser(usage='stegcracker <file> [<wordlist>]',
                          formatter_class=CustomHelpFormatter,
                          description=__description__)

    args.add_argument(
        'file',
        action='store',
        help=
        (f'Input file you think contains hidden information and wish to crack. '
         f'Note: Stegcracker only accepts the following file types: '
         f'{", ".join(Cracker.SUPPORTED_FILES)}'))

    args.add_argument(
        'wordlist',
        action='store',
        nargs='?',
        help=
        ('Wordlist containing the one or more passwords (one password per line). '
         'If no password list is supplied, this will default to the rockyou.txt '
         'wordlist on Kali Linux.'),
        default=None)

    args.add_argument(
        '-o',
        '--output',
        default=None,
        help=
        ('Output file location, this will be the file the data will be written '
         'to on a successful cracked password. If no output location is '
         'specified, the default location will be the same filename with ".out" '
         'appended to the name.'))

    args.add_argument(
        '-t',
        '--threads',
        type=int,
        default=16,
        help=
        ('Number of concurrent threads used to crack passwords with, increasing '
         'this number might lead to better performance. Default: 16'))

    args.add_argument(
        '-c',
        '--chunk-size',
        type=int,
        default=64,
        help=
        ('Number of passwords loaded into memory per thread cycle. After each '
         'password of the chunk has been depleted a status update will be '
         'printed to the console with the attempted password. Default: 64'))

    args.add_argument(
        '-q',
        '--quiet',
        '--stfu',
        action='store_true',
        help=
        ('Runs the program in "quiet mode", meaning no status updates or other '
         'output besides the cracked password will be echoed to the terminal. '
         'By default, all logging / error messages are printed to stderr (making '
         'piping to other processes easier).'),
        default=False)

    args.add_argument('-v',
                      '--version',
                      action='store_true',
                      help=('Print the current version number and exit.'))

    args.add_argument(
        '-V',
        '--verbose',
        action='store_true',
        help=
        ('Runs the program in "verbose mode", this will print additional '
         'debugging information (include this output when submitting bug '
         'reports). Cannot be used in conjunction with the "--quiet" argument.'
         ),
        default=False)

    args = args.parse_args()

    output = args.output or args.file + '.out'
    extension = args.file.split('.')[::-1][0].lower()

    if not find_executable('steghide'):
        return error(
            'Steghide does not appear to be installed, or has not been added to '
            'your current PATH, please install it using: "apt-get install '
            'steghide -y" or by downloading it from the official code '
            'repository: http://steghide.sourceforge.net/')

    if args.wordlist is None:
        if isfile(DEFAULT_WORDLIST_PATH):
            log('No wordlist was specified, using default rockyou.txt wordlist.'
                )
            args.wordlist = DEFAULT_WORDLIST_PATH

        elif isfile(DEFAULT_WORDLIST_PATH + '.gz'):
            return error(
                f'No wordlist was specified, but a gzipped variant of the '
                f'rockyou.txt wordlist was found on your system. If you wish '
                f'to use it, please decompress it first using the following command: '
                f'gzip -d {DEFAULT_WORDLIST_PATH}.gz')

        else:
            return error('No wordlist was specified. '
                         'For more help, please run: stegcracker --help')

    if isfile(output):
        return error(f'Output file {output!r} already exists!')

    if not isfile(args.file):
        return error(f'Input file {args.file!r} does not exist!')

    if not isfile(args.wordlist):
        return error(f'Wordlist {args.wordlist!r} does not exist!')

    if args.wordlist.endswith('.gz'):
        return error(
            f"It appears you're using a gzipped variant of a wordlist, instead "
            f"of the actual wordlist itself. You can decompress the gzipped "
            f"using the following command: gzip -d {args.wordlist}")

    if extension not in Cracker.SUPPORTED_FILES:
        return error(f'Unsupported file type {extension!r}! Supported '
                     f'extensions: {", ".join(Cracker.SUPPORTED_FILES)}')

    if not args.quiet:
        log(f'Counting lines in wordlist..')
        line_count = wc(args.wordlist)
    else:
        line_count = None

    with open(args.wordlist, mode='rb') as wordlist:
        cracker = Cracker(file=args.file,
                          output=output,
                          line_count=line_count,
                          chunk_size=args.chunk_size,
                          quiet=args.quiet,
                          verbose=args.verbose,
                          threads=args.threads)

        if not args.quiet:
            log(f'Attacking file {args.file!r} '
                f'with wordlist {args.wordlist!r}..')

        cracker.run(wordlist)

    if cracker.password:
        log(f'Successfully cracked file with password: {cracker.password}')
        log(f'Tried {cracker.attempts} passwords')
        log(f'Your file has been written to: {output}')
        print(cracker.password)

    elif cracker.has_error:
        return error('Terminating due to previous exception..')

    else:
        return error('Failed to crack file, ran out of passwords.')