Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
FileExtMismatchIngestModule.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2012-2021 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 */
19package org.sleuthkit.autopsy.modules.fileextmismatch;
20
21import java.text.MessageFormat;
22import java.util.Collections;
23import java.util.HashMap;
24import java.util.Set;
25import java.util.logging.Level;
26import org.openide.util.NbBundle;
27import org.openide.util.NbBundle.Messages;
28import org.sleuthkit.autopsy.casemodule.Case;
29import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
30import org.sleuthkit.autopsy.coreutils.Logger;
31import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
32import org.sleuthkit.autopsy.ingest.FileIngestModule;
33import org.sleuthkit.autopsy.ingest.IngestJobContext;
34import org.sleuthkit.autopsy.ingest.IngestMessage;
35import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
36import org.sleuthkit.autopsy.ingest.IngestServices;
37import org.sleuthkit.autopsy.modules.fileextmismatch.FileExtMismatchDetectorModuleSettings.CHECK_TYPE;
38import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
39import org.sleuthkit.datamodel.AbstractFile;
40import org.sleuthkit.datamodel.Blackboard;
41import org.sleuthkit.datamodel.BlackboardArtifact;
42import org.sleuthkit.datamodel.Score;
43import org.sleuthkit.datamodel.TskData;
44import org.sleuthkit.datamodel.TskData.FileKnown;
45import org.sleuthkit.datamodel.TskException;
46
50@NbBundle.Messages({
51 "CannotRunFileTypeDetection=Unable to run file type detection.",
52 "FileExtMismatchIngestModule.readError.message=Could not read settings."
53})
54public class FileExtMismatchIngestModule implements FileIngestModule {
55
56 private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName());
58 private final FileExtMismatchDetectorModuleSettings settings;
59 private HashMap<String, Set<String>> mimeTypeToExtsMap = new HashMap<>();
60 private long jobId;
61 private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();
63 private static Blackboard blackboard;
65
66 private static class IngestJobTotals {
67
68 private long processTime = 0;
69 private long numFiles = 0;
70 }
71
78 private static synchronized void addToTotals(long ingestJobId, long processTimeInc) {
79 IngestJobTotals ingestJobTotals = totalsForIngestJobs.get(ingestJobId);
80 if (ingestJobTotals == null) {
81 ingestJobTotals = new IngestJobTotals();
82 totalsForIngestJobs.put(ingestJobId, ingestJobTotals);
83 }
84
85 ingestJobTotals.processTime += processTimeInc;
86 ingestJobTotals.numFiles++;
87 totalsForIngestJobs.put(ingestJobId, ingestJobTotals);
88 }
89
90 FileExtMismatchIngestModule(FileExtMismatchDetectorModuleSettings settings) {
91 this.settings = settings;
92 }
93
94 @Override
95 public void startUp(IngestJobContext context) throws IngestModuleException {
96 jobId = context.getJobId();
97 refCounter.incrementAndGet(jobId);
98
99 try {
100 mimeTypeToExtsMap = FileExtMismatchSettings.readSettings().getMimeTypeToExtsMap();
101 this.detector = new FileTypeDetector();
102 } catch (FileExtMismatchSettings.FileExtMismatchSettingsException ex) {
103 throw new IngestModuleException(Bundle.FileExtMismatchIngestModule_readError_message(), ex);
105 throw new IngestModuleException(Bundle.CannotRunFileTypeDetection(), ex);
106 }
107 }
108
109 @Override
110 @Messages({"FileExtMismatchIngestModule.indexError.message=Failed to index file extension mismatch artifact for keyword search."})
111 public ProcessResult process(AbstractFile abstractFile) {
112 try {
114 } catch (NoCurrentCaseException ex) {
115 logger.log(Level.WARNING, "Exception while getting open case.", ex); //NON-NLS
116 return ProcessResult.ERROR;
117 }
118 if (this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) {
119 return ProcessResult.OK;
120 }
121
122 // skip non-files
123 if ((abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
124 || (abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
125 || (abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
126 || (abstractFile.isFile() == false)) {
127 return ProcessResult.OK;
128 }
129
130 // deleted files often have content that was not theirs and therefor causes mismatch
131 if ((abstractFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC))
132 || (abstractFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC))) {
133 return ProcessResult.OK;
134 }
135
136 try {
137 long startTime = System.currentTimeMillis();
138
139 boolean mismatchDetected = compareSigTypeToExt(abstractFile);
140
141 addToTotals(jobId, System.currentTimeMillis() - startTime);
142
143 if (mismatchDetected) {
144 String justification = MessageFormat.format("File has MIME type of {0}", detector.getMIMEType(abstractFile));
145
146 // add artifact
147 BlackboardArtifact bart = abstractFile.newAnalysisResult(
148 BlackboardArtifact.Type.TSK_EXT_MISMATCH_DETECTED, Score.SCORE_LIKELY_NOTABLE,
149 null, null, justification, Collections.emptyList())
150 .getAnalysisResult();
151
152 try {
153 /*
154 * post the artifact which will index the artifact for
155 * keyword search, and fire an event to notify UI of this
156 * new artifact
157 */
158 blackboard.postArtifact(bart, FileExtMismatchDetectorModuleFactory.getModuleName(), jobId);
159 } catch (Blackboard.BlackboardException ex) {
160 logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bart.getArtifactID(), ex); //NON-NLS
161 MessageNotifyUtil.Notify.error(FileExtMismatchDetectorModuleFactory.getModuleName(), Bundle.FileExtMismatchIngestModule_indexError_message());
162 }
163
164 }
165 return ProcessResult.OK;
166 } catch (TskException ex) {
167 logger.log(Level.WARNING, "Error matching file signature", ex); //NON-NLS
168 return ProcessResult.ERROR;
169 }
170 }
171
179 private boolean compareSigTypeToExt(AbstractFile abstractFile) {
180 String currActualExt = abstractFile.getNameExtension();
181
182 // If we are skipping names with no extension
183 if (settings.skipFilesWithNoExtension() && currActualExt.isEmpty()) {
184 return false;
185 }
186 String currActualSigType = detector.getMIMEType(abstractFile);
187 if (settings.getCheckType() != CHECK_TYPE.ALL) {
188 if (settings.getCheckType() == CHECK_TYPE.NO_TEXT_FILES) {
189 if (!currActualExt.isEmpty() && currActualSigType.equals("text/plain")) { //NON-NLS
190 return false;
191 }
192 }
193 if (settings.getCheckType() == CHECK_TYPE.ONLY_MEDIA_AND_EXE) {
194 if (!FileExtMismatchDetectorModuleSettings.MEDIA_AND_EXE_MIME_TYPES.contains(currActualSigType)) {
195 return false;
196 }
197 }
198 }
199
200 //get known allowed values from the map for this type
201 Set<String> allowedExtSet = mimeTypeToExtsMap.get(currActualSigType);
202 if (allowedExtSet != null) {
203 // see if the filename ext is in the allowed list
204 for (String e : allowedExtSet) {
205 if (e.equals(currActualExt)) {
206 return false;
207 }
208 }
209 return true; //potential mismatch
210 }
211
212 return false;
213 }
214
215 @Override
216 public void shutDown() {
217 // We only need to post the summary msg from the last module per job
218 if (refCounter.decrementAndGet(jobId) == 0) {
219 IngestJobTotals jobTotals;
220 synchronized (this) {
221 jobTotals = totalsForIngestJobs.remove(jobId);
222 }
223 if (jobTotals != null) {
224 StringBuilder detailsSb = new StringBuilder();
225 detailsSb.append("<table border='0' cellpadding='4' width='280'>"); //NON-NLS
226 detailsSb.append("<tr><td>").append(FileExtMismatchDetectorModuleFactory.getModuleName()).append("</td></tr>"); //NON-NLS
227 detailsSb.append("<tr><td>").append( //NON-NLS
228 NbBundle.getMessage(this.getClass(), "FileExtMismatchIngestModule.complete.totalProcTime"))
229 .append("</td><td>").append(jobTotals.processTime).append("</td></tr>\n"); //NON-NLS
230 detailsSb.append("<tr><td>").append( //NON-NLS
231 NbBundle.getMessage(this.getClass(), "FileExtMismatchIngestModule.complete.totalFiles"))
232 .append("</td><td>").append(jobTotals.numFiles).append("</td></tr>\n"); //NON-NLS
233 detailsSb.append("</table>"); //NON-NLS
234
236 NbBundle.getMessage(this.getClass(),
237 "FileExtMismatchIngestModule.complete.svcMsg.text"),
238 detailsSb.toString()));
239 }
240 }
241 }
242}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
static synchronized IngestServices getInstance()
static synchronized void addToTotals(long ingestJobId, long processTimeInc)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.