Skip to content
Snippets Groups Projects
Commit d29f94ce authored by Mark McKinnon's avatar Mark McKinnon
Browse files

Merge remote-tracking branch 'upstream/develop' into 2452-change-ct-option-panel

parents 14def3c8 3e7e331a
No related branches found
No related tags found
No related merge requests found
......@@ -775,7 +775,11 @@ private void createAnalysisResults(IngestJobState ingestJobState, List<CTCloudBe
for (Long objId : objIds) {
AnalysisResult res = createAnalysisResult(ingestJobState, trans, result, objId);
if (res != null) {
createdArtifacts.add(res);
// only post results that have score NOTABLE or LIKELY_NOTABLE
Score score = res.getScore();
if (score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE) {
createdArtifacts.add(res);
}
}
}
}
......@@ -837,7 +841,7 @@ private AnalysisResult createAnalysisResult(IngestJobState ingestJobState, Sleut
: Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No();
String justification = cloudBean.getMalwareResult().getStatusDescription();
return ingestJobState.getTskCase().getBlackboard().newAnalysisResult(
ingestJobState.getMalwareType(),
objId,
......
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2021 Basis Technology Corp.
* Copyright 2011-2023 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
......@@ -72,6 +72,10 @@ public class Artifacts {
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST
= EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
// this is currently a custom TSK artifact type, created in MalwareScanIngestModule
private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null;
private static final String MALWARE_HITS = "TSK_MALWARE";
/**
* Base class for a parent node of artifacts.
......@@ -242,6 +246,16 @@ static class TypeFactory extends ChildFactory.Detachable<TypeNodeKey> implements
*/
@SuppressWarnings("deprecation")
private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) {
// Get the custom TSK_MALWARE artifact type from case database
if (MALWARE_ARTIFACT_TYPE == null) {
try {
MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS
}
}
int typeId = type.getTypeID();
if (TSK_EMAIL_MSG.getTypeID() == typeId) {
EmailExtracted.RootNode emailNode = new EmailExtracted(skCase, dsObjId).new RootNode();
......@@ -267,7 +281,9 @@ private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCas
} else if (TSK_HASHSET_HIT.getTypeID() == typeId) {
HashsetHits.RootNode hashsetHits = new HashsetHits(skCase, dsObjId).new RootNode();
return new TypeNodeKey(hashsetHits, TSK_HASHSET_HIT);
} else if (MALWARE_ARTIFACT_TYPE != null && MALWARE_ARTIFACT_TYPE.getTypeID() == typeId) {
MalwareHits.RootNode malwareHits = new MalwareHits(skCase, dsObjId).new RootNode();
return new TypeNodeKey(malwareHits, MALWARE_ARTIFACT_TYPE);
} else {
return new TypeNodeKey(type, dsObjId);
}
......
......@@ -60,6 +60,8 @@ public interface AutopsyItemVisitor<T> {
T visit(KeywordHits kh);
T visit(HashsetHits hh);
T visit(MalwareHits mh);
T visit(EmailExtracted ee);
......@@ -169,6 +171,11 @@ public T visit(HashsetHits hh) {
return defaultVisit(hh);
}
@Override
public T visit(MalwareHits mh) {
return defaultVisit(mh);
}
@Override
public T visit(InterestingHits ih) {
return defaultVisit(ih);
......
......@@ -111,6 +111,8 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(HashsetHits.RootNode hhrn);
T visit(HashsetHits.HashsetNameNode hhsn);
T visit(MalwareHits.RootNode mhrn);
T visit(EmailExtracted.RootNode eern);
......@@ -431,6 +433,11 @@ public T visit(HashsetHits.HashsetNameNode hhsn) {
return defaultVisit(hhsn);
}
@Override
public T visit(MalwareHits.RootNode mhrn) {
return defaultVisit(mhrn);
}
@Override
public T visit(InterestingHits.RootNode ihrn) {
return defaultVisit(ihrn);
......
/*
* Autopsy Forensic Browser
*
* Copyright 2023 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode;
import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.Score;
/**
* Malware hits node support. Inner classes have all of the nodes in the tree.
*/
public class MalwareHits implements AutopsyVisitableItem {
private static final String MALWARE_HITS = "TSK_MALWARE"; // this is currently a custom TSK artifact type, created in MalwareScanIngestModule
private static BlackboardArtifact.Type MALWARE_ARTIFACT_TYPE = null;
private static String DISPLAY_NAME;
private static final Logger logger = Logger.getLogger(MalwareHits.class.getName());
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.COMPLETED, IngestManager.IngestJobEvent.CANCELLED);
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED);
private SleuthkitCase skCase;
private final MalwareResults malwareResults;
private final long filteringDSObjId; // 0 if not filtering/grouping by data source
/**
* Constructor
*
* @param skCase Case DB
*
*/
public MalwareHits(SleuthkitCase skCase) {
this(skCase, 0);
}
/**
* Constructor
*
* @param skCase Case DB
* @param objId Object id of the data source
*
*/
public MalwareHits(SleuthkitCase skCase, long objId) {
this.skCase = skCase;
this.filteringDSObjId = objId;
malwareResults = new MalwareResults();
}
@Override
public <T> T accept(AutopsyItemVisitor<T> visitor) {
return visitor.visit(this);
}
/**
* Stores all of the malware results in a single class that is observable
* for the child nodes
*/
private class MalwareResults extends Observable implements Observer {
// list of artifacts
// NOTE: the list can be accessed by multiple worker threads and needs to be synchronized
private final Set<Long> malwareHits = new HashSet<>();
MalwareResults() {
addNotify();
update();
}
Set<Long> getArtifactIds() {
synchronized (malwareHits) {
return Collections.unmodifiableSet(malwareHits);
}
}
@SuppressWarnings("deprecation")
final void update() {
synchronized (malwareHits) {
malwareHits.clear();
}
if (skCase == null) {
return;
}
// Get the custom TSK_MALWARE artifact type from case database
if (MALWARE_ARTIFACT_TYPE == null) {
try {
MALWARE_ARTIFACT_TYPE = skCase.getArtifactType(MALWARE_HITS);
DISPLAY_NAME = MALWARE_ARTIFACT_TYPE.getDisplayName();
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Unable to get TSK_MALWARE artifact type from database : ", ex); //NON-NLS
return;
}
}
String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS
+ "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS
+ "blackboard_artifacts.artifact_type_id=" + MALWARE_ARTIFACT_TYPE.getTypeID() //NON-NLS
+ " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS
+ " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() //NON-NLS
+ " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NOTABLE.getId() + " )"; //NON-NLS
if (filteringDSObjId > 0) {
query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; //NON-NLS
}
try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
ResultSet resultSet = dbQuery.getResultSet();
synchronized (malwareHits) {
while (resultSet.next()) {
long artifactObjId = resultSet.getLong("artifact_obj_id"); //NON-NLS
malwareHits.add(artifactObjId);
}
}
} catch (TskCoreException | SQLException ex) {
logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
}
setChanged();
notifyObservers();
}
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
/**
* Checking for a current case is a stop gap measure until a
* different way of handling the closing of cases is worked
* out. Currently, remote events may be received for a case
* that is already closed.
*/
try {
Case.getCurrentCaseThrows();
/**
* Due to some unresolved issues with how cases are
* closed, it is possible for the event to have a null
* oldValue if the event is a remote event.
*/
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == MALWARE_ARTIFACT_TYPE.getTypeID()) {
malwareResults.update();
}
} catch (NoCurrentCaseException notUsed) {
/**
* Case is closed, do nothing.
*/
}
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
/**
* Checking for a current case is a stop gap measure until a
* different way of handling the closing of cases is worked
* out. Currently, remote events may be received for a case
* that is already closed.
*/
try {
Case.getCurrentCaseThrows();
malwareResults.update();
} catch (NoCurrentCaseException notUsed) {
/**
* Case is closed, do nothing.
*/
}
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
// case was closed. Remove listeners so that we don't get called with a stale case handle
if (evt.getNewValue() == null) {
removeNotify();
skCase = null;
}
}
}
};
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, weakPcl);
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakPcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
}
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(weakPcl);
IngestManager.getInstance().removeIngestModuleEventListener(weakPcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
removeNotify();
}
@Override
public void update(Observable o, Object arg) {
update();
}
}
/**
* Top-level node for all malware hits
*/
public class RootNode extends UpdatableCountTypeNode {
public RootNode() {
super(Children.create(new HitFactory(DISPLAY_NAME), true),
Lookups.singleton(DISPLAY_NAME),
DISPLAY_NAME,
filteringDSObjId,
MALWARE_ARTIFACT_TYPE);
super.setName(MALWARE_HITS);
// TODO make an icon
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/artifact-icon.png");
}
@Override
public boolean isLeafTypeNode() {
return true;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
return visitor.visit(this);
}
@Override
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
if (sheetSet == null) {
sheetSet = Sheet.createPropertiesSet();
sheet.put(sheetSet);
}
sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.desc"),
getName()));
return sheet;
}
@Override
public String getItemType() {
return getClass().getName();
}
/**
* When this method is called, the count to be displayed will be
* updated.
*/
@Override
void updateDisplayName() {
super.setDisplayName(DISPLAY_NAME + " (" + malwareResults.getArtifactIds().size() + ")");
}
}
/**
* Creates the nodes for the malware hits.
*/
private class HitFactory extends BaseChildFactory<AnalysisResult> implements Observer {
private final Map<Long, AnalysisResult> artifactHits = new HashMap<>();
private HitFactory(String nodeName) {
super(nodeName);
}
@Override
protected void onAdd() {
malwareResults.addObserver(this);
}
@Override
protected void onRemove() {
malwareResults.deleteObserver(this);
}
@Override
protected Node createNodeForKey(AnalysisResult key) {
return new BlackboardArtifactNode(key);
}
@Override
public void update(Observable o, Object arg) {
refresh(true);
}
@Override
protected List<AnalysisResult> makeKeys() {
if (skCase != null) {
malwareResults.getArtifactIds().forEach((id) -> {
try {
if (!artifactHits.containsKey(id)) {
AnalysisResult art = skCase.getBlackboard().getAnalysisResultById(id);
//Cache attributes while we are off the EDT.
//See JIRA-5969
art.getAttributes();
artifactHits.put(id, art);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS
}
});
return new ArrayList<>(artifactHits.values());
}
return Collections.emptyList();
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment