Python绝技第一章 入门 python3实现密码破解
前言
对我而言,武术的非凡之处在于它的简单。简单的方法也是正确的方法,同时武术也没有什么特别之处。越接近武术的真谛,招式表现上浪费越少
简介
python 绝技
第一章是python
入门语法,两个需要编写的程序分别是用字典攻击法破解UNIX口令
,暴力破解ZIP文件
,两者都是使用暴力法直接进行破解,另外第一个程序在当前的网络环境中已经不太适用了,我们将其升级为破解SHA-512 hash
的版本
背景故事
虽然在书中已经有背景故事的翻译了,但是这里我还是采用乌云
之前翻译的版本
C. Stoll的《杜鹃蛋》(1989)堪称新派武侠的开山之作。它第一次把黑客活动与国家安全联系在一起。黑客极具破坏性的黑暗面也浮出海面,并且永远改变了黑客的形象。迄今仍是经久不衰的畅销书。Stoll是劳伦斯伯克利实验室的天文学家和系统管理员。1986年夏,一个区区75美分的帐目错误引起了他的警觉,在追查这次未经授权的入侵过程中,他开始卷入一个错综复杂的电脑间谍案。神秘的入侵者是西德混沌俱乐部的成员。他们潜入美国,窃取敏感的军事和安全情报。出售给克格勃,以换取现金及可卡因。一场网络跨国大搜索开始了,并牵涉出FBI、CIA、克格勃、西德邮电部等。《杜鹃蛋》为后来的黑客作品奠定了一个主题:追捕与反追捕的惊险故事。而且也开始了新模式:一个坚韧和智慧的孤胆英雄,成为国家安全力量的化身,与狡猾的对手展开传奇的较量。
SHA-512 hash 破解
环境 : python3
在破解之前我们先了解一下shadow格式
root:$1$v2wT9rQF$XSpGgoB93STC4EFSlgpjg1:14181:0:99999:7:::
可以发现shadow中每一行对应这一个用户的用户名和密码等信息,格式为0:1:2:3:4:5:6:7:8
冒号是分割符,分别代表着,每个字段分别代表着:
0:用户名
1:密码hash值
2:密码修改距离1970年1月1日的时间
3:密码将被允许修改之前的天数(0 表示“可在任何时间修改”)
4:系统将强制用户修改为新密码之前的天数(1 表示“永远都不能修改”)
5:密码过期之前,用户将被警告过期的天数(-1 表示“没有警告”)
6:密码过期之后,系统自动禁用帐户的天数(-1 表示“永远不会禁用”)
7:该帐户被禁用的天数(-1 表示“该帐户被启用”)
8:保留供将来使用
hash值一览格式如:$id$salt$密文
id代表的是使用不同的加密算法,不同的系统使用的算法也不尽相同。salt是加密的时候需要用到盐。最后就是密文。
数字和所使用的加密算法对应关系:
格式 | 算法 |
---|---|
$1 | md5 |
$2a | blowfish |
$2y | blowfish |
$5 | sha-256 |
$6 | sha-512 |
注意:如果密码字符串为*
,表示系统用户不能被登入,为!
表示用户名被禁用,如果密码字符串为空,表示没有密码。
这里我们使用python3
中的hashlib
库计算sha-512
hash=hashlib.sha512(salt.encode('utf-8'))
hash.update(word.encode('utf-8'))
print(hash.hexdigest())
这样实现了sha-512
加密,但是,这里的结果并不像是我们Linux
操作系统中的密码,譬如我们上面举例的密码中:
XSpGgoB93STC4EFSlgpjg1
其中就包含了不在十六进制中的字符
事实上以$6
为例并不是单纯的sha512(pass+salt)
或者sha512(salt+passwd)
,而是经历了一系列复杂的运算而获得的。
我们先实现sha-512
的解密
import hashlib'''
testPass(cryptPass)函数
功能:传入 cryptPass 待解密密码print 破解结果
算法:穷举法
'''
def testPass(cryptPass):salt,shadowPass=cryptPass.split('$')[2],cryptPass.split('$')[3]dictFile=open('dictionary.txt','r')for word in dictFile.readlines():word=word.strip()# print(word)hash=hashlib.sha512(salt.encode('utf-8'))hash.update(word.encode('utf-8'))# print(hash.hexdigest())if shadowPass==hash.hexdigest():print("[+] Found Password {}".format(word))returnprint("[-] Password Not Found ")returndef main():passFile=open('passwords.txt')for line in passFile.readlines():if ":" in line:user=line.split(':')[0]cryptPass=line.split(':')[1].strip(' ')print("[*] Now cracking Password For :{}".format(user))testPass(cryptPass)if __name__ == '__main__':main()
这里的密码文件是我们构造的
root:$6$123$263fec58861449aacc1c328a4aff64aff4c62df4a2d50b3f207fa89b6e242c9aa778e7a8baeffef85b6ca6d2e7dc16ff0a760d59c13c238f6bcdc32f8ce9cc62:15503:0:99999:7:::
实际上是密文123
同时盐值123
运行破解
破解成功
shadow密码破解
上面举例的密码是我们在cmd5
网站上自行构造的,但*nix
操作系统上密码并不是简单的sha512(pass+salt)
或者sha512(salt+passwd)
,但在简书上找到了一位师傅之前使用hashlib
来还原该加密算法python生成shadow中密码(SHA512)
import hashlib,mathdef rstr_sha512(text: bytes) -> bytes:sha512 = hashlib.sha512()sha512.update(text)return sha512.digest()def _extend(source: bytes, size_ref: int) -> bytes :extended = b"";for i in range(math.floor(size_ref/64)):extended += source;extended += source[:size_ref % 64]return extended;def _sha512crypt_intermediate(password: bytes,salt: bytes) -> bytes:#digest_a = rstr_sha512(password + salt)digest_b = rstr_sha512(password + salt + password)digest_b_extended = _extend(digest_b,len(password))intermediate_input = password + salt + digest_b_extendedpasswd_len = len(password)while passwd_len!=0:if passwd_len&1 == 1:intermediate_input += digest_belse:intermediate_input += passwordpasswd_len >>= 1return rstr_sha512(intermediate_input)def _sha512crypt(password :bytes,salt :bytes,rounds :int) -> bytes:digest_a = _sha512crypt_intermediate(password, salt)p = _extend(rstr_sha512(password*len(password)),len(password))s = _extend(rstr_sha512(salt*(16+digest_a[0])),len(salt))digest = digest_afor i in range(rounds):c_input = b""if i&1 :c_input += pelse:c_input += digestif i % 3:c_input += sif i % 7:c_input += pif i & 1:c_input += digestelse:c_input += pdigest = rstr_sha512(c_input)return digestdef sha512crypt(password :bytes,salt :bytes, rounds=5000) -> str:salt = salt[:16] # max 16 bytes for saltinput = _sha512crypt(password, salt, rounds)tab = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"order = [ 42, 21, 0, 1, 43, 22, 23, 2, 44, 45, 24, 3,4, 46, 25, 26, 5, 47, 48, 27, 6, 7, 49, 28,29, 8, 50, 51, 30, 9, 10, 52, 31, 32, 11, 53,54, 33, 12, 13, 55, 34, 35, 14, 56, 57, 36, 15,16, 58, 37, 38, 17, 59, 60, 39, 18, 19, 61, 40,41, 20, 62, 63]output = ""for i in range(0,len(input),3):# special case for the end of the inputif i+1 >= len(order): # i == 63char_1 = input[order[i+0]] & 0b00111111char_2 = (input[order[i+0]] & 0b11000000) >> 6output += tab[char_1] + tab[char_2]else:char_1 = input[order[i+0]] & 0b00111111char_2 = (((input[order[i+0]] & 0b11000000) >> 6) |(input[order[i+1]] & 0b00001111) << 2)char_3 = (((input[order[i+1]] & 0b11110000) >> 4) | (input[order[i+2]] & 0b00000011) << 4)char_4 = (input[order[i+2]] & 0b11111100) >> 2output += tab[char_1] + tab[char_2] + tab[char_3] + tab[char_4]if rounds!=5000:return "$6$rounds={}${}${}".format(rounds,salt.decode("utf-8"),output)else:return "$6${}${}".format(salt.decode("utf-8"),output)if __name__ == "__main__":# 与crypt.crypt("123456","$6$123456") 运算结果一致print(sha512crypt(b"123456",b"123456",5000))
在ubuntu 16.04
虚拟机里面添加一个账号为test123
,密码为123
的用户
接着查看shadow
文件中其对应的密码
test123:$6$DhlRUwqV$Jln02cwolkp3adJjELMn9q2MxKRalcdzyyJnMg3EayVMgNQ0v9plYEnFns58sBkfUROfhT4Fsdksoxjfr5nVA/:18664:0:99999:7:::
将简书的师傅代码修改为字典破解的版本
import hashlib,mathdef rstr_sha512(text: bytes) -> bytes:sha512 = hashlib.sha512()sha512.update(text)return sha512.digest()def _extend(source: bytes, size_ref: int) -> bytes :extended = b""for i in range(math.floor(size_ref/64)):extended += sourceextended += source[:size_ref % 64]return extendeddef _sha512crypt_intermediate(password: bytes,salt: bytes) -> bytes:#digest_a = rstr_sha512(password + salt)digest_b = rstr_sha512(password + salt + password)digest_b_extended = _extend(digest_b,len(password))intermediate_input = password + salt + digest_b_extendedpasswd_len = len(password)while passwd_len!=0:if passwd_len&1 == 1:intermediate_input += digest_belse:intermediate_input += passwordpasswd_len >>= 1return rstr_sha512(intermediate_input)def _sha512crypt(password :bytes,salt :bytes,rounds :int) -> bytes:digest_a = _sha512crypt_intermediate(password, salt)p = _extend(rstr_sha512(password*len(password)),len(password))s = _extend(rstr_sha512(salt*(16+digest_a[0])),len(salt))digest = digest_afor i in range(rounds):c_input = b""if i&1 :c_input += pelse:c_input += digestif i % 3:c_input += sif i % 7:c_input += pif i & 1:c_input += digestelse:c_input += pdigest = rstr_sha512(c_input)return digestdef sha512crypt(password :bytes,salt :bytes, rounds=5000) -> str:salt = salt[:16] # max 16 bytes for saltinput = _sha512crypt(password, salt, rounds)tab = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"order = [ 42, 21, 0, 1, 43, 22, 23, 2, 44, 45, 24, 3,4, 46, 25, 26, 5, 47, 48, 27, 6, 7, 49, 28,29, 8, 50, 51, 30, 9, 10, 52, 31, 32, 11, 53,54, 33, 12, 13, 55, 34, 35, 14, 56, 57, 36, 15,16, 58, 37, 38, 17, 59, 60, 39, 18, 19, 61, 40,41, 20, 62, 63]output = ""for i in range(0,len(input),3):# special case for the end of the inputif i+1 >= len(order): # i == 63char_1 = input[order[i+0]] & 0b00111111char_2 = (input[order[i+0]] & 0b11000000) >> 6output += tab[char_1] + tab[char_2]else:char_1 = input[order[i+0]] & 0b00111111char_2 = (((input[order[i+0]] & 0b11000000) >> 6) |(input[order[i+1]] & 0b00001111) << 2)char_3 = (((input[order[i+1]] & 0b11110000) >> 4) | (input[order[i+2]] & 0b00000011) << 4)char_4 = (input[order[i+2]] & 0b11111100) >> 2output += tab[char_1] + tab[char_2] + tab[char_3] + tab[char_4]if rounds!=5000:return "$6$rounds={}${}${}".format(rounds,salt.decode("utf-8"),output)else:return "$6${}${}".format(salt.decode("utf-8"),output)def testPass(cryptPass):salt,shadowPass=cryptPass.split('$')[2],cryptPass.split('$')[3]dictFile=open('dictionary.txt','r')for word in dictFile.readlines():word=word.strip()# print(word)tempPassWord=sha512crypt(bytes(word, encoding = "utf8"), bytes(salt, encoding = "utf8"), 5000)# print("temppassword is {}".format(tempPassWord))# print("shadowpassword is {}".format(shadowPass))if cryptPass==tempPassWord:print("[+] Found Password {}".format(word))returnprint("[-] Password Not Found ")returndef main():passFile=open('passwords.txt')for line in passFile.readlines():if ":" in line:user=line.split(':')[0]cryptPass=line.split(':')[1].strip(' ')print("[*] Now cracking Password For :{}".format(user))testPass(cryptPass)if __name__ == "__main__":# 与crypt.crypt("123456","$6$123456") 运算结果一致# print(sha512crypt(b"123",b"DhlRUwqV",5000))main()
运行结果如图:
破解成功,该脚本可用于Linux
弱口令批量爆破
zip口令破解
zip口令破解比较简单,破解的成功与否还是在于密码文件的构造,同时可能会出现在CTF
题目中,阴间题目比如说设置压缩包密码为不可见字符
,需要自己编写脚本来进行破解
另外如果python3
代码完全按照书上这么写会有一个报错
def extractFile(zFile,password):try:# print(password)zFile.extractall(pwd=password)print("[+] Found password {}".format(password))except Exception as e:pass
需要将password
转为二进制传入
zFile.extractall(pwd=password.encode(encoding='utf-8', errors = 'strict'))
完整代码如下
import zipfile
import optparse
from threading import Threaddef extractFile(zFile,password):try:# print(password)zFile.extractall(pwd=password.encode(encoding='utf-8', errors = 'strict'))print("[+] Found password {}".format(password))except Exception as e:passdef main():parser=optparse.OptionParser("参数说明 -f <压缩包文件名> -d <密码txt文件名>")parser.add_option('-f',dest='zname',type='string',help='压缩包文件名')parser.add_option('-d',dest='dname',type='string',help='密码文件名')(options,args)=parser.parse_args()if (options.zname==None) or (options.dname==None):print(parser.usage)exit(0)zname,dname=options.zname,options.dnamezFile=zipfile.ZipFile(zname)passFile=open(dname)for line in passFile.readlines():password=line.strip()t=Thread(target=extractFile,args=(zFile,password))t.start()returnif __name__ == '__main__':main()
创建一个密码为admin
的压缩包 key.zip
使用程序破解之
破解成功
完整代码和字典文件放在github
上了,欢迎师傅们Star:https://github.com/Cl0udG0d/pythonStunt
参考链接
http://www.vuln.cn/8178
https://gv7.me/articles/2017/batch-crack-shadows/
https://blog.csdn.net/deargua/article/details/6666121
https://www.jianshu.com/p/9da78abd6a96
欢迎关注公众号 芸潘
Python绝技第一章 入门 python3实现密码破解相关推荐
- Python绝技 第一章 入门
0X00 前言 此书名为<Python绝技:运用Python成为顶级黑客>. 书中使用的代码为Python 2.6.5版本,与Python3有部分语法不通,会产生报错.由于我使用的是Pyt ...
- 【李刚-21天通关Python】第一章:Python入门与字符串
[李刚-21天通关Python]第一章:Python入门与字符串 第一章:Python入门与字符串 数据类型 字符串 运算符 实操:简易计算器 & 进制转换 章节分篇链接: [李刚-21天通关 ...
- 《HeadFirst Python》第一章学习笔记
对于Python初学者来说,舍得强烈推荐从<HeadFirst Python>开始读起,这本书当真做到了深入浅出,HeadFirst系列,本身亦是品质的保证.这本书舍得已在<Pyth ...
- .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
写在前面 千呼万唤始出来,首先,请允许我长吸一口气!真没想到一份来自28岁老程序员的自白 这篇文章会这么火,更没想到的是张善友队长的公众号居然也转载了这篇文章,这就导致两天的时间就有两百多位读者朋友加 ...
- python 机器学习第一章
机器学习是一门能够发掘数据价值的算法和应用,是计算机科学中最激动人心的一个领域之一. 接下来的时间,开始学习吧! python机器学习第一章 1.机器学习方法分为三类:监督学习,无监督学习,强化学习. ...
- Python Cookbook --第一章:数据结构和算法(1)
问题1:现在有一个包含N个元素的元组或者是序列,怎样将它里面的值解压后同时赋值给N个变量? >>> p = (4,5) >>> x,y = p >>&g ...
- (Raytracing)光线追踪技术 - 第一章 – 入门
(Raytracing)光线追踪技术 - 第一章 – 入门 RAYTRACING TOPICS & TECHNIQUES - PART 1 – INTRODUCTION 原作者:Jacco B ...
- pip环境变量配置 python3.6_零基础学python之爬虫第一节环境配置第一章:Python3+Pip环境配置...
大家好,本节课讲解有关Python环境安装的一个过程,学习Python爬虫的话,第一步就要安装Python的一个环境安装以及配置!那安装的Python是Python3,安装的过程呢还会对一个Pytho ...
- python第一章笔记_head first python(第一章)–学习笔记
head first python(第一章)--学习流程图 1.安装python 这里是用python3的,除了windows之外,linux和macos都自带了,只是版本没有这么新. 举例:cent ...
最新文章
- 别把你的目光停留在周围
- Androidn Notification的使用,解决找不到setLatestEventInfo方法
- 常考数据结构与算法:最长回文子串
- 数值范围_如何理解PLC对数值运算的定义与处理方式?
- Python2寿命只剩一个月啦!还不快赶紧学起Python3酷炫到爆的新特性!
- tomcat启动时出现错误
- cognos report在做同比时遇到的问题解决方法
- pytorch 画loss曲线_Pytorch使用tensorboardX可视化。超详细!!!
- for命令不跳过空白行_Java程序员必备:查看日志常用的linux命令
- if __name__ == __main___一文带你弄懂python中if __name__ == #39;__main__#39;
- web标准三个要素 此标准的好处
- 架构可视化支撑系统演进探索
- linux下查看mysql数据库的字段类型_系统运维|[小白技巧]如何在Linux上检查MySQL数据表的存储引擎类型...
- ASPxGridView1用法-
- 解决:linux系统磁盘空间被占满,但是找不到大文件
- 转:孩子,上学去!乖
- 算法导论学习笔记13_贪心算法
- “梧桐杯”中国移动大数据应用创新大赛 - 智慧金融赛道Baseline
- 分区函数Partition By的用法
- 打开软件提示丢失vcruntime140.dll下载安装详细教程