19 package org.sleuthkit.autopsy.modules.stix;
22 import java.io.IOException;
23 import java.util.HashMap;
25 import java.util.List;
26 import java.util.logging.Level;
27 import java.io.BufferedWriter;
28 import java.io.FileWriter;
29 import java.util.Arrays;
30 import javax.swing.JPanel;
31 import javax.xml.bind.JAXBContext;
32 import javax.xml.bind.JAXBException;
33 import javax.xml.bind.Unmarshaller;
34 import javax.xml.namespace.QName;
36 import org.mitre.cybox.cybox_2.ObjectType;
37 import org.mitre.cybox.cybox_2.Observable;
38 import org.mitre.cybox.cybox_2.ObservableCompositionType;
39 import org.mitre.stix.common_1.IndicatorBaseType;
40 import org.mitre.stix.indicator_2.Indicator;
41 import org.mitre.stix.stix_1.STIXPackage;
45 import org.openide.util.NbBundle;
49 import org.mitre.cybox.cybox_2.OperatorTypeEnum;
50 import org.mitre.cybox.objects.Address;
51 import org.mitre.cybox.objects.FileObjectType;
52 import org.mitre.cybox.objects.URIObjectType;
53 import org.mitre.cybox.objects.EmailMessage;
54 import org.mitre.cybox.objects.WindowsNetworkShare;
55 import org.mitre.cybox.objects.AccountObjectType;
56 import org.mitre.cybox.objects.SystemObjectType;
57 import org.mitre.cybox.objects.URLHistory;
58 import org.mitre.cybox.objects.DomainName;
59 import org.mitre.cybox.objects.WindowsRegistryKey;
75 private Map<String, ObjectType>
idToObjectMap =
new HashMap<String, ObjectType>();
76 private Map<String, ObservableResult>
idToResult =
new HashMap<String, ObservableResult>();
82 private BufferedWriter
output = null;
90 if (instance == null) {
106 progressPanel.
start();
107 progressPanel.
updateStatusLabel(NbBundle.getMessage(
this.getClass(),
"STIXReportModule.progress.readSTIX"));
115 File file =
new File(reportPath);
116 output =
new BufferedWriter(
new FileWriter(file));
117 }
catch (IOException ex) {
118 logger.log(Level.SEVERE, String.format(
"Unable to open STIX report file %s", reportPath), ex);
120 NbBundle.getMessage(
this.getClass(),
121 "STIXReportModule.notifyMsg.unableToOpenReportFile",
126 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.progress.completedWithErrors"));
131 boolean hadErrors =
false;
135 if (stixFileName == null) {
136 logger.log(Level.SEVERE,
"STIXReportModuleConfigPanel.stixFile not initialized ");
138 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.notifyErr.noFildDirProvided"));
141 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.progress.noFildDirProvided"));
144 if (stixFileName.isEmpty()) {
145 logger.log(Level.SEVERE,
"No STIX file/directory provided ");
147 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.notifyErr.noFildDirProvided"));
150 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.progress.noFildDirProvided"));
153 File stixFile =
new File(stixFileName);
155 if (!stixFile.exists()) {
156 logger.log(Level.SEVERE, String.format(
"Unable to open STIX file/directory %s", stixFileName));
158 "STIXReportModule.notifyMsg.unableToOpenFileDir",
162 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
171 if (stixFile.isFile()) {
172 stixFiles =
new File[1];
173 stixFiles[0] = stixFile;
175 stixFiles = stixFile.listFiles();
182 for (File file : stixFiles) {
184 processFile(file.getAbsolutePath(), progressPanel);
186 logger.log(Level.SEVERE, String.format(
"Unable to process STIX file %s", file), ex);
188 ex.getLocalizedMessage(),
194 idToObjectMap =
new HashMap<String, ObjectType>();
195 idToResult =
new HashMap<String, ObservableResult>();
199 if (output != null) {
202 }
catch (IOException ex) {
203 logger.log(Level.SEVERE, String.format(
"Error closing STIX report file %s", reportPath), ex);
212 NbBundle.getMessage(
this.getClass(),
"STIXReportModule.progress.completedWithErrors"));
236 progressPanel.increment();
243 progressPanel.increment();
257 File file =
new File(stixFileName);
258 JAXBContext jaxbContext = JAXBContext.newInstance(
"org.mitre.stix.stix_1:org.mitre.stix.common_1:org.mitre.stix.indicator_2:"
259 +
"org.mitre.cybox.objects:org.mitre.cybox.cybox_2:org.mitre.cybox.common_2");
260 Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
261 STIXPackage stix = (STIXPackage) jaxbUnmarshaller.unmarshal(file);
263 }
catch (JAXBException ex) {
264 logger.log(Level.SEVERE, String.format(
"Unable to load STIX file %s", stixFileName), ex.getLocalizedMessage());
265 throw new TskCoreException(
"Error loading STIX file (" + ex.toString() +
")");
276 if (stix.getObservables() != null) {
277 List<Observable> obs = stix.getObservables().getObservables();
278 for (Observable o : obs) {
279 if (o.getId() != null) {
293 if (stix.getIndicators() != null) {
294 List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
295 for (IndicatorBaseType t : s) {
296 if (t instanceof Indicator) {
297 Indicator ind = (Indicator) t;
298 if (ind.getObservable() != null) {
299 if (ind.getObservable().getObject() != null) {
304 if (result.isTrue()) {
307 }
else if (ind.getObservable().getObservableComposition() != null) {
313 if (result.isTrue()) {
332 if (result.getArtifacts() == null) {
339 for (StixArtifactData s : result.getArtifacts()) {
344 if (ind.getTitle() != null) {
345 s.createArtifact(ind.getTitle());
346 }
else if (ind.getId() != null) {
347 s.createArtifact(ind.getId().toString());
349 s.createArtifact(
"Unnamed indicator(s)");
357 NbBundle.getMessage(
this.getClass(),
358 "STIXReportModule.notifyMsg.tooManyArtifactsgt1000",
375 if (output != null) {
378 output.write(
"----------------\r\n"
379 +
"Found indicator:\r\n");
381 output.write(
"-----------------------\r\n"
382 +
"Did not find indicator:\r\n");
384 if (ind.getTitle() != null) {
385 output.write(
"Title: " + ind.getTitle() +
"\r\n");
387 output.write(
"\r\n");
389 if (ind.getId() != null) {
390 output.write(
"ID: " + ind.getId() +
"\r\n");
393 if (ind.getDescription() != null) {
394 String desc = ind.getDescription().getValue();
396 output.write(
"Description: " + desc +
"\r\n");
398 output.write(
"\r\nObservable results:\r\n" + resultStr +
"\r\n\r\n");
399 }
catch (IOException ex) {
400 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex);
411 if (output != null) {
413 char[] chars =
new char[a_fileName.length() + 8];
414 Arrays.fill(chars,
'#');
415 String header =
new String(chars);
416 output.write(
"\r\n" + header);
417 output.write(
"\r\n");
418 output.write(
"### " + a_fileName +
" ###\r\n");
419 output.write(header +
"\r\n\r\n");
420 }
catch (IOException ex) {
421 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex);
436 if (obs.getId() != null) {
438 }
else if (obs.getIdref() != null) {
439 idQ = obs.getIdref();
444 return idQ.getLocalPart();
454 if (obs.getObject() != null) {
455 idToObjectMap.put(
makeMapKey(obs), obs.getObject());
468 if (comp.getOperator() == null) {
472 if (comp.getObservables() != null) {
473 List<Observable> obsList = comp.getObservables();
476 if (comp.getOperator() == OperatorTypeEnum.AND) {
477 ObservableResult result =
new ObservableResult(OperatorTypeEnum.AND, spacing);
478 for (Observable o : obsList) {
480 ObservableResult newResult;
481 if (o.getObservableComposition() != null) {
483 if (result == null) {
486 result.addResult(newResult, OperatorTypeEnum.AND);
490 if (result == null) {
493 result.addResult(newResult, OperatorTypeEnum.AND);
497 if ((!skipShortCircuit) && !result.isFalse()) {
503 if (result == null) {
506 return new ObservableResult(
"",
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
512 ObservableResult result =
new ObservableResult(OperatorTypeEnum.OR, spacing);
513 for (Observable o : obsList) {
515 ObservableResult newResult;
517 if (o.getObservableComposition() != null) {
519 if (result == null) {
522 result.addResult(newResult, OperatorTypeEnum.OR);
526 if (result == null) {
529 result.addResult(newResult, OperatorTypeEnum.OR);
533 if ((!skipShortCircuit) && result.isTrue()) {
539 if (result == null) {
542 return new ObservableResult(
"",
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
564 if (idToResult.containsKey(
makeMapKey(obs))) {
568 if (obs.getIdref() == null) {
572 if (obs.getId() != null) {
576 if (obs.getObject() != null) {
584 if (idToObjectMap.containsKey(
makeMapKey(obs))) {
590 throw new TskCoreException(
"Error loading/finding object for observable " + obs.getIdref());
601 private ObservableResult
evaluateObject(ObjectType obj, String spacing, String
id) {
603 EvaluatableObject evalObj;
605 if (obj.getProperties() instanceof FileObjectType) {
606 evalObj =
new EvalFileObj((FileObjectType) obj.getProperties(), id, spacing);
607 }
else if (obj.getProperties() instanceof Address) {
608 evalObj =
new EvalAddressObj((Address) obj.getProperties(), id, spacing);
609 }
else if (obj.getProperties() instanceof URIObjectType) {
610 evalObj =
new EvalURIObj((URIObjectType) obj.getProperties(), id, spacing);
611 }
else if (obj.getProperties() instanceof EmailMessage) {
612 evalObj =
new EvalEmailObj((EmailMessage) obj.getProperties(), id, spacing);
613 }
else if (obj.getProperties() instanceof WindowsNetworkShare) {
614 evalObj =
new EvalNetworkShareObj((WindowsNetworkShare) obj.getProperties(), id, spacing);
615 }
else if (obj.getProperties() instanceof AccountObjectType) {
616 evalObj =
new EvalAccountObj((AccountObjectType) obj.getProperties(), id, spacing);
617 }
else if (obj.getProperties() instanceof SystemObjectType) {
618 evalObj =
new EvalSystemObj((SystemObjectType) obj.getProperties(), id, spacing);
619 }
else if (obj.getProperties() instanceof URLHistory) {
620 evalObj =
new EvalURLHistoryObj((URLHistory) obj.getProperties(), id, spacing);
621 }
else if (obj.getProperties() instanceof DomainName) {
622 evalObj =
new EvalDomainObj((DomainName) obj.getProperties(), id, spacing);
623 }
else if (obj.getProperties() instanceof WindowsRegistryKey) {
624 evalObj =
new EvalRegistryObj((WindowsRegistryKey) obj.getProperties(), id, spacing,
registryFileData);
627 String type = obj.getProperties().toString();
628 type = type.substring(0, type.indexOf(
"@"));
629 if ((type.lastIndexOf(
".") + 1) < type.length()) {
630 type = type.substring(type.lastIndexOf(
".") + 1);
632 return new ObservableResult(
id, type +
" not supported",
633 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
637 return evalObj.evaluate();
642 String name = NbBundle.getMessage(this.getClass(),
"STIXReportModule.getName.text");
653 String desc = NbBundle.getMessage(this.getClass(),
"STIXReportModule.getDesc.text");
void saveToObjectMap(Observable obs)
ObservableResult evaluateObservableComposition(ObservableCompositionType comp, String spacing)
void printFileHeader(String a_fileName)
void generateReport(String baseReportDir, ReportProgressPanel progressPanel)
void processFile(String stixFile, ReportProgressPanel progressPanel)
String getRelativeFilePath()
JPanel getConfigurationPanel()
ObservableResult evaluateObject(ObjectType obj, String spacing, String id)
Map< String, ObjectType > idToObjectMap
String makeMapKey(Observable obs)
static synchronized STIXReportModule getDefault()
static final Logger logger
static STIXReportModule instance
final boolean skipShortCircuit
void writeResultsToFile(Indicator ind, String resultStr, boolean found)
void saveResultsAsArtifacts(Indicator ind, ObservableResult result)
void processObservables(STIXPackage stix)
STIXPackage loadSTIXFile(String stixFileName)
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
ObservableResult evaluateSingleObservable(Observable obs, String spacing)
List< EvalRegistryObj.RegistryFileInfo > registryFileData
STIXReportModuleConfigPanel configPanel
void updateStatusLabel(final String status)
void setMaximumProgress(final int max)
static void show(String title, String message, MessageType type, ActionListener actionListener)
void processIndicators(STIXPackage stix)
Map< String, ObservableResult > idToResult
static Logger getLogger(String name)
void setIndeterminate(final boolean indeterminate)
static void error(String message)
boolean getShowAllResults()