Autopsy  4.21.0
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.apache.commons.codec.DecoderException;
32 import org.apache.commons.codec.binary.Hex;
33 import org.openide.util.io.NbObjectInputStream;
34 import org.openide.util.io.NbObjectOutputStream;
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Element;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.NodeList;
42 import org.xml.sax.SAXException;
43 
48 final class CustomFileTypesManager {
49 
50  private static final String SERIALIZED_SETTINGS_FILE = "UserFileTypeDefinitions.settings"; //NON-NLS
51  private static final String XML_SETTINGS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS
52  private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS
53  private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS
54  private static final String MIME_TYPE_TAG_NAME = "MimeType"; //NON-NLS
55  private static final String SIGNATURE_TAG_NAME = "Signature"; //NON-NLS
56  private static final String SIGNATURE_TYPE_ATTRIBUTE = "type"; //NON-NLS
57  private static final String BYTES_TAG_NAME = "Bytes"; //NON-NLS
58  private static final String OFFSET_TAG_NAME = "Offset"; //NON-NLS
59  private static final String RELATIVE_ATTRIBUTE = "RelativeToStart"; //NON-NLS
60  private static CustomFileTypesManager instance;
61  private final List<FileType> autopsyDefinedFileTypes = new ArrayList<>();
62  private List<FileType> userDefinedFileTypes = new ArrayList<>();
63 
73  synchronized static CustomFileTypesManager getInstance() throws CustomFileTypesException {
74  if (null == instance) {
75  instance = new CustomFileTypesManager();
76  try {
77  instance.loadUserDefinedFileTypes();
78  instance.createAutopsyDefinedFileTypes();
79  } catch (CustomFileTypesException ex) {
80  instance = null;
81  throw ex;
82  }
83  }
84  return instance;
85  }
86 
91  private CustomFileTypesManager() {
92  }
93 
99  synchronized List<FileType> getFileTypes() {
104  List<FileType> customTypes = new ArrayList<>(userDefinedFileTypes);
105  customTypes.addAll(autopsyDefinedFileTypes);
106  return customTypes;
107  }
108 
114  synchronized List<FileType> getAutopsyDefinedFileTypes() {
119  return new ArrayList<>(autopsyDefinedFileTypes);
120  }
121 
127  synchronized List<FileType> getUserDefinedFileTypes() {
132  return new ArrayList<>(userDefinedFileTypes);
133  }
134 
143  synchronized void setUserDefinedFileTypes(List<FileType> newFileTypes) throws CustomFileTypesException {
144  String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE);
145  writeSerializedFileTypes(newFileTypes, filePath);
146  userDefinedFileTypes = newFileTypes;
147  }
148 
155  private void createAutopsyDefinedFileTypes() throws CustomFileTypesException {
156  byte[] byteArray;
157  FileType fileType;
158  try {
159  /*
160  * Add type for xml.
161  */
162  List<Signature> signatureList;
163  signatureList = new ArrayList<>();
164  signatureList.add(new Signature("<?xml", 0L)); //NON-NLS
165  fileType = new FileType("text/xml", signatureList); //NON-NLS
166  autopsyDefinedFileTypes.add(fileType);
167 
168  /*
169  * Add type for gzip.
170  */
171  byteArray = Hex.decodeHex("1F8B"); //NON-NLS
172  signatureList.clear();
173  signatureList.add(new Signature(byteArray, 0L));
174  fileType = new FileType("application/x-gzip", signatureList); //NON-NLS
175  autopsyDefinedFileTypes.add(fileType);
176 
177  /*
178  * Add type for wk1.
179  */
180  byteArray = Hex.decodeHex("0000020006040600080000000000"); //NON-NLS
181  signatureList.clear();
182  signatureList.add(new Signature(byteArray, 0L));
183  fileType = new FileType("application/x-123", signatureList); //NON-NLS
184  autopsyDefinedFileTypes.add(fileType);
185 
186  /*
187  * Add type for Radiance images.
188  */
189  byteArray = Hex.decodeHex("233F52414449414E43450A");//NON-NLS
190  signatureList.clear();
191  signatureList.add(new Signature(byteArray, 0L));
192  fileType = new FileType("image/vnd.radiance", signatureList); //NON-NLS
193  autopsyDefinedFileTypes.add(fileType);
194 
195  /*
196  * Add type for dcx images.
197  */
198  byteArray = Hex.decodeHex("B168DE3A"); //NON-NLS
199  signatureList.clear();
200  signatureList.add(new Signature(byteArray, 0L));
201  fileType = new FileType("image/x-dcx", signatureList); //NON-NLS
202  autopsyDefinedFileTypes.add(fileType);
203 
204  /*
205  * Add type for ics images.
206  */
207  signatureList.clear();
208  signatureList.add(new Signature("icns", 0L)); //NON-NLS
209  fileType = new FileType("image/x-icns", signatureList); //NON-NLS
210  autopsyDefinedFileTypes.add(fileType);
211 
212  /*
213  * Add type for pict images.
214  */
215  byteArray = Hex.decodeHex("001102FF"); //NON-NLS
216  signatureList.clear();
217  signatureList.add(new Signature(byteArray, 522L));
218  fileType = new FileType("image/x-pict", signatureList); //NON-NLS
219  autopsyDefinedFileTypes.add(fileType);
220 
221  /*
222  * NOTE: see JIRA-4269. This MIME type seems to match a lot of
223  * random file types, including ZIP archives. As a result those
224  * files get assigned this MIME type instead of having their MIME
225  * type detected by Tika. byteArray =
226  * DatatypeConverter.parseHexBinary("1100"); //NON-NLS
227  * signatureList.clear(); signatureList.add(new Signature(byteArray,
228  * 522L)); fileType = new FileType("image/x-pict", signatureList);
229  * //NON-NLS
230  autopsyDefinedFileTypes.add(fileType);
231  */
232 
233  /*
234  * Add type for pam.
235  */
236  signatureList.clear();
237  signatureList.add(new Signature("P7", 0L)); //NON-NLS
238  fileType = new FileType("image/x-portable-arbitrarymap", signatureList); //NON-NLS
239  autopsyDefinedFileTypes.add(fileType);
240 
241  /*
242  * Add type for pfm.
243  */
244  signatureList.clear();
245  signatureList.add(new Signature("PF", 0L)); //NON-NLS
246  fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS
247  autopsyDefinedFileTypes.add(fileType);
248  signatureList.clear();
249  signatureList.add(new Signature("Pf", 0L)); //NON-NLS
250  fileType = new FileType("image/x-portable-floatmap", signatureList); //NON-NLS
251  autopsyDefinedFileTypes.add(fileType);
252 
253  /*
254  * Add type for tga.
255  */
256  byteArray = Hex.decodeHex("54525545564953494F4E2D5846494C452E00"); //NON-NLS
257  signatureList.clear();
258  signatureList.add(new Signature(byteArray, 17, false));
259  fileType = new FileType("image/x-tga", signatureList); //NON-NLS
260  autopsyDefinedFileTypes.add(fileType);
261 
262  /*
263  * Add type for ilbm.
264  */
265  signatureList.clear();
266  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
267  signatureList.add(new Signature("ILBM", 8L)); //NON-NLS
268  fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS
269  autopsyDefinedFileTypes.add(fileType);
270  signatureList.clear();
271  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
272  signatureList.add(new Signature("PBM", 8L)); //NON-NLS
273  fileType = new FileType("image/x-ilbm", signatureList); //NON-NLS
274  autopsyDefinedFileTypes.add(fileType);
275 
276  /*
277  * Add type for webp.
278  */
279  signatureList.clear();
280  signatureList.add(new Signature("RIFF", 0L)); //NON-NLS
281  signatureList.add(new Signature("WEBP", 8L)); //NON-NLS
282  fileType = new FileType("image/webp", signatureList); //NON-NLS
283  autopsyDefinedFileTypes.add(fileType);
284 
285  /*
286  * Add type for aiff.
287  */
288  signatureList.clear();
289  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
290  signatureList.add(new Signature("AIFF", 8L)); //NON-NLS
291  fileType = new FileType("audio/aiff", signatureList); //NON-NLS
292  autopsyDefinedFileTypes.add(fileType);
293  signatureList.clear();
294  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
295  signatureList.add(new Signature("AIFC", 8L)); //NON-NLS
296  fileType = new FileType("audio/aiff", signatureList); //NON-NLS
297  autopsyDefinedFileTypes.add(fileType);
298  signatureList.clear();
299  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
300  signatureList.add(new Signature("8SVX", 8L)); //NON-NLS
301  fileType = new FileType("audio/aiff", signatureList); //NON-NLS
302  autopsyDefinedFileTypes.add(fileType);
303 
304  /*
305  * Add type for iff.
306  */
307  signatureList.clear();
308  signatureList.add(new Signature("FORM", 0L)); //NON-NLS
309  fileType = new FileType("application/x-iff", signatureList); //NON-NLS
310  autopsyDefinedFileTypes.add(fileType);
311 
312  /*
313  * Add type for .tec files with leading End Of Image marker (JFIF
314  * JPEG)
315  */
316  byteArray = Hex.decodeHex("FFD9FFD8"); //NON-NLS
317  signatureList.clear();
318  signatureList.add(new Signature(byteArray, 0L));
319  fileType = new FileType("image/jpeg", signatureList); //NON-NLS
320  autopsyDefinedFileTypes.add(fileType);
321 
322  /*
323  * Add type for Windows NT registry files with leading End Of Image marker (JFIF
324  * JPEG)
325  */
326  byteArray = Hex.decodeHex("72656766"); //NON-NLS
327  signatureList.clear();
328  signatureList.add(new Signature(byteArray, 0L));
329  fileType = new FileType("application/x.windows-registry", signatureList); //NON-NLS
330  autopsyDefinedFileTypes.add(fileType);
331 
332  /*
333  * Add custom file type for hdb files that can be found in android os on the system volume
334  * in the hdic folder
335  */
336  byteArray = DatatypeConverter.parseHexBinary("CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC");
337  signatureList.clear();
338  signatureList.add(new Signature(byteArray, 8L));
339  fileType = new FileType("application/x.android-hdb", signatureList);
340  autopsyDefinedFileTypes.add(fileType);
341 
345  signatureList.clear();
346  signatureList.add(new Signature("conectix", 511L, false)); //NON-NLS
347  fileType = new FileType("application/x-vhd", signatureList); //NON-NLS
348  autopsyDefinedFileTypes.add(fileType);
349 
350  } catch (DecoderException ex) {
351  /*
352  * decodeHex() throws this if an odd number of characters or illegal
353  * characters are supplied
354  */
355  throw new CustomFileTypesException("Error creating Autopsy defined custom file types", ex); //NON-NLS
356  }
357  }
358 
365  private void loadUserDefinedFileTypes() throws CustomFileTypesException {
366  userDefinedFileTypes.clear();
367  String filePath = getFileTypeDefinitionsFilePath(SERIALIZED_SETTINGS_FILE);
368  if (new File(filePath).exists()) {
369  userDefinedFileTypes = readSerializedFileTypes(filePath);
370  } else {
371  filePath = getFileTypeDefinitionsFilePath(XML_SETTINGS_FILE);
372  if (new File(filePath).exists()) {
373  userDefinedFileTypes = readFileTypesXML(filePath);
374  }
375  }
376  }
377 
387  private static void writeSerializedFileTypes(List<FileType> fileTypes, String filePath) throws CustomFileTypesException {
388  try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) {
389  UserDefinedFileTypesSettings settings = new UserDefinedFileTypesSettings(fileTypes);
390  out.writeObject(settings);
391  } catch (IOException ex) {
392  throw new CustomFileTypesException(String.format("Failed to write settings to %s", filePath), ex); //NON-NLS
393  }
394  }
395 
406  private static List<FileType> readSerializedFileTypes(String filePath) throws CustomFileTypesException {
407  File serializedDefs = new File(filePath);
408  try {
409  try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(serializedDefs))) {
410  UserDefinedFileTypesSettings filesSetsSettings = (UserDefinedFileTypesSettings) in.readObject();
411  return filesSetsSettings.getUserDefinedFileTypes();
412  }
413  } catch (IOException | ClassNotFoundException ex) {
414  throw new CustomFileTypesException(String.format("Failed to read settings from %s", filePath), ex); //NON-NLS
415  }
416  }
417 
432  private static List<FileType> readFileTypesXML(String filePath) throws CustomFileTypesException {
433  try {
434  List<FileType> fileTypes = new ArrayList<>();
435  Document doc = XMLUtil.loadDocument(filePath);
436  if (doc != null) {
437  Element fileTypesElem = doc.getDocumentElement();
438  if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) {
439  NodeList fileTypeElems = fileTypesElem.getElementsByTagName(FILE_TYPE_TAG_NAME);
440  for (int i = 0; i < fileTypeElems.getLength(); ++i) {
441  Element fileTypeElem = (Element) fileTypeElems.item(i);
442  FileType fileType = parseFileType(fileTypeElem);
443  fileTypes.add(fileType);
444  }
445  }
446  }
447  return fileTypes;
448  } catch (IOException | ParserConfigurationException | SAXException | DecoderException ex) {
449  throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS
450  }
451  }
452 
465  private static FileType parseFileType(Element fileTypeElem) throws DecoderException, NumberFormatException {
466  String mimeType = parseMimeType(fileTypeElem);
467  Signature signature = parseSignature(fileTypeElem);
468  // File type definitions in the XML file were written prior to the
469  // implementation of multiple signatures per type.
470  List<Signature> sigList = new ArrayList<>();
471  sigList.add(signature);
472  return new FileType(mimeType, sigList);
473  }
474 
482  private static String parseMimeType(Element fileTypeElem) {
483  return getChildElementTextContent(fileTypeElem, MIME_TYPE_TAG_NAME);
484  }
485 
493  private static Signature parseSignature(Element fileTypeElem) throws DecoderException, NumberFormatException {
494  NodeList signatureElems = fileTypeElem.getElementsByTagName(SIGNATURE_TAG_NAME);
495  Element signatureElem = (Element) signatureElems.item(0);
496 
497  String sigTypeAttribute = signatureElem.getAttribute(SIGNATURE_TYPE_ATTRIBUTE);
498  Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute);
499 
500  String sigBytesString = getChildElementTextContent(signatureElem, BYTES_TAG_NAME);
501  byte[] signatureBytes = Hex.decodeHex(sigBytesString);
502 
503  Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0);
504  String offsetString = offsetElem.getTextContent();
505  long offset = Long.parseLong(offsetString);
506 
507  boolean isRelativeToStart;
508  String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE);
509  if (null == relativeString || relativeString.equals("")) {
510  isRelativeToStart = true;
511  } else {
512  isRelativeToStart = Boolean.parseBoolean(relativeString);
513  }
514 
515  return new Signature(signatureBytes, offset, signatureType, isRelativeToStart);
516  }
517 
526  private static String getChildElementTextContent(Element elem, String tagName) {
527  NodeList childElems = elem.getElementsByTagName(tagName);
528  Node childNode = childElems.item(0);
529  if (childNode == null) {
530  return null;
531  }
532  Element childElem = (Element) childNode;
533  return childElem.getTextContent();
534  }
535 
543  private static String getFileTypeDefinitionsFilePath(String fileName) {
544  Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), fileName);
545  return filePath.toAbsolutePath().toString();
546  }
547 
551  static class CustomFileTypesException extends Exception {
552 
553  private static final long serialVersionUID = 1L;
554 
555  CustomFileTypesException(String message) {
556  super(message);
557  }
558 
559  CustomFileTypesException(String message, Throwable throwable) {
560  super(message, throwable);
561  }
562  }
563 
564 }

Copyright © 2012-2022 Basis Technology. Generated on: Tue Feb 6 2024
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.