11import itertools
2+ import re
23import string
4+ import sqlite3
35from pathlib import Path
4- from os .path import join
56
67from scripts .artifact_report import ArtifactHtmlReport
7- from scripts .ilapfuncs import logfunc , tsv , timeline , is_platform_windows , media_to_html , open_sqlite_db_readonly
8+ from scripts .ilapfuncs import logfunc , tsv , media_to_html , open_sqlite_db_readonly
89
910
10- '''def extract_PIN_from_db(file_found):
11- try:
12- connection = open_sqlite_db_readonly(file_found)
13-
14- set_pointer = connection.cursor()
15- set_pointer.execute("SELECT passwd_temp FROM albumstemp")
11+ def sanitize_output_filename (filename , default_name = 'recovered_file.bin' ):
12+ raw_name = str (filename or '' )
13+ normalized = raw_name .replace ('\\ ' , '/' )
14+ safe_name = Path (normalized ).name
15+ safe_name = re .sub (r'[\x00-\x1f<>:"/\\|?*]+' , '_' , safe_name )
16+ safe_name = safe_name .strip ().strip ('.' )
17+ if not safe_name :
18+ return default_name
19+ return safe_name
1620
17- encrypted_password = set_pointer.fetchone()[0]
1821
19- return encrypted_password, file_found
20- except:
21- return None'''
22+ def build_safe_output_path (report_folder , original_filename ):
23+ report_root = Path (report_folder ).resolve ()
24+ sanitized_name = sanitize_output_filename (original_filename )
25+ output_path = (report_root / sanitized_name ).resolve ()
26+ try :
27+ output_path .relative_to (report_root )
28+ except ValueError :
29+ output_path = report_root / sanitize_output_filename (None )
30+
31+ if output_path .exists ():
32+ stem = output_path .stem
33+ suffix = output_path .suffix
34+ index = 1
35+ while True :
36+ candidate = report_root / f'{ stem } _{ index } { suffix } '
37+ if not candidate .exists ():
38+ output_path = candidate
39+ break
40+ index += 1
41+ return output_path
2242
2343
2444def extract_data_from_db (file_found ):
@@ -63,7 +83,7 @@ def extract_data_from_db(file_found):
6383 dict_of_dicts [encrypted_filename ] = new_dict
6484
6585 return dict_of_dicts , list_of_enc_pins , file_found
66- except :
86+ except ( sqlite3 . Error , OSError , ValueError , TypeError , AttributeError , IndexError , KeyError ) :
6787 return None
6888
6989
@@ -95,8 +115,7 @@ def brute_force_pin(encoded_PIN):
95115 if decoded_test_value_string == encoded_PIN :
96116 #logfunc(f'Decrypted PIN is: {pin}')
97117 return pin
98- else :
99- pin_len += 1
118+ pin_len += 1
100119
101120 if decoded_PIN is None :
102121 print ('Sorry. No PIN found.' )
@@ -120,30 +139,6 @@ def raw_pin_to_XOR_key(pin):
120139
121140 return hex_XOR_key
122141
123-
124- '''def read_file_info(file_found):
125- file_match_dict = {}
126- print(f'readfileinfo: {file_found}')
127- connection = open_sqlite_db_readonly(file_found)
128-
129- set_pointer = connection.cursor()
130- set_pointer.execute("SELECT file_name_from, file_path_new FROM hideimagevideo")
131-
132- required_column = set_pointer.fetchall()
133-
134- if len(required_column) < 1:
135- logfunc('No encrypted media present')
136- return
137- else:
138- for filename in required_column:
139- decrypted_filename = filename[0]
140- encrypted_filename = filename[1].split('/')[-1]
141-
142- file_match_dict[decrypted_filename] = encrypted_filename
143-
144- return file_match_dict'''
145-
146-
147142def file_decryption (files_found , dict_of_file_info , dict_of_pin_dicts , report_folder ):
148143 data_list = []
149144 logfunc ('Encrypted files found! File Decryption in progress...' )
@@ -187,12 +182,13 @@ def file_decryption(files_found, dict_of_file_info, dict_of_pin_dicts, report_fo
187182 byte = file_to_decrypt .read (1 )
188183
189184 xord_bytes_decrypted = bytes (xor_list )
190- with open (join (report_folder , decrypted_file_name ), 'wb' ) as decryptedFile :
185+ decrypted_output_path = build_safe_output_path (report_folder , decrypted_file_name )
186+ with open (decrypted_output_path , 'wb' ) as decryptedFile :
191187 decryptedFile .write (xord_bytes_decrypted )
192188 decryptedFile .close ()
193189
194190 tolink = []
195- pathdec = join ( report_folder , decrypted_file_name )
191+ pathdec = str ( decrypted_output_path )
196192 tolink .append (pathdec )
197193 thumb = media_to_html (pathdec , tolink , report_folder )
198194
@@ -213,24 +209,28 @@ def file_decryption(files_found, dict_of_file_info, dict_of_pin_dicts, report_fo
213209 html_no_escape = ['Media' ])
214210 report .end_artifact_report ()
215211
216- tsvname = f 'NQVault'
212+ tsvname = 'NQVault'
217213 tsv (report_folder , data_headers , data_list , tsvname )
218214
219215
220216# MAIN #
221217def get_NQVault (files_found , report_folder , seeker , wrap_text ):
218+ _ = seeker , wrap_text
222219 data_list = []
223220 list_of_enc_pins = []
224221 dict_of_file_info = {}
225222 dict_of_pin_dicts = {}
226- sucess = 0
223+ file_found_pin = ''
224+ success = 0
227225 # Get the "encrypted" PIN from DB
228226 for file_found in files_found :
229227 if file_found .endswith ('322w465ay423xy11' ):
230228 # multiple password hashes may be present, so these are stored as a list
231- dict_of_file_info , list_of_enc_pins , file_found_pin = extract_data_from_db (file_found )
232- sucess = 1
233- if sucess == 0 :
229+ extraction_result = extract_data_from_db (file_found )
230+ if extraction_result :
231+ dict_of_file_info , list_of_enc_pins , file_found_pin = extraction_result
232+ success = 1
233+ if success == 0 :
234234 logfunc ('No Database DB Found or no hashed PIN present.' )
235235 return
236236
@@ -256,7 +256,8 @@ def get_NQVault(files_found, report_folder, seeker, wrap_text):
256256 report .add_script ()
257257 data_headers = ('Encrypted PIN' , 'Decrypted PIN' )
258258
259- report .write_artifact_data_table (data_headers , data_list , file_found_pin , html_no_escape = ['Media' ])
259+ report_source = file_found_pin if file_found_pin else 'NQ Vault Source DB'
260+ report .write_artifact_data_table (data_headers , data_list , report_source , html_no_escape = ['Media' ])
260261 report .end_artifact_report ()
261262
262263 # Media decryption funct
0 commit comments