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()
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.')