diff --git a/test_data/apm.dmg b/test_data/apm.dmg new file mode 100644 index 00000000..a5c13cb7 Binary files /dev/null and b/test_data/apm.dmg differ diff --git a/tests/analyzer/analyzer.py b/tests/analyzer/analyzer.py index c5ee66cb..980cfcaa 100644 --- a/tests/analyzer/analyzer.py +++ b/tests/analyzer/analyzer.py @@ -318,9 +318,9 @@ def testGetStorageMediaImageTypeIndicatorsBodyFile(self): path_spec) self.assertEqual(type_indicators, expected_type_indicators) - def testGetVolumeSystemTypeIndicatorsTSK(self): - """Tests the GetVolumeSystemTypeIndicators function on partitions.""" - test_file = self._GetTestFilePath(['mbr.raw']) + def testGetVolumeSystemTypeIndicatorsAPM(self): + """Tests the GetVolumeSystemTypeIndicators function on APM partitions.""" + test_file = self._GetTestFilePath(['apm.dmg']) self._SkipIfPathNotExists(test_file) path_spec = os_path_spec.OSPathSpec(location=test_file) @@ -329,18 +329,6 @@ def testGetVolumeSystemTypeIndicatorsTSK(self): type_indicators = analyzer.Analyzer.GetVolumeSystemTypeIndicators(path_spec) self.assertEqual(type_indicators, expected_type_indicators) - def testGetVolumeSystemTypeIndicatorsVSS(self): - """Tests the GetVolumeSystemTypeIndicators function on a VSS volume.""" - test_file = self._GetTestFilePath(['vss.raw']) - self._SkipIfPathNotExists(test_file) - - path_spec = os_path_spec.OSPathSpec(location=test_file) - path_spec = raw_path_spec.RawPathSpec(parent=path_spec) - - expected_type_indicators = [definitions.TYPE_INDICATOR_VSHADOW] - type_indicators = analyzer.Analyzer.GetVolumeSystemTypeIndicators(path_spec) - self.assertEqual(type_indicators, expected_type_indicators) - def testGetVolumeSystemTypeIndicatorsBDE(self): """Tests the GetVolumeSystemTypeIndicators function on a BDE ToGo drive.""" test_file = self._GetTestFilePath(['bdetogo.raw']) @@ -399,6 +387,29 @@ def testGetVolumeSystemTypeIndicatorsLVM(self): type_indicators = analyzer.Analyzer.GetVolumeSystemTypeIndicators(path_spec) self.assertEqual(type_indicators, expected_type_indicators) + def testGetVolumeSystemTypeIndicatorsMBR(self): + """Tests the GetVolumeSystemTypeIndicators function on MBR partitions.""" + test_file = self._GetTestFilePath(['mbr.raw']) + self._SkipIfPathNotExists(test_file) + + path_spec = os_path_spec.OSPathSpec(location=test_file) + + expected_type_indicators = [definitions.TYPE_INDICATOR_TSK_PARTITION] + type_indicators = analyzer.Analyzer.GetVolumeSystemTypeIndicators(path_spec) + self.assertEqual(type_indicators, expected_type_indicators) + + def testGetVolumeSystemTypeIndicatorsVSS(self): + """Tests the GetVolumeSystemTypeIndicators function on a VSS volume.""" + test_file = self._GetTestFilePath(['vss.raw']) + self._SkipIfPathNotExists(test_file) + + path_spec = os_path_spec.OSPathSpec(location=test_file) + path_spec = raw_path_spec.RawPathSpec(parent=path_spec) + + expected_type_indicators = [definitions.TYPE_INDICATOR_VSHADOW] + type_indicators = analyzer.Analyzer.GetVolumeSystemTypeIndicators(path_spec) + self.assertEqual(type_indicators, expected_type_indicators) + if __name__ == '__main__': unittest.main() diff --git a/tests/helpers/source_scanner.py b/tests/helpers/source_scanner.py index cc2bf75b..171a1b55 100644 --- a/tests/helpers/source_scanner.py +++ b/tests/helpers/source_scanner.py @@ -347,6 +347,30 @@ def testScanOnAPFS(self): self.assertIsNotNone(scan_node) self.assertEqual(scan_node.type_indicator, definitions.TYPE_INDICATOR_APFS) + def testScanOnAPM(self): + """Test the Scan function on APM.""" + test_path = self._GetTestFilePath(['apm.dmg']) + self._SkipIfPathNotExists(test_path) + + scan_context = source_scanner.SourceScannerContext() + scan_context.OpenSourcePath(test_path) + + self._source_scanner.Scan(scan_context) + self.assertEqual( + scan_context.source_type, definitions.SOURCE_TYPE_STORAGE_MEDIA_IMAGE) + + scan_node = self._GetTestScanNode(scan_context) + self.assertIsNotNone(scan_node) + self.assertEqual( + scan_node.type_indicator, definitions.TYPE_INDICATOR_TSK_PARTITION) + + self.assertEqual(len(scan_node.sub_nodes), 5) + + scan_node = scan_node.sub_nodes[3].GetSubNodeByLocation('/') + self.assertIsNotNone(scan_node) + self.assertEqual( + scan_node.type_indicator, definitions.PREFERRED_HFS_BACK_END) + def testScanOnEncryptedAPFS(self): """Test the Scan function on an encrypted APFS image.""" resolver.Resolver.key_chain.Empty() @@ -439,8 +463,8 @@ def testScanOnLVM(self): self.assertEqual( scan_node.type_indicator, definitions.PREFERRED_EXT_BACK_END) - def testScanOnMBRPartitionedImage(self): - """Test the Scan function on a MBR partitioned image.""" + def testScanOnMBR(self): + """Test the Scan function on MBR.""" test_path = self._GetTestFilePath(['mbr.raw']) self._SkipIfPathNotExists(test_path) diff --git a/tests/helpers/volume_scanner.py b/tests/helpers/volume_scanner.py index ed320da1..c4113fdd 100644 --- a/tests/helpers/volume_scanner.py +++ b/tests/helpers/volume_scanner.py @@ -192,8 +192,8 @@ def testGetPartitionIdentifiersOnAPFS(self): self.assertEqual(len(identifiers), 1) self.assertEqual(identifiers, ['p1']) - def testGetPartitionIdentifiersOnPartitionedImage(self): - """Tests the _GetPartitionIdentifiers function on partitions.""" + def testGetPartitionIdentifiersOnMBR(self): + """Tests the _GetPartitionIdentifiers function on MBR.""" test_path = self._GetTestFilePath(['mbr.raw']) self._SkipIfPathNotExists(test_path) @@ -321,8 +321,8 @@ def testGetVolumeSnapshotIdentifiers(self): self.assertEqual(len(identifiers), 2) self.assertEqual(identifiers, ['vss1', 'vss2']) - def testNormalizedVolumeIdentifiersPartitionedImage(self): - """Tests the _NormalizedVolumeIdentifiers function on partitions.""" + def testNormalizedVolumeIdentifiersMBR(self): + """Tests the _NormalizedVolumeIdentifiers function on MBR.""" test_path = self._GetTestFilePath(['mbr.raw']) self._SkipIfPathNotExists(test_path) @@ -799,8 +799,8 @@ def testScanVolumeSystemRootOnAPFS(self): scan_context, apfs_container_scan_node.sub_nodes[0], test_options, base_path_specs) - def testScanVolumeSystemRootOnPartitionedImage(self): - """Tests the _ScanVolumeSystemRoot function on partitions.""" + def testScanVolumeSystemRootOnMBR(self): + """Tests the _ScanVolumeSystemRoot function on MBR.""" test_path = self._GetTestFilePath(['mbr.raw']) self._SkipIfPathNotExists(test_path) @@ -872,8 +872,8 @@ def testGetBasePathSpecsOnRAW(self): with self.assertRaises(errors.ScannerError): test_scanner.GetBasePathSpecs('/bogus') - def testGetBasePathSpecsOnPartitionedImage(self): - """Tests the GetBasePathSpecs function on partitions.""" + def testGetBasePathSpecsOnMBR(self): + """Tests the GetBasePathSpecs function on MBR.""" test_path = self._GetTestFilePath(['mbr.raw']) self._SkipIfPathNotExists(test_path) diff --git a/tests/vfs/tsk_partition_file_entry.py b/tests/vfs/tsk_partition_file_entry.py index 623964b9..95066d6d 100644 --- a/tests/vfs/tsk_partition_file_entry.py +++ b/tests/vfs/tsk_partition_file_entry.py @@ -54,8 +54,205 @@ def testEntriesGenerator(self): self.assertEqual(len(entries), 8) -class TSKPartitionFileEntryTest(shared_test_lib.BaseTestCase): - """TSK partition file entry tests.""" +class TSKPartitionFileEntryTestAPM(shared_test_lib.BaseTestCase): + """TSK partition file entry tests on APM.""" + + def setUp(self): + """Sets up the needed objects used throughout the test.""" + self._resolver_context = context.Context() + test_path = self._GetTestFilePath(['apm.dmg']) + self._SkipIfPathNotExists(test_path) + + self._os_path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_OS, location=test_path) + self._tsk_partition_path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, location='/', + parent=self._os_path_spec) + + self._file_system = tsk_partition_file_system.TSKPartitionFileSystem( + self._resolver_context, self._tsk_partition_path_spec) + self._file_system.Open() + + def tearDown(self): + """Cleans up the needed objects used throughout the test.""" + self._resolver_context.Empty() + + # mmls test_data/apm.dmg + # MAC Partition Map + # Offset Sector: 0 + # Units are in 512-byte sectors + # + # Slot Start End Length Description + # 000: ------- 0000000000 0000000000 0000000001 Unallocated + # 001: 000 0000000001 0000000063 0000000063 Apple_partition_map + # 002: Meta 0000000001 0000000003 0000000003 Table + # 003: 001 0000000064 0000008175 0000008112 Apple_HFS + # 004: 002 0000008176 0000008191 0000000016 Apple_Free + + def testIntialize(self): + """Test the __init__ function.""" + file_entry = tsk_partition_file_entry.TSKPartitionFileEntry( + self._resolver_context, self._file_system, + self._tsk_partition_path_spec, is_virtual=True) + + self.assertIsNotNone(file_entry) + + # TODO: add tests for _GetDirectory + # TODO: add tests for _GetSubFileEntries + + def testName(self): + """Test the name property.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=3, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + + self.assertIsNotNone(file_entry) + self.assertEqual(file_entry.name, 'p1') + + def testSize(self): + """Test the size property.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=3, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + + self.assertIsNotNone(file_entry) + self.assertEqual(file_entry.size, 8112 * 512) + + def testGetParentFileEntry(self): + """Tests the GetParentFileEntry function.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=0, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + + self.assertIsNotNone(file_entry) + parent_file_entry = file_entry.GetParentFileEntry() + self.assertIsNone(parent_file_entry) + + def testGetStat(self): + """Tests the GetStat function.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=0, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + stat_object = file_entry.GetStat() + + self.assertIsNotNone(stat_object) + self.assertEqual(stat_object.type, stat_object.TYPE_FILE) + self.assertEqual(stat_object.size, 512) + + # TODO: add tests for GetTSKVsPart + + def testIsFunctions(self): + """Test the Is? functions.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=0, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + self.assertFalse(file_entry.IsRoot()) + self.assertFalse(file_entry.IsVirtual()) + self.assertFalse(file_entry.IsAllocated()) + + self.assertFalse(file_entry.IsDevice()) + self.assertFalse(file_entry.IsDirectory()) + self.assertTrue(file_entry.IsFile()) + self.assertFalse(file_entry.IsLink()) + self.assertFalse(file_entry.IsPipe()) + self.assertFalse(file_entry.IsSocket()) + + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, location='/', + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + self.assertTrue(file_entry.IsRoot()) + self.assertTrue(file_entry.IsVirtual()) + self.assertTrue(file_entry.IsAllocated()) + + self.assertFalse(file_entry.IsDevice()) + self.assertTrue(file_entry.IsDirectory()) + self.assertFalse(file_entry.IsFile()) + self.assertFalse(file_entry.IsLink()) + self.assertFalse(file_entry.IsPipe()) + self.assertFalse(file_entry.IsSocket()) + + def testSubFileEntries(self): + """Test the sub file entries iteration functionality.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, location='/', + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + self.assertEqual(file_entry.number_of_sub_file_entries, 5) + + expected_sub_file_entry_names = ['', '', '', '', 'p1'] + + sub_file_entry_names = [] + for sub_file_entry in file_entry.sub_file_entries: + sub_file_entry_names.append(sub_file_entry.name) + + self.assertEqual( + len(sub_file_entry_names), len(expected_sub_file_entry_names)) + self.assertEqual( + sorted(sub_file_entry_names), sorted(expected_sub_file_entry_names)) + + def testDataStreams(self): + """Test the data streams functionality.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=0, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + self.assertEqual(file_entry.number_of_data_streams, 1) + + data_stream_names = [] + for data_stream in file_entry.data_streams: + data_stream_names.append(data_stream.name) + + self.assertEqual(data_stream_names, ['']) + + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, location='/', + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + self.assertEqual(file_entry.number_of_data_streams, 0) + + data_stream_names = [] + for data_stream in file_entry.data_streams: + data_stream_names.append(data_stream.name) + + self.assertEqual(data_stream_names, []) + + def testGetDataStream(self): + """Tests the GetDataStream function.""" + path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, part_index=0, + parent=self._os_path_spec) + file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) + self.assertIsNotNone(file_entry) + + data_stream_name = '' + data_stream = file_entry.GetDataStream(data_stream_name) + self.assertIsNotNone(data_stream) + self.assertEqual(data_stream.name, data_stream_name) + + data_stream = file_entry.GetDataStream('bogus') + self.assertIsNone(data_stream) + + +class TSKPartitionFileEntryTestMBR(shared_test_lib.BaseTestCase): + """TSK partition file entry tests on MBR.""" def setUp(self): """Sets up the needed objects used throughout the test.""" @@ -121,7 +318,7 @@ def testSize(self): file_entry = self._file_system.GetFileEntryByPathSpec(path_spec) self.assertIsNotNone(file_entry) - self.assertEqual(file_entry.size, 66048) + self.assertEqual(file_entry.size, 129 * 512) def testGetParentFileEntry(self): """Tests the GetParentFileEntry function.""" diff --git a/tests/volume/tsk_volume_system.py b/tests/volume/tsk_volume_system.py index f8e4a6a7..00c652d2 100644 --- a/tests/volume/tsk_volume_system.py +++ b/tests/volume/tsk_volume_system.py @@ -11,8 +11,137 @@ from tests import test_lib as shared_test_lib -class TSKVolumeSystemTest(shared_test_lib.BaseTestCase): - """Tests the SleuthKit (TSK) volume system.""" +class TSKVolumeSystemTestAPM(shared_test_lib.BaseTestCase): + """Tests the SleuthKit (TSK) volume system on APM.""" + + def setUp(self): + """Sets up the needed objects used throughout the test.""" + test_path = self._GetTestFilePath(['apm.dmg']) + self._SkipIfPathNotExists(test_path) + + test_os_path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_OS, location=test_path) + self._tsk_path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, location='/', + parent=test_os_path_spec) + + # mmls test_data/apm.dmg + # MAC Partition Map + # Offset Sector: 0 + # Units are in 512-byte sectors + # + # Slot Start End Length Description + # 000: ------- 0000000000 0000000000 0000000001 Unallocated + # 001: 000 0000000001 0000000063 0000000063 Apple_partition_map + # 002: Meta 0000000001 0000000003 0000000003 Table + # 003: 001 0000000064 0000008175 0000008112 Apple_HFS + # 004: 002 0000008176 0000008191 0000000016 Apple_Free + + def testIterateVolumes(self): + """Test the iterate volumes functionality.""" + volume_system = tsk_volume_system.TSKVolumeSystem() + volume_system.Open(self._tsk_path_spec) + + self.assertEqual(volume_system.bytes_per_sector, 512) + + self.assertEqual(volume_system.number_of_sections, 5) + self.assertEqual(volume_system.number_of_volumes, 1) + + self.assertEqual(volume_system.volume_identifiers, ['p1']) + + volume = volume_system.GetVolumeByIndex(0) + self.assertIsNotNone(volume) + + self.assertEqual(volume.number_of_extents, 1) + self.assertEqual(volume.number_of_attributes, 2) + self.assertEqual(volume.identifier, 'p1') + + volume_attribute = volume.GetAttribute('address') + self.assertIsNotNone(volume_attribute) + self.assertEqual(volume_attribute.value, 3) + + volume_attribute = volume.GetAttribute('description') + self.assertIsNotNone(volume_attribute) + self.assertEqual(volume_attribute.value, 'Apple_HFS') + + volume_extent = volume.extents[0] + self.assertIsNotNone(volume_extent) + self.assertEqual(volume_extent.offset, 64 * 512) + self.assertEqual(volume_extent.size, 8112 * 512) + self.assertEqual(volume_extent.extent_type, volume_extent.EXTENT_TYPE_DATA) + + volume = volume_system.GetVolumeByIndex(9) + self.assertIsNone(volume) + + +class TSKVolumeSystemTestGPT(shared_test_lib.BaseTestCase): + """Tests the SleuthKit (TSK) volume system on GPT.""" + + def setUp(self): + """Sets up the needed objects used throughout the test.""" + test_path = self._GetTestFilePath(['gpt.raw']) + self._SkipIfPathNotExists(test_path) + + test_os_path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_OS, location=test_path) + self._tsk_path_spec = path_spec_factory.Factory.NewPathSpec( + definitions.TYPE_INDICATOR_TSK_PARTITION, location='/', + parent=test_os_path_spec) + + # mmls test_data/gpt.raw + # GUID Partition Table (EFI) + # Offset Sector: 0 + # Units are in 512-byte sectors + # + # Slot Start End Length Description + # 000: Meta 0000000000 0000000000 0000000001 Safety Table + # 001: ------- 0000000000 0000002047 0000002048 Unallocated + # 002: Meta 0000000001 0000000001 0000000001 GPT Header + # 003: Meta 0000000002 0000000033 0000000032 Partition Table + # 004: 000 0000002048 0000002175 0000000128 Linux filesystem + # 005: ------- 0000002176 0000004095 0000001920 Unallocated + # 006: 001 0000004096 0000004223 0000000128 Linux filesystem + # 007: ------- 0000004224 0000008191 0000003968 Unallocated + + def testIterateVolumes(self): + """Test the iterate volumes functionality.""" + volume_system = tsk_volume_system.TSKVolumeSystem() + volume_system.Open(self._tsk_path_spec) + + self.assertEqual(volume_system.bytes_per_sector, 512) + + self.assertEqual(volume_system.number_of_sections, 8) + self.assertEqual(volume_system.number_of_volumes, 2) + + self.assertEqual(volume_system.volume_identifiers, ['p1', 'p2']) + + volume = volume_system.GetVolumeByIndex(1) + self.assertIsNotNone(volume) + + self.assertEqual(volume.number_of_extents, 1) + self.assertEqual(volume.number_of_attributes, 2) + self.assertEqual(volume.identifier, 'p2') + + volume_attribute = volume.GetAttribute('address') + self.assertIsNotNone(volume_attribute) + self.assertEqual(volume_attribute.value, 6) + + volume_attribute = volume.GetAttribute('description') + self.assertIsNotNone(volume_attribute) + self.assertEqual(volume_attribute.value, 'Linux filesystem') + + volume_extent = volume.extents[0] + self.assertIsNotNone(volume_extent) + self.assertEqual(volume_extent.offset, 4096 * 512) + self.assertEqual(volume_extent.size, 128 * 512) + self.assertEqual(volume_extent.extent_type, volume_extent.EXTENT_TYPE_DATA) + + volume = volume_system.GetVolumeByIndex(9) + self.assertIsNone(volume) + + +class TSKVolumeSystemTestMBR(shared_test_lib.BaseTestCase): + """Tests the SleuthKit (TSK) volume system on MBR.""" def setUp(self): """Sets up the needed objects used throughout the test.""" @@ -73,7 +202,7 @@ def testIterateVolumes(self): self.assertEqual(volume_extent.size, 129 * 512) self.assertEqual(volume_extent.extent_type, volume_extent.EXTENT_TYPE_DATA) - volume = volume_system.GetVolumeByIndex(7) + volume = volume_system.GetVolumeByIndex(9) self.assertIsNone(volume) diff --git a/utils/generate_test_data_macos.sh b/utils/generate_test_data_macos.sh index 9b7c11f2..660c2d65 100755 --- a/utils/generate_test_data_macos.sh +++ b/utils/generate_test_data_macos.sh @@ -47,6 +47,7 @@ This is a text file. We should be able to parse it. EOT + # On older versions of Mac OS use `xattr -s' instead. xattr -w myxattr "My extended attribute" ${MOUNT_POINT}/a_directory/a_file cat >${MOUNT_POINT}/passwords.txt <