Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.datamodel;
20
21import java.beans.PropertyChangeEvent;
22import java.beans.PropertyChangeListener;
23import java.sql.ResultSet;
24import java.sql.SQLException;
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.EnumSet;
28import java.util.HashMap;
29import java.util.HashSet;
30import java.util.List;
31import java.util.Map;
32import java.util.Observable;
33import java.util.Observer;
34import java.util.Set;
35import java.util.logging.Level;
36import org.openide.nodes.Children;
37import org.openide.nodes.Node;
38import org.openide.nodes.Sheet;
39import org.openide.util.NbBundle;
40import org.openide.util.WeakListeners;
41import org.openide.util.lookup.Lookups;
42import org.sleuthkit.autopsy.casemodule.Case;
43import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
44import org.sleuthkit.autopsy.coreutils.Logger;
45import org.sleuthkit.autopsy.ingest.IngestManager;
46import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
47import org.sleuthkit.datamodel.SleuthkitCase;
48import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
49import org.sleuthkit.datamodel.TskCoreException;
50import org.sleuthkit.autopsy.datamodel.Artifacts.UpdatableCountTypeNode;
51import org.sleuthkit.datamodel.AnalysisResult;
52import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_MALWARE;
53import org.sleuthkit.datamodel.Score;
54
58public 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;
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
212
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}
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:757
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition Case.java:712
synchronized static Logger getLogger(String name)
Definition Logger.java:124
UpdatableCountTypeNode(Children children, Lookup lookup, String baseName, long filteringDSObjId, BlackboardArtifact.Type... types)
static final Set< IngestManager.IngestJobEvent > INGEST_JOB_EVENTS_OF_INTEREST
static final Set< IngestManager.IngestModuleEvent > INGEST_MODULE_EVENTS_OF_INTEREST
MalwareHits(SleuthkitCase skCase, long objId)
static synchronized IngestManager getInstance()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestModuleEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.