看《python绝技》看到“你的第一个程序,一个unix密码破解器!”,涌上一种中学生回小学装逼的幸福感。但书里只写了test:$1$HXEtlo/Qz.0mA
这种情况,对于现行的情况懒得提,所以更新下代码顺便复习(好吧是学习)unix密码相关知识点
- unix密码:
root:$1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.:14838:0:99999:7:::
1)“登录名”是与/etc/passwd文件中的登录名相一致的用户账号
2)“口令”字段存放的是加密后的用户口令字,长度为13个字符。如果为空,则对应用户没有口令,登录时不需要口令;如果含有不属于集合{./0-9A-Za-z}中的字符,则对应的用户不能登录。
3)“最后一次修改时间”表示的是从某个时刻起,到用户最后一次修改口令时的天数。时间起点对不同的系统可能不一样。例如在SCOLinux中,这个时间起点是1970年1月1日。
4)“最小时间间隔”指的是两次修改口令之间所需的最小天数。
5)“最大时间间隔”指的是口令保持有效的最大天数。
6)“警告时间”字段表示的是从系统开始警告用户到用户密码正式失效之间的天数。
7)“不活动时间”表示的是用户没有登录活动但账号仍能保持有效的最大天数。
8)“失效时间”字段给出的是一个绝对的天数,如果使用了这个字段,那么就给出相应账号的生存期。期满后,该账号就不再是一个合法的账号,也就不能再用来登录了。 - 代码环境
unix环境,py2,crypt
FILE
/usr/lib/python2.7/lib-dynload/crypt.x86_64-linux-gnu.so
MODULE DOCS
https://docs.python.org/library/crypt
FUNCTIONS
crypt(...)
crypt(word, salt) -> string
word will usually be a user's password. salt is a 2-character string which will be used to select one of 4096 variations of DES. The characters in salt must be either ".", "/", or an alphanumeric character. Returns the hashed password as a string, which will be composed of characters from the same alphabet as the salt.
>>>import crypt
>>>crypt.crypt('19830617','$6$Jn47piWf$') #密码,$算法类型$salt值
- 实验:
>>useradd nino
>>passwd nino #19830617
>>cat /etc/shadow
nino:$6$Jn47piWf$J2vYwIbHDgrAC4Lt3TD/KWj.F7Hu7W2wUmfA/J1iCKN7KyraKmQ9/jWcC9MLjiuICTKKTGB8t4vhEAx754Rq7/:17903:0:99999:7:::
#$6 表示类型标记为6的密码散列算法——SHA-512哈希算法;$Jn47piWf$指的是加盐(Salt)值
>>> crypt.crypt('19830617','$6$Jn47piWf$')
'$6$Jn47piWf$J2vYwIbHDgrAC4Lt3TD/KWj.F7Hu7W2wUmfA/J1iCKN7KyraKmQ9/jWcC9MLjiuICTKKTGB8t4vhEAx754Rq7/'
完整代码
# -*- coding: utf-8 -*-
import crypt
import sys
import hashlib
file = '''
test:$1$HXEtlo/Qz.0mA
root:$1$Bg1H/4mz$X89TqH7tpi9dX1B9j5YsF.:14838:0:99999:7:::
nino:$6$Jn47piWf$J2vYwIbHDgrAC4Lt3TD/KWj.F7Hu7W2wUmfA/J1iCKN7KyraKmQ9/jWcC9MLjiuICTKKTGB8t4vhEAx754Rq7/:17903:0:99999:7:::
'''
#test:123456(HX是salt);root:123;nino:19830617
#dictionary=sys.argv[1]
#dictFile=open(dictionary,'r').readlines()
def testPass(cryptPass,dictFile):
for word in dictFile:
word=word.strip('\n')
cryptWord=crypt.crypt(word,cryptPass)
if (cryptWord==cryptPass):
print "[+] Found Password:"+word+"\n"
return word
print "[-] Password Not Found.\n"
def main():
passFile=file.split()#open('/etc/shadow').readlines()
dictionary= ['123','19830617']
for line in passFile:
if ":" in line:
user=line.split(':')[0]
cryptPass=line.split(':')[1].strip()
print "[*] Cracking Password For:"+user
testPass(cryptPass,dictionary)
if __name__=="__main__":
main()
运行结果
总结
- 熟悉shadow文件每个字段的含义
nino:$6$Jn47piWf$J2vYwIbHDgrAC4Lt3TD/KWj.F7Hu7W2wUmfA/J1iCKN7KyraKmQ9/jWcC9MLjiuICTKKTGB8t4vhEAx754Rq7/:17903:0:99999:7:::
- 根据字典遍历破解crypt.crypt('密码','salt值')
网友评论