-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathBitlocker Key Finder v3.1
152 lines (138 loc) · 7.55 KB
/
Bitlocker Key Finder v3.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#Python3
#Bitlocker_Key_FinderGUI v3
import re
import os
import fnmatch
import shutil
import PySimpleGUI as sg
import subprocess
import string
import ctypes, os
import datetime
pattern = re.compile(r"\d{6}-\d{6}-\d{6}-\d{6}-\d{6}-\d{6}-\d{6}-\d{6}")
Bit_Keys = []
txt_Files = []
now = datetime.datetime.now()
def isAdmin(): #Checks admin status of the program
try:
is_admin = (os.getuid() == 0)
except AttributeError:
is_admin = ctypes.windll.shell32.IsUserAnAdmin() != 0
return is_admin
def walk(): #Walks the directory tree to find txt files
for root, dirs, file in folder:
for filename in file:
if filename.endswith(('.txt', '.TXT', '.bek', '.BEK')): #filters to txt and bek files
txt_Files.append(os.path.join(root, filename)) #creates list of txt and bek files
def name_search(): #Finds txt and bek files and adds them to the bit_keys list
for ele in txt_Files:
if fnmatch.fnmatch(ele, "*BitLocker Recovery Key*"):
print(ele + '\n')
Bit_Keys.append(ele)
if fnmatch.fnmatch(ele, "*.BEK"):
print(ele + '\n')
Bit_Keys.append(ele)
def string_search(): #Regex for key values
for ele in txt_Files:
try:
too_big = os.path.getsize(ele)
if too_big >= 1048576: #Check file size is less than 10mb
pass
else:
with open(ele, 'r', encoding="utf-16-le") as text: #this encoding is the default used by Microsoft in creating the txt files
text = text.read()
k = re.findall(pattern, text)
for key in k:
Bit_Keys.append(ele)
print(ele + " - " + key + '\n')
except UnicodeDecodeError:
pass
except PermissionError:
pass
def copy_key_files(): #COPIES THE KEYS FROM BIT_KEYS LIST TO USER SELECTED DIRECTORY
destination = values['OUTPUT']
print("*** COPYING KEY RELATED FILES... ***")
copy_list = []
for i in Bit_Keys:
if i not in copy_list:
copy_list.append(i)
try:
for key_File in copy_list:
shutil.copy(key_File, destination)
except Exception:
print(key_File +' - Error Copying- check for user access to file or name collision in destination')
pass
print("\n*** FILES COPIED TO DESTINATION DIRECTORY. ***\n")
def get_active_keys(): #Searches for key values for mounted volumes
print("\n*** TRIAGING KEYS ON CURRENT SYSTEM ***\n")
if isAdmin(): #checks admin status before proceeding
print("\nRunning as Admin...")
Drive_letters = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)] #Produces list of volumes on target system
comp_name = os.environ['COMPUTERNAME'] #gets target computer name for report title
comp_name = comp_name.strip('\\')
key_report = os.path.join(values['OUTPUT'], comp_name + '-BitlockerReport.txt')
with open(key_report, 'w') as report:
report.write("Bitlocker Key Finder v3.0 \n") #writing the header for the report 1) Version 2) Date 3)User of System
report.write(now)
report.write("\nUser Account Used: ")
report.write(os.getlogin())
report.write("\n\n")
for drive in Drive_letters:
try:
mng_bde = subprocess.check_output(["manage-bde", "-protectors", drive, "-get"]) #runs the manage-bde query for each drive letter in drive letter list
mng_bde = (mng_bde.splitlines(True))
print(drive, " - Key protectors found!\n")
for drive_state in mng_bde:
drive_state = drive_state.decode("utf-8")
print(drive_state)
report.write(drive_state) #writes query output to file
print('\n')
except:
subprocess.CalledProcessError
print(drive, ' - No key protectors found. Not Bitlocked. ')
else:
print("Not running as Admin! Restart as Admin to continue.")
working_Dir = os.getcwd() #Used for default output folder
sg.theme('LightGrey2')
layout = [ [sg.Text('Bitlocker Key Finder', size=(18, 1), font=('Impact', 25, 'bold italic'))],
[sg.Text('')],
[sg.Text('Find Saved Bitlocker .TXT and .BEK Files', font=('Arial', 12,'bold'))],
[sg.Text('Select Volume or Directory to Search:'),sg.Input(key='SOURCE',), sg.FolderBrowse(key='SOURCE')],
[sg.Checkbox('File Name Search', key="FILENAME"), sg.Checkbox('String Pattern Search', key="REG")],
#[sg.Text('_'*82)],
[sg.Checkbox('Copy responsive files to Output Directory', enable_events=True ,key="COPYSWITCH")],
[sg.Text('')],
[sg.Text('Recover Keys from Current Machine', font=('Arial', 12,'bold'))],
[sg.Checkbox('Save keys for mounted volumes to Output Directory - MUST BE RUN AS ADMIN', key="MGBDE")],
[sg.Text('')],
[sg.Text(" Output Directory: ", font=('Arial', 11, 'bold')), sg.Input(key='OUTPUT', default_text=working_Dir, disabled=False), sg.FolderBrowse(key='OUTPUT1', enable_events=True, disabled=False)],
# [sg.Output(size=(85,10),)],
[sg.Text('')],
[sg.Button('Find Keys', key='Ok'), sg.Text(' '*125), sg.Button('?', key='HELP')]]
# Create the Window
window = sg.Window('North Loop Consulting', layout, no_titlebar=False, alpha_channel=1, grab_anywhere=False)
# Event Loop to process "events" and get the "values" of the inputs
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit': # if user closes window or clicks cancel
break
if event == 'HELP':
sg.Popup("FOR BEST RESULTS RUN AS ADMIN \n\nThis tool seeks to find Bitlocker Recovery Keys with a focus for on-scene triage. On opening the tool you will see both an interface window to input selections and a console window which will display search results. Closing one window will close the other. \n\nThe tool uses three methods to recover keys: \n\nThe first method searches for file names consistent with Recovery Key files including .TXT and .BEK file extensions. This method returns the file's path. \n\nThe second method performs pattern searches for key values in text files encoded in UTF 16 LE. This method returns the file's path and the string hit.\n\nIf you are running both methods, expect duplicate file hits. \n\nFiles meeting your search criteria can be saved to an output folder of your choice.\n\nThe third method makes use of the manage-bde interface to collect keys for mounted volumes on an active system and save those keys to a text file. \n\nNo warranty or guarantee is offered with this tool. Use at your own risk. \n\nCopyright 2021 North Loop Consulting\n")
window.refresh()
elif event == 'Ok':
folder = os.walk(values["SOURCE"])
print("*** SEARCHING FOR KEY FILES... ***")
walk()
if values["FILENAME"] == True:
print("Searching for file names in " + values['SOURCE'])
name_search()
if values["REG"] == True:
print("Conducting string search in " + values['SOURCE'])
string_search()
if values['COPYSWITCH'] == True:
copy_key_files()
if values['MGBDE'] == True:
get_active_keys()
print("\n****** COMPLETE ******")
window.refresh()
window.close()