利用Python破解Linux密码

利用Python破解Linux密码

import sys
import optparse
import os
import crypt


# The Program is intended to decyrpt Linux hashed password
# The main module will be crypt

# crypt.crypt(word, salt=None)
#     word will usually be a user’s password as typed at a prompt or in a graphical interface. The optional salt is either a string as returned from mksalt(), one of the crypt.METHOD_* values (though not all may be available on all platforms), or a full encrypted password including salt, as returned by this function. If salt is not provided, the strongest method available in methods will be used.
#     Checking a password is usually done by passing the plain-text password as word and the full results of a previous crypt() call, which should be the same as the results of this call.
#     salt (either a random 2 or 16 character string, possibly prefixed with $digit$ to indicate the method) which will be used to perturb the encryption algorithm. The characters in salt must be in the set [./a-zA-Z0-9], with the exception of Modular Crypt Format which prefixes a $digit$.
#     Returns the hashed password as a string, which will be composed of characters from the same alphabet as the salt.
#     Since a few crypt(3) extensions allow different values, with different sizes in the salt, it is recommended to use the full crypted password as salt when checking for a password.
#     Changed in version 3.3: Accept crypt.METHOD_* values in addition to strings for salt.


class PasswordDecryptor:
    def __init__(self) -> None:
        self.filename = self.get_params()[0]
        self.wordlist = self.get_params()[1]
        self.check_file(self.filename)
        self.check_file(self.wordlist)

    def get_params(self):
        parser = optparse.OptionParser('Usage:./%s -f password filename -w wordlist' % sys.argv[0])
        parser.add_option('-f', '--filename', dest='filename', type='string', help='Specify hashed password to crack')
        parser.add_option('-w', '--wordlist', dest='wordlist', type='string', help='Specify wordlist')
        options, args = parser.parse_args()
        if options.filename is None or options.wordlist is None:
            print('[-]',parser.usage)
            sys.exit()
        return options.filename, options.wordlist
    
    def check_file(self,filename):
        if not os.path.isfile(filename):
            print("The file %s does not exist!" % filename)
            sys.exit()
        elif not os.access(filename,os.R_OK):
            print("No privilege to access the file %s" % filename)
            sys.exit()
    
    def decrypt(self,salt, hashed_password):
        with open(self.wordlist,'r') as f:            
            while True:
                try:
                    line = f.readline()
                    if len(line) == 0:
                        break
                    clear_text = line.strip()
                    print("[-] Attempt to decrypt with %s" % clear_text)            
              
                    result = crypt.crypt(clear_text, salt)
                   
                    if result == salt + '$' +  hashed_password:
                        print("[+] Password found!  %s" % clear_text)
                        sys.exit()

                except:
                    continue
    
    def run(self):
        with open(self.filename,'r') as pf:
            for line in pf.readlines():
                username = line.split(':')[0]
                hash_password_all = line.split(':')[1].strip()
                salt = '$' + hash_password_all.split('$')[1] + '$' + hash_password_all.split('$')[2]
                hash_password = hash_password_all.split('$')[3]
                print('[+] Start to crack password for %s' % username)
                self.decrypt(salt,hash_password)


if __name__ == '__main__':
    decryptor = PasswordDecryptor()
    decryptor.run()


注意点

Python crypt模块的crypt方法传输的salt值需要将表示Hash加密算法的值同时传入,比如对于MD5加密的密码需要将以下值作为salt传入:

$1$XN10Zj2c

而不仅仅是

XN10Zj2c
posted @ 2023-01-08 22:44  Jason_huawen  阅读(121)  评论(0编辑  收藏  举报