前言
对我而言,武术的非凡之处在于它的简单。简单的方法也是正确的方法,同时武术也没有什么特别之处。越接近武术的真谛,招式表现上浪费越少
简介
python 绝技
第一章是python
入门语法,两个需要编写的程序分别是用字典攻击法破解UNIX口令
,暴力破解ZIP文件
,两者都是使用暴力法直接进行破解,另外第一个程序在当前的网络环境中已经不太适用了,我们将其升级为破解SHA-512 hash
的版本
背景故事
虽然在书中已经有背景故事的翻译了,但是这里我还是采用乌云
之前翻译的版本
C. Stoll的《杜鹃蛋》(1989)堪称新派武侠的开山之作。它第一次把黑客活动与国家安全联系在一起。黑客极具破坏性的黑暗面也浮出海面,并且永远改变了黑客的形象。迄今仍是经久不衰的畅销书。Stoll是劳伦斯伯克利实验室的天文学家和系统管理员。1986年夏,一个区区75美分的帐目错误引起了他的警觉,在追查这次未经授权的入侵过程中,他开始卷入一个错综复杂的电脑间谍案。神秘的入侵者是西德混沌俱乐部的成员。他们潜入美国,窃取敏感的军事和安全情报。出售给克格勃,以换取现金及可卡因。一场网络跨国大搜索开始了,并牵涉出FBI、CIA、克格勃、西德邮电部等。《杜鹃蛋》为后来的黑客作品奠定了一个主题:追捕与反追捕的惊险故事。而且也开始了新模式:一个坚韧和智慧的孤胆英雄,成为国家安全力量的化身,与狡猾的对手展开传奇的较量。
SHA-512 hash 破解
环境 : python3
在破解之前我们先了解一下shadow格式
可以发现shadow中每一行对应这一个用户的用户名和密码等信息,格式为0:1:2:3:4:5:6:7:8
冒号是分割符,分别代表着,每个字段分别代表着:
hash值一览格式如:$id$salt$密文
id代表的是使用不同的加密算法,不同的系统使用的算法也不尽相同。salt是加密的时候需要用到盐。最后就是密文。
数字和所使用的加密算法对应关系:
格式
算法
$1
md5
$2a
blowfish
$2y
blowfish
$5
sha-256
$6
sha-512
注意:如果密码字符串为*
,表示系统用户不能被登入,为!
表示用户名被禁用,如果密码字符串为空,表示没有密码。
这里我们使用python3
中的hashlib
库计算sha-512
这样实现了sha-512
加密,但是,这里的结果并不像是我们Linux
操作系统中的密码,譬如我们上面举例的密码中:
其中就包含了不在十六进制中的字符
事实上以$6
为例并不是单纯的sha512(pass+salt)
或者sha512(salt+passwd)
,而是经历了一系列复杂的运算而获得的。
我们先实现sha-512
的解密
这里的密码文件是我们构造的
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,math
def 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_b = rstr_sha512(password + salt + password)
digest_b_extended = _extend(digest_b,len (password))
intermediate_input = password + salt + digest_b_extended
passwd_len = len (password)
while passwd_len!=0 :
if passwd_len&1 == 1 :
intermediate_input += digest_b
else :
intermediate_input += password
passwd_len >>= 1
return 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_a
for i in range (rounds):
c_input = b""
if i&1 :
c_input += p
else :
c_input += digest
if i % 3 :
c_input += s
if i % 7 :
c_input += p
if i & 1 :
c_input += digest
else :
c_input += p
digest = rstr_sha512(c_input)
return digest
def sha512crypt (password :bytes ,salt :bytes , rounds=5000 ) -> str :
salt = salt[:16 ]
input = _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 ):
if i+1 >= len (order):
char_1 = input [order[i+0 ]] & 0b00111111
char_2 = (input [order[i+0 ]] & 0b11000000 ) >> 6
output += tab[char_1] + tab[char_2]
else :
char_1 = input [order[i+0 ]] & 0b00111111
char_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 ) >> 2
output += 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__" :
print (sha512crypt(b"123456" ,b"123456" ,5000 ))
在ubuntu 16.04
虚拟机里面添加一个账号为test123
,密码为123
的用户
接着查看shadow
文件中其对应的密码
test123:$6$DhlRUwqV$Jln02cwolkp3adJjELMn9q2MxKRalcdzyyJnMg3EayVMgNQ0v9plYEnFns58sBkfUROfhT4Fsdksoxjfr5nVA/:18664:0:99999:7:::
将简书的师傅代码修改为字典破解的版本
import hashlib,math
def 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_b = rstr_sha512(password + salt + password)
digest_b_extended = _extend(digest_b,len (password))
intermediate_input = password + salt + digest_b_extended
passwd_len = len (password)
while passwd_len!=0 :
if passwd_len&1 == 1 :
intermediate_input += digest_b
else :
intermediate_input += password
passwd_len >>= 1
return 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_a
for i in range (rounds):
c_input = b""
if i&1 :
c_input += p
else :
c_input += digest
if i % 3 :
c_input += s
if i % 7 :
c_input += p
if i & 1 :
c_input += digest
else :
c_input += p
digest = rstr_sha512(c_input)
return digest
def sha512crypt (password :bytes ,salt :bytes , rounds=5000 ) -> str :
salt = salt[:16 ]
input = _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 ):
if i+1 >= len (order):
char_1 = input [order[i+0 ]] & 0b00111111
char_2 = (input [order[i+0 ]] & 0b11000000 ) >> 6
output += tab[char_1] + tab[char_2]
else :
char_1 = input [order[i+0 ]] & 0b00111111
char_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 ) >> 2
output += 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()
tempPassWord=sha512crypt(bytes (word, encoding = "utf8" ), bytes (salt, encoding = "utf8" ), 5000 )
if cryptPass==tempPassWord:
print ("[+] Found Password {}" .format (word))
return
print ("[-] Password Not Found " )
return
def 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()
运行结果如图:
破解成功,该脚本可用于Linux
弱口令批量爆破
zip口令破解
zip口令破解比较简单,破解的成功与否还是在于密码文件的构造,同时可能会出现在CTF
题目中,阴间题目比如说设置压缩包密码为不可见字符
,需要自己编写脚本来进行破解
另外如果python3
代码完全按照书上这么写会有一个报错
需要将password
转为二进制传入
完整代码如下
创建一个密码为admin
的压缩包 key.zip
使用程序破解之
破解成功
完整代码和字典文件放在github
上了,欢迎师傅们Star:https://github.com/Cl0udG0d/pythonStunt
参考链接
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2020-02-06 Linux权限管理