Autopsy  4.19.3
Graphical digital forensics platform for The Sleuth Kit and other tools.
CustomFileTypesManager.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2016 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.modules.filetypeid;
20 
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.List;
29 import javax.xml.bind.DatatypeConverter;
30 import javax.xml.parsers.ParserConfigurationException;
31 import org.openide.util.io.NbObjectInputStream;
32 import org.openide.util.io.NbObjectOutputStream;
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.Node;
39 import org.w3c.dom.NodeList;
40 import org.xml.sax.SAXException;
41 
46 final class CustomFileTypesManager {
47 
48  private static final String SERIALIZED_SETTINGS_FILE = "UserFileTypeDefinitions.settings"; //NON-NLS
49  private static final String XML_SETTINGS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS
50  private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS
51  private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS
52  private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS
53  private static final String SIGNATURE_TAG_NAME = "Signature"; //NON-NLS
54  private static final String SIGNATURE_TYPE_ATTRIBUTE = "type"; //NON-NLS
55  private static final String BYTES_TAG_NAME = "Bytes"; //NON-NLS
56  private static final String OFFSET_TAG_NAME = "Offset"; //NON-NLS
57  private static final String RELATIVE_ATTRIBUTE = "RelativeToStart"; //NON-NLS
58  private static CustomFileTypesManager instance;
59  private final List<FileType> autopsyDefinedFileTypes = new ArrayList<>();
60  private List<FileType> userDefinedFileTypes = new ArrayList<>();
61 
71  synchronized static CustomFileTypesManager getInstance() throws CustomFileTypesException {
72  if (null == instance) {
73  instance = new CustomFileTypesManager();
74  try {
75  instance.loadUserDefinedFileTypes();
76  instance.createAutopsyDefinedFileTypes();
77  } catch (CustomFileTypesException ex) {
78  instance = null;
79  throw ex;
80  }
81  }
82  return instance;
83  }
84 
89  private CustomFileTypesManager() {
90  }
91 
97  synchronized List<FileType> getFileTypes() {
102  List<FileType> customTypes = new ArrayList<>(userDefinedFileTypes);
103  customTypes.addAll(autopsyDefinedFileTypes);
104  return customTypes;
105  }
106 
112  synchronized List<FileType> getAutopsyDefinedFileTypes() {
117  return new ArrayList<>(autopsyDefinedFileTypes);
118  }
119 
125  synchronized List<FileType> getUserDefinedFileTypes() {
130  return new ArrayList<>(userDefinedFileTypes);
131  }
132 
141  synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws CustomFileTypesException {
142  String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE);
143  writeSerializedFileTypes(newFileTypes, filePath);
144  userDefinedFileTypes = newFileTypes;
145  }
146 
153  private void createAutopsyDefinedFileTypes() throws CustomFileTypesException {
154  byte[] byteArray;
155  FileType fileType;
156  try {
157  /*
158  * Add type for xml.
159  */
160  List<Signature> signatureList;
161  signatureList = new ArrayList<>();
162  signatureList.add(new Signature("<?xml", 0L)); //NON-NLS
163  fileType = new FileType("text/xml", signatureList); //NON-NLS
164  autopsyDefinedFileTypes.add(fileType);
165 
166  /*
167  * Add type for gzip.
168  */
169  byteArray = DatatypeConverter.parseHexBinary("1F8B"); //NON-NLS
170  signatureList.clear();
171  signatureList.add(new Signature(byteArray, 0L));
172  fileType = new FileType("application/x-gzip", signatureList); //NON-NLS
173  autopsyDefinedFileTypes.add(fileType);
174 
175  /*
176  * Add type for wk1.
177  */
178  byteArray = DatatypeConverter.parseHexBinary("0000020006040600080000000000"); //NON-NLS
179  signatureList.clear();
180  signatureList.add(new Signature(byteArray, 0L));
181  fileType = new FileType("application/x-123", signatureList); //NON-NLS
182  autopsyDefinedFileTypes.add(fileType);
183 
184  /*
185  * Add type for Radiance images.
186  */
187  byteArray = DatatypeConverter.parseHexBinary("233F52414449414E43450A");//NON-NLS
188  signatureList.clear();
189  signatureList.add(new Signature(byteArray, 0L));
190  fileType = new FileType("image/vnd.radiance", signatureList); //NON-NLS
191  autopsyDefinedFileTypes.add(fileType);
192 
193  /*
194  * Add type for dcx images.
195  */
196  byteArray = DatatypeConverter.parseHexBinary("B168DE3A"); //NON-NLS
197  signatureList.clear();
198  signatureList.add(new Signature(byteArray, 0L));
199  fileType = new FileType("image/x-dcx", signatureList); //NON-NLS
200  autopsyDefinedFileTypes.add(fileType);
201 
202  /*
203  * Add type for ics images.
204  */
205  signatureList.clear();
206  signatureList.add(new Signature("icns", 0L)); //NON-NLS
207  fileType = new FileType("image/x-icns", signatureList); //NON-NLS
208  autopsyDefinedFileTypes.add(fileType);
209 
210  /*
211  * Add type for pict images.
212  */
213  byteArray = DatatypeConverter.parseHexBinary("001102FF"); //NON-NLS
214  signatureList.clear();
215  signatureList.add(new Signature(byteArray, 522L));
216  fileType = new FileType("image/x-pict", signatureList); //NON-NLS
217  autopsyDefinedFileTypes.add(fileType);
218 
219  /*
220  * NOTE: see JIRA-4269. This MIME type seems to match a lot of
221  * random file types, including ZIP archives. As a result those
222  * files get assigned this MIME type instead of having their MIME
223  * type detected by Tika. byteArray =
224  * DatatypeConverter.parseHexBinary("1100"); //NON-NLS
225  * signatureList.clear(); signatureList.add(new Signature(byteArray,
226  * 522L)); fileType = new FileType("image/x-pict", signatureList);
227  * //NON-NLS
228  autopsyDefinedFileTypes.add(fileType);
229  */
230 
231  /*
232  * Add type for pam.
233  */
234  signatureList.clear();
235  signatureList.add(new Signature("P7", 0L)); //NON-NLS
236  fileType = new FileType("image/x-portable-arbitrarymap", signatureList); //NON-NLS
237  autopsyDefinedFileTypes.add(fileType);
238 
239  /*
240  * Add type for pfm.
241  */
242  signatureList.clear();
243  signatureList.add(new Signature("PF", 0L)); //NON-NLS
244  fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS
245  autopsyDefinedFileTypes.add(fileType);
246  signatureList.clear();
247  signatureList.add(new Signature("Pf", 0L)); //NON-NLS
248  fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS
249  autopsyDefinedFileTypes.add(fileType);
250 
251  /*
252  * Add type for tga.
253  */
254  byteArray = DatatypeConverter.parseHexBinary("54525545564953494F4E2D5846494C452E00"); //NON-NLS
255  signatureList.clear();
256  signatureList.add(new Signature(byteArray, 17, false));
257  fileType = new FileType("image/x-tga", signatureList); //NON-NLS
258  autopsyDefinedFileTypes.add(fileType);
259 
260  /*
261  * Add type for ilbm.
262  */
263  signatureList.clear();
264  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
265  signatureList.add(new Signature("ILBM", 8L)); //NON-NLS
266  fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS
267  autopsyDefinedFileTypes.add(fileType);
268  signatureList.clear();
269  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
270  signatureList.add(new Signature("PBM", 8L)); //NON-NLS
271  fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS
272  autopsyDefinedFileTypes.add(fileType);
273 
274  /*
275  * Add type for webp.
276  */
277  signatureList.clear();
278  signatureList.add(new Signature("RIFF", 0L)); //NON-NLS
279  signatureList.add(new Signature("WEBP", 8L)); //NON-NLS
280  fileType = new FileType("image/webp", signatureList); //NON-NLS
281  autopsyDefinedFileTypes.add(fileType);
282 
283  /*
284  * Add type for aiff.
285  */
286  signatureList.clear();
287  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
288  signatureList.add(new Signature("AIFF", 8L)); //NON-NLS
289  fileType = new FileType("audio/aiff", signatureList); //NON-NLS
290  autopsyDefinedFileTypes.add(fileType);
291  signatureList.clear();
292  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
293  signatureList.add(new Signature("AIFC", 8L)); //NON-NLS
294  fileType = new FileType("audio/aiff", signatureList); //NON-NLS
295  autopsyDefinedFileTypes.add(fileType);
296  signatureList.clear();
297  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
298  signatureList.add(new Signature("8SVX", 8L)); //NON-NLS
299  fileType = new FileType("audio/aiff", signatureList); //NON-NLS
300  autopsyDefinedFileTypes.add(fileType);
301 
302  /*
303  * Add type for iff.
304  */
305  signatureList.clear();
306  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
307  fileType = new FileType("application/x-iff", signatureList); //NON-NLS
308  autopsyDefinedFileTypes.add(fileType);
309 
310  /*
311  * Add type for .tec files with leading End Of Image marker (JFIF
312  * JPEG)
313  */
314  byteArray = DatatypeConverter.parseHexBinary("FFD9FFD8"); //NON-NLS
315  signatureList.clear();
316  signatureList.add(new Signature(byteArray, 0L));
317  fileType = new FileType("image/jpeg", signatureList); //NON-NLS
318  autopsyDefinedFileTypes.add(fileType);
319 
320  /*
321  * Add type for Windows NT registry files with leading End Of Image marker (JFIF
322  * JPEG)
323  */
324  byteArray = DatatypeConverter.parseHexBinary("72656766"); //NON-NLS
325  signatureList.clear();
326  signatureList.add(new Signature(byteArray, 0L));
327  fileType = new FileType("application/x.windows-registry", signatureList); //NON-NLS
328  autopsyDefinedFileTypes.add(fileType);
329 
330  /*
331  * Add custom file type for hdb files that can be found in android os on the system volume
332  * in the hdic folder
333  */
334  byteArray = DatatypeConverter.parseHexBinary("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC");
335  signatureList.clear();
336  signatureList.add(new Signature(byteArray, 8L));
337  fileType = new FileType("application/x.android-hdb", signatureList);
338  autopsyDefinedFileTypes.add(fileType);
339 
343  signatureList.clear();
344  signatureList.add(new Signature("conectix", 511L, false)); //NON-NLS
345  fileType = new FileType("application/x-vhd", signatureList); //NON-NLS
346  autopsyDefinedFileTypes.add(fileType);
347 
348  } catch (IllegalArgumentException ex) {
349  /*
350  * parseHexBinary() throws this if the argument passed in is not hex
351  */
352  throw new CustomFileTypesException("Error creating Autopsy defined custom file types", ex); //NON-NLS
353  }
354  }
355 
362  private void loadUserDefinedFileTypes() throws CustomFileTypesException {
363  userDefinedFileTypes.clear();
364  String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE);
365  if (new File(filePath).exists()) {
366  userDefinedFileTypes = readSerializedFileTypes(filePath);
367  } else {
368  filePath = getFileTypeDefinitionsFilePath(XML_SETTINGS_FILE);
369  if (new File(filePath).exists()) {
370  userDefinedFileTypes = readFileTypesXML(filePath);
371  }
372  }
373  }
374 
384  private static void writeSerializedFileTypes(List<FileType> fileTypes, String filePath) throws CustomFileTypesException {
385  try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) {
386  UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes);
387  out.writeObject(settings);
388  } catch (IOException ex) {
389  throw new CustomFileTypesException(String.format("Failed to write settings to %s", filePath), ex); //NON-NLS
390  }
391  }
392 
403  private static List<FileType> readSerializedFileTypes(String filePath) throws CustomFileTypesException {
404  File serializedDefs = new File(filePath);
405  try {
406  try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) {
407  UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject();
408  return filesSetsSettings.getUserDefinedFileTypes();
409  }
410  } catch (IOException | ClassNotFoundException ex) {
411  throw new CustomFileTypesException(String.format("Failed to read settings from %s", filePath), ex); //NON-NLS
412  }
413  }
414 
429  private static List<FileType> readFileTypesXML(String filePath) throws CustomFileTypesException {
430  try {
431  List<FileType> fileTypes = new ArrayList<>();
432  Document doc = XMLUtil.loadDocument(filePath);
433  if (doc != null) {
434  Element fileTypesElem = doc.getDocumentElement();
435  if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) {
436  NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME);
437  for (int i = 0; i < fileTypeElems.getLength(); ++i) {
438  Element fileTypeElem = (Element) fileTypeElems.item(i);
439  FileType fileType = parseFileType(fileTypeElem);
440  fileTypes.add(fileType);
441  }
442  }
443  }
444  return fileTypes;
445  } catch (IOException | ParserConfigurationException | SAXException ex) {
446  throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS
447  }
448  }
449 
462  private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
463  String mimeType = parseMimeType(fileTypeElem);
464  Signature signature = parseSignature(fileTypeElem);
465  // File type definitions in the XML file were written prior to the
466  // implementation of multiple signatures per type.
467  List<Signature> sigList = new ArrayList<>();
468  sigList.add(signature);
469  return new FileType(mimeType, sigList);
470  }
471 
479  private static String parseMimeType(Element fileTypeElem) {
480  return getChildElementTextContent(fileTypeElem, MIME_TYPE_TAG_NAME);
481  }
482 
490  private static Signature parseSignature(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
491  NodeList signatureElems = fileTypeElem.getElementsByTagName(SIGNATURE_TAG_NAME);
492  Element signatureElem = (Element) signatureElems.item(0);
493 
494  String sigTypeAttribute = signatureElem.getAttribute(SIGNATURE_TYPE_ATTRIBUTE);
495  Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute);
496 
497  String sigBytesString = getChildElementTextContent(signatureElem, BYTES_TAG_NAME);
498  byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString);
499 
500  Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0);
501  String offsetString = offsetElem.getTextContent();
502  long offset = DatatypeConverter.parseLong(offsetString);
503 
504  boolean isRelativeToStart;
505  String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE);
506  if (null == relativeString || relativeString.equals("")) {
507  isRelativeToStart = true;
508  } else {
509  isRelativeToStart = DatatypeConverter.parseBoolean(relativeString);
510  }
511 
512  return new Signature(signatureBytes, offset, signatureType, isRelativeToStart);
513  }
514 
523  private static String getChildElementTextContent(Element elem, String tagName) {
524  NodeList childElems = elem.getElementsByTagName(tagName);
525  Node childNode = childElems.item(0);
526  if (childNode == null) {
527  return null;
528  }
529  Element childElem = (Element) childNode;
530  return childElem.getTextContent();
531  }
532 
540  private static String getFileTypeDefinitionsFilePath(String fileName) {
541  Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName);
542  return filePath.toAbsolutePath().toString();
543  }
544 
548  static class CustomFileTypesException extends Exception {
549 
550  private static final long serialVersionUID = 1L;
551 
552  CustomFileTypesException(String message) {
553  super(message);
554  }
555 
556  CustomFileTypesException(String message, Throwable throwable) {
557  super(message, throwable);
558  }
559  }
560 
561 }

Copyright © 2012-2022 Basis Technology. Generated on: Mon Dec 5 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.