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);
185 }
catch (TskCoreException ex) {
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"));
237 progressPanel.increment();
244 progressPanel.increment();
257 private STIXPackage
loadSTIXFile(String stixFileName)
throws TskCoreException {
260 File file =
new File(stixFileName);
261 JAXBContext jaxbContext = JAXBContext.newInstance(
"org.mitre.stix.stix_1:org.mitre.stix.common_1:org.mitre.stix.indicator_2:"
262 +
"org.mitre.cybox.objects:org.mitre.cybox.cybox_2:org.mitre.cybox.common_2");
263 Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
264 STIXPackage stix = (STIXPackage) jaxbUnmarshaller.unmarshal(file);
266 }
catch (JAXBException ex) {
267 logger.log(Level.SEVERE, String.format(
"Unable to load STIX file %s", stixFileName), ex.getLocalizedMessage());
268 throw new TskCoreException(
"Error loading STIX file (" + ex.toString() +
")");
279 if (stix.getObservables() != null) {
280 List<Observable> obs = stix.getObservables().getObservables();
281 for (Observable o : obs) {
282 if (o.getId() != null) {
296 if (stix.getIndicators() != null) {
297 List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
298 for (IndicatorBaseType t : s) {
299 if (t instanceof Indicator) {
300 Indicator ind = (Indicator) t;
301 if (ind.getObservable() != null) {
302 if (ind.getObservable().getObject() != null) {
307 if (result.isTrue()) {
310 }
else if (ind.getObservable().getObservableComposition() != null) {
316 if (result.isTrue()) {
336 if (result.getArtifacts() == null) {
343 for (StixArtifactData s : result.getArtifacts()) {
348 if (ind.getTitle() != null) {
349 s.createArtifact(ind.getTitle());
350 }
else if (ind.getId() != null) {
351 s.createArtifact(ind.getId().toString());
353 s.createArtifact(
"Unnamed indicator(s)");
361 NbBundle.getMessage(
this.getClass(),
362 "STIXReportModule.notifyMsg.tooManyArtifactsgt1000",
380 if (output != null) {
383 output.write(
"----------------\r\n"
384 +
"Found indicator:\r\n");
386 output.write(
"-----------------------\r\n"
387 +
"Did not find indicator:\r\n");
389 if (ind.getTitle() != null) {
390 output.write(
"Title: " + ind.getTitle() +
"\r\n");
392 output.write(
"\r\n");
394 if (ind.getId() != null) {
395 output.write(
"ID: " + ind.getId() +
"\r\n");
398 if (ind.getDescription() != null) {
399 String desc = ind.getDescription().getValue();
401 output.write(
"Description: " + desc +
"\r\n");
403 output.write(
"\r\nObservable results:\r\n" + resultStr +
"\r\n\r\n");
404 }
catch (IOException ex) {
405 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex);
416 if (output != null) {
418 char[] chars =
new char[a_fileName.length() + 8];
419 Arrays.fill(chars,
'#');
420 String header =
new String(chars);
421 output.write(
"\r\n" + header);
422 output.write(
"\r\n");
423 output.write(
"### " + a_fileName +
" ###\r\n");
424 output.write(header +
"\r\n\r\n");
425 }
catch (IOException ex) {
426 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex);
442 if (obs.getId() != null) {
444 }
else if (obs.getIdref() != null) {
445 idQ = obs.getIdref();
450 return idQ.getLocalPart();
460 if (obs.getObject() != null) {
461 idToObjectMap.put(
makeMapKey(obs), obs.getObject());
476 if (comp.getOperator() == null) {
477 throw new TskCoreException(
"No operator found in composition");
480 if (comp.getObservables() != null) {
481 List<Observable> obsList = comp.getObservables();
484 if (comp.getOperator() == OperatorTypeEnum.AND) {
485 ObservableResult result =
new ObservableResult(OperatorTypeEnum.AND, spacing);
486 for (Observable o : obsList) {
488 ObservableResult newResult;
489 if (o.getObservableComposition() != null) {
491 if (result == null) {
494 result.addResult(newResult, OperatorTypeEnum.AND);
498 if (result == null) {
501 result.addResult(newResult, OperatorTypeEnum.AND);
505 if ((!skipShortCircuit) && !result.isFalse()) {
511 if (result == null) {
514 return new ObservableResult(
"",
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
520 ObservableResult result =
new ObservableResult(OperatorTypeEnum.OR, spacing);
521 for (Observable o : obsList) {
523 ObservableResult newResult;
525 if (o.getObservableComposition() != null) {
527 if (result == null) {
530 result.addResult(newResult, OperatorTypeEnum.OR);
534 if (result == null) {
537 result.addResult(newResult, OperatorTypeEnum.OR);
541 if ((!skipShortCircuit) && result.isTrue()) {
547 if (result == null) {
550 return new ObservableResult(
"",
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
556 throw new TskCoreException(
"No observables found in list");
574 if (idToResult.containsKey(
makeMapKey(obs))) {
578 if (obs.getIdref() == null) {
582 if (obs.getId() != null) {
586 if (obs.getObject() != null) {
594 if (idToObjectMap.containsKey(
makeMapKey(obs))) {
600 throw new TskCoreException(
"Error loading/finding object for observable " + obs.getIdref());
612 private ObservableResult
evaluateObject(ObjectType obj, String spacing, String
id) {
614 EvaluatableObject evalObj;
616 if (obj.getProperties() instanceof FileObjectType) {
617 evalObj =
new EvalFileObj((FileObjectType) obj.getProperties(), id, spacing);
618 }
else if (obj.getProperties() instanceof Address) {
619 evalObj =
new EvalAddressObj((Address) obj.getProperties(), id, spacing);
620 }
else if (obj.getProperties() instanceof URIObjectType) {
621 evalObj =
new EvalURIObj((URIObjectType) obj.getProperties(), id, spacing);
622 }
else if (obj.getProperties() instanceof EmailMessage) {
623 evalObj =
new EvalEmailObj((EmailMessage) obj.getProperties(), id, spacing);
624 }
else if (obj.getProperties() instanceof WindowsNetworkShare) {
625 evalObj =
new EvalNetworkShareObj((WindowsNetworkShare) obj.getProperties(), id, spacing);
626 }
else if (obj.getProperties() instanceof AccountObjectType) {
627 evalObj =
new EvalAccountObj((AccountObjectType) obj.getProperties(), id, spacing);
628 }
else if (obj.getProperties() instanceof SystemObjectType) {
629 evalObj =
new EvalSystemObj((SystemObjectType) obj.getProperties(), id, spacing);
630 }
else if (obj.getProperties() instanceof URLHistory) {
631 evalObj =
new EvalURLHistoryObj((URLHistory) obj.getProperties(), id, spacing);
632 }
else if (obj.getProperties() instanceof DomainName) {
633 evalObj =
new EvalDomainObj((DomainName) obj.getProperties(), id, spacing);
634 }
else if (obj.getProperties() instanceof WindowsRegistryKey) {
635 evalObj =
new EvalRegistryObj((WindowsRegistryKey) obj.getProperties(), id, spacing,
registryFileData);
638 String type = obj.getProperties().toString();
639 type = type.substring(0, type.indexOf(
"@"));
640 if ((type.lastIndexOf(
".") + 1) < type.length()) {
641 type = type.substring(type.lastIndexOf(
".") + 1);
643 return new ObservableResult(
id, type +
" not supported",
644 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
648 return evalObj.evaluate();
653 String name = NbBundle.getMessage(this.getClass(),
"STIXReportModule.getName.text");
664 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
void complete(ReportStatus reportStatus)
String makeMapKey(Observable obs)
static synchronized STIXReportModule getDefault()
static final Logger logger
static STIXReportModule instance
void setIndeterminate(boolean indeterminate)
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)
void setMaximumProgress(int max)
ObservableResult evaluateSingleObservable(Observable obs, String spacing)
List< EvalRegistryObj.RegistryFileInfo > registryFileData
STIXReportModuleConfigPanel configPanel
synchronized static Logger getLogger(String name)
static void show(String title, String message, MessageType type, ActionListener actionListener)
void updateStatusLabel(String statusMessage)
void processIndicators(STIXPackage stix)
Map< String, ObservableResult > idToResult
static void error(String message)
boolean getShowAllResults()