diff --git a/src/filereport/mod.rs b/src/filereport/mod.rs index 07a39ea..4ca75a6 100644 --- a/src/filereport/mod.rs +++ b/src/filereport/mod.rs @@ -63,6 +63,9 @@ pub struct ScanResultAttributes { /// A description of the file type pub type_description: String, + /// Exiftool results, requires VirusTotal Premium + pub exiftool: Option, + /// Trend Micro's Locality Sensitive Hash: [https://tlsh.org/] pub tlsh: Option, @@ -272,6 +275,165 @@ pub struct AnalysisResult { pub engine_update: Option, } +/// ExifTool metadata, requires VirusTotal Premium. See [https://docs.virustotal.com/reference/exiftool] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct ExifTool { + /// Windows PE: Application character set + pub character_set: Option, + + /// Windows PE: code side + pub code_size: Option, + + /// Windows PE: Company name + pub company_name: Option, + + /// PDF: Creation date + pub create_date: Option, + + /// PDF: Creator application + pub creator: Option, + + /// PDF: Creator tool + pub creator_tool: Option, + + /// PDF: Document ID + #[serde(rename = "DocumentID")] + pub document_id: Option, + + /// Windows PE: entry point address + pub entry_point: Option, + + /// Windows PE: description about the file + pub file_description: Option, + + /// Windows PE: File flags mask + pub file_flags_mask: Option, + + /// Windows PE: expected operating system + #[serde(rename = "FileOS")] + pub file_os: Option, + + /// Windows PE: size of the file + pub file_size: Option, + + /// Windows PE: File subtype + pub file_subtype: Option, + + /// PDF & Windows PE: File type + pub file_type: Option, + + /// PDF & Windows PE: file extension for the file type + pub file_type_extension: Option, + + /// Windows PE: file version + pub file_version: Option, + + /// Windows PE: file version number + pub file_version_number: Option, + + /// PDF (others?): File format + pub format: Option, + + /// PDF: Has forms (XML Forms Architecture) + #[serde(rename = "HasXFA")] + pub hasxfa: Option, + + /// Windows PE: image file characteristics + pub image_file_characteristics: Option, + + /// Windows PE: image version + pub image_version: Option, + + /// Windows PE: initialized data size + pub initialized_data_size: Option, + + /// PDF: Instance ID + #[serde(rename = "InstanceID")] + pub instance_id: Option, + + /// Windows PE: internal name + pub internal_name: Option, + + /// Windows PE: language code + pub language_code: Option, + + /// Windows PE: copyright information + pub legal_copyright: Option, + + /// PDF: If linearized + pub linearized: Option, + + /// Windows PE: linker version + pub linker_version: Option, + + /// PDF & Windows PE: MIME type + #[serde(rename = "MIMEType")] + pub mimetype: Option, + + /// Windows PE: Machine type + pub machine_type: Option, + + /// PDF: Metadata date + pub metadata_date: Option, + + /// PDF: Modification date + pub modify_date: Option, + + /// Windows PE: operating system version + #[serde(rename = "OSVersion")] + pub os_version: Option, + + /// Windows PE: Object file type + pub object_file_type: Option, + + /// Windows PE: original file name + pub original_file_name: Option, + + /// PDF: Page count + pub page_count: Option, + + /// PDF: PDF version + #[serde(rename = "PDFVersion")] + pub pdf_version: Option, + + /// Windows PE: PE type + #[serde(rename = "PEType")] + pub petype: Option, + + /// PDF: Producer + pub producer: Option, + + /// Windows PE: Product name + pub product_name: Option, + + /// Windows PE: product version + pub product_version: Option, + + /// Windows PE: product version number + pub product_version_number: Option, + + /// Windows PE: Windows subsystem type + pub subsystem: Option, + + /// Windows PE: Windows subsystem version + pub subsystem_version: Option, + + /// Windows PE: creation timestamp + pub time_stamp: Option, + + /// Windows PE: Uninitialized data size + pub uninitialized_data_size: Option, + + /// PDF: XMP (extensible metadata platform) toolkit + #[serde(rename = "XMPToolkit")] + pub xmp_toolkit: Option, + + /// Anything else not capture by this struct + #[serde(flatten)] + pub extra: HashMap, +} + /// File type based on TrID /// [https://virustotal.readme.io/reference/files-object-trid] /// [https://mark0.net/soft-trid-e.html] @@ -489,4 +651,68 @@ mod tests { FileReportRequestResponse::Error(_) => {} } } + + #[test] + fn pe_exif() { + // Data comes from VirusTotal documentation + const PE_JSON: &str = r#"{ + "CodeSize": "86528", + "EntryPoint": "0x5d45", + "FileFlagsMask": "0x003f", + "FileOS": "Windows NT 32-bit", + "FileSubtype": "0", + "FileType": "Win32 EXE", + "FileTypeExtension": "exe", + "FileVersionNumber": "1.0.0.1", + "ImageFileCharacteristics": "Executable, 32-bit", + "ImageVersion": "0.0", + "InitializedDataSize": "15447552", + "LinkerVersion": "10.0", + "MIMEType": "application/octet-stream", + "MachineType": "Intel 386 or later, and compatibles", + "OSVersion": "5.1", + "ObjectFileType": "Executable application", + "PEType": "PE32", + "ProductVersionNumber": "1.0.0.1", + "Subsystem": "Windows GUI", + "SubsystemVersion": "5.1", + "TimeStamp": "2018:06:10 05:04:21+02:00", + "UninitializedDataSize": "0" + }"#; + + let exiftool: ExifTool = serde_json::from_str(PE_JSON).unwrap(); + assert_eq!(exiftool.file_type.unwrap(), "Win32 EXE"); + assert_eq!(exiftool.mimetype.unwrap(), "application/octet-stream"); + assert_eq!(exiftool.os_version.unwrap(), "5.1"); + assert!(exiftool.extra.is_empty()); + } + + #[test] + fn pdf_exif() { + // Data comes from VirusTotal documentation + const PDF_JSON: &str = r#"{ + "CreateDate": "2020:02:27 18:03:45+03:00", + "DocumentID": "uuid:5ac8d66b-6716-466c-b665-965766c06571", + "FileType": "PDF", + "FileTypeExtension": "pdf", + "Format": "application/pdf", + "HasXFA": "No", + "InstanceID": "uuid:696b3606-6627-606f-b636-769b656676f0", + "Linearized": "No", + "MIMEType": "application/pdf", + "MetadataDate": "2020:02:27 18:03:45+03:00", + "ModifyDate": "2020:02:27 18:03:45+03:00", + "PDFVersion": "1.6", + "PageCount": "2", + "XMPToolkit": "Adobe XMP Core 5.4-c005 78.147326, 2012/08/23-13:03:03" + }"#; + + let exiftool: ExifTool = serde_json::from_str(PDF_JSON).unwrap(); + assert_eq!(exiftool.pdf_version.unwrap(), "1.6"); + assert_eq!( + exiftool.xmp_toolkit.unwrap(), + "Adobe XMP Core 5.4-c005 78.147326, 2012/08/23-13:03:03" + ); + assert!(exiftool.extra.is_empty()); + } }