19 package org.sleuthkit.autopsy.modules.hashdatabase;
 
   21 import java.io.IOException;
 
   22 import java.util.ArrayList;
 
   23 import java.util.Collection;
 
   24 import java.util.Collections;
 
   25 import java.util.HashMap;
 
   26 import java.util.List;
 
   27 import java.util.concurrent.atomic.AtomicLong;
 
   28 import java.util.logging.Level;
 
   29 import org.openide.util.NbBundle;
 
   30 import org.openide.util.NbBundle.Messages;
 
   46 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   48 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   60     "HashDbIngestModule.noKnownBadHashDbSetMsg=No notable hash set.",
 
   61     "HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=Notable file search will not be executed.",
 
   62     "HashDbIngestModule.noKnownHashDbSetMsg=No known hash set.",
 
   63     "HashDbIngestModule.knownFileSearchWillNotExecuteWarn=Known file search will not be executed." 
   68     private static final int MAX_COMMENT_SIZE = 500;
 
   72     private final HashLookupModuleSettings 
settings;
 
   73     private final List<HashDb> knownBadHashSets = 
new ArrayList<>();
 
   74     private final List<HashDb> knownHashSets = 
new ArrayList<>();
 
   76     private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = 
new HashMap<>();
 
   85         private final AtomicLong totalKnownBadCount = 
new AtomicLong(0);
 
   86         private final AtomicLong totalCalctime = 
new AtomicLong(0);
 
   87         private final AtomicLong totalLookuptime = 
new AtomicLong(0);
 
   94             totalsForIngestJobs.put(ingestJobId, totals);
 
  109         this.settings = settings;
 
  115         jobId = context.getJobId();
 
  116         if (!hashDbManager.verifyAllDatabasesLoadedCorrectly()) {
 
  117             throw new IngestModuleException(
"Could not load all hash sets");
 
  124             getTotalsForIngestJobs(jobId);
 
  127             if (knownBadHashSets.isEmpty()) {
 
  130                         Bundle.HashDbIngestModule_noKnownBadHashDbSetMsg(),
 
  131                         Bundle.HashDbIngestModule_knownBadFileSearchWillNotExecuteWarn()));
 
  134             if (knownHashSets.isEmpty()) {
 
  137                         Bundle.HashDbIngestModule_noKnownHashDbSetMsg(),
 
  138                         Bundle.HashDbIngestModule_knownFileSearchWillNotExecuteWarn()));
 
  150         enabledHashSets.clear();
 
  151         for (
HashDb db : allHashSets) {
 
  152             if (settings.isHashSetEnabled(db)) {
 
  155                         enabledHashSets.add(db);
 
  157                 } 
catch (TskCoreException ex) {
 
  158                     logger.log(Level.WARNING, 
"Error getting index status for " + db.getDisplayName() + 
" hash set", ex); 
 
  166         "HashDbIngestModule.dialogTitle.errorFindingArtifacts=Error Finding Artifacts: {0}",
 
  168         "HashDbIngestModule.errorMessage.lookingForFileArtifacts=Error encountered while looking for existing artifacts for {0}." 
  175             logger.log(Level.SEVERE, 
"Exception while getting open case.", ex); 
 
  180         if ((file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
 
  181                 || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK))) {
 
  196         if ((knownHashSets.isEmpty()) && (knownBadHashSets.isEmpty()) && (!settings.shouldCalculateHashes())) {
 
  204         String name = file.getName();
 
  205         long fileId = file.getId();
 
  206         String md5Hash = file.getMd5Hash();
 
  207         if (md5Hash == null || md5Hash.isEmpty()) {
 
  210                 long calcstart = System.currentTimeMillis();
 
  211                 md5Hash = HashUtility.calculateMd5Hash(file);
 
  212                 if (file.getSize() > 0) {
 
  216                     if (file.getSize() < 1000000) {
 
  223                 file.setMd5Hash(md5Hash);
 
  224                 long delta = (System.currentTimeMillis() - calcstart);
 
  227             } 
catch (IOException ex) {
 
  228                 logger.log(Level.WARNING, String.format(
"Error calculating hash of file '%s' (id=%d).", name, fileId), ex); 
 
  231                         NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.fileReadErrorMsg", name),
 
  232                         NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.calcHashValueErr", 
 
  233                                 file.getParentPath() + file.getName(), 
 
  234                                 file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)?
"Allocated File" : 
"Deleted File")));
 
  240         boolean foundBad = 
false;
 
  242         for (
HashDb db : knownBadHashSets) {
 
  244                 long lookupstart = System.currentTimeMillis();
 
  245                 HashHitInfo hashInfo = db.lookupMD5(file);
 
  246                 if (null != hashInfo) {
 
  250                     file.setKnown(TskData.FileKnown.BAD);
 
  252                     String hashSetName = db.getDisplayName();
 
  255                     ArrayList<String> comments = hashInfo.getComments();
 
  257                     for (String c : comments) {
 
  262                         if (comment.length() > MAX_COMMENT_SIZE) {
 
  263                             comment = comment.substring(0, MAX_COMMENT_SIZE) + 
"...";
 
  272                     List<BlackboardAttribute> attributesList = 
new ArrayList<>();
 
  273                     attributesList.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, 
HashLookupModuleFactory.getModuleName(), hashSetName));
 
  275                         org.
sleuthkit.datamodel.Blackboard tskBlackboard = skCase.getBlackboard();
 
  276                         if (tskBlackboard.artifactExists(file, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT, attributesList) == 
false) {
 
  277                             postHashSetHitToBlackboard(file, md5Hash, hashSetName, comment, db.getSendIngestMessages());
 
  279                     } 
catch (TskCoreException ex) {
 
  280                         logger.log(Level.SEVERE, String.format(
 
  281                                 "A problem occurred while checking for existing artifacts for file '%s' (id=%d).", name, fileId), ex); 
 
  284                                 Bundle.HashDbIngestModule_dialogTitle_errorFindingArtifacts(name),
 
  285                                 Bundle.HashDbIngestModule_errorMessage_lookingForFileArtifacts(name)));
 
  289                 long delta = (System.currentTimeMillis() - lookupstart);
 
  292             } 
catch (TskException ex) {
 
  293                 logger.log(Level.WARNING, String.format(
 
  294                         "Couldn't lookup notable hash for file '%s' (id=%d) - see sleuthkit log for details", name, fileId), ex); 
 
  297                         NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.hashLookupErrorMsg", name),
 
  298                         NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.lookingUpKnownBadHashValueErr", name)));
 
  307             for (
HashDb db : knownHashSets) {
 
  309                     long lookupstart = System.currentTimeMillis();
 
  310                     if (db.lookupMD5Quick(file)) {
 
  311                         file.setKnown(TskData.FileKnown.KNOWN);
 
  314                     long delta = (System.currentTimeMillis() - lookupstart);
 
  317                 } 
catch (TskException ex) {
 
  318                     logger.log(Level.WARNING, String.format(
 
  319                             "Couldn't lookup known hash for file '%s' (id=%d) - see sleuthkit log for details", name, fileId), ex); 
 
  322                             NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.hashLookupErrorMsg", name),
 
  323                             NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.lookingUpKnownHashValueErr", name)));
 
  343         "HashDbIngestModule.indexError.message=Failed to index hashset hit artifact for keyword search." 
  345     private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, 
boolean showInboxMessage) {
 
  348             BlackboardArtifact badFile = abstractFile.newArtifact(ARTIFACT_TYPE.TSK_HASHSET_HIT);
 
  349             Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  352             attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, moduleName, hashSetName));
 
  353             attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_HASH_MD5, moduleName, md5Hash));
 
  354             attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, moduleName, comment));
 
  356             badFile.addAttributes(attributes);
 
  362                 logger.log(Level.SEVERE, 
"Unable to index blackboard artifact " + badFile.getArtifactID(), ex); 
 
  364                         Bundle.HashDbIngestModule_indexError_message(), badFile.getDisplayName());
 
  367             if (showInboxMessage) {
 
  368                 StringBuilder detailsSb = 
new StringBuilder();
 
  370                 detailsSb.append(
"<table border='0' cellpadding='4' width='280'>"); 
 
  372                 detailsSb.append(
"<tr>"); 
 
  373                 detailsSb.append(
"<th>") 
 
  374                         .append(NbBundle.getMessage(
this.getClass(), 
"HashDbIngestModule.postToBB.fileName"))
 
  376                 detailsSb.append(
"<td>") 
 
  377                         .append(abstractFile.getName())
 
  379                 detailsSb.append(
"</tr>"); 
 
  381                 detailsSb.append(
"<tr>"); 
 
  382                 detailsSb.append(
"<th>") 
 
  383                         .append(NbBundle.getMessage(
this.getClass(), 
"HashDbIngestModule.postToBB.md5Hash"))
 
  385                 detailsSb.append(
"<td>").append(md5Hash).append(
"</td>"); 
 
  386                 detailsSb.append(
"</tr>"); 
 
  388                 detailsSb.append(
"<tr>"); 
 
  389                 detailsSb.append(
"<th>") 
 
  390                         .append(NbBundle.getMessage(
this.getClass(), 
"HashDbIngestModule.postToBB.hashsetName"))
 
  392                 detailsSb.append(
"<td>").append(hashSetName).append(
"</td>"); 
 
  393                 detailsSb.append(
"</tr>"); 
 
  395                 detailsSb.append(
"</table>"); 
 
  398                         NbBundle.getMessage(this.getClass(), 
"HashDbIngestModule.postToBB.knownBadMsg", abstractFile.getName()),
 
  399                         detailsSb.toString(),
 
  400                         abstractFile.getName() + md5Hash,
 
  404         } 
catch (TskException ex) {
 
  405             logger.log(Level.WARNING, 
"Error creating blackboard artifact", ex); 
 
  417             List<HashDb> knownBadHashSets, List<HashDb> knownHashSets) {
 
  419         totalsForIngestJobs.remove(jobId);
 
  421         if ((!knownBadHashSets.isEmpty()) || (!knownHashSets.isEmpty())) {
 
  422             StringBuilder detailsSb = 
new StringBuilder();
 
  424             detailsSb.append(
"<table border='0' cellpadding='4' width='280'>"); 
 
  426             detailsSb.append(
"<tr><td>") 
 
  427                     .append(NbBundle.getMessage(
HashDbIngestModule.class, 
"HashDbIngestModule.complete.knownBadsFound"))
 
  429             detailsSb.append(
"<td>").append(jobTotals.
totalKnownBadCount.get()).append(
"</td></tr>"); 
 
  431             detailsSb.append(
"<tr><td>") 
 
  432                     .append(NbBundle.getMessage(
HashDbIngestModule.class, 
"HashDbIngestModule.complete.totalCalcTime"))
 
  433                     .append(
"</td><td>").append(jobTotals.
totalCalctime.get()).append(
"</td></tr>\n"); 
 
  434             detailsSb.append(
"<tr><td>") 
 
  435                     .append(NbBundle.getMessage(
HashDbIngestModule.class, 
"HashDbIngestModule.complete.totalLookupTime"))
 
  436                     .append(
"</td><td>").append(jobTotals.
totalLookuptime.get()).append(
"</td></tr>\n"); 
 
  437             detailsSb.append(
"</table>"); 
 
  439             detailsSb.append(
"<p>") 
 
  440                     .append(NbBundle.getMessage(
HashDbIngestModule.class, 
"HashDbIngestModule.complete.databasesUsed"))
 
  441                     .append(
"</p>\n<ul>"); 
 
  442             for (
HashDb db : knownBadHashSets) {
 
  443                 detailsSb.append(
"<li>").append(db.getHashSetName()).append(
"</li>\n"); 
 
  446             detailsSb.append(
"</ul>"); 
 
  451                     NbBundle.getMessage(
HashDbIngestModule.class, 
"HashDbIngestModule.complete.hashLookupResults"),
 
  452                     detailsSb.toString()));
 
  459             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)
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)
final AtomicLong totalLookuptime
final AtomicLong totalCalctime
void updateEnabledHashSets(List< HashDb > allHashSets, List< HashDb > enabledHashSets)
static TimingMetric getTimingMetric(String name)
void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, boolean showInboxMessage)
final SleuthkitCase skCase
synchronized List< HashDb > getKnownBadFileHashSets()
static synchronized HashDbManager getInstance()
final AtomicLong totalKnownBadCount
void postMessage(final IngestMessage message)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
SleuthkitCase getSleuthkitCase()
static void submitTimingMetric(TimingMetric metric)
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)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static IngestMessage createWarningMessage(String source, String subject, String detailsHtml)
static void submitNormalizedTimingMetric(TimingMetric metric, long normalization)
synchronized List< HashDb > getKnownFileHashSets()
static synchronized IngestServices getInstance()