|
|
@ -0,0 +1,296 @@
|
|
|
|
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
|
|
|
|
import pandas as pd
|
|
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
from passlib.hash import lmhash
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RainbowTable():
|
|
|
|
|
|
|
|
# 初始化方法或构造函数
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, table, chain, pw, collisionchecklist, hashingfunction, rainbow):
|
|
|
|
|
|
|
|
self.table = table
|
|
|
|
|
|
|
|
self.chain = chain
|
|
|
|
|
|
|
|
self.pw = pw
|
|
|
|
|
|
|
|
self.collisionchecklist = collisionchecklist
|
|
|
|
|
|
|
|
self.hashingfunction = hashingfunction
|
|
|
|
|
|
|
|
self.rainbow = rainbow
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def progressbar(self, it, prefix="", size=60, out=sys.stdout): # Python3.6+方法用于显示生成彩虹表的进度条
|
|
|
|
|
|
|
|
count = len(it)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def show(j):
|
|
|
|
|
|
|
|
x = int(size * j / count)
|
|
|
|
|
|
|
|
print(f"{prefix}[{u'█' * x}{('.' * (size - x))}] {j}/{count}", end='\r', file=out, flush=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
show(0)
|
|
|
|
|
|
|
|
for i, item in enumerate(it):
|
|
|
|
|
|
|
|
yield item
|
|
|
|
|
|
|
|
show(i + 1)
|
|
|
|
|
|
|
|
print("\n", flush=True, file=out)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# simple normal binary search二分查找
|
|
|
|
|
|
|
|
def binary_search(self, arr, x):
|
|
|
|
|
|
|
|
low = 0
|
|
|
|
|
|
|
|
high = len(arr) - 1
|
|
|
|
|
|
|
|
mid = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while low <= high:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mid = (high + low) // 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if arr[mid] < x:
|
|
|
|
|
|
|
|
low = mid + 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elif arr[mid] > x:
|
|
|
|
|
|
|
|
high = mid - 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return mid
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# If we reach here, then the element was not present如果到达这里,元素就不存在了
|
|
|
|
|
|
|
|
return 'notfound'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def transversechain(self, reduction, chainhead): # 生成彩虹链
|
|
|
|
|
|
|
|
for i in range(0, self.chain - 1):
|
|
|
|
|
|
|
|
passwords = self.pw[0][reduction]
|
|
|
|
|
|
|
|
# 将它转成字符串并将其用十六进制表示
|
|
|
|
|
|
|
|
passwordhash = self.hashingfunction(str(passwords))
|
|
|
|
|
|
|
|
reduction = int(passwordhash, 16) % len(self.pw)
|
|
|
|
|
|
|
|
self.rainbow.append([chainhead, passwordhash])
|
|
|
|
|
|
|
|
return self.rainbow.sort(key=lambda x: int(x[1], 16))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate(self): # 生成彩虹表
|
|
|
|
|
|
|
|
for i in self.progressbar(range(len(self.pw)), "Computing: ", 70):
|
|
|
|
|
|
|
|
passwords = self.pw[0][i]
|
|
|
|
|
|
|
|
if (self.pw[0][i][-4:] != 'used'):
|
|
|
|
|
|
|
|
self.pw[0][i] = self.pw[0][i] + 'used'
|
|
|
|
|
|
|
|
elif (self.pw[0][i][-4:] == 'used'):
|
|
|
|
|
|
|
|
passwords = self.pw[0][i][:-4]
|
|
|
|
|
|
|
|
passwordhash = self.hashingfunction(passwords)
|
|
|
|
|
|
|
|
reduction = int(passwordhash, 16) % len(self.pw)
|
|
|
|
|
|
|
|
chaintail = self.transversechain(reduction, passwords)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# save tables so we dont have to run the creation everytime保存表,这样我们就不必每次都运行创建
|
|
|
|
|
|
|
|
def saveandsorttables(self): # 保存和排序彩虹表
|
|
|
|
|
|
|
|
# df1 = pd.DataFrame(self.table)
|
|
|
|
|
|
|
|
df2 = pd.DataFrame(self.rainbow)
|
|
|
|
|
|
|
|
np.savetxt(r'Rainbow.txt', df2.values, fmt='%s')
|
|
|
|
|
|
|
|
with open('Passwords.txt', 'w') as sortedbooks:
|
|
|
|
|
|
|
|
for i in range(len(self.pw)):
|
|
|
|
|
|
|
|
sortedbooks.writelines(str(self.pw[0][i]) + '\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# np.savetxt(r'passhash.txt', df1.values, fmt='%s')
|
|
|
|
|
|
|
|
# df1.to_excel("output1.xlsx")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# df2.to_excel("output2.xlsx")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def loopchain(self, i, readpasswordhash, password): # 遍历彩虹表
|
|
|
|
|
|
|
|
for x in range(self.chain):
|
|
|
|
|
|
|
|
passwordhash = self.hashingfunction(str(readpasswordhash.iloc[i][0]))
|
|
|
|
|
|
|
|
reduction = int(passwordhash, 16) % len(self.pw)
|
|
|
|
|
|
|
|
if (self.hashingfunction(self.pw[0][reduction]) == password):
|
|
|
|
|
|
|
|
# print(type(self.hashingfunction(self.pw[0][reduction].encode('utf8')).hexdigest()))
|
|
|
|
|
|
|
|
# print('\n找到了 : : ' + self.pw[0][reduction] + '\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 'found'
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return 'notfound'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def crack(self, hash, readpasswordhash): # 破解hash函数,hash为目标的hash函数,readpasswordhash是从表中找到相关数值
|
|
|
|
|
|
|
|
password = hash
|
|
|
|
|
|
|
|
# 查找彩虹表找到密码
|
|
|
|
|
|
|
|
index = self.binary_search([int(i, 16) for i in readpasswordhash['passwordhash']], int(password, 16))
|
|
|
|
|
|
|
|
if (index != 'notfound'):
|
|
|
|
|
|
|
|
stoploop = self.loopchain(index, readpasswordhash, password)
|
|
|
|
|
|
|
|
# print(readpasswordhash.iloc[0][index])
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
for i in range(len(self.pw)):
|
|
|
|
|
|
|
|
if (i == len(self.pw) - 2):
|
|
|
|
|
|
|
|
print('\n在表中无法找到相应的 password \n\n')
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
elif (self.hashingfunction(str(readpasswordhash.iloc[i][0])) == password):
|
|
|
|
|
|
|
|
print('\n找到了想找到的password : ' + str(readpasswordhash.iloc[i][0]) + '\n')
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
pointer = self.loopchain(i, readpasswordhash, password)
|
|
|
|
|
|
|
|
if (pointer == 'found'):
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
|
|
|
passwordFileArg = ''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def createList(r1, r2):
|
|
|
|
|
|
|
|
# Testing if range r1 and r2测试r1、r2的范围
|
|
|
|
|
|
|
|
if (r1 == r2):
|
|
|
|
|
|
|
|
return r1
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
#建立空列表
|
|
|
|
|
|
|
|
res = []
|
|
|
|
|
|
|
|
#循环将后继程序追加到list,直到到达r2为止。
|
|
|
|
|
|
|
|
while (r1 < r2 + 1):
|
|
|
|
|
|
|
|
res.append(r1)
|
|
|
|
|
|
|
|
r1 += 1
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (len(sys.argv) > 1):
|
|
|
|
|
|
|
|
passwordFileArg = str(sys.argv[1])
|
|
|
|
|
|
|
|
if (passwordFileArg[-4:] != '.txt'):
|
|
|
|
|
|
|
|
passwordFileArg = passwordFileArg + '.txt'
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
if (passwordFileArg[-4:] != '.txt'):
|
|
|
|
|
|
|
|
passwordFileArg = passwordFileArg + '.txt'
|
|
|
|
|
|
|
|
file = Path(str(passwordFileArg))
|
|
|
|
|
|
|
|
if (file.exists()):
|
|
|
|
|
|
|
|
print("\n\n密码可以被找到 !\n\n")
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
passwordFileArg = input("没有找到密码参考文件(ARGUMENT),请输入另一个文件名\n")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
if (len(passwordFileArg) == 0):
|
|
|
|
|
|
|
|
passwordFileArg = input("请输入参考密码文件名\n")
|
|
|
|
|
|
|
|
if (passwordFileArg[-4:] != '.txt'):
|
|
|
|
|
|
|
|
passwordFileArg = passwordFileArg + '.txt'
|
|
|
|
|
|
|
|
file = Path(str(passwordFileArg))
|
|
|
|
|
|
|
|
if (file.exists()):
|
|
|
|
|
|
|
|
print("\n\n已找到密码文件 !\n\n")
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
passwordFileArg = input("没有找到文件,请输入另一个文件名\n")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
if (passwordFileArg[-4:] != '.txt'):
|
|
|
|
|
|
|
|
passwordFileArg = passwordFileArg + '.txt'
|
|
|
|
|
|
|
|
file = Path(str(passwordFileArg))
|
|
|
|
|
|
|
|
if (file.exists()):
|
|
|
|
|
|
|
|
print("\n\n已找到密码文件 !\n\n")
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
passwordFileArg = input("没有找到文件,请输入另一个文件名\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("彩虹表操作流程,请选择操作流程")
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
|
|
"//请注意,相关的文件,如密码文件和生成的彩虹表文件将在同一目录下//")
|
|
|
|
|
|
|
|
print("1 . 生成彩虹表")
|
|
|
|
|
|
|
|
print("2 . 破解哈希函数")
|
|
|
|
|
|
|
|
print("3 . 刷新参考文件(删除参考文件中密码上所有已使用的标记)")
|
|
|
|
|
|
|
|
print("4 . 退出程序")
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
chioce = float(input())
|
|
|
|
|
|
|
|
if chioce < 1 or chioce > 4:
|
|
|
|
|
|
|
|
raise ValueError
|
|
|
|
|
|
|
|
elif (chioce == 1):
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
file = Path(str(passwordFileArg))
|
|
|
|
|
|
|
|
if file.exists():
|
|
|
|
|
|
|
|
df = pd.read_csv(passwordFileArg, header=None)
|
|
|
|
|
|
|
|
df = df.replace(np.nan, 'null', regex=True)
|
|
|
|
|
|
|
|
instance = RainbowTable([], 5, df, createList(0, len(df) - 1), lmhash.hash, [])
|
|
|
|
|
|
|
|
print("Reading")
|
|
|
|
|
|
|
|
print(len(df))
|
|
|
|
|
|
|
|
print("rows of password")
|
|
|
|
|
|
|
|
instance.generate()
|
|
|
|
|
|
|
|
instance.saveandsorttables()
|
|
|
|
|
|
|
|
print('已在当前目录中创建彩虹表Rainbow.txt')
|
|
|
|
|
|
|
|
print("1 . 生成彩虹表")
|
|
|
|
|
|
|
|
print("2 . 破解哈希函数")
|
|
|
|
|
|
|
|
print("3 . 刷新参考文件(删除参考文件中密码上所有已使用的标记)")
|
|
|
|
|
|
|
|
print("4 . 退出程序")
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print("文件名不存在,请输入另一个文件")
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
elif (chioce == 2):
|
|
|
|
|
|
|
|
filename = 'Rainbow.txt'
|
|
|
|
|
|
|
|
if (Path(str(filename)).exists()):
|
|
|
|
|
|
|
|
readpasswordhash = pd.read_csv(filename, sep=' ', names=['password', 'passwordhash'])
|
|
|
|
|
|
|
|
unused = []
|
|
|
|
|
|
|
|
df = pd.read_csv(passwordFileArg, header=None)
|
|
|
|
|
|
|
|
df = df.replace(np.nan, 'null', regex=True)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
hash = input("请输入有效的哈希值进行破解 \n")
|
|
|
|
|
|
|
|
if (len(hash) == 32):
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
|
|
"----------------------------------------------------------------------------------------------------------------------")
|
|
|
|
|
|
|
|
print("不支持彩虹表的重新哈希和追加功能")
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
|
|
"\n请注意以下密码未被散列(错误)或未在参考文件中进行标记 : ")
|
|
|
|
|
|
|
|
df2 = df
|
|
|
|
|
|
|
|
df = [x[:-4] if x[-4:] == 'used' else x for x in df[0]]
|
|
|
|
|
|
|
|
dfreport = [x[:-4] if x[-4:] == 'used' else unused.append(x) for x in df2[0]]
|
|
|
|
|
|
|
|
if (len(unused) != 0 and len(unused) != len(df)):
|
|
|
|
|
|
|
|
for i in range(len(unused)):
|
|
|
|
|
|
|
|
print(unused[i])
|
|
|
|
|
|
|
|
elif (len(unused) == len(df)):
|
|
|
|
|
|
|
|
print("参考文件密码已取消标记。请考虑重新设置密码")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print('参考文件散列中的所有密码都已被标记使用')
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
|
|
"----------------------------------------------------------------------------------------------------------------------")
|
|
|
|
|
|
|
|
instance = RainbowTable([], 5, pd.DataFrame(df), createList(0, len(df) - 1), lmhash.hash,
|
|
|
|
|
|
|
|
[])
|
|
|
|
|
|
|
|
instance.crack(hash, readpasswordhash)
|
|
|
|
|
|
|
|
print("1 . 生成彩虹表")
|
|
|
|
|
|
|
|
print("2 . 破解哈希函数")
|
|
|
|
|
|
|
|
print(
|
|
|
|
|
|
|
|
"3 . 刷新参考文件(删除参考文件中密码上所有已使用的标记)")
|
|
|
|
|
|
|
|
print("4 . 退出程序")
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print("WARNING: 输入的不是32位hash")
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print("***************彩虹表不存在,请生成彩虹表")
|
|
|
|
|
|
|
|
print("1 . 生成彩虹表")
|
|
|
|
|
|
|
|
print("2 . 破解哈希函数")
|
|
|
|
|
|
|
|
print("3 . 刷新参考文件(删除参考文件中密码上所有已使用的标记)")
|
|
|
|
|
|
|
|
print("4 . 退出程序")
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
elif (chioce == 3):
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
|
|
|
if (Path(str(passwordFileArg)).exists()):
|
|
|
|
|
|
|
|
df = pd.read_csv(passwordFileArg, header=None)
|
|
|
|
|
|
|
|
df = df.replace(np.nan, 'null', regex=True)
|
|
|
|
|
|
|
|
df = [str(x[:-4]) if str(x[-4:]) == 'used' else str(x) for x in df[0]]
|
|
|
|
|
|
|
|
df = pd.DataFrame(df)
|
|
|
|
|
|
|
|
instance = RainbowTable([], 5, df, createList(0, len(df) - 1), lmhash.hash, [])
|
|
|
|
|
|
|
|
with open(passwordFileArg, 'w') as sortedbooks:
|
|
|
|
|
|
|
|
for i in instance.progressbar(range(len(df)), "Computing: ", 60):
|
|
|
|
|
|
|
|
sortedbooks.writelines(str(df[0][i]) + '\n')
|
|
|
|
|
|
|
|
print("1 . 生成彩虹表")
|
|
|
|
|
|
|
|
print("2 . 破解哈希函数")
|
|
|
|
|
|
|
|
print("3 . 刷新参考文件(删除参考文件中密码上所有已使用的标记)")
|
|
|
|
|
|
|
|
print("4 . 退出程序")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
print("没有找到密码参考文件")
|
|
|
|
|
|
|
|
passwordFileArg = input("请再次输入密码文件名")
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
|
|
print('Please enter a valid chioce//输入有效选择.')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
|
|
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|