19 package org.sleuthkit.autopsy.modules.stix;
 
   21 import java.io.BufferedWriter;
 
   23 import java.io.FileWriter;
 
   24 import java.io.IOException;
 
   25 import java.util.Arrays;
 
   26 import java.util.HashMap;
 
   27 import java.util.List;
 
   29 import java.util.logging.Level;
 
   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;
 
   35 import org.mitre.cybox.cybox_2.ObjectType;
 
   36 import org.mitre.cybox.cybox_2.Observable;
 
   37 import org.mitre.cybox.cybox_2.ObservableCompositionType;
 
   38 import org.mitre.cybox.cybox_2.OperatorTypeEnum;
 
   39 import org.mitre.cybox.objects.AccountObjectType;
 
   40 import org.mitre.cybox.objects.Address;
 
   41 import org.mitre.cybox.objects.DomainName;
 
   42 import org.mitre.cybox.objects.EmailMessage;
 
   43 import org.mitre.cybox.objects.FileObjectType;
 
   44 import org.mitre.cybox.objects.SystemObjectType;
 
   45 import org.mitre.cybox.objects.URIObjectType;
 
   46 import org.mitre.cybox.objects.URLHistory;
 
   47 import org.mitre.cybox.objects.WindowsNetworkShare;
 
   48 import org.mitre.cybox.objects.WindowsRegistryKey;
 
   49 import org.mitre.stix.common_1.IndicatorBaseType;
 
   50 import org.mitre.stix.indicator_2.Indicator;
 
   51 import org.mitre.stix.stix_1.STIXPackage;
 
   52 import org.openide.util.NbBundle;
 
   53 import org.openide.util.NbBundle.Messages;
 
   75     private Map<String, ObjectType> 
idToObjectMap = 
new HashMap<String, ObjectType>();
 
   76     private Map<String, ObservableResult> 
idToResult = 
new HashMap<String, ObservableResult>();
 
   88         if (instance == null) {
 
   99     @Messages({
"STIXReportModule.srcModuleName.text=STIX Report"})
 
  103         progressPanel.
start();
 
  104         progressPanel.
updateStatusLabel(NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.readSTIX"));        
 
  106         File reportFile = 
new File(reportPath);
 
  111         boolean hadErrors = 
false;
 
  116         if (stixFileName == null) {
 
  117             logger.log(Level.SEVERE, 
"STIXReportModuleConfigPanel.stixFile not initialized "); 
 
  119                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.notifyErr.noFildDirProvided"));
 
  122                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.noFildDirProvided"));
 
  123             new File(baseReportDir).delete();
 
  126         if (stixFileName.isEmpty()) {
 
  127             logger.log(Level.SEVERE, 
"No STIX file/directory provided "); 
 
  129                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.notifyErr.noFildDirProvided"));
 
  132                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.noFildDirProvided"));
 
  133             new File(baseReportDir).delete();
 
  136         File stixFile = 
new File(stixFileName);
 
  138         if (!stixFile.exists()) {
 
  139             logger.log(Level.SEVERE, String.format(
"Unable to open STIX file/directory %s", stixFileName)); 
 
  141                     "STIXReportModule.notifyMsg.unableToOpenFileDir",
 
  145                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
 
  146             new File(baseReportDir).delete();
 
  150         try (BufferedWriter output = 
new BufferedWriter(
new FileWriter(reportFile))) {
 
  156             if (stixFile.isFile()) {
 
  157                 stixFiles = 
new File[1];
 
  158                 stixFiles[0] = stixFile;
 
  160                 stixFiles = stixFile.listFiles();
 
  167             for (File file : stixFiles) {
 
  172                     processFile(file.getAbsolutePath(), progressPanel, output);
 
  173                 } 
catch (TskCoreException | JAXBException ex) {
 
  174                     String errMsg = String.format(
"Unable to process STIX file %s", file);
 
  175                     logger.log(Level.SEVERE, errMsg, ex); 
 
  183                 idToObjectMap = 
new HashMap<String, ObjectType>();
 
  184                 idToResult = 
new HashMap<String, ObservableResult>();
 
  193                         NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.completedWithErrors"));
 
  197         } 
catch (IOException ex) {
 
  198             logger.log(Level.SEVERE, 
"Unable to complete STIX report.", ex); 
 
  200                     NbBundle.getMessage(
this.getClass(),
 
  201                             "STIXReportModule.notifyMsg.unableToOpenReportFile"),
 
  205                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.completedWithErrors"));
 
  207             logger.log(Level.SEVERE, 
"Unable to add report to database.", ex);
 
  222             JAXBException, TskCoreException {
 
  252     private STIXPackage 
loadSTIXFile(String stixFileName) 
throws JAXBException {
 
  254         File file = 
new File(stixFileName);
 
  255         JAXBContext jaxbContext = JAXBContext.newInstance(
"org.mitre.stix.stix_1:org.mitre.stix.common_1:org.mitre.stix.indicator_2:"  
  256                 + 
"org.mitre.cybox.objects:org.mitre.cybox.cybox_2:org.mitre.cybox.common_2"); 
 
  257         Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
 
  258         STIXPackage stix = (STIXPackage) jaxbUnmarshaller.unmarshal(file);
 
  269         if (stix.getObservables() != null) {
 
  270             List<Observable> obs = stix.getObservables().getObservables();
 
  271             for (Observable o : obs) {
 
  272                 if (o.getId() != null) {
 
  286     private void processIndicators(STIXPackage stix, BufferedWriter output) 
throws TskCoreException {
 
  287         if (stix.getIndicators() != null) {
 
  288             List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
 
  289             for (IndicatorBaseType t : s) {
 
  290                 if (t instanceof Indicator) {
 
  291                     Indicator ind = (Indicator) t;
 
  292                     if (ind.getObservable() != null) {
 
  293                         if (ind.getObservable().getObject() != null) {
 
  298                             if (result.isTrue()) {
 
  301                         } 
else if (ind.getObservable().getObservableComposition() != null) {
 
  307                             if (result.isTrue()) {
 
  327         if (result.getArtifacts() == null) {
 
  334         for (StixArtifactData s : result.getArtifacts()) {
 
  339             if (ind.getTitle() != null) {
 
  340                 s.createArtifact(ind.getTitle());
 
  341             } 
else if (ind.getId() != null) {
 
  342                 s.createArtifact(ind.getId().toString());
 
  344                 s.createArtifact(
"Unnamed indicator(s)"); 
 
  352                         NbBundle.getMessage(
this.getClass(),
 
  353                                 "STIXReportModule.notifyMsg.tooManyArtifactsgt1000",
 
  371     private void writeResultsToFile(Indicator ind, String resultStr, 
boolean found, BufferedWriter output) {
 
  372         if (output != null) {
 
  375                     output.write(
"----------------\r\n" 
  376                             + 
"Found indicator:\r\n"); 
 
  378                     output.write(
"-----------------------\r\n" 
  379                             + 
"Did not find indicator:\r\n"); 
 
  381                 if (ind.getTitle() != null) {
 
  382                     output.write(
"Title: " + ind.getTitle() + 
"\r\n"); 
 
  384                     output.write(
"\r\n");
 
  386                 if (ind.getId() != null) {
 
  387                     output.write(
"ID: " + ind.getId() + 
"\r\n"); 
 
  390                 if (ind.getDescription() != null) {
 
  391                     String desc = ind.getDescription().getValue();
 
  393                     output.write(
"Description: " + desc + 
"\r\n"); 
 
  395                 output.write(
"\r\nObservable results:\r\n" + resultStr + 
"\r\n\r\n"); 
 
  396             } 
catch (IOException ex) {
 
  397                 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex); 
 
  409         if (output != null) {
 
  411                 char[] chars = 
new char[a_fileName.length() + 8];
 
  412                 Arrays.fill(chars, 
'#');
 
  413                 String header = 
new String(chars);
 
  414                 output.write(
"\r\n" + header);
 
  415                 output.write(
"\r\n");
 
  416                 output.write(
"### " + a_fileName + 
" ###\r\n");
 
  417                 output.write(header + 
"\r\n\r\n");
 
  418             } 
catch (IOException ex) {
 
  419                 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex); 
 
  435         if (obs.getId() != null) {
 
  437         } 
else if (obs.getIdref() != null) {
 
  438             idQ = obs.getIdref();
 
  443         return idQ.getLocalPart();
 
  453         if (obs.getObject() != null) {
 
  454             idToObjectMap.put(
makeMapKey(obs), obs.getObject());
 
  469         if (comp.getOperator() == null) {
 
  470             throw new TskCoreException(
"No operator found in composition"); 
 
  473         if (comp.getObservables() != null) {
 
  474             List<Observable> obsList = comp.getObservables();
 
  477             if (comp.getOperator() == OperatorTypeEnum.AND) {
 
  478                 ObservableResult result = 
new ObservableResult(OperatorTypeEnum.AND, spacing);
 
  479                 for (Observable o : obsList) {
 
  481                     ObservableResult newResult; 
 
  482                     if (o.getObservableComposition() != null) {
 
  484                         if (result == null) {
 
  487                             result.addResult(newResult, OperatorTypeEnum.AND);
 
  491                         if (result == null) {
 
  494                             result.addResult(newResult, OperatorTypeEnum.AND);
 
  498                     if ((!skipShortCircuit) && !result.isFalse()) {
 
  504                 if (result == null) {
 
  507                     return new ObservableResult(
"", 
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  513                 ObservableResult result = 
new ObservableResult(OperatorTypeEnum.OR, spacing);
 
  514                 for (Observable o : obsList) {
 
  516                     ObservableResult newResult;
 
  518                     if (o.getObservableComposition() != null) {
 
  520                         if (result == null) {
 
  523                             result.addResult(newResult, OperatorTypeEnum.OR);
 
  527                         if (result == null) {
 
  530                             result.addResult(newResult, OperatorTypeEnum.OR);
 
  534                     if ((!skipShortCircuit) && result.isTrue()) {
 
  540                 if (result == null) {
 
  543                     return new ObservableResult(
"", 
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  549             throw new TskCoreException(
"No observables found in list"); 
 
  567         if (idToResult.containsKey(
makeMapKey(obs))) {
 
  571         if (obs.getIdref() == null) {
 
  575             if (obs.getId() != null) {
 
  579             if (obs.getObject() != null) {
 
  587         if (idToObjectMap.containsKey(
makeMapKey(obs))) {
 
  593         throw new TskCoreException(
"Error loading/finding object for observable " + obs.getIdref()); 
 
  606     private ObservableResult 
evaluateObject(ObjectType obj, String spacing, String 
id) {
 
  608         EvaluatableObject evalObj;
 
  610         if (obj.getProperties() instanceof FileObjectType) {
 
  611             evalObj = 
new EvalFileObj((FileObjectType) obj.getProperties(), id, spacing);
 
  612         } 
else if (obj.getProperties() instanceof Address) {
 
  613             evalObj = 
new EvalAddressObj((Address) obj.getProperties(), id, spacing);
 
  614         } 
else if (obj.getProperties() instanceof URIObjectType) {
 
  615             evalObj = 
new EvalURIObj((URIObjectType) obj.getProperties(), id, spacing);
 
  616         } 
else if (obj.getProperties() instanceof EmailMessage) {
 
  617             evalObj = 
new EvalEmailObj((EmailMessage) obj.getProperties(), id, spacing);
 
  618         } 
else if (obj.getProperties() instanceof WindowsNetworkShare) {
 
  619             evalObj = 
new EvalNetworkShareObj((WindowsNetworkShare) obj.getProperties(), id, spacing);
 
  620         } 
else if (obj.getProperties() instanceof AccountObjectType) {
 
  621             evalObj = 
new EvalAccountObj((AccountObjectType) obj.getProperties(), id, spacing);
 
  622         } 
else if (obj.getProperties() instanceof SystemObjectType) {
 
  623             evalObj = 
new EvalSystemObj((SystemObjectType) obj.getProperties(), id, spacing);
 
  624         } 
else if (obj.getProperties() instanceof URLHistory) {
 
  625             evalObj = 
new EvalURLHistoryObj((URLHistory) obj.getProperties(), id, spacing);
 
  626         } 
else if (obj.getProperties() instanceof DomainName) {
 
  627             evalObj = 
new EvalDomainObj((DomainName) obj.getProperties(), id, spacing);
 
  628         } 
else if (obj.getProperties() instanceof WindowsRegistryKey) {
 
  629             evalObj = 
new EvalRegistryObj((WindowsRegistryKey) obj.getProperties(), id, spacing, 
registryFileData);
 
  632             String type = obj.getProperties().toString();
 
  633             type = type.substring(0, type.indexOf(
"@"));
 
  634             if ((type.lastIndexOf(
".") + 1) < type.length()) {
 
  635                 type = type.substring(type.lastIndexOf(
".") + 1);
 
  637             return new ObservableResult(
id, type + 
" not supported", 
 
  638                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  642         return evalObj.evaluate();
 
  647         String name = NbBundle.getMessage(this.getClass(), 
"STIXReportModule.getName.text");
 
  658         String desc = NbBundle.getMessage(this.getClass(), 
"STIXReportModule.getDesc.text");
 
void saveToObjectMap(Observable obs)
ObservableResult evaluateObservableComposition(ObservableCompositionType comp, String spacing)
void generateReport(String baseReportDir, 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)
void processFile(String stixFile, ReportProgressPanel progressPanel, BufferedWriter output)
static synchronized STIXReportModule getDefault()
static final Logger logger
void addReport(String localPath, String srcModuleName, String reportName)
static STIXReportModule instance
void setIndeterminate(boolean indeterminate)
final boolean skipShortCircuit
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 printFileHeader(String a_fileName, BufferedWriter output)
void setMaximumProgress(int max)
ObservableResult evaluateSingleObservable(Observable obs, String spacing)
List< EvalRegistryObj.RegistryFileInfo > registryFileData
void writeResultsToFile(Indicator ind, String resultStr, boolean found, BufferedWriter output)
STIXReportModuleConfigPanel configPanel
synchronized static Logger getLogger(String name)
static void show(String title, String message, MessageType type, ActionListener actionListener)
static Case getCurrentCaseThrows()
void updateStatusLabel(String statusMessage)
Map< String, ObservableResult > idToResult
static void error(String message)
boolean getShowAllResults()
void processIndicators(STIXPackage stix, BufferedWriter output)