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;
 
   74     private Map<String, ObjectType> 
idToObjectMap = 
new HashMap<String, ObjectType>();
 
   75     private Map<String, ObservableResult> 
idToResult = 
new HashMap<String, ObservableResult>();
 
   87         if (instance == null) {
 
   98     @Messages({
"STIXReportModule.srcModuleName.text=STIX Report"})
 
  102         progressPanel.
start();
 
  103         progressPanel.
updateStatusLabel(NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.readSTIX"));
 
  105         File reportFile = 
new File(reportPath);
 
  110         boolean hadErrors = 
false;
 
  115         if (stixFileName == null) {
 
  116             logger.log(Level.SEVERE, 
"STIXReportModuleConfigPanel.stixFile not initialized "); 
 
  118                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.notifyErr.noFildDirProvided"));
 
  121                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.noFildDirProvided"));
 
  122             new File(baseReportDir).delete();
 
  125         if (stixFileName.isEmpty()) {
 
  126             logger.log(Level.SEVERE, 
"No STIX file/directory provided "); 
 
  128                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.notifyErr.noFildDirProvided"));
 
  131                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.noFildDirProvided"));
 
  132             new File(baseReportDir).delete();
 
  135         File stixFile = 
new File(stixFileName);
 
  137         if (!stixFile.exists()) {
 
  138             logger.log(Level.SEVERE, String.format(
"Unable to open STIX file/directory %s", stixFileName)); 
 
  140                     "STIXReportModule.notifyMsg.unableToOpenFileDir",
 
  144                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
 
  145             new File(baseReportDir).delete();
 
  149         try (BufferedWriter output = 
new BufferedWriter(
new FileWriter(reportFile))) {
 
  155             if (stixFile.isFile()) {
 
  156                 stixFiles = 
new File[1];
 
  157                 stixFiles[0] = stixFile;
 
  159                 stixFiles = stixFile.listFiles();
 
  166             for (File file : stixFiles) {
 
  171                     processFile(file.getAbsolutePath(), progressPanel, output);
 
  172                 } 
catch (TskCoreException | JAXBException ex) {
 
  173                     String errMsg = String.format(
"Unable to process STIX file %s", file);
 
  174                     logger.log(Level.SEVERE, errMsg, ex); 
 
  182                 idToObjectMap = 
new HashMap<String, ObjectType>();
 
  183                 idToResult = 
new HashMap<String, ObservableResult>();
 
  192                         NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.completedWithErrors"));
 
  196         } 
catch (IOException ex) {
 
  197             logger.log(Level.SEVERE, 
"Unable to complete STIX report.", ex); 
 
  199                     NbBundle.getMessage(
this.getClass(),
 
  200                             "STIXReportModule.notifyMsg.unableToOpenReportFile"),
 
  204                     NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.completedWithErrors"));
 
  205         } 
catch (TskCoreException ex) {
 
  206             logger.log(Level.SEVERE, 
"Unable to add report to database.", ex);
 
  221             JAXBException, TskCoreException {
 
  251     private STIXPackage 
loadSTIXFile(String stixFileName) 
throws JAXBException {
 
  253         File file = 
new File(stixFileName);
 
  254         JAXBContext jaxbContext = JAXBContext.newInstance(
"org.mitre.stix.stix_1:org.mitre.stix.common_1:org.mitre.stix.indicator_2:"  
  255                 + 
"org.mitre.cybox.objects:org.mitre.cybox.cybox_2:org.mitre.cybox.common_2"); 
 
  256         Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
 
  257         STIXPackage stix = (STIXPackage) jaxbUnmarshaller.unmarshal(file);
 
  268         if (stix.getObservables() != null) {
 
  269             List<Observable> obs = stix.getObservables().getObservables();
 
  270             for (Observable o : obs) {
 
  271                 if (o.getId() != null) {
 
  285     private void processIndicators(STIXPackage stix, BufferedWriter output) 
throws TskCoreException {
 
  286         if (stix.getIndicators() != null) {
 
  287             List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
 
  288             for (IndicatorBaseType t : s) {
 
  289                 if (t instanceof Indicator) {
 
  290                     Indicator ind = (Indicator) t;
 
  291                     if (ind.getObservable() != null) {
 
  292                         if (ind.getObservable().getObject() != null) {
 
  297                             if (result.isTrue()) {
 
  300                         } 
else if (ind.getObservable().getObservableComposition() != null) {
 
  306                             if (result.isTrue()) {
 
  326         if (result.getArtifacts() == null) {
 
  333         for (StixArtifactData s : result.getArtifacts()) {
 
  338             if (ind.getTitle() != null) {
 
  339                 s.createArtifact(ind.getTitle());
 
  340             } 
else if (ind.getId() != null) {
 
  341                 s.createArtifact(ind.getId().toString());
 
  343                 s.createArtifact(
"Unnamed indicator(s)"); 
 
  351                         NbBundle.getMessage(
this.getClass(),
 
  352                                 "STIXReportModule.notifyMsg.tooManyArtifactsgt1000",
 
  370     private void writeResultsToFile(Indicator ind, String resultStr, 
boolean found, BufferedWriter output) {
 
  371         if (output != null) {
 
  374                     output.write(
"----------------\r\n" 
  375                             + 
"Found indicator:\r\n"); 
 
  377                     output.write(
"-----------------------\r\n" 
  378                             + 
"Did not find indicator:\r\n"); 
 
  380                 if (ind.getTitle() != null) {
 
  381                     output.write(
"Title: " + ind.getTitle() + 
"\r\n"); 
 
  383                     output.write(
"\r\n");
 
  385                 if (ind.getId() != null) {
 
  386                     output.write(
"ID: " + ind.getId() + 
"\r\n"); 
 
  389                 if (ind.getDescription() != null) {
 
  390                     String desc = ind.getDescription().getValue();
 
  392                     output.write(
"Description: " + desc + 
"\r\n"); 
 
  394                 output.write(
"\r\nObservable results:\r\n" + resultStr + 
"\r\n\r\n"); 
 
  395             } 
catch (IOException ex) {
 
  396                 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex); 
 
  408         if (output != null) {
 
  410                 char[] chars = 
new char[a_fileName.length() + 8];
 
  411                 Arrays.fill(chars, 
'#');
 
  412                 String header = 
new String(chars);
 
  413                 output.write(
"\r\n" + header);
 
  414                 output.write(
"\r\n");
 
  415                 output.write(
"### " + a_fileName + 
" ###\r\n");
 
  416                 output.write(header + 
"\r\n\r\n");
 
  417             } 
catch (IOException ex) {
 
  418                 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex); 
 
  434         if (obs.getId() != null) {
 
  436         } 
else if (obs.getIdref() != null) {
 
  437             idQ = obs.getIdref();
 
  442         return idQ.getLocalPart();
 
  452         if (obs.getObject() != null) {
 
  453             idToObjectMap.put(
makeMapKey(obs), obs.getObject());
 
  468         if (comp.getOperator() == null) {
 
  469             throw new TskCoreException(
"No operator found in composition"); 
 
  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);
 
  548             throw new TskCoreException(
"No observables found in list"); 
 
  566         if (idToResult.containsKey(
makeMapKey(obs))) {
 
  570         if (obs.getIdref() == null) {
 
  574             if (obs.getId() != null) {
 
  578             if (obs.getObject() != null) {
 
  586         if (idToObjectMap.containsKey(
makeMapKey(obs))) {
 
  592         throw new TskCoreException(
"Error loading/finding object for observable " + obs.getIdref()); 
 
  605     private ObservableResult 
evaluateObject(ObjectType obj, String spacing, String 
id) {
 
  607         EvaluatableObject evalObj;
 
  609         if (obj.getProperties() instanceof FileObjectType) {
 
  610             evalObj = 
new EvalFileObj((FileObjectType) obj.getProperties(), id, spacing);
 
  611         } 
else if (obj.getProperties() instanceof Address) {
 
  612             evalObj = 
new EvalAddressObj((Address) obj.getProperties(), id, spacing);
 
  613         } 
else if (obj.getProperties() instanceof URIObjectType) {
 
  614             evalObj = 
new EvalURIObj((URIObjectType) obj.getProperties(), id, spacing);
 
  615         } 
else if (obj.getProperties() instanceof EmailMessage) {
 
  616             evalObj = 
new EvalEmailObj((EmailMessage) obj.getProperties(), id, spacing);
 
  617         } 
else if (obj.getProperties() instanceof WindowsNetworkShare) {
 
  618             evalObj = 
new EvalNetworkShareObj((WindowsNetworkShare) obj.getProperties(), id, spacing);
 
  619         } 
else if (obj.getProperties() instanceof AccountObjectType) {
 
  620             evalObj = 
new EvalAccountObj((AccountObjectType) obj.getProperties(), id, spacing);
 
  621         } 
else if (obj.getProperties() instanceof SystemObjectType) {
 
  622             evalObj = 
new EvalSystemObj((SystemObjectType) obj.getProperties(), id, spacing);
 
  623         } 
else if (obj.getProperties() instanceof URLHistory) {
 
  624             evalObj = 
new EvalURLHistoryObj((URLHistory) obj.getProperties(), id, spacing);
 
  625         } 
else if (obj.getProperties() instanceof DomainName) {
 
  626             evalObj = 
new EvalDomainObj((DomainName) obj.getProperties(), id, spacing);
 
  627         } 
else if (obj.getProperties() instanceof WindowsRegistryKey) {
 
  628             evalObj = 
new EvalRegistryObj((WindowsRegistryKey) obj.getProperties(), id, spacing, 
registryFileData);
 
  631             String type = obj.getProperties().toString();
 
  632             type = type.substring(0, type.indexOf(
"@"));
 
  633             if ((type.lastIndexOf(
".") + 1) < type.length()) {
 
  634                 type = type.substring(type.lastIndexOf(
".") + 1);
 
  636             return new ObservableResult(
id, type + 
" not supported", 
 
  637                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  641         return evalObj.evaluate();
 
  646         String name = NbBundle.getMessage(this.getClass(), 
"STIXReportModule.getName.text");
 
  657         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
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static void show(String title, String message, MessageType type, ActionListener actionListener)
void updateStatusLabel(String statusMessage)
Map< String, ObservableResult > idToResult
static void error(String message)
boolean getShowAllResults()
void processIndicators(STIXPackage stix, BufferedWriter output)