19 package org.sleuthkit.autopsy.modules.hashdatabase;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.concurrent.atomic.AtomicLong;
27 import java.util.logging.Level;
28 import org.openide.util.NbBundle;
29 import org.openide.util.NbBundle.Messages;
42 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
44 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
53 "HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash database set.",
54 "HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=Notable file search will not be executed.",
55 "HashDbIngestModule.noKnownHashDbSetMsg=No known hash database set.",
56 "HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed."
61 private static final int MAX_COMMENT_SIZE = 500;
65 private final HashLookupModuleSettings
settings;
66 private List<HashDb> knownBadHashSets =
new ArrayList<>();
67 private List<HashDb> knownHashSets =
new ArrayList<>();
69 private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs =
new HashMap<>();
75 private AtomicLong totalKnownBadCount =
new AtomicLong(0);
76 private AtomicLong totalCalctime =
new AtomicLong(0);
77 private AtomicLong totalLookuptime =
new AtomicLong(0);
84 totalsForIngestJobs.put(ingestJobId, totals);
90 this.settings = settings;
95 jobId = context.getJobId();
96 if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) {
97 throw new IngestModuleException(
"Could not load all hash databases");
104 getTotalsForIngestJobs(jobId);
107 if (knownBadHashSets.isEmpty()) {
110 Bundle.HashDbIngestModule_noKnownBadHashDbSetMsg(),
111 Bundle.HashDbIngestModule_knownBadFileSearchWillNotExecuteWarn()));
114 if (knownHashSets.isEmpty()) {
117 Bundle.HashDbIngestModule_noKnownHashDbSetMsg(),
118 Bundle.HashDbIngestModule_knownFileSearchWillNotExecuteWarn()));
130 enabledHashSets.clear();
131 for (
HashDb db : allHashSets) {
132 if (settings.isHashSetEnabled(db.getHashSetName())) {
135 enabledHashSets.add(db);
137 }
catch (TskCoreException ex) {
138 logger.log(Level.WARNING,
"Error getting index status for " + db.getHashSetName() +
" hash database", ex);
149 if ((file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) ||
150 file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) {
165 if ((knownHashSets.isEmpty()) && (knownBadHashSets.isEmpty()) && (!settings.shouldCalculateHashes())) {
173 String name = file.getName();
174 String md5Hash = file.getMd5Hash();
175 if (md5Hash == null || md5Hash.isEmpty()) {
177 long calcstart = System.currentTimeMillis();
178 md5Hash = HashUtility.calculateMd5(file);
179 long delta = (System.currentTimeMillis() - calcstart);
182 }
catch (IOException ex) {
183 logger.log(Level.WARNING,
"Error calculating hash of file " + name, ex);
186 NbBundle.getMessage(this.getClass(),
187 "HashDbIngestModule.fileReadErrorMsg",
189 NbBundle.getMessage(this.getClass(),
190 "HashDbIngestModule.calcHashValueErr",
197 boolean foundBad =
false;
199 for (
HashDb db : knownBadHashSets) {
201 long lookupstart = System.currentTimeMillis();
202 HashHitInfo hashInfo = db.lookupMD5(file);
203 if (null != hashInfo) {
208 skCase.setKnown(file, TskData.FileKnown.BAD);
209 }
catch (TskException ex) {
210 logger.log(Level.WARNING,
"Couldn't set notable state for file " + name +
" - see sleuthkit log for details", ex);
213 NbBundle.getMessage(this.getClass(),
214 "HashDbIngestModule.hashLookupErrorMsg",
216 NbBundle.getMessage(this.getClass(),
217 "HashDbIngestModule.settingKnownBadStateErr",
221 String hashSetName = db.getHashSetName();
224 ArrayList<String> comments = hashInfo.getComments();
226 for (String c : comments) {
231 if (comment.length() > MAX_COMMENT_SIZE) {
232 comment = comment.substring(0, MAX_COMMENT_SIZE) +
"...";
237 postHashSetHitToBlackboard(file, md5Hash, hashSetName, comment, db.getSendIngestMessages());
239 long delta = (System.currentTimeMillis() - lookupstart);
242 }
catch (TskException ex) {
243 logger.log(Level.WARNING,
"Couldn't lookup notable hash for file " + name +
" - see sleuthkit log for details", ex);
246 NbBundle.getMessage(this.getClass(),
247 "HashDbIngestModule.hashLookupErrorMsg",
249 NbBundle.getMessage(this.getClass(),
250 "HashDbIngestModule.lookingUpKnownBadHashValueErr",
260 for (
HashDb db : knownHashSets) {
262 long lookupstart = System.currentTimeMillis();
263 if (db.lookupMD5Quick(file)) {
265 skCase.setKnown(file, TskData.FileKnown.KNOWN);
267 }
catch (TskException ex) {
268 logger.log(Level.WARNING,
"Couldn't set known state for file " + name +
" - see sleuthkit log for details", ex);
272 long delta = (System.currentTimeMillis() - lookupstart);
275 }
catch (TskException ex) {
276 logger.log(Level.WARNING,
"Couldn't lookup known hash for file " + name +
" - see sleuthkit log for details", ex);
279 NbBundle.getMessage(this.getClass(),
280 "HashDbIngestModule.hashLookupErrorMsg",
282 NbBundle.getMessage(this.getClass(),
283 "HashDbIngestModule.lookingUpKnownHashValueErr",
293 @Messages({
"HashDbIngestModule.indexError.message=Failed to index hashset hit artifact for keyword search."})
294 private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment,
boolean showInboxMessage) {
296 String MODULE_NAME = NbBundle.getMessage(
HashDbIngestModule.class,
"HashDbIngestModule.moduleName");
298 BlackboardArtifact badFile = abstractFile.newArtifact(ARTIFACT_TYPE.TSK_HASHSET_HIT);
301 BlackboardAttribute att2 =
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, hashSetName);
302 badFile.addAttribute(att2);
303 BlackboardAttribute att3 =
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_HASH_MD5, MODULE_NAME, md5Hash);
304 badFile.addAttribute(att3);
305 BlackboardAttribute att4 =
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, comment);
306 badFile.addAttribute(att4);
312 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + badFile.getArtifactID(), ex);
314 Bundle.HashDbIngestModule_indexError_message(), badFile.getDisplayName());
317 if (showInboxMessage) {
318 StringBuilder detailsSb =
new StringBuilder();
320 detailsSb.append(
"<table border='0' cellpadding='4' width='280'>");
322 detailsSb.append(
"<tr>");
323 detailsSb.append(
"<th>")
324 .append(NbBundle.getMessage(
this.getClass(),
"HashDbIngestModule.postToBB.fileName"))
326 detailsSb.append(
"<td>")
327 .append(abstractFile.getName())
329 detailsSb.append(
"</tr>");
331 detailsSb.append(
"<tr>");
332 detailsSb.append(
"<th>")
333 .append(NbBundle.getMessage(
this.getClass(),
"HashDbIngestModule.postToBB.md5Hash"))
335 detailsSb.append(
"<td>").append(md5Hash).append(
"</td>");
336 detailsSb.append(
"</tr>");
338 detailsSb.append(
"<tr>");
339 detailsSb.append(
"<th>")
340 .append(NbBundle.getMessage(
this.getClass(),
"HashDbIngestModule.postToBB.hashsetName"))
342 detailsSb.append(
"<td>").append(hashSetName).append(
"</td>");
343 detailsSb.append(
"</tr>");
345 detailsSb.append(
"</table>");
348 NbBundle.getMessage(this.getClass(),
349 "HashDbIngestModule.postToBB.knownBadMsg",
350 abstractFile.getName()),
351 detailsSb.toString(),
352 abstractFile.getName() + md5Hash,
356 }
catch (TskException ex) {
357 logger.log(Level.WARNING,
"Error creating blackboard artifact", ex);
362 List<HashDb> knownBadHashSets, List<HashDb> knownHashSets) {
364 totalsForIngestJobs.remove(jobId);
366 if ((!knownBadHashSets.isEmpty()) || (!knownHashSets.isEmpty())) {
367 StringBuilder detailsSb =
new StringBuilder();
369 detailsSb.append(
"<table border='0' cellpadding='4' width='280'>");
371 detailsSb.append(
"<tr><td>")
372 .append(NbBundle.getMessage(
HashDbIngestModule.class,
"HashDbIngestModule.complete.knownBadsFound"))
374 detailsSb.append(
"<td>").append(jobTotals.
totalKnownBadCount.get()).append(
"</td></tr>");
376 detailsSb.append(
"<tr><td>")
377 .append(NbBundle.getMessage(
HashDbIngestModule.class,
"HashDbIngestModule.complete.totalCalcTime"))
378 .append(
"</td><td>").append(jobTotals.
totalCalctime.get()).append(
"</td></tr>\n");
379 detailsSb.append(
"<tr><td>")
380 .append(NbBundle.getMessage(
HashDbIngestModule.class,
"HashDbIngestModule.complete.totalLookupTime"))
381 .append(
"</td><td>").append(jobTotals.
totalLookuptime.get()).append(
"</td></tr>\n");
382 detailsSb.append(
"</table>");
384 detailsSb.append(
"<p>")
385 .append(NbBundle.getMessage(
HashDbIngestModule.class,
"HashDbIngestModule.complete.databasesUsed"))
386 .append(
"</p>\n<ul>");
387 for (
HashDb db : knownBadHashSets) {
388 detailsSb.append(
"<li>").append(db.getHashSetName()).append(
"</li>\n");
391 detailsSb.append(
"</ul>");
397 "HashDbIngestModule.complete.hashLookupResults"),
398 detailsSb.toString()));
405 postSummary(jobId, knownBadHashSets, knownHashSets);
synchronized long decrementAndGet(long jobId)
ProcessResult process(AbstractFile file)
static IngestMessage createDataMessage(String source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data)
final HashLookupModuleSettings settings
static IngestMessage createErrorMessage(String source, String subject, String detailsHtml)
AtomicLong totalKnownBadCount
AtomicLong totalLookuptime
void startUp(org.sleuthkit.autopsy.ingest.IngestJobContext context)
synchronized long incrementAndGet(long jobId)
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
static synchronized IngestJobTotals getTotalsForIngestJobs(long ingestJobId)
void updateEnabledHashSets(List< HashDb > allHashSets, List< HashDb > enabledHashSets)
void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, boolean showInboxMessage)
synchronized List< HashDb > getKnownBadFileHashSets()
static synchronized HashDbManager getInstance()
void postMessage(final IngestMessage message)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
SleuthkitCase getSleuthkitCase()
Blackboard getBlackboard()
static synchronized void postSummary(long jobId, List< HashDb > knownBadHashSets, List< HashDb > knownHashSets)
static void error(String title, String message)
synchronized void indexArtifact(BlackboardArtifact artifact)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static IngestMessage createWarningMessage(String source, String subject, String detailsHtml)
synchronized List< HashDb > getKnownFileHashSets()
static synchronized IngestServices getInstance()