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 known bad hash database set.",
 
   54     "HashDbIngestModule.knownBadFileSearchWillNotExecuteWarn=Known bad 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 known bad 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 known bad 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()