蓝域黑客:Linux密码破解python实现+多进程

0x01思路

我们只需要用标准库中的crypt 模块的crypt()函数。传入密码和盐即可。(注意crypt不是通用库Windows下无法使用),关于多进程是因为我编写好爆破脚本之后发现爆破时间太久,而爆破时CPU只有14%的使用率,所以加了多进程,啥??你问我怎么不用多线程?python的多线程比单线程还慢。


    因为在 Cpython 解释器中,有一把全局解释锁(Global Interpreter Lock),在解释器解释执行 Python 代码时,先要得到这把锁,意味着,任何时候只可能有一个线程在执行代码,其它线程要想获得 CPU 执行代码指令,就必须先获得这把锁,如果锁被其它线程占用了,那么该线程就只能等待,直到占有该锁的线程释放锁才有执行代码指令的可能.

 因此,这也就是为什么两个线程一起执行反而更加慢的原因,因为同一时刻,只有一个线程在运行,其它线程只能等待,即使是多核CPU,也没办法让多个线程并行执行代码,只能是交替执行,因为多线程涉及到上线文切换、锁机制处理(获取锁,释放锁等),所以,多线程执行不快反慢。

0x02扩展知识

1.Linux密码

Linux密码存放在/etc/shadow文件中:
root@kali:~# cat /etc/shadow
root:$6$JLMgzb8Z$xwG9YinG5utxbTWq6Ij9zajlut9jD471h6w4Rx4Y4uQZiTsRBTmMV/8EOAJzS2svSuGtNKkWJ8wl1mqCdDokQ/:17890:0:99999:7:::

其格式为:


{用户名}:{加密后的口令密码}:{口令最后修改时间距原点(1970-1-1)的天数}:{口令最小修改间隔(防止修改口令,如果时限未到,将恢复至旧口令):{口令最大修改间隔}:{口令失效前的警告天数}:{账户不活动天数}:{账号失效天数}:

【注】:shadow文件为可读文件,普通用户没有读写权限,超级用户拥有读写权限。如果密码字符串为*,则表示系统用户不能被登入;如果字符串为!,则表示用户名被禁用;如果字符串为空,则表示没有密码。

对于示例的密码域:
`$6$JLMgzb8Z$xwG9YinG5utxbTWq6Ij9zajlut9jD471h6w4Rx4Y4uQZiTsRBTmMV/8EOAJzS2svSuGtNKkWJ8wl1mqCdDokQ/`

参考了linux标准源文件passwd.c,在其中的pw_encrypt函数中找到了加密方法。发现所谓的加密算法,其实就是用明文密码和一个叫salt的东西通过函数crypt()完成加密。

而所谓的密码域密文也是由三部分组成的,即:

$id$salt$encrypted

【 注】: id为1时,采用md5进行加密;id为5时,采用SHA256进行加密;id为6时,采用SHA512进行加密。


2、python中关于crypt的介绍

该模块实现了crypt()例程的接口,该例程是基于修改的DES算法的单向散列函数; 有关更多详细信息,请参见Unix手册页。可能的用途包括存储散列密码,以便您可以在不存储实际密码的情况下检查密码,或者尝试使用字典破解Unix密码。


请注意,此模块的行为取决于正在运行的系统中crypt(3)例程的实际实现。因此,此模块也将提供当前实现中可用的任何扩展。


散列方法:

版本3.3中的新功能。


该crypt模块定义了散列方法列表(并非所有平台都提供所有方法):

    crypt.METHOD_SHA512
        模块化加密格式方法,基于SHA-512哈希函数,具有16个字符的盐和86个字符的哈希值。这是最强的方法。
        
    crypt.METHOD_SHA256
        另一种Modular Crypt Format方法,基于SHA-256哈希函数,具有16个字符的盐和43个字符的哈希值。
        
    crypt.METHOD_BLOWFISH
        另一种模块化密码格式方法,基于Blowfish密码,具有22个字符的盐和31个字符的哈希值。
        
        版本3.7中的新功能。
        
    crypt.METHOD_MD5
        另一种Modular Crypt Format方法,基于MD5哈希函数,具有8个字符的盐和22个字符的哈希值。
        
    crypt.METHOD_CRYPT
        传统方法使用2个字符的盐和13个字符的哈希值。这是最弱的方法。
        
模块功能:
该crypt模块定义了以下功能:

crypt.crypt(word,salt = None )

word通常是在提示符或图形界面中输入的用户密码。可选的salt是从返回的字符串 mksalt(),其中一个crypt.METHOD_*值(尽管并非所有平台上都可用),或者是由此函数返回的包含salt的完整加密密码。如果没有提供盐,将使用最强的方法(由返回 methods())。

检查密码通常是通过将纯文本密码作为单词和前一次crypt()调用的完整结果传递来完成的,该结果应该与此调用的结果相同。

salt(可以是随机的2或16个字符的字符串,可能带有前缀 $digit$以表示方法),它将用于扰乱加密算法。salt中的字符必须在集合中 [./a-zA-Z0-9],但模块化加密格式除外,其前缀为a $digit$。

以字符串形式返回哈希密码,该字符串将由与盐相同的字母组成。


由于少数crypt(3)扩展允许使用不同的值,并且盐中的大小不同,因此建议在检查密码时使用完整的加密密码作为salt。

在版本3.3中更改:crypt.METHOD_*除了salt的字符串之外还接受值。

crypt.mksalt(method = None,*,rounds = None )

 返回指定方法的随机生成的salt。如果没有 方法给出,如返回可用的最强方法 methods()被使用。
 
 返回值是一个适合作为salt参数传递的字符串crypt()。
 
 rounds指定的轮数METHOD_SHA256, METHOD_SHA512和METHOD_BLOWFISH。对于METHOD_SHA256和METHOD_SHA512它必须是1000和之间的整数 999999999,默认为5000。因为 METHOD_BLOWFISH它必须是16(2^4)和2147483648(2^31)之间的2 的幂,默认值是4096 (2^12)。
 
 版本3.3中的新功能。
 版本3.7中已更改:添加了rounds参数。

0x03代码编写

1、导入模块设置全局变量

    # -*- coding: UTF-8 -*-
    import crypt
    import sys, getopt
    import multiprocessing
    user_pwflie = ""
    dicti = ""

2、usage函数

def usage():
    print('linux passwd 爆破')
    print()
    print("Usage: lpd.py -p shadow -d dic.txt")
    print("-p  --passwd  - 需要破解的密码文件")
    print("-d  --dictionary  - 字典文件")
    sys.exit(0)

1、处理密码文件

def get_pw(u_p):
        # 定义用户名和密码对应的字典
        user_pw = {}
        # 读取shadow文件
        f = open(u_p,'r')
        userline = f.readlines()
        f.close()
        for l in userline:
            # 筛选掉系统用户
            if len(l.split(":")[1]) > 3:
                # 将用户和密码加入字典user_pw
                user_pw[l.split(":")[0]] = l.split(":")[1]
       return user_pw

2、读取字典文件


   def get_dic(g_d):
        f = open(g_d,'r')
        mw_dic = f.readlines()
        f.close()
        return mw_dic

3、加密爆破

    def hashmd5 (user_passwd,mw_dic):
        for u in user_passwd:
            passwd = user_passwd[u]
            salt = "$6$" + passwd.split("$")[2]
            for pw_mv in mw_dic:
                if passwd == crypt.crypt(pw_mv.rstrip(), salt):
                    print("用户名:%s  密码:%s" % (u, pw_mv.rstrip()))

4、主程序及建立多进程


def main():
        if not len(sys.argv[1:]):
            usage()
        try:
            opts,args = getopt.getopt(sys.argv[1:],"hp:d:",["passwd","dictionary"])
        except getopt.GetoptError as err:
            print("err")
            usage()
        for opt, arg in opts:
            if opt in ('-h','--help'):
                usage()
                sys.exit()
            elif opt in ("-p", "--passwd"):
                user_pwfile = arg
            elif opt in ("-d", "--dictionary"):
                dicti = arg
            else:
                assert False,"Unhandled Option"
        user_passwd = get_pw(user_pwfile)
        mw_dic = get_dic(dicti)
        #mw_dic = mw_dic.split('\n')
        s = len(mw_dic)
        s = s//20
        #创建进程池
        pool = multiprocessing.Pool(processes=50)
        #添加进程
        for i in range(1,22):
            pool.apply_async(hashmd5,(user_passwd,mw_dic[(i-1)*s:s*i]))
        pool.close()
        pool.join()

以上就是蓝域安全网为您带来的,Linux密码破解python实现+多进程如果您喜欢该篇文章
(转载请注明本文链接:http://www.yemogege.cn/wzaq-stwz/345.html

版权保护: 本文由admin所发布,转载请保留本文链接: http://www.yemogege.cn/wzaq-stwz/345.html

免责声明:蓝域安全网所发布的一切渗透技术视频文章,逆向脱壳病毒分析教程,以及相关实用源码仅限用于学习和研究目的
请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除! 

侵权删帖/违法举报/投稿等事物联系邮箱:yemogege@vip.qq.com 网站地图