Autopsy  4.21.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
MalwareHits.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2023 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  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.EnumSet;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Observable;
33 import java.util.Observer;
34 import java.util.Set;
35 import java.util.logging.Level;
36 import org.openide.nodes.Children;
37 import org.openide.nodes.Node;
38 import org.openide.nodes.Sheet;
39 import org.openide.util.NbBundle;
40 import org.openide.util.WeakListeners;
41 import org.openide.util.lookup.Lookups;
47 import org.sleuthkit.datamodel.SleuthkitCase;
48 import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
49 import org.sleuthkit.datamodel.TskCoreException;
51 import org.sleuthkit.datamodel.AnalysisResult;
52 import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE;
53 import org.sleuthkit.datamodel.Score;
54 
58 public class MalwareHits implements AutopsyVisitableItem {
59 
60  private static final Logger logger = Logger.getLogger(MalwareHits.class.getName());
63  private SleuthkitCase skCase;
65  private final long filteringDSObjId; // 0 if not filtering/grouping by data source
66 
73  public MalwareHits(SleuthkitCase skCase) {
74  this(skCase, 0);
75  }
76 
84  public MalwareHits(SleuthkitCase skCase, long objId) {
85  this.skCase = skCase;
86  this.filteringDSObjId = objId;
87  malwareResults = new MalwareResults();
88  }
89 
90  @Override
91  public <T> T accept(AutopsyItemVisitor<T> visitor) {
92  return visitor.visit(this);
93  }
94 
99  private class MalwareResults extends Observable implements Observer {
100 
101  // list of artifacts
102  // NOTE: the list can be accessed by multiple worker threads and needs to be synchronized
103  private final Set<Long> malwareHits = new HashSet<>();
104 
105  MalwareResults() {
106  addNotify();
107  update();
108  }
109 
110  Set<Long> getArtifactIds() {
111  synchronized (malwareHits) {
112  return Collections.unmodifiableSet(malwareHits);
113  }
114  }
115 
116  @SuppressWarnings("deprecation")
117  final void update() {
118  synchronized (malwareHits) {
119  malwareHits.clear();
120  }
121 
122  if (skCase == null) {
123  return;
124  }
125 
126  String query = "SELECT blackboard_artifacts.artifact_obj_id " //NON-NLS
127  + "FROM blackboard_artifacts,tsk_analysis_results WHERE " //NON-NLS
128  + "blackboard_artifacts.artifact_type_id=" + TSK_MALWARE.getTypeID() //NON-NLS
129  + " AND tsk_analysis_results.artifact_obj_id=blackboard_artifacts.artifact_obj_id" //NON-NLS
130  + " AND (tsk_analysis_results.significance=" + Score.Significance.NOTABLE.getId() //NON-NLS
131  + " OR tsk_analysis_results.significance=" + Score.Significance.LIKELY_NOTABLE.getId() + " )"; //NON-NLS
132  if (filteringDSObjId > 0) {
133  query += " AND blackboard_artifacts.data_source_obj_id = " + filteringDSObjId; //NON-NLS
134  }
135 
136  try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
137  ResultSet resultSet = dbQuery.getResultSet();
138  synchronized (malwareHits) {
139  while (resultSet.next()) {
140  long artifactObjId = resultSet.getLong("artifact_obj_id"); //NON-NLS
141  malwareHits.add(artifactObjId);
142  }
143  }
144  } catch (TskCoreException | SQLException ex) {
145  logger.log(Level.WARNING, "SQL Exception occurred: ", ex); //NON-NLS
146  }
147 
148  setChanged();
149  notifyObservers();
150  }
151 
152  private final PropertyChangeListener pcl = new PropertyChangeListener() {
153  @Override
154  public void propertyChange(PropertyChangeEvent evt) {
155  String eventType = evt.getPropertyName();
156  if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
163  try {
170  ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
171  if (null != eventData && eventData.getBlackboardArtifactType().getTypeID() == TSK_MALWARE.getTypeID()) {
172  malwareResults.update();
173  }
174  } catch (NoCurrentCaseException notUsed) {
178  }
179  } else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
180  || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
187  try {
189  malwareResults.update();
190  } catch (NoCurrentCaseException notUsed) {
194  }
195  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
196  // case was closed. Remove listeners so that we don't get called with a stale case handle
197  if (evt.getNewValue() == null) {
198  removeNotify();
199  skCase = null;
200  }
201  }
202  }
203  };
204 
205  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(pcl, null);
206 
207  protected void addNotify() {
211  }
212 
213  protected void removeNotify() {
217  }
218 
219  @Override
220  protected void finalize() throws Throwable {
221  super.finalize();
222  removeNotify();
223  }
224 
225  @Override
226  public void update(Observable o, Object arg) {
227  update();
228  }
229  }
230 
234  public class RootNode extends UpdatableCountTypeNode {
235 
236  public RootNode() {
237  super(Children.create(new HitFactory(TSK_MALWARE.getDisplayName()), true),
238  Lookups.singleton(TSK_MALWARE.getDisplayName()),
239  TSK_MALWARE.getDisplayName(),
241  TSK_MALWARE);
242 
243  super.setName(TSK_MALWARE.getTypeName());
244  // TODO make an icon
245  this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/artifact-icon.png");
246  }
247 
248  @Override
249  public boolean isLeafTypeNode() {
250  return true;
251  }
252 
253  @Override
254  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
255  return visitor.visit(this);
256  }
257 
258  @Override
259  protected Sheet createSheet() {
260  Sheet sheet = super.createSheet();
261  Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
262  if (sheetSet == null) {
263  sheetSet = Sheet.createPropertiesSet();
264  sheet.put(sheetSet);
265  }
266 
267  sheetSet.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.name"),
268  NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.displayName"),
269  NbBundle.getMessage(this.getClass(), "MalwareHits.createSheet.name.desc"),
270  getName()));
271 
272  return sheet;
273  }
274 
275  @Override
276  public String getItemType() {
277  return getClass().getName();
278  }
279 
284  @Override
285  void updateDisplayName() {
286  super.setDisplayName(TSK_MALWARE.getDisplayName() + " (" + malwareResults.getArtifactIds().size() + ")");
287  }
288  }
289 
293  private class HitFactory extends BaseChildFactory<AnalysisResult> implements Observer {
294 
295  private final Map<Long, AnalysisResult> artifactHits = new HashMap<>();
296 
297  private HitFactory(String nodeName) {
298  super(nodeName);
299  }
300 
301  @Override
302  protected void onAdd() {
303  malwareResults.addObserver(this);
304  }
305 
306  @Override
307  protected void onRemove() {
308  malwareResults.deleteObserver(this);
309  }
310 
311  @Override
312  protected Node createNodeForKey(AnalysisResult key) {
313  return new BlackboardArtifactNode(key);
314  }
315 
316  @Override
317  public void update(Observable o, Object arg) {
318  refresh(true);
319  }
320 
321  @Override
322  protected List<AnalysisResult> makeKeys() {
323  if (skCase != null) {
324 
325  malwareResults.getArtifactIds().forEach((id) -> {
326  try {
327  if (!artifactHits.containsKey(id)) {
328  AnalysisResult art = skCase.getBlackboard().getAnalysisResultById(id);
329  //Cache attributes while we are off the EDT.
330  //See JIRA-5969
331  art.getAttributes();
332  artifactHits.put(id, art);
333  }
334  } catch (TskCoreException ex) {
335  logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS
336  }
337  });
338  return new ArrayList<>(artifactHits.values());
339  }
340  return Collections.emptyList();
341  }
342  }
343 }
BlackboardArtifact.Type getBlackboardArtifactType()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
final Map< Long, AnalysisResult > artifactHits
void removeIngestJobEventListener(final PropertyChangeListener listener)
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
void addIngestJobEventListener(final PropertyChangeListener listener)
MalwareHits(SleuthkitCase skCase, long objId)
void addIngestModuleEventListener(final PropertyChangeListener listener)
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:708
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:753

Copyright © 2012-2022 Basis Technology. Generated on: Tue Feb 6 2024
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.