From dfbed78a74006d659d4f131cf354a7d2bed60a8d Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Thu, 2 Jun 2022 17:09:26 +1000 Subject: [PATCH 01/20] Improve resource id parsing, trim whitespace and trailing '/' from ARNs. --- src/main/java/com/evimetry/aff4/Containers.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/evimetry/aff4/Containers.java b/src/main/java/com/evimetry/aff4/Containers.java index 959d6ff..7920dc1 100644 --- a/src/main/java/com/evimetry/aff4/Containers.java +++ b/src/main/java/com/evimetry/aff4/Containers.java @@ -89,7 +89,7 @@ private static IAFF4Container openContainer(File file) throws IOException { } String resourceID = getResourceID(file); - if (resourceID == null || resourceID.trim().isEmpty()) { + if (resourceID == null || resourceID.isEmpty()) { throw new IOException("File does not appear to be an AFF4 File."); } try { @@ -151,6 +151,14 @@ public static String getResourceID(File file) { logger.error(e.getMessage(), e); } + if (resourceID != null) { + resourceID = resourceID.trim(); + + if (resourceID.endsWith("/")) { + resourceID = resourceID.substring(0, resourceID.length() - 1); + } + } + return resourceID; } From 12319878fbc23be1987ca6a224edc44017e34094 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Thu, 2 Jun 2022 17:14:19 +1000 Subject: [PATCH 02/20] Resolve failing blank.aff4 and blank5.aff4 test cases. --- .../container/TestImageMaterialisation.java | 6 +++--- .../aff4/imagestream/TestZipImageStream.java | 2 +- src/test/resources/README.txt | 6 +++++- src/test/resources/blank.aff4 | Bin 0 -> 19132 bytes src/test/resources/blank5.aff4 | Bin 0 -> 19133 bytes 5 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 src/test/resources/blank.aff4 create mode 100644 src/test/resources/blank5.aff4 diff --git a/src/test/java/com/evimetry/aff4/container/TestImageMaterialisation.java b/src/test/java/com/evimetry/aff4/container/TestImageMaterialisation.java index 813b72d..ae0de49 100644 --- a/src/test/java/com/evimetry/aff4/container/TestImageMaterialisation.java +++ b/src/test/java/com/evimetry/aff4/container/TestImageMaterialisation.java @@ -63,7 +63,7 @@ public class TestImageMaterialisation { private final static String linearSHA1 = "7d3d27f667f95f7ec5b9d32121622c0f4b60b48d"; private final static String allocatedSHA1 = "e8650e89b262cf0b4b73c025312488d5a6317a26"; private final static String readErrorSHA1 = "67e245a640e2784ead30c1ff1a3f8d237b58310f"; - private final static String blankSHA1 = "e68329455580cb50fb1debc88cecf2e9aaf3f7fe"; + private final static String blankSHA1 = "5e3ba42e404c04f85ac8f0d09b85635fb5e88243"; /** * The size of the read to perform. */ @@ -212,7 +212,7 @@ public void testContainerBlank() throws UnsupportedOperationException, IOExcepti IAFF4Map map = image.getMap(); assertEquals("aff4://223fb1d7-7826-4631-a35b-df14ad7bf75e", map.getResourceID()); try (SeekableByteChannel channel = map.getChannel()) { - assertEquals(99983360, channel.size()); + assertEquals(268435456, channel.size()); assertEquals(blankSHA1, getDigest(channel, readSize)); } } @@ -232,7 +232,7 @@ public void testContainerBlank5() throws UnsupportedOperationException, IOExcept IAFF4Map map = image.getMap(); assertEquals("aff4://6e3c59b5-e660-4adf-8eb6-472cef961c2d", map.getResourceID()); try (SeekableByteChannel channel = map.getChannel()) { - assertEquals(99983360, channel.size()); + assertEquals(268435456, channel.size()); assertEquals(blankSHA1, getDigest(channel, readSize)); } } diff --git a/src/test/java/com/evimetry/aff4/imagestream/TestZipImageStream.java b/src/test/java/com/evimetry/aff4/imagestream/TestZipImageStream.java index d538462..4026f74 100644 --- a/src/test/java/com/evimetry/aff4/imagestream/TestZipImageStream.java +++ b/src/test/java/com/evimetry/aff4/imagestream/TestZipImageStream.java @@ -180,7 +180,7 @@ public void testContainerImageStreamCompressedContents() throws Exception { AFF4ZipContainer con = (AFF4ZipContainer) container; // Test the contents of the map stream via a sha1 hash. - testStreamContents(con.getSegment("information.turtle"), "1e69f88af3547bb339b8d2f4538cdfbb9627f2da"); + testStreamContents(con.getSegment("information.turtle"), "046c1bb8d55eab3550a4649e080a8f8bf8242884"); } } diff --git a/src/test/resources/README.txt b/src/test/resources/README.txt index d81f78e..6569b8b 100644 --- a/src/test/resources/README.txt +++ b/src/test/resources/README.txt @@ -12,4 +12,8 @@ These images are produced using the Evimetry 2.2 AFF4 implementation. The following Images were produced via unit tests for emulation of Physical Memory acquisition: Micro7.001.aff4 - Micro9.001.aff4 \ No newline at end of file + Micro9.001.aff4 + +Additional Images used for unit testing purposes: + blank.aff4 + blank5.aff4 \ No newline at end of file diff --git a/src/test/resources/blank.aff4 b/src/test/resources/blank.aff4 new file mode 100644 index 0000000000000000000000000000000000000000..de7611114c20d9ab852e00b3b750555bc72fb382 GIT binary patch literal 19132 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 GPyY$AZ9`iC literal 0 HcmV?d00001 diff --git a/src/test/resources/blank5.aff4 b/src/test/resources/blank5.aff4 new file mode 100644 index 0000000000000000000000000000000000000000..2405044f65656986a0244f268db2fc06873fd3fc GIT binary patch literal 19133 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 Hk?21GXZlU3 literal 0 HcmV?d00001 From 2f03eef54442fc178c5242bbb796e96083fdbb76 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 12:07:57 +1000 Subject: [PATCH 03/20] Upgrade build and source dependencies, move to Java 11 LTS. --- META-INF/MANIFEST.MF | 22 +++++++++++----------- pom.xml | 38 +++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF index 113a8a7..94278fe 100644 --- a/META-INF/MANIFEST.MF +++ b/META-INF/MANIFEST.MF @@ -5,7 +5,7 @@ Bundle-Name: AFF4 Java Bundle-SymbolicName: com.evimetry.aff4;singleton:=true Bundle-Version: 1.0.3 Bundle-Vendor: Schatz Forensic -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-RequiredExecutionEnvironment: JavaSE-11 Bundle-Classpath: . Export-Package: com.evimetry.aff4, com.evimetry.aff4.codec, @@ -19,16 +19,16 @@ Export-Package: com.evimetry.aff4, com.evimetry.aff4.resolver, com.evimetry.aff4.resource, com.evimetry.aff4.struct -Import-Package: com.github.benmanes.caffeine.cache;version="2.7.0", +Import-Package: com.github.benmanes.caffeine.cache;version="3.1.1", net.jpountz.lz4, - org.apache.commons.compress.archivers.zip;version="1.18.0", - org.apache.commons.io;version="2.6.0", - org.apache.jena;version="3.10.0", - org.apache.jena.datatypes.xsd;version="3.10.0", - org.apache.jena.rdf.model;version="3.10.0", - org.apache.jena.util;version="3.10.0", - org.apache.jena.vocabulary;version="3.10.0", - org.slf4j;version="1.7.2", - org.xerial.snappy;version="1.1.7" + org.apache.commons.compress.archivers.zip;version="1.21", + org.apache.commons.io;version="2.11.0", + org.apache.jena;version="4.5.0", + org.apache.jena.datatypes.xsd;version="4.5.0", + org.apache.jena.rdf.model;version="4.5.0", + org.apache.jena.util;version="4.5.0", + org.apache.jena.vocabulary;version="4.5.0", + org.slf4j;version="1.7.36", + org.xerial.snappy;version="1.1.8.4" diff --git a/pom.xml b/pom.xml index 648e3b5..76f43eb 100644 --- a/pom.xml +++ b/pom.xml @@ -48,22 +48,22 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.0 + 3.10.1 - 1.8 - 1.8 + 11 + 11 org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M3 + 3.0.0-M6 org.apache.maven.plugins maven-jar-plugin - 3.1.1 + 3.2.2 @@ -89,13 +89,13 @@ - -quiet -Xdoclint:none + none org.apache.maven.plugins maven-source-plugin - 3.1.0 + 3.2.1 attach-sources @@ -116,7 +116,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 3.0.0-M3 + 3.0.0-M6 @@ -124,47 +124,51 @@ org.slf4j slf4j-api - 1.7.26 + 1.7.36 org.slf4j slf4j-log4j12 - 1.7.26 + 1.7.36 test org.xerial.snappy snappy-java - 1.1.7.3 + 1.1.8.4 org.lz4 lz4-java - 1.6.0 + 1.8.0 org.apache.jena apache-jena-libs - 3.11.0 + 4.4.0 pom com.github.ben-manes.caffeine caffeine - 2.7.0 + 3.1.0 junit junit - 4.12 + 4.13.2 test org.apache.commons commons-compress - 1.18 + 1.21 - + + commons-io + commons-io + 2.11.0 + 2017 From 558aff791ecfc2f4916a700e308a33b69ec0ff82 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 12:14:17 +1000 Subject: [PATCH 04/20] Resolve build warning: slf4j-log4j12 has been relocated to slf4j-reload4j. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 76f43eb..c5cdf03 100644 --- a/pom.xml +++ b/pom.xml @@ -128,7 +128,7 @@ org.slf4j - slf4j-log4j12 + slf4j-reload4j 1.7.36 test From 5e4a459e7139962f71cbb885933b6a8dad5813f3 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 12:30:13 +1000 Subject: [PATCH 05/20] Introduce AFF4-L lexicon. --- .../java/com/evimetry/aff4/AFF4Lexicon.java | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/evimetry/aff4/AFF4Lexicon.java b/src/main/java/com/evimetry/aff4/AFF4Lexicon.java index a6e2068..faa5f54 100644 --- a/src/main/java/com/evimetry/aff4/AFF4Lexicon.java +++ b/src/main/java/com/evimetry/aff4/AFF4Lexicon.java @@ -328,7 +328,63 @@ public enum AFF4Lexicon { /** * Volume/Disk contains unallocated regions (sparse). */ - ContainsUnallocated(AFF4.BBT_BASE_URI + "ContainsUnallocated"); + ContainsUnallocated(AFF4.BBT_BASE_URI + "ContainsUnallocated"), + + /* AFF4-L Properties */ + /** + * The original unencoded file path and name of a logical evidence object. + */ + originalFileName(AFF4.AFF4_BASE_URI + "originalFileName"), + + /** + * The birth time of a file's content and metadata. + */ + birthTime(AFF4.AFF4_BASE_URI + "birthTime"), + + /** + * The last modified time of a file's content. + */ + lastWritten(AFF4.AFF4_BASE_URI + "lastWritten"), + + /** + * The last modified time of a file's filesystem metadata. + */ + recordChanged(AFF4.AFF4_BASE_URI + "recordChanged"), + + /** + * The last access time of a file's content. + */ + lastAccessed(AFF4.AFF4_BASE_URI + "lastAccessed"), + + /** + * Folder Class representing a suspect folder. + */ + Folder(AFF4.AFF4_BASE_URI + "Folder"), + + /** + * Folder Class representing a suspect folder. + */ + FolderImage(AFF4.AFF4_BASE_URI + "FolderImage"), + + /** + * FileImage Class representing a suspect file. + */ + FileImage(AFF4.AFF4_BASE_URI + "FileImage"), + + /** + * Property representing the FilesImages contained in a Folder. + */ + FilesImages(AFF4.AFF4_BASE_URI + "FilesImages"), + + /** + * Class representing a logical acquisition activity. + */ + LogicalAcquisitionTask(AFF4.AFF4_BASE_URI + "LogicalAcquisitionTask"), + + /** + * Property pointing to a Folder or FileImage which forms the root of an acquisition operation. + */ + FilesystemRoot(AFF4.AFF4_BASE_URI + "filesystemRoot"); /** * Map of all values to activities. From b0706e5bddb104beb49242691b2ff287d14b989b Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 12:40:08 +1000 Subject: [PATCH 06/20] Handle malformed images with invalid XSD typename: datetime. --- src/main/java/com/evimetry/aff4/rdf/RDFUtil.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/evimetry/aff4/rdf/RDFUtil.java b/src/main/java/com/evimetry/aff4/rdf/RDFUtil.java index acee767..8200d55 100644 --- a/src/main/java/com/evimetry/aff4/rdf/RDFUtil.java +++ b/src/main/java/com/evimetry/aff4/rdf/RDFUtil.java @@ -17,8 +17,12 @@ package com.evimetry.aff4.rdf; import java.time.Instant; +import java.time.ZonedDateTime; +import java.util.Calendar; +import java.util.Date; import java.util.Optional; +import org.apache.jena.datatypes.BaseDatatype; import org.apache.jena.datatypes.xsd.XSDDateTime; import org.apache.jena.rdf.model.Literal; import org.apache.jena.rdf.model.Model; @@ -182,6 +186,13 @@ public static Optional readDateTimeProperty(Model model, String resourc if (literalValue instanceof XSDDateTime) { XSDDateTime datetime = (XSDDateTime) literalValue; return Optional.of(datetime.asCalendar().toInstant()); + } else if (literalValue instanceof BaseDatatype.TypedValue) { + BaseDatatype.TypedValue type = (BaseDatatype.TypedValue) literalValue; + if (type.datatypeURI.toLowerCase().contains("datetime")) { + Calendar datetime = Calendar.getInstance(); + datetime.setTime(Date.from(ZonedDateTime.parse(type.lexicalValue).toInstant())); + return Optional.of(datetime.toInstant()); + } } } } From 9490f35ded8e1012d3af2673ad0d5fbaa6a52c03 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 12:47:11 +1000 Subject: [PATCH 07/20] Exposed date-time (ISO 8601) parsing via AFF4Resource. --- .../com/evimetry/aff4/resource/AFF4Resource.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/com/evimetry/aff4/resource/AFF4Resource.java b/src/main/java/com/evimetry/aff4/resource/AFF4Resource.java index 354e418..e582175 100644 --- a/src/main/java/com/evimetry/aff4/resource/AFF4Resource.java +++ b/src/main/java/com/evimetry/aff4/resource/AFF4Resource.java @@ -16,6 +16,7 @@ */ package com.evimetry.aff4.resource; +import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -177,6 +178,20 @@ protected void addBooleanProperty(Model model, String resource, AFF4Lexicon prop } } + /** + * Add the given date property to this objects property list if present. + * + * @param model The RDF model to use. + * @param resource The resource to enquire + * @param property The property to add. + */ + public void addDateTimeProperty(Model model, String resource, AFF4Lexicon property) { + Optional value = RDFUtil.readDateTimeProperty(model, resource, property); + if (value.isPresent()) { + properties.put(property, Collections.singletonList(value.get())); + } + } + /** * Add the given resource property to this objects property list if present. *

From c10f214d21299199265ba708a06dabb6cba30151 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 12:52:02 +1000 Subject: [PATCH 08/20] Add logical image details to AFF4Image instances, if present. --- src/main/java/com/evimetry/aff4/image/AFF4Image.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/evimetry/aff4/image/AFF4Image.java b/src/main/java/com/evimetry/aff4/image/AFF4Image.java index 89dea96..4f44b84 100644 --- a/src/main/java/com/evimetry/aff4/image/AFF4Image.java +++ b/src/main/java/com/evimetry/aff4/image/AFF4Image.java @@ -78,6 +78,14 @@ private void initProperties(Model model) { addStringProperty(model, getResourceID(), AFF4Lexicon.acquisitionType); addResourceProperty(model, getResourceID(), AFF4Lexicon.dataStream); addResourceProperty(model, getResourceID(), AFF4Lexicon.dependentStream); + + // Logical image details + addDateTimeProperty(model, getResourceID(), AFF4Lexicon.birthTime); + addDateTimeProperty(model, getResourceID(), AFF4Lexicon.lastAccessed); + addDateTimeProperty(model, getResourceID(), AFF4Lexicon.lastWritten); + addDateTimeProperty(model, getResourceID(), AFF4Lexicon.recordChanged); + addStringProperty(model, getResourceID(), AFF4Lexicon.originalFileName); + // Is disk or memory image? if (properties.get(AFF4Lexicon.RDFType).contains(AFF4Lexicon.MemoryImage)) { // Memory From 51d39229850642fbc83479ba1fe86852d84ec1be Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 13:02:37 +1000 Subject: [PATCH 09/20] Enable version 1.1 containers. --- src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java index 92c4fff..f0eeb30 100644 --- a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java +++ b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java @@ -223,7 +223,7 @@ private boolean checkSupportedVersion() throws IOException { try { long maj = Long.parseLong(major.iterator().next().toString()); long min = Long.parseLong(minor.iterator().next().toString()); - return (maj == 1 && min == 0); + return maj == 1 && (min == 0 || min == 1); } catch (NumberFormatException e) { // Ignore. logger.warn(e.getMessage(), e); From 03111ff63a2641db9d0c838c049fa47e0b667775 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 14:35:57 +1000 Subject: [PATCH 10/20] Removed 'No Map aff4:dataStream defined for Image.' warning, no dataStream is present for logical images. --- src/main/java/com/evimetry/aff4/image/AFF4Image.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/evimetry/aff4/image/AFF4Image.java b/src/main/java/com/evimetry/aff4/image/AFF4Image.java index 4f44b84..2bec941 100644 --- a/src/main/java/com/evimetry/aff4/image/AFF4Image.java +++ b/src/main/java/com/evimetry/aff4/image/AFF4Image.java @@ -129,7 +129,7 @@ public IAFF4Map getMap() { // we are also a aff4:Map return new AFF4Map(getResourceID(), getResourceID(), parent, model); } - logger.warn("No Map aff4:dataStream defined for Image " + getResourceID()); + return null; } From 249cc5f9c8b3f1d1e5415b3a4a7964f570eba47f Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 14:37:01 +1000 Subject: [PATCH 11/20] Updated Information extraction example for AFF4 1.1 images. --- .../evimetry/aff4/examples/Information.java | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/test/java/com/evimetry/aff4/examples/Information.java b/src/test/java/com/evimetry/aff4/examples/Information.java index c2a103d..6634e5f 100644 --- a/src/test/java/com/evimetry/aff4/examples/Information.java +++ b/src/test/java/com/evimetry/aff4/examples/Information.java @@ -51,45 +51,42 @@ public static void main(String[] args) { return; } String filename = args[0]; - File file = new File(filename); + /* * Open the container. */ - try (IAFF4Container container = Containers.open(file)) { - + try (IAFF4Container container = Containers.open(new File(filename))) { exportProperties("Container: ", container.getResourceID(), container.getProperties()); + /* - * Get an iterator to all images available in this container. + * Iterate over the available images in the container. */ Iterator images = container.getImages(); - /* - * Get the first image in the container, and print some details of the image. - */ while (images.hasNext()) { IAFF4Image image = images.next(); exportProperties("\nImage: ", image.getResourceID(), image.getProperties()); /* - * Get the map object of the image, and print come details of the map. + * Get the map object of the image, print some map details. */ IAFF4Map map = image.getMap(); - exportProperties("\nMap: ", map.getResourceID(), map.getProperties()); + if (map != null) { + exportProperties("\nMap: ", map.getResourceID(), map.getProperties()); - /* - * Add look for dependent streams on the map. - */ - Collection streams = map.getProperty(AFF4Lexicon.dependentStream); - if (streams != null) { - Iterator elements = streams.iterator(); - while (elements.hasNext()) { - String element = elements.next().toString(); - IAFF4Resource resource = container.open(element); - if (resource != null) { - exportProperties("\nStream: ", resource.getResourceID(), resource.getProperties()); + /* + * Look for dependent streams on the map. + */ + Collection streams = map.getProperty(AFF4Lexicon.dependentStream); + if (streams != null) { + for (Object stream : streams) { + String element = stream.toString(); + IAFF4Resource resource = container.open(element); + if (resource != null) { + exportProperties("\nStream: ", resource.getResourceID(), resource.getProperties()); + } } } } - } } catch (Throwable e) { logger.error(e.getMessage()); @@ -110,7 +107,6 @@ private static void exportProperties(String type, String resource, if (types != null) { System.out.print(" AFF4 Types: "); print(types); - } for (Entry> entry : properties.entrySet()) { if (entry.getKey() != AFF4Lexicon.RDFType) { From 6aaf1fe8bba3acd5551a209754f3dd3773bc443d Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 14:52:08 +1000 Subject: [PATCH 12/20] Updated Information extraction example to print ImageStream details for AFF4 1.1 images. --- src/test/java/com/evimetry/aff4/examples/Information.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/com/evimetry/aff4/examples/Information.java b/src/test/java/com/evimetry/aff4/examples/Information.java index 6634e5f..92a5bad 100644 --- a/src/test/java/com/evimetry/aff4/examples/Information.java +++ b/src/test/java/com/evimetry/aff4/examples/Information.java @@ -86,6 +86,11 @@ public static void main(String[] args) { } } } + } else if (image.getProperty(AFF4Lexicon.RDFType).contains(AFF4Lexicon.ImageStream)) { + IAFF4Resource resource = container.open(image.getResourceID()); + if (resource != null) { + exportProperties("\nStream: ", resource.getResourceID(), resource.getProperties()); + } } } } catch (Throwable e) { From d320313ff1fb1f73bfd79f2127a3943697305394 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 3 Jun 2022 15:58:58 +1000 Subject: [PATCH 13/20] Drop logic to remove trail '/' from ARNs, keep trim whitespace. --- src/main/java/com/evimetry/aff4/Containers.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main/java/com/evimetry/aff4/Containers.java b/src/main/java/com/evimetry/aff4/Containers.java index 7920dc1..1386704 100644 --- a/src/main/java/com/evimetry/aff4/Containers.java +++ b/src/main/java/com/evimetry/aff4/Containers.java @@ -151,15 +151,7 @@ public static String getResourceID(File file) { logger.error(e.getMessage(), e); } - if (resourceID != null) { - resourceID = resourceID.trim(); - - if (resourceID.endsWith("/")) { - resourceID = resourceID.substring(0, resourceID.length() - 1); - } - } - - return resourceID; + return (resourceID == null) ? null : resourceID.trim(); } /** From 2d186ee6cf29e3164e631f4fccd169fe17596fad Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Mon, 6 Jun 2022 12:22:15 +1000 Subject: [PATCH 14/20] Fix AFF4ZipContainer method name setPropety to setProperty. --- .../com/evimetry/aff4/container/AFF4ZipContainer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java index f0eeb30..41a6992 100644 --- a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java +++ b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java @@ -143,9 +143,9 @@ private void loadVersionInformation() throws ZipException, IOException { try (InputStream stream = zip.getInputStream(entry)) { Properties prop = new Properties(); prop.load(stream); - setPropety(prop, "tool", AFF4Lexicon.Tool); - setPropety(prop, "major", AFF4Lexicon.majorVersion); - setPropety(prop, "minor", AFF4Lexicon.minorVersion); + setProperty(prop, "tool", AFF4Lexicon.Tool); + setProperty(prop, "major", AFF4Lexicon.majorVersion); + setProperty(prop, "minor", AFF4Lexicon.minorVersion); if(!checkSupportedVersion()) { try { close(); @@ -172,7 +172,7 @@ private void loadVersionInformation() throws ZipException, IOException { * @param property The property to enquire * @param key The key to use to insert into the main properties. */ - private void setPropety(Properties input, String property, AFF4Lexicon key) { + private void setProperty(Properties input, String property, AFF4Lexicon key) { String v = input.getProperty(property); if (v != null) { this.properties.put(key, Collections.singletonList(v)); From 46b752efb6a83dad1637d60241c63e629809fad4 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Mon, 6 Jun 2022 13:02:49 +1000 Subject: [PATCH 15/20] Move AFF4ZipContainer.sanitizeResource to NameCodec.SanitizeResource. --- .../aff4/container/AFF4ZipContainer.java | 27 ++----------------- .../java/com/evimetry/aff4/rdf/NameCodec.java | 24 +++++++++++++++++ 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java index 41a6992..52d0ede 100644 --- a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java +++ b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java @@ -365,7 +365,7 @@ public Model getModel() { */ public IAFF4ImageStream getSegment(String resource) throws IOException { // Strip any leading URI for this container. - String res = sanitizeResource(resource); + String res = NameCodec.SanitizeResource(resource, getResourceID()); ZipArchiveEntry entry = zip.getEntry(res); if (entry != null) { if (entry.getMethod() != ZipMethod.STORED.getCode()) { @@ -421,7 +421,7 @@ public IAFF4ImageStream getImageStream(String resource) throws IOException { } } else { // Check for index file. - String res = sanitizeResource(resource + "/00000000.index"); + String res = NameCodec.SanitizeResource(resource + "/00000000.index", getResourceID()); ZipArchiveEntry entry = zip.getEntry(res); if (entry != null) { // This is us! @@ -470,29 +470,6 @@ public IAFF4Image getImage(String resource) throws IOException { return null; } - /** - * Attempt to sanitise the given resource string - * - * @param res The resource string to sanitise - * @return The sanitised resource string. - */ - private String sanitizeResource(String res) { - // strip any leading "/" - while (res.startsWith("/")) { - res = res.substring(1); - } - if (res.startsWith(getResourceID())) { - res = res.substring(getResourceID().length()); - } - // Convert any "aff4://" characters to "aff4%3A%2F%2F" - res = NameCodec.encode(res); - // strip any leading "/" - while (res.startsWith("/")) { - res = res.substring(1); - } - return res; - } - /** * Notify this container that the ZipImageStream has been closed. * diff --git a/src/main/java/com/evimetry/aff4/rdf/NameCodec.java b/src/main/java/com/evimetry/aff4/rdf/NameCodec.java index 264a43e..cb2d7c0 100644 --- a/src/main/java/com/evimetry/aff4/rdf/NameCodec.java +++ b/src/main/java/com/evimetry/aff4/rdf/NameCodec.java @@ -44,4 +44,28 @@ public static final String decode(String path) { return path; } } + + /** + * Attempt to sanitise the given resource string + * + * @param res The resource string to sanitise + * @param resourceID The resource ID. + * @return The sanitised resource string. + */ + public static final String SanitizeResource(String res, String resourceID) { + // strip any leading "/" + while (res.startsWith("/")) { + res = res.substring(1); + } + if (res.startsWith(resourceID)) { + res = res.substring(resourceID.length()); + } + // Convert any "aff4://" characters to "aff4%3A%2F%2F" + res = NameCodec.encode(res); + // strip any leading "/" + while (res.startsWith("/")) { + res = res.substring(1); + } + return res; + } } From c17a9481da3f13160eb9e5399378940b537e3e26 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Mon, 6 Jun 2022 13:07:20 +1000 Subject: [PATCH 16/20] BevvyIndex sanitized chunk-name and chunk-index zip entry discovery. --- .../java/com/evimetry/aff4/struct/BevvyIndex.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java b/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java index d834115..57697cd 100644 --- a/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java +++ b/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java @@ -62,15 +62,24 @@ public BevvyIndex(String resource, int bevvyID, AFF4ZipContainer parent, ZipFile this.bevvyID = bevvyID; // Get the offset of the bevvy segment into the primary channel. - String bevvyChunkName = NameCodec.encode(String.format("%s/%08d", resource, bevvyID)); + String resourceID = String.format("%s/%08d", resource, bevvyID); + String bevvyChunkName = NameCodec.encode(resourceID); ZipArchiveEntry entry = zipContainer.getEntry(bevvyChunkName); + if (entry == null) { + bevvyChunkName = NameCodec.SanitizeResource(resourceID, parent.getResourceID()); + entry = zipContainer.getEntry(bevvyChunkName); + } if (entry == null) throw new IOException("Missing bevvy segment"); this.offset = entry.getDataOffset(); // Load the indices - String bevvyIndexName = NameCodec.encode(String.format("%s/%08d.index", resource, bevvyID)); + String bevvyIndexID = String.format("%s/%08d.index", resource, bevvyID); + String bevvyIndexName = NameCodec.encode(bevvyIndexID); IAFF4ImageStream stream = parent.getSegment(bevvyIndexName); + if (stream == null) { + stream = parent.getSegment(bevvyIndexID); + } try (SeekableByteChannel channel = stream.getChannel()) { ByteBuffer buffer = ByteBuffer.allocateDirect((int) channel.size()).order(ByteOrder.LITTLE_ENDIAN); Streams.readFull(channel, 0, buffer); From e30686616b9071246c04232c85097c434e560f81 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Tue, 7 Jun 2022 16:08:41 +1000 Subject: [PATCH 17/20] Add ZipFileSegement lexicon. --- src/main/java/com/evimetry/aff4/AFF4Lexicon.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/evimetry/aff4/AFF4Lexicon.java b/src/main/java/com/evimetry/aff4/AFF4Lexicon.java index faa5f54..5ccb553 100644 --- a/src/main/java/com/evimetry/aff4/AFF4Lexicon.java +++ b/src/main/java/com/evimetry/aff4/AFF4Lexicon.java @@ -38,6 +38,11 @@ public enum AFF4Lexicon { * Base type for AFF4 Zip64-based containers. */ ZipVolume(AFF4.AFF4_BASE_URI + "ZipVolume"), + + /** + * ZipFileSegment is an AFF4 object representing a single member of the zip file. + */ + ZipFileSegment(AFF4.AFF4_BASE_URI + "zip_segment"), /** * The creation time of the volume. From 98f16925ebac8327121bb6dd8be5542b7450f442 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Tue, 7 Jun 2022 16:10:08 +1000 Subject: [PATCH 18/20] Resolve data hygiene issue around zip entry names; different tools, different rules. --- .../com/evimetry/aff4/container/AFF4ZipContainer.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java index 52d0ede..67094ee 100644 --- a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java +++ b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java @@ -367,6 +367,14 @@ public IAFF4ImageStream getSegment(String resource) throws IOException { // Strip any leading URI for this container. String res = NameCodec.SanitizeResource(resource, getResourceID()); ZipArchiveEntry entry = zip.getEntry(res); + // Some AFF4 tools strip leading '/' characters from the + // entity name, others leave it in. Same goes for trailing + // '/' characters on ARNs. + if (entry == null) { + res = "/" + res; + entry = zip.getEntry(res); + } + if (entry != null) { if (entry.getMethod() != ZipMethod.STORED.getCode()) { if (entry.getSize() < ZipSegmentImageCompressedStream.MAX_BUFFER_SIZE) { From 7f5814075fe822db681d4a34b8181b1dbc80b7de Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Tue, 7 Jun 2022 16:36:19 +1000 Subject: [PATCH 19/20] More data hygiene issues re:zip entry naming. --- .../com/evimetry/aff4/container/AFF4ZipContainer.java | 10 ++++++++-- src/main/java/com/evimetry/aff4/rdf/NameCodec.java | 3 +++ src/main/java/com/evimetry/aff4/struct/BevvyIndex.java | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java index 67094ee..5b70144 100644 --- a/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java +++ b/src/main/java/com/evimetry/aff4/container/AFF4ZipContainer.java @@ -371,8 +371,7 @@ public IAFF4ImageStream getSegment(String resource) throws IOException { // entity name, others leave it in. Same goes for trailing // '/' characters on ARNs. if (entry == null) { - res = "/" + res; - entry = zip.getEntry(res); + entry = zip.getEntry("/" + res); } if (entry != null) { @@ -431,6 +430,13 @@ public IAFF4ImageStream getImageStream(String resource) throws IOException { // Check for index file. String res = NameCodec.SanitizeResource(resource + "/00000000.index", getResourceID()); ZipArchiveEntry entry = zip.getEntry(res); + // Some AFF4 tools strip leading '/' characters from the + // entity name, others leave it in. Same goes for trailing + // '/' characters on ARNs. + if (entry == null) { + entry = zip.getEntry("/" + res); + } + if (entry != null) { // This is us! IAFF4ImageStream stream = new AFF4ImageStream(resource, this, zip, channel, model); diff --git a/src/main/java/com/evimetry/aff4/rdf/NameCodec.java b/src/main/java/com/evimetry/aff4/rdf/NameCodec.java index cb2d7c0..74eb244 100644 --- a/src/main/java/com/evimetry/aff4/rdf/NameCodec.java +++ b/src/main/java/com/evimetry/aff4/rdf/NameCodec.java @@ -57,8 +57,11 @@ public static final String SanitizeResource(String res, String resourceID) { while (res.startsWith("/")) { res = res.substring(1); } + var encodedResourceID = NameCodec.encode(resourceID); if (res.startsWith(resourceID)) { res = res.substring(resourceID.length()); + } else if (res.startsWith(encodedResourceID)) { + res = res.substring(encodedResourceID.length()); } // Convert any "aff4://" characters to "aff4%3A%2F%2F" res = NameCodec.encode(res); diff --git a/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java b/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java index 57697cd..d4d064c 100644 --- a/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java +++ b/src/main/java/com/evimetry/aff4/struct/BevvyIndex.java @@ -68,6 +68,12 @@ public BevvyIndex(String resource, int bevvyID, AFF4ZipContainer parent, ZipFile if (entry == null) { bevvyChunkName = NameCodec.SanitizeResource(resourceID, parent.getResourceID()); entry = zipContainer.getEntry(bevvyChunkName); + // Some AFF4 tools strip leading '/' characters from the + // entity name, others leave it in. Same goes for trailing + // '/' characters on ARNs. + if (entry == null) { + entry = zipContainer.getEntry("/" + bevvyChunkName); + } } if (entry == null) throw new IOException("Missing bevvy segment"); From 52057da44e21cf8f1531b106f3008d5027c87355 Mon Sep 17 00:00:00 2001 From: Ben Crowhurst Date: Fri, 17 Jun 2022 15:42:46 +1000 Subject: [PATCH 20/20] Minor version number bump 1.0.3 to 1.0.4 --- ChangeLog.txt | 3 +++ META-INF/MANIFEST.MF | 2 +- README.md | 4 ++-- pom.xml | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 1b00837..da4bb6b 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,6 @@ +[1.0.4] 17-Jun-2022 + - Support AFF4 1.1 containers + [1.0.3] 5-Jul-2019 - Support MQ custom lexicon items diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF index 94278fe..845a734 100644 --- a/META-INF/MANIFEST.MF +++ b/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Automatic-Module-Name: com.evimetry.aff4 Bundle-ManifestVersion: 2 Bundle-Name: AFF4 Java Bundle-SymbolicName: com.evimetry.aff4;singleton:=true -Bundle-Version: 1.0.3 +Bundle-Version: 1.0.4 Bundle-Vendor: Schatz Forensic Bundle-RequiredExecutionEnvironment: JavaSE-11 Bundle-Classpath: . diff --git a/README.md b/README.md index 9e5b28e..15018c2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -AFF4 Java v1.0.3 +AFF4 Java v1.0.4 ----- -An AFF4 Standard v1.0 compliant reader library. +An AFF4 Standard v1.1 compliant reader library. Copyright (c) Schatz Forensic Pty Ltd, 2017-2019 diff --git a/pom.xml b/pom.xml index c5cdf03..8ecae7f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.evimetry.aff4 aff4-reader-lite - 1.0.3 + 1.0.4 AFF4 Java Reader-lite https://github.com/aff4/aff4-java/