Remove stix module

This commit is contained in:
apriestman 2021-09-21 11:45:04 -04:00
parent cb9a4c01c8
commit 8a4de6ea34
27 changed files with 0 additions and 4718 deletions

View File

@ -334,11 +334,6 @@
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.modules.kml.KMLReport.getDefault"/>
<attr name="position" intvalue="904"/>
</file>
<file name="org-sleuthkit-autopsy-report-modules-stix-STIXReportModule.instance">
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.report.GeneralReportModule"/>
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.modules.stix.STIXReportModule.getDefault"/>
<attr name="position" intvalue="910"/>
</file>
<file name="org-sleuthkit-autopsy-report-modules-caseuco-CaseUcoReportModule.instance">
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.report.GeneralReportModule"/>
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.modules.caseuco.CaseUcoReportModule.getDefault"/>

View File

@ -1,15 +0,0 @@
OpenIDE-Module-Name=stixModule
STIXReportModule.getName.text=STIX
STIXReportModule.getDesc.text=Generate a report by running a collection of STIX (Structured Threat Information eXpression) files against the data sources. Also creates artifacts under Interesting Files.
STIXReportModule.progress.readSTIX=Parsing STIX files
STIXReportModuleConfigPanel.jLabel2.text=Select a STIX file or directory of STIX files
STIXReportModuleConfigPanel.jButton1.text=Choose file
STIXReportModuleConfigPanel.jCheckBox1.text=Include results for false indicators in output file
STIXReportModule.notifyMsg.unableToOpenReportFile=Unable to complete STIX report.
STIXReportModule.progress.completedWithErrors=Completed with errors
STIXReportModule.notifyMsg.unableToOpenFileDir=Unable to open STIX file/directory {0}
STIXReportModule.progress.couldNotOpenFileDir=Could not open file/directory {0}
STIXReportModule.notifyMsg.tooManyArtifactsgt1000=Too many STIX-related artifacts generated for "{0}". Only saving first 1000.
STIXReportModule.notifyErr.noFildDirProvided=No STIX file/directory provided
STIXReportModule.progress.noFildDirProvided=No STIX file/directory provided
STIXReportModuleConfigPanel.jStixFileTextField.text=

View File

@ -1,18 +0,0 @@
OpenIDE-Module-Name=stixModule
StixArtifactData.indexError.message=Failed to index STIX interesting file hit artifact for keyword search.
StixArtifactData.noOpenCase.errMsg=No open case available.
STIXReportModule.getName.text=STIX
STIXReportModule.getDesc.text=Generate a report by running a collection of STIX (Structured Threat Information eXpression) files against the data sources. Also creates artifacts under Interesting Files.
STIXReportModule.progress.readSTIX=Parsing STIX files
STIXReportModule.srcModuleName.text=STIX Report
STIXReportModuleConfigPanel.jLabel2.text=Select a STIX file or directory of STIX files
STIXReportModuleConfigPanel.jButton1.text=Choose file
STIXReportModuleConfigPanel.jCheckBox1.text=Include results for false indicators in output file
STIXReportModule.notifyMsg.unableToOpenReportFile=Unable to complete STIX report.
STIXReportModule.progress.completedWithErrors=Completed with errors
STIXReportModule.notifyMsg.unableToOpenFileDir=Unable to open STIX file/directory {0}
STIXReportModule.progress.couldNotOpenFileDir=Could not open file/directory {0}
STIXReportModule.notifyMsg.tooManyArtifactsgt1000=Too many STIX-related artifacts generated for "{0}". Only saving first 1000.
STIXReportModule.notifyErr.noFildDirProvided=No STIX file/directory provided
STIXReportModule.progress.noFildDirProvided=No STIX file/directory provided
STIXReportModuleConfigPanel.jStixFileTextField.text=

View File

@ -1,18 +0,0 @@
#Mon Jul 12 13:22:00 UTC 2021
OpenIDE-Module-Name=stix\u30e2\u30b8\u30e5\u30fc\u30eb
STIXReportModule.getDesc.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u5e7e\u3064\u304b\u306eSTIX\uff08Structured Threat Information eXpression\uff1b\u8105\u5a01\u60c5\u5831\u69cb\u9020\u5316\u8a18\u8ff0\u5f62\u5f0f\uff09\u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u5185\u306b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u4f5c\u6210\u3002
STIXReportModule.getName.text=STIX
STIXReportModule.notifyErr.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093
STIXReportModule.notifyMsg.tooManyArtifactsgt1000="{0}"\u7528\u306b\u751f\u6210\u3055\u308c\u305fSTIX\u95a2\u9023\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304c\u591a\u3059\u304e\u307e\u3059\u3002\u6700\u521d\u306e1000\u306e\u307f\u4fdd\u5b58\u3055\u308c\u307e\u3059\u3002
STIXReportModule.notifyMsg.unableToOpenFileDir=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
STIXReportModule.notifyMsg.unableToOpenReportFile=STIX\u30ec\u30dd\u30fc\u30c8\u3092\u5b8c\u4e86\u3067\u304d\u307e\u305b\u3093\u3002
STIXReportModule.progress.completedWithErrors=\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u304c\u3001\u5b8c\u4e86\u3057\u307e\u3057\u305f
STIXReportModule.progress.couldNotOpenFileDir=\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
STIXReportModule.progress.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093
STIXReportModule.progress.readSTIX=STIX\u30d5\u30a1\u30a4\u30eb\u3092\u30d1\u30fc\u30b9\u4e2d
STIXReportModule.srcModuleName.text=STIX\u30ec\u30dd\u30fc\u30c8
STIXReportModuleConfigPanel.jButton1.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e
STIXReportModuleConfigPanel.jCheckBox1.text=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u8aa4\u3063\u305f\u30a4\u30f3\u30b8\u30b1\u30fc\u30bf\u30fc\u306e\u7d50\u679c\u3082\u542b\u3080
STIXReportModuleConfigPanel.jLabel2.text=STIX\u30d5\u30a1\u30a4\u30eb\u307e\u305f\u306fSTIX\u30d5\u30a1\u30a4\u30eb\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e
StixArtifactData.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u7528\u306eSTIX\u8208\u5473\u6df1\u3044\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
StixArtifactData.noOpenCase.errMsg=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u306f\u3042\u308a\u307e\u305b\u3093\u3002

View File

@ -1,227 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.objects.AccountObjectType;
import org.mitre.cybox.objects.UserAccountObjectType;
import org.mitre.cybox.objects.WindowsUserAccount;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalAccountObj extends EvaluatableObject {
private final AccountObjectType obj;
EvalAccountObj(AccountObjectType a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@SuppressWarnings( "deprecation" )
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
// Fields we can search for:
// UserAccount: Home_Directory, Username
// WinUserAccount: SID
if (!(obj instanceof UserAccountObjectType)) {
return new ObservableResult(id, "AccountObject: Can not process \"Account\" - need a User_Account or Windows_User_Account", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// For displaying what we were looking for in the results
String searchString = "";
// Check which fields are present and record them
boolean haveHomeDir = false;
boolean haveUsername = false;
boolean haveSID = false;
UserAccountObjectType userAccountObj = (UserAccountObjectType) obj;
if (userAccountObj.getHomeDirectory() != null) {
haveHomeDir = true;
searchString = "HomeDir \"" + userAccountObj.getHomeDirectory().getValue().toString() + "\""; //NON-NLS
}
if (userAccountObj.getUsername() != null) {
haveUsername = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Username \"" + userAccountObj.getUsername().getValue().toString() + "\""; //NON-NLS
}
WindowsUserAccount winUserObj = null;
if (obj instanceof WindowsUserAccount) {
winUserObj = (WindowsUserAccount) obj;
if (winUserObj.getSecurityID() != null) {
haveSID = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "SID \"" + winUserObj.getSecurityID().getValue().toString() + "\""; //NON-NLS
}
}
if (!(haveHomeDir || haveUsername || haveSID)) {
return new ObservableResult(id, "AccountObject: No evaluatable fields found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// Set warnings for any unsupported fields
setUnsupportedFieldWarnings();
// The assumption here is that there aren't going to be too many network shares, so we
// can cycle through all of them.
try {
List<BlackboardArtifact> finalHits = new ArrayList<>();
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT);
for (BlackboardArtifact art : artList) {
boolean foundHomeDirMatch = false;
boolean foundUsernameMatch = false;
boolean foundSIDMatch = false;
for (BlackboardAttribute attr : art.getAttributes()) {
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID())
&& (haveHomeDir)) {
foundHomeDirMatch = compareStringObject(userAccountObj.getHomeDirectory(), attr.getValueString());
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())
&& (haveUsername)) {
foundUsernameMatch = compareStringObject(userAccountObj.getUsername(), attr.getValueString());
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID())
&& (haveSID) && (winUserObj != null)) {
foundSIDMatch = compareStringObject(winUserObj.getSecurityID(), attr.getValueString());
}
}
if (((!haveHomeDir) || foundHomeDirMatch)
&& ((!haveUsername) || foundUsernameMatch)
&& ((!haveSID) || foundSIDMatch)) {
finalHits.add(art);
}
}
// Check if we found any matches
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "Account")); //NON-NLS
}
return new ObservableResult(id, "AccountObject: Found a match for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
// Didn't find any matches
return new ObservableResult(id, "AccountObject: No matches found for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} catch (TskCoreException | NoCurrentCaseException ex) {
return new ObservableResult(id, "AccountObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
/**
* Set up the warning for any fields in the object that aren't supported.
*/
private void setUnsupportedFieldWarnings() {
List<String> fieldNames = new ArrayList<String>();
if (obj.getDescription() != null) {
fieldNames.add("Description"); //NON-NLS
}
if (obj.getDomain() != null) {
fieldNames.add("Domain"); //NON-NLS
}
if (obj.getAuthentications() != null) {
fieldNames.add("Authentication"); //NON-NLS
}
if (obj.getCreationDate() != null) {
fieldNames.add("Creation_Date"); //NON-NLS
}
if (obj.getModifiedDate() != null) {
fieldNames.add("Modified_Date"); //NON-NLS
}
if (obj.getLastAccessedTime() != null) {
fieldNames.add("Last_Accessed_Time"); //NON-NLS
}
if (obj instanceof UserAccountObjectType) {
UserAccountObjectType userAccountObj = (UserAccountObjectType) obj;
if (userAccountObj.getFullName() != null) {
fieldNames.add("Full_Name"); //NON-NLS
}
if (userAccountObj.getGroupList() != null) {
fieldNames.add("Group_List"); //NON-NLS
}
if (userAccountObj.getLastLogin() != null) {
fieldNames.add("Last_Login"); //NON-NLS
}
if (userAccountObj.getPrivilegeList() != null) {
fieldNames.add("Privilege_List"); //NON-NLS
}
if (userAccountObj.getScriptPath() != null) {
fieldNames.add("Script_Path"); //NON-NLS
}
if (userAccountObj.getUserPasswordAge() != null) {
fieldNames.add("User_Password_Age"); //NON-NLS
}
}
if (obj instanceof WindowsUserAccount) {
WindowsUserAccount winUserObj = (WindowsUserAccount) obj;
if (winUserObj.getSecurityType() != null) {
fieldNames.add("Security_Type"); //NON-NLS
}
}
String warningStr = "";
for (String name : fieldNames) {
if (!warningStr.isEmpty()) {
warningStr += ", ";
}
warningStr += name;
}
addWarning("Unsupported field(s): " + warningStr); //NON-NLS
}
}

View File

@ -1,194 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.common_2.ConditionApplicationEnum;
import org.mitre.cybox.common_2.ConditionTypeEnum;
import org.mitre.cybox.objects.Address;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalAddressObj extends EvaluatableObject {
private final Address obj;
public EvalAddressObj(Address a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
if (obj.getAddressValue() == null) {
return new ObservableResult(id, "AddressObject: No address value field found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
Case case1;
try {
case1 = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
return new ObservableResult(id, "Exception while getting open case.", //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
String origAddressStr = obj.getAddressValue().getValue().toString();
// For now, we don't support "NONE" because it honestly doesn't seem like it
// would ever appear in practice.
if (((obj.getAddressValue().getApplyCondition() != null)
&& (obj.getAddressValue().getApplyCondition() == ConditionApplicationEnum.NONE))) {
return new ObservableResult(id, "AddressObject: Can not process apply condition " + obj.getAddressValue().getApplyCondition().toString() //NON-NLS
+ " on Address object", spacing, ObservableResult.ObservableState.INDETERMINATE, null); //NON-NLS
}
// Set warnings for any unsupported fields
setUnsupportedFieldWarnings();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
try {
// Need to check that every part of the string had at least one match
// in the AND case
boolean everyPartMatched = true;
List<BlackboardArtifact> combinedArts = new ArrayList<BlackboardArtifact>();
String searchString = "";
String[] parts = origAddressStr.split("##comma##"); //NON-NLS
for (String addressStr : parts) {
// Update the string to show in the results
if (!searchString.isEmpty()) {
if ((obj.getAddressValue().getApplyCondition() != null)
&& (obj.getAddressValue().getApplyCondition() == ConditionApplicationEnum.ALL)) {
searchString += " AND "; //NON-NLS
} else {
searchString += " OR "; //NON-NLS
}
}
searchString += addressStr;
if ((obj.getAddressValue().getCondition() == null)
|| (obj.getAddressValue().getCondition() == ConditionTypeEnum.EQUALS)) {
List<BlackboardArtifact> arts = sleuthkitCase.getBlackboardArtifacts(
BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD,
addressStr);
if (arts.isEmpty()) {
everyPartMatched = false;
} else {
combinedArts.addAll(arts);
}
} else {
// This is inefficient, but the easiest way to do it.
List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>();
// Get all the URL artifacts
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
for (BlackboardArtifact art : artList) {
for (BlackboardAttribute attr : art.getAttributes()) {
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
if (compareStringObject(addressStr, obj.getAddressValue().getCondition(),
obj.getAddressValue().getApplyCondition(), attr.getValueString())) {
finalHits.add(art);
}
}
}
}
if (finalHits.isEmpty()) {
everyPartMatched = false;
} else {
combinedArts.addAll(finalHits);
}
}
}
// If we're in the ALL case, make sure every piece matched
if ((obj.getAddressValue().getApplyCondition() != null)
&& (obj.getAddressValue().getApplyCondition() == ConditionApplicationEnum.ALL)
&& (!everyPartMatched)) {
return new ObservableResult(id, "AddressObject: No matches for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
if (!combinedArts.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : combinedArts) {
artData.add(new StixArtifactData(a.getObjectID(), id, "AddressObject")); //NON-NLS
}
return new ObservableResult(id, "AddressObject: Found a match for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
return new ObservableResult(id, "AddressObject: Found no matches for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} catch (TskCoreException ex) {
return new ObservableResult(id, "AddressObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
/**
* Set up the warning for any fields in the object that aren't supported.
*/
private void setUnsupportedFieldWarnings() {
List<String> fieldNames = new ArrayList<String>();
if (obj.getVLANName() != null) {
fieldNames.add("VLAN_Name"); //NON-NLS
}
if (obj.getVLANName() != null) {
fieldNames.add("VLAN_Num"); //NON-NLS
}
String warningStr = "";
for (String name : fieldNames) {
if (!warningStr.isEmpty()) {
warningStr += ", ";
}
warningStr += name;
}
addWarning("Unsupported field(s): " + warningStr); //NON-NLS
}
}

View File

@ -1,123 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.util.ArrayList;
import java.util.List;
import org.mitre.cybox.common_2.ConditionApplicationEnum;
import org.mitre.cybox.common_2.ConditionTypeEnum;
import org.mitre.cybox.objects.DomainName;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.SleuthkitCase;
/**
*
*/
class EvalDomainObj extends EvaluatableObject {
private final DomainName obj;
public EvalDomainObj(DomainName a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
if (obj.getValue() == null) {
return new ObservableResult(id, "DomainObject: No domain value field found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
Case case1;
try {
case1 = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
return new ObservableResult(id, "Exception while getting open case.", //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
// Since we have single URL artifacts, ALL and NONE conditions probably don't make sense to test
if (!((obj.getValue().getApplyCondition() == null)
|| (obj.getValue().getApplyCondition() == ConditionApplicationEnum.ANY))) {
return new ObservableResult(id, "DomainObject: Can not process apply condition " + obj.getValue().getApplyCondition().toString() //NON-NLS
+ " on Domain object", spacing, ObservableResult.ObservableState.INDETERMINATE, null); //NON-NLS
}
// If the condition is not "CONTAINS", add a warning that it's being ignored
if ((obj.getValue().getCondition() != null)
&& (obj.getValue().getCondition() != ConditionTypeEnum.CONTAINS)) {
addWarning("Warning: Ignoring condition " + obj.getValue().getCondition().toString() //NON-NLS
+ " on DomainName - using substring comparison"); //NON-NLS
}
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
try {
// Set up the list of matching artifacts
List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>();
// Get all the URL artifacts
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
for (BlackboardArtifact art : artList) {
for (BlackboardAttribute attr : art.getAttributes()) {
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
String url = attr.getValueString();
// Check whether the domain name is a substring of the URL (regardless
// of the condition on the domain name object)
if (compareStringObject(obj.getValue().getValue().toString(), ConditionTypeEnum.CONTAINS,
obj.getValue().getApplyCondition(), url)) {
finalHits.add(art);
}
}
}
}
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "DomainNameObject")); //NON-NLS
}
return new ObservableResult(id, "DomainNameObject: Found a match for " + obj.getValue().getValue().toString() //NON-NLS
+ " " + getPrintableWarnings(),
spacing, ObservableResult.ObservableState.TRUE, artData);
}
return new ObservableResult(id, "DomainNameObject: Found no matches for " + obj.getValue().getValue().toString() //NON-NLS
+ " " + getPrintableWarnings(),
spacing, ObservableResult.ObservableState.FALSE, null);
} catch (TskCoreException ex) {
return new ObservableResult(id, "DomainNameObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
}

View File

@ -1,274 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.objects.EmailMessage;
import org.mitre.cybox.objects.Address;
/**
*
*/
class EvalEmailObj extends EvaluatableObject {
private final EmailMessage obj;
private List<BlackboardArtifact> finalHits;
public EvalEmailObj(EmailMessage a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
finalHits = null;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
List<BlackboardArtifact> toHits = null;
boolean hadToFields = false;
List<BlackboardArtifact> ccHits = null;
boolean hadCcFields = false;
List<BlackboardArtifact> fromHits = null;
boolean hadFromField = false;
List<BlackboardArtifact> subjectHits = null;
boolean hadSubjectField = false;
if (obj.getHeader() != null) {
if ((obj.getHeader().getTo() != null)
&& (obj.getHeader().getTo().getRecipients() != null)
&& (!obj.getHeader().getTo().getRecipients().isEmpty())) {
for (Address addr : obj.getHeader().getTo().getRecipients()) {
if (addr.getAddressValue() != null) {
hadToFields = true;
try {
toHits = findArtifactsBySubstring(addr.getAddressValue(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
}
}
if ((obj.getHeader().getCC() != null)
&& (obj.getHeader().getCC().getRecipients() != null)
&& (!obj.getHeader().getCC().getRecipients().isEmpty())) {
for (Address addr : obj.getHeader().getCC().getRecipients()) {
if (addr.getAddressValue() != null) {
hadCcFields = true;
try {
ccHits = findArtifactsBySubstring(addr.getAddressValue(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CC);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
}
}
if ((obj.getHeader().getFrom() != null)
&& (obj.getHeader().getFrom().getAddressValue() != null)) {
hadFromField = true;
try {
fromHits = findArtifactsBySubstring(obj.getHeader().getFrom().getAddressValue(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if ((obj.getHeader().getSubject() != null)
&& (obj.getHeader().getSubject().getValue() != null)) {
hadSubjectField = true;
try {
subjectHits = findArtifactsBySubstring(obj.getHeader().getSubject(),
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
}
// Make sure at least one test had some data
if ((!hadToFields) && (!hadFromField) && (!hadCcFields) && (!hadSubjectField)) {
return new ObservableResult(id, "EmailMessage: Could not find any parsable EmailMessage fields " //NON-NLS
+ getPrintableWarnings(),
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// Check if there were more fields that aren't currently supported
String fieldNames = getListOfUnsupportedFields();
if (fieldNames.length() > 0) {
addWarning("Unsupported field(s) found: " + fieldNames); //NON-NLS
}
// Find the artifacts that matched all of the fields
finalHits = null;
boolean finalHitsStarted = false;
if (hadToFields) {
combineHits(toHits, finalHitsStarted);
finalHitsStarted = true;
}
if (hadCcFields) {
combineHits(ccHits, finalHitsStarted);
finalHitsStarted = true;
}
if (hadFromField) {
combineHits(fromHits, finalHitsStarted);
finalHitsStarted = true;
}
if (hadSubjectField) {
combineHits(subjectHits, finalHitsStarted);
finalHitsStarted = true;
}
if (!finalHitsStarted) {
// We didn't find any fields that could be evaluated
return new ObservableResult(id, "EmailMessage: EmailObj parsing incomplete " + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// If there are any artifacts left in finalHits, we have a match
if (finalHits.size() > 0) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "EmailMessage")); //NON-NLS
}
return new ObservableResult(id, "EmailMessage: " + finalHits.size() + " matching artifacts found " + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
} else {
return new ObservableResult(id, "EmailMessage: No matching artifacts found " + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
}
/**
* Add a set of hits to the final set of hits. Removes any artifacts that
* aren't found in the new set. The final list is the artifacts found in all
* sets.
*
* @param newHits The new hits to add to the list
* @param finalHitsStarted Whether we've started the list or not
*/
private void combineHits(List<BlackboardArtifact> newHits, boolean finalHitsStarted) {
if (finalHitsStarted && (finalHits != null)) {
finalHits.retainAll(newHits);
} else {
finalHits = newHits;
}
}
/**
* Test to see if the Email Object has any fields set that we don't support
* right now.
*
* @return a list of unsupported fields found.
*/
private String getListOfUnsupportedFields() {
String fieldNames = "";
if (obj.getHeader() != null) {
if (obj.getHeader().getReceivedLines() != null) {
fieldNames += "Received_Lines "; //NON-NLS
}
if (obj.getHeader().getBCC() != null) {
fieldNames += "BCC "; //NON-NLS
}
if (obj.getHeader().getInReplyTo() != null) {
fieldNames += "In_Reply_To "; //NON-NLS
}
if (obj.getHeader().getDate() != null) {
fieldNames += "Date "; //NON-NLS
}
if (obj.getHeader().getMessageID() != null) {
fieldNames += "Message_ID "; //NON-NLS
}
if (obj.getHeader().getSender() != null) {
fieldNames += "Sender "; //NON-NLS
}
if (obj.getHeader().getReplyTo() != null) {
fieldNames += "Reply_To "; //NON-NLS
}
if (obj.getHeader().getErrorsTo() != null) {
fieldNames += "Errors_To "; //NON-NLS
}
if (obj.getHeader().getBoundary() != null) {
fieldNames += "Boundary "; //NON-NLS
}
if (obj.getHeader().getContentType() != null) {
fieldNames += "Content_Type "; //NON-NLS
}
if (obj.getHeader().getMIMEVersion() != null) {
fieldNames += "MIME_Version "; //NON-NLS
}
if (obj.getHeader().getPrecedence() != null) {
fieldNames += "Precedence "; //NON-NLS
}
if (obj.getHeader().getUserAgent() != null) {
fieldNames += "User_Agent "; //NON-NLS
}
if (obj.getHeader().getXMailer() != null) {
fieldNames += "X_Mailer "; //NON-NLS
}
if (obj.getHeader().getXOriginatingIP() != null) {
fieldNames += "X_Originiating_IP "; //NON-NLS
}
if (obj.getHeader().getXPriority() != null) {
fieldNames += "X_Priority "; //NON-NLS
}
}
if (obj.getEmailServer() != null) {
fieldNames += "Email_Server "; //NON-NLS
}
if (obj.getRawBody() != null) {
fieldNames += "Raw_Body "; //NON-NLS
}
if (obj.getRawHeader() != null) {
fieldNames += "Raw_Header "; //NON-NLS
}
if (obj.getAttachments() != null) {
fieldNames += "Attachments "; //NON-NLS
}
if (obj.getLinks() != null) {
fieldNames += "Links "; //NON-NLS
}
return fieldNames;
}
}

View File

@ -1,699 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.mitre.cybox.common_2.ConditionApplicationEnum;
import org.mitre.cybox.objects.FileObjectType;
import org.mitre.cybox.objects.WindowsExecutableFileObjectType;
import org.mitre.cybox.common_2.ConditionTypeEnum;
import org.mitre.cybox.common_2.DatatypeEnum;
import org.mitre.cybox.common_2.HashType;
import org.mitre.cybox.common_2.DateTimeObjectPropertyType;
import org.mitre.cybox.common_2.StringObjectPropertyType;
import org.mitre.cybox.common_2.UnsignedLongObjectPropertyType;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalFileObj extends EvaluatableObject {
private final FileObjectType obj;
public EvalFileObj(FileObjectType a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
@SuppressWarnings("deprecation")
public synchronized ObservableResult evaluate() {
Case case1;
try {
case1 = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
return new ObservableResult(id, "Exception while getting open case.", //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
setWarnings("");
String whereClause = "";
if (obj.getSizeInBytes() != null) {
try {
String newClause = processULongObject(obj.getSizeInBytes(), "size"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if (obj.getFileName() != null) {
try {
String newClause = processStringObject(obj.getFileName(), "name"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if (obj.getFileExtension() != null) {
if ((obj.getFileExtension().getCondition() == null)
|| (obj.getFileExtension().getCondition() == ConditionTypeEnum.EQUALS)) {
String newClause = "LOWER(name) LIKE LOWER(\'%" + obj.getFileExtension().getValue() + "\')"; //NON-NLS
whereClause = addClause(whereClause, newClause);
} else {
addWarning(
"Could not process condition " + obj.getFileExtension().getCondition().value() + " on file extension"); //NON-NLS
}
}
if (obj.getFilePath() != null) {
try {
String[] parts = obj.getFilePath().getValue().toString().split("##comma##"); //NON-NLS
String finalPathStr = "";
for (String filePath : parts) {
// First, we need to normalize the path
String currentFilePath = filePath;
// Remove the drive letter
if (currentFilePath.matches("^[A-Za-z]:.*")) {
currentFilePath = currentFilePath.substring(2);
}
// Change any backslashes to forward slashes
currentFilePath = currentFilePath.replace("\\", "/");
// The path needs to start with a slash
if (!currentFilePath.startsWith("/")) {
currentFilePath = "/" + currentFilePath;
}
// If the path does not end in a slash, the final part should be the file name.
if (!currentFilePath.endsWith("/")) {
int lastSlash = currentFilePath.lastIndexOf('/');
if (lastSlash >= 0) {
currentFilePath = currentFilePath.substring(0, lastSlash + 1);
}
}
// Reconstruct the path string (which may be multi-part)
if (!finalPathStr.isEmpty()) {
finalPathStr += "##comma##"; //NON-NLS
}
finalPathStr += currentFilePath;
}
String newClause = processStringObject(finalPathStr, obj.getFilePath().getCondition(),
obj.getFilePath().getApplyCondition(), "parent_path"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if (obj.getCreatedTime() != null) {
try {
String newClause = processTimestampObject(obj.getCreatedTime(), "crtime"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if (obj.getModifiedTime() != null) {
try {
String newClause = processTimestampObject(obj.getModifiedTime(), "mtime"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if (obj.getAccessedTime() != null) {
try {
String newClause = processTimestampObject(obj.getAccessedTime(), "atime"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
if (obj.getHashes() != null) {
for (HashType h : obj.getHashes().getHashes()) {
if (h.getSimpleHashValue() != null) {
if (h.getType().getValue().equals("MD5")) { //NON-NLS
String newClause = "";
if (h.getSimpleHashValue().getValue().toString().toLowerCase().contains("##comma##")) { //NON-NLS
String[] parts = h.getSimpleHashValue().getValue().toString().toLowerCase().split("##comma##"); //NON-NLS
String hashList = "";
for (String s : parts) {
if (!hashList.isEmpty()) {
hashList += ", ";
}
hashList += "\'" + s + "\'";
}
newClause = "md5 IN (" + hashList + ")"; //NON-NLS
} else {
newClause = "md5=\'" + h.getSimpleHashValue().getValue().toString().toLowerCase() + "\'"; //NON-NLS
}
whereClause = addClause(whereClause, newClause);
} else {
addWarning("Could not process hash type " + h.getType().getValue().toString()); //NON-NLS
}
} else {
addWarning("Could not process non-simple hash value"); //NON-NLS
}
}
}
if (obj instanceof WindowsExecutableFileObjectType) {
WindowsExecutableFileObjectType winExe = (WindowsExecutableFileObjectType) obj;
if (winExe.getHeaders() != null) {
if (winExe.getHeaders().getFileHeader() != null) {
if (winExe.getHeaders().getFileHeader().getTimeDateStamp() != null) {
try {
String result = convertTimestampString(winExe.getHeaders().getFileHeader().getTimeDateStamp().getValue().toString());
String newClause = processNumericFields(result,
winExe.getHeaders().getFileHeader().getTimeDateStamp().getCondition(),
winExe.getHeaders().getFileHeader().getTimeDateStamp().getApplyCondition(),
"crtime"); //NON-NLS
whereClause = addClause(whereClause, newClause);
} catch (TskCoreException ex) {
addWarning(ex.getLocalizedMessage());
}
}
}
}
}
String unsupportedFields = listUnsupportedFields();
if (!unsupportedFields.isEmpty()) {
addWarning("Unsupported fields: " + unsupportedFields); //NON-NLS
}
if (whereClause.length() > 0) {
try {
List<AbstractFile> matchingFiles = sleuthkitCase.findAllFilesWhere(whereClause);
if (!matchingFiles.isEmpty()) {
if (listSecondaryFields().isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (AbstractFile a : matchingFiles) {
artData.add(new StixArtifactData(a, id, "FileObject")); //NON-NLS
}
return new ObservableResult(id, "FileObject: Found " + matchingFiles.size() + " matches for " + whereClause + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
} else {
// We need to tag the matching files in Autopsy, so keep track of them
List<AbstractFile> secondaryHits = new ArrayList<AbstractFile>();
for (AbstractFile file : matchingFiles) {
boolean passedTests = true;
if (obj.isIsMasqueraded() != null) {
List<BlackboardArtifact> arts = file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED);
boolean isMasq = false;
if (!arts.isEmpty()) {
isMasq = true;
}
if (obj.isIsMasqueraded() != isMasq) {
passedTests = false;
}
}
if (obj.getFileFormat() != null) {
String formatsFound = file.getMIMEType();
if (formatsFound != null) {
if (!(formatsFound.equalsIgnoreCase(obj.getFileFormat().getValue().toString()))) {
addWarning("Warning: Did not match File_Format field " + obj.getFileFormat().getValue().toString() //NON-NLS
+ " against " + formatsFound); //NON-NLS
}
} else {
addWarning("Warning: Did not match File_Format field " + obj.getFileFormat().getValue().toString() //NON-NLS
+ " (no file formats found)"); //NON-NLS
}
// It looks like the STIX file formats can be different than what Autopsy stores
// (mime vs. unix file), so don't kill a file based on this field not matching.
//if (!foundMatch) {
// passedTests = false;
//}
}
if (passedTests) {
secondaryHits.add(file);
}
}
if (secondaryHits.isEmpty()) {
return new ObservableResult(id, "FileObject: Found " + matchingFiles.size() + " matches for " + whereClause //NON-NLS
+ " but none for secondary tests on " + listSecondaryFields() + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} else {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (AbstractFile a : secondaryHits) {
artData.add(new StixArtifactData(a, id, "FileObject")); //NON-NLS
}
return new ObservableResult(id, "FileObject: Found " + secondaryHits.size() + " matches for " + whereClause //NON-NLS
+ " and secondary tests on " + listSecondaryFields() + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
}
} else {
return new ObservableResult(id, "FileObject: Found no matches for " + whereClause + getPrintableWarnings(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
} catch (TskCoreException ex) {
return new ObservableResult(id, "FileObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
} else {
}
return new ObservableResult(id, "FileObject: No evaluatable fields " + getPrintableWarnings(), spacing, //NON-NLS
ObservableResult.ObservableState.INDETERMINATE, null);
}
/**
* Create a list of secondary fields. These are the ones that we only test
* on the matches for the primary fields.
*
* @return List of secondary fields
*/
private String listSecondaryFields() {
String secondaryFields = "";
if (obj.isIsMasqueraded() != null) {
secondaryFields += "is_masqueraded "; //NON-NLS
}
if (obj.getFileFormat() != null) {
secondaryFields += "File_Format "; //NON-NLS
}
return secondaryFields;
}
/**
* List unsupported fields found in the object.
*
* @return List of unsupported fields
*/
private String listUnsupportedFields() {
String unsupportedFields = "";
if (obj.isIsPacked() != null) {
unsupportedFields += "is_packed "; //NON-NLS
}
if (obj.getDevicePath() != null) {
unsupportedFields += "Device_Path "; //NON-NLS
}
if (obj.getFullPath() != null) {
unsupportedFields += "Full_Path "; //NON-NLS
}
if (obj.getMagicNumber() != null) {
unsupportedFields += "Magic_Number "; //NON-NLS
}
if (obj.getDigitalSignatures() != null) {
unsupportedFields += "Digital_Signatures "; //NON-NLS
}
if (obj.getFileAttributesList() != null) {
unsupportedFields += "File_Attributes_List "; //NON-NLS
}
if (obj.getPermissions() != null) {
unsupportedFields += "Permissions "; //NON-NLS
}
if (obj.getUserOwner() != null) {
unsupportedFields += "User_Owner "; //NON-NLS
}
if (obj.getPackerList() != null) {
unsupportedFields += "Packer_List "; //NON-NLS
}
if (obj.getPeakEntropy() != null) {
unsupportedFields += "Peak_Entropy "; //NON-NLS
}
if (obj.getSymLinks() != null) {
unsupportedFields += "Sym_Links "; //NON-NLS
}
if (obj.getByteRuns() != null) {
unsupportedFields += "Bytes_Runs "; //NON-NLS
}
if (obj.getExtractedFeatures() != null) {
unsupportedFields += "Extracted_Features "; //NON-NLS
}
if (obj.getEncryptionAlgorithm() != null) {
unsupportedFields += "Encryption_Algorithm "; //NON-NLS
}
if (obj.getDecryptionKey() != null) {
unsupportedFields += "Decryption_Key "; //NON-NLS
}
if (obj.getCompressionMethod() != null) {
unsupportedFields += "Compression_Method "; //NON-NLS
}
if (obj.getCompressionVersion() != null) {
unsupportedFields += "Compression_Version "; //NON-NLS
}
if (obj.getCompressionComment() != null) {
unsupportedFields += "Compression_Comment "; //NON-NLS
}
return unsupportedFields;
}
/**
* Convert timestamp string into a long.
*
* @param timeStr
*
* @return
*
* @throws ParseException
*/
private static long convertTimestamp(String timeStr) throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); //NON-NLS
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); //NON-NLS
Date parsedDate = dateFormat.parse(timeStr);
Long unixTime = parsedDate.getTime() / 1000;
return unixTime;
}
/**
* Return the SQL clause for an unsigned long object. Splits into fields and
* call the more generic version of the function.
*
* @param longObj The Cybox UnsignedLong object
* @param fieldName Name of the field to test against
*
* @return SQL clause
*
* @throws TskCoreException
*/
private static String processULongObject(UnsignedLongObjectPropertyType longObj, String fieldName)
throws TskCoreException {
return processNumericFields(longObj.getValue().toString(), longObj.getCondition(),
longObj.getApplyCondition(), fieldName);
}
/**
* Return the SQL clause for a numeric object.
*
* @param valueStr Value (as string)
* @param typeCondition Cybox condition
* @param applyCondition Cybox apply_condition
* @param fieldName Name of the field to test against
*
* @return SQL clause
*
* @throws TskCoreException
*/
private static String processNumericFields(String valueStr, ConditionTypeEnum typeCondition,
ConditionApplicationEnum applyCondition, String fieldName)
throws TskCoreException {
if ((typeCondition == null)
|| ((typeCondition != ConditionTypeEnum.INCLUSIVE_BETWEEN)
&& (typeCondition != ConditionTypeEnum.EXCLUSIVE_BETWEEN))) {
String fullClause = "";
if (valueStr.isEmpty()) {
throw new TskCoreException("Empty value field"); //NON-NLS
}
String[] parts = valueStr.split("##comma##"); //NON-NLS
for (String valuePart : parts) {
String partialClause;
if ((typeCondition == null)
|| (typeCondition == ConditionTypeEnum.EQUALS)) {
partialClause = fieldName + "=" + valuePart;
} else if (typeCondition == ConditionTypeEnum.DOES_NOT_EQUAL) {
partialClause = fieldName + "!=" + valuePart;
} else if (typeCondition == ConditionTypeEnum.GREATER_THAN) {
partialClause = fieldName + ">" + valuePart;
} else if (typeCondition == ConditionTypeEnum.GREATER_THAN_OR_EQUAL) {
partialClause = fieldName + ">=" + valuePart;
} else if (typeCondition == ConditionTypeEnum.LESS_THAN) {
partialClause = fieldName + "<" + valuePart;
} else if (typeCondition == ConditionTypeEnum.LESS_THAN_OR_EQUAL) {
partialClause = fieldName + "<=" + valuePart;
} else {
throw new TskCoreException("Could not process condition " + typeCondition.value() + " on " + fieldName); //NON-NLS
}
if (fullClause.isEmpty()) {
if (parts.length > 1) {
fullClause += "( ";
}
if (applyCondition == ConditionApplicationEnum.NONE) {
fullClause += " NOT "; //NON-NLS
}
fullClause += partialClause;
} else {
if (applyCondition == ConditionApplicationEnum.ALL) {
fullClause += " AND " + partialClause; //NON-NLS
} else if (applyCondition == ConditionApplicationEnum.NONE) {
fullClause += " AND NOT " + partialClause; //NON-NLS
} else {
fullClause += " OR " + partialClause; //NON-NLS
}
}
}
if (parts.length > 1) {
fullClause += " )";
}
return fullClause;
} else {
// I don't think apply conditions make sense for these two.
if (typeCondition == ConditionTypeEnum.INCLUSIVE_BETWEEN) {
String[] parts = valueStr.split("##comma##"); //NON-NLS
if (parts.length != 2) {
throw new TskCoreException("Unexpected number of arguments in INCLUSIVE_BETWEEN on " + fieldName //NON-NLS
+ "(" + valueStr + ")");
}
return (fieldName + ">=" + parts[0] + " AND " + fieldName + "<=" + parts[1]); //NON-NLS
} else {
String[] parts = valueStr.split("##comma##"); //NON-NLS
if (parts.length != 2) {
throw new TskCoreException("Unexpected number of arguments in EXCLUSIVE_BETWEEN on " + fieldName //NON-NLS
+ "(" + valueStr + ")");
}
return (fieldName + ">" + parts[0] + " AND " + fieldName + "<" + parts[1]); //NON-NLS
}
}
}
/**
* Return the SQL clause for a String object
*
* @param stringObj The full Cybox String object
* @param fieldName Name of the field we're testing against
*
* @return SQL clause
*
* @throws TskCoreException
*/
private static String processStringObject(StringObjectPropertyType stringObj, String fieldName)
throws TskCoreException {
return processStringObject(stringObj.getValue().toString(), stringObj.getCondition(),
stringObj.getApplyCondition(), fieldName);
}
/**
* Return the SQL clause for a String object
*
* @param valueStr Value as a string
* @param condition Cybox condition
* @param applyCondition Cybox apply_condition
* @param fieldName Name of the field we're testing against
*
* @return SQL clause
*
* @throws TskCoreException
*/
public static String processStringObject(String valueStr, ConditionTypeEnum condition,
ConditionApplicationEnum applyCondition, String fieldName)
throws TskCoreException {
String fullClause = "";
String lowerFieldName = "lower(" + fieldName + ")"; //NON-NLS
if (valueStr.isEmpty()) {
throw new TskCoreException("Empty value field"); //NON-NLS
}
String[] parts = valueStr.split("##comma##"); //NON-NLS
for (String value : parts) {
String lowerValue = value.toLowerCase();
String partialClause;
if ((condition == null)
|| (condition == ConditionTypeEnum.EQUALS)) {
partialClause = lowerFieldName + "=\'" + lowerValue + "\'";
} else if (condition == ConditionTypeEnum.DOES_NOT_EQUAL) {
partialClause = lowerFieldName + " !=\'%" + lowerValue + "%\'";
} else if (condition == ConditionTypeEnum.CONTAINS) {
partialClause = lowerFieldName + " LIKE \'%" + lowerValue + "%\'"; //NON-NLS
} else if (condition == ConditionTypeEnum.DOES_NOT_CONTAIN) {
partialClause = lowerFieldName + " NOT LIKE \'%" + lowerValue + "%\'"; //NON-NLS
} else if (condition == ConditionTypeEnum.STARTS_WITH) {
partialClause = lowerFieldName + " LIKE \'" + lowerValue + "%\'"; //NON-NLS
} else if (condition == ConditionTypeEnum.ENDS_WITH) {
partialClause = lowerFieldName + " LIKE \'%" + lowerValue + "\'"; //NON-NLS
} else {
throw new TskCoreException("Could not process condition " + condition.value() + " on " + fieldName); //NON-NLS
}
if (fullClause.isEmpty()) {
if (parts.length > 1) {
fullClause += "( ";
}
if (applyCondition == ConditionApplicationEnum.NONE) {
fullClause += " NOT "; //NON-NLS
}
fullClause += partialClause;
} else {
if (applyCondition == ConditionApplicationEnum.ALL) {
fullClause += " AND " + partialClause; //NON-NLS
} else if (applyCondition == ConditionApplicationEnum.NONE) {
fullClause += " AND NOT " + partialClause; //NON-NLS
} else {
fullClause += " OR " + partialClause; //NON-NLS
}
}
}
if (parts.length > 1) {
fullClause += " )";
}
return fullClause;
}
/**
* Create the SQL clause for a timestamp object. Converts the time into a
* numeric field and then creates the clause from that.
*
* @param dateObj Cybox DateTimeObject
* @param fieldName Name of the field we're testing against
*
* @return SQL clause
*
* @throws TskCoreException
*/
private static String processTimestampObject(DateTimeObjectPropertyType dateObj, String fieldName)
throws TskCoreException {
if (DatatypeEnum.DATE_TIME == dateObj.getDatatype()) {
// Change the string into unix timestamps
String result = convertTimestampString(dateObj.getValue().toString());
return processNumericFields(result, dateObj.getCondition(), dateObj.getApplyCondition(), fieldName);
} else {
throw new TskCoreException("Found non DATE_TIME field on " + fieldName); //NON-NLS
}
}
/**
* Convert a timestamp string into a numeric one. Leave it as a string since
* that's what we get from other object types.
*
* @param timestampStr
*
* @return String version with timestamps replaced by numeric values
*
* @throws TskCoreException
*/
private static String convertTimestampString(String timestampStr)
throws TskCoreException {
try {
String result = "";
if (timestampStr.length() > 0) {
String[] parts = timestampStr.split("##comma##"); //NON-NLS
for (int i = 0; i < parts.length - 1; i++) {
long unixTime = convertTimestamp(parts[i]);
result += unixTime + "##comma##"; //NON-NLS
}
result += convertTimestamp(parts[parts.length - 1]);
}
return result;
} catch (java.text.ParseException ex) {
throw new TskCoreException("Error parsing timestamp string " + timestampStr); //NON-NLS
}
}
/**
* Add a new clause to the existing clause
*
* @param a_clause Current clause
* @param a_newClause New clause
*
* @return Full clause
*/
private static String addClause(String a_clause, String a_newClause) {
if ((a_clause == null) || a_clause.isEmpty()) {
return a_newClause;
}
return (a_clause + " AND " + a_newClause); //NON-NLS
}
}

View File

@ -1,162 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.util.ArrayList;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import org.mitre.cybox.common_2.ConditionApplicationEnum;
import org.mitre.cybox.objects.WindowsNetworkShare;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalNetworkShareObj extends EvaluatableObject {
private final WindowsNetworkShare obj;
public EvalNetworkShareObj(WindowsNetworkShare a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
if ((obj.getNetname() == null) && (obj.getLocalPath() == null)) {
return new ObservableResult(id, "NetworkShareObjet: No remote name or local path found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// For displaying what we were looking for in the results
String searchString = "";
if (obj.getNetname() != null) {
searchString += "Netname \"" + obj.getNetname().getValue() + "\""; //NON-NLS
// The apply conditions ALL or NONE probably won't work correctly. Neither seems
// all that likely to come up in practice, so just give a warning.
if ((obj.getNetname().getApplyCondition() != null)
&& (obj.getNetname().getApplyCondition() != ConditionApplicationEnum.ANY)) {
addWarning("Apply condition " + obj.getNetname().getApplyCondition().value() //NON-NLS
+ " may not work correctly"); //NON-NLS
}
}
if (obj.getLocalPath() != null) {
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "LocalPath \"" + obj.getLocalPath().getValue() + "\""; //NON-NLS
// Same as above - the apply conditions ALL or NONE probably won't work correctly. Neither seems
// all that likely to come up in practice, so just give a warning.
if ((obj.getLocalPath().getApplyCondition() != null)
&& (obj.getLocalPath().getApplyCondition() != ConditionApplicationEnum.ANY)) {
addWarning("Apply condition " + obj.getLocalPath().getApplyCondition().value() //NON-NLS
+ " may not work correctly"); //NON-NLS
}
}
setUnsupportedFieldWarnings();
// The assumption here is that there aren't going to be too many network shares, so we
// can cycle through all of them.
try {
List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>();
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
for (BlackboardArtifact art : artList) {
boolean foundRemotePathMatch = false;
boolean foundLocalPathMatch = false;
for (BlackboardAttribute attr : art.getAttributes()) {
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH.getTypeID())
&& (obj.getNetname() != null)) {
foundRemotePathMatch = compareStringObject(obj.getNetname(), attr.getValueString());
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCAL_PATH.getTypeID())
&& (obj.getLocalPath() != null)) {
foundLocalPathMatch = compareStringObject(obj.getLocalPath(), attr.getValueString());
}
}
// Check whether we found everything we were looking for
if (((foundRemotePathMatch) || (obj.getNetname() == null))
&& ((foundLocalPathMatch) || (obj.getLocalPath() == null))) {
finalHits.add(art);
}
}
// Check if we found any matches
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "NetworkShare")); //NON-NLS
}
return new ObservableResult(id, "NetworkShareObject: Found a match for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
// Didn't find any matches
return new ObservableResult(id, "NetworkObject: No matches found for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} catch (TskCoreException | NoCurrentCaseException ex) {
return new ObservableResult(id, "NetworkObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
private void setUnsupportedFieldWarnings() {
List<String> fieldNames = new ArrayList<String>();
if (obj.getCurrentUses() != null) {
fieldNames.add("Current_Uses"); //NON-NLS
}
if (obj.getMaxUses() != null) {
fieldNames.add("Max_Uses"); //NON-NLS
}
if (obj.getType() != null) {
fieldNames.add("Type"); //NON-NLS
}
String warningStr = "";
for (String name : fieldNames) {
if (!warningStr.isEmpty()) {
warningStr += ", ";
}
warningStr += name;
}
addWarning("Unsupported field(s): " + warningStr); //NON-NLS
}
}

View File

@ -1,485 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import com.williballenthin.rejistry.RegistryHiveFile;
import com.williballenthin.rejistry.RegistryKey;
import com.williballenthin.rejistry.RegistryParseException;
import com.williballenthin.rejistry.RegistryValue;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.AbstractFile;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.File;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.mitre.cybox.objects.WindowsRegistryKey;
import org.mitre.cybox.common_2.ConditionTypeEnum;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalRegistryObj extends EvaluatableObject {
private final WindowsRegistryKey obj;
private final List<RegistryFileInfo> regFiles = new ArrayList<>();
EvalRegistryObj(WindowsRegistryKey a_obj, String a_id, String a_spacing, List<RegistryFileInfo> a_regFiles) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
regFiles.addAll(a_regFiles);
}
private EvalRegistryObj() {
obj = null;
id = null;
spacing = "";
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
// Key name is required
if (obj.getKey() == null) {
return new ObservableResult(id, "RegistryObject: No key found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// For now, only support a full string match
if (!((obj.getKey().getCondition() == null)
|| (obj.getKey().getCondition() == ConditionTypeEnum.EQUALS))) {
return new ObservableResult(id, "RegistryObject: Can not support condition " + obj.getKey().getCondition() //NON-NLS
+ " on Key field", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
setUnsupportedFieldWarnings();
// Make a list of hives to test
List<RegistryFileInfo> hiveList = new ArrayList<>();
if (obj.getHive() == null) {
// If the hive field is missing, add everything
hiveList.addAll(regFiles);
} else if (obj.getHive().getValue().toString().startsWith("HKEY")) { //NON-NLS
// If the hive name is HKEY_LOCAL_MACHINE, add the ones from the config directory.
// Otherwise, add the others
for (RegistryFileInfo regFile : regFiles) {
if (regFile.getAbstractFile().getParentPath() != null) {
Pattern pattern = Pattern.compile("system32", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(regFile.getAbstractFile().getParentPath());
if (matcher.find()) {
// Looking for system files and found one, so add it to the list
if (obj.getHive().getValue().toString().equalsIgnoreCase("HKEY_LOCAL_MACHINE")) { //NON-NLS
hiveList.add(regFile);
}
} else {
// Looking for non-system files and found one, so add it to the list
if (!obj.getHive().getValue().toString().equalsIgnoreCase("HKEY_LOCAL_MACHINE")) { //NON-NLS
hiveList.add(regFile);
}
}
}
}
} else {
// Otherwise, try to match the name
String stixHiveName = obj.getHive().getValue().toString();
// The temp files will end \Temp\STIX\(hive)_(number)
Pattern pattern = Pattern.compile("Temp.STIX." + stixHiveName, Pattern.CASE_INSENSITIVE);
for (RegistryFileInfo hive : regFiles) {
Matcher matcher = pattern.matcher(hive.getTempFileName());
if (matcher.find()) {
hiveList.add(hive);
}
}
// If nothing matched, add all the files
if (hiveList.isEmpty()) {
hiveList.addAll(regFiles);
}
}
// This is unlikely to happen unless we have no registry files to test against
if (hiveList.isEmpty()) {
return new ObservableResult(id, "RegistryObject: No matching registry hives found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
for (RegistryFileInfo hive : hiveList) {
try {
ObservableResult result = testRegistryFile(hive);
if (result.isTrue()) {
return result;
}
} catch (Exception ex) {
// The registry parser seems to throw lots of different types of exceptions,
// so make sure to catch them all by this point. Malformed registry files
// in particular cause problems.
addWarning("Error processing registry file " + hive); //NON-NLS
}
}
if (obj.getHive() == null) {
return new ObservableResult(id, "RegistryObject: Could not find key " + obj.getKey().getValue(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
return new ObservableResult(id, "RegistryObject: Could not find key " + obj.getKey().getValue() //NON-NLS
+ " in hive " + obj.getHive().getValue(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
/**
* Test the Registry object against one registry file.
*
* @param a_regInfo The registry file
*
* @return Result of the test
*/
private ObservableResult testRegistryFile(RegistryFileInfo a_regInfo) {
try {
RegistryKey root = openRegistry(a_regInfo.getTempFileName());
RegistryKey result = findKey(root, obj.getKey().getValue().toString());
if (result == null) {
// Take another shot looking for the key minus the first part of the path (sometimes the
// hive file name is here). This should only happen if the hive name started
// with "HKEY"
if ((obj.getHive() != null)
&& obj.getHive().getValue().toString().startsWith("HKEY")) { //NON-NLS
String[] parts = obj.getKey().getValue().toString().split("\\\\");
String newKey = "";
for (int i = 1; i < parts.length; i++) {
if (newKey.length() > 0) {
newKey += "\\";
}
newKey += parts[i];
}
result = findKey(root, newKey);
}
if (result == null) {
return new ObservableResult(id, "RegistryObject: Could not find key " + obj.getKey().getValue(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
}
if ((obj.getValues() == null) || (obj.getValues().getValues().isEmpty())) {
// No values to test
List<StixArtifactData> artData = new ArrayList<>();
artData.add(new StixArtifactData(a_regInfo.getAbstractFile().getId(), id, "Registry")); //NON-NLS
return new ObservableResult(id, "RegistryObject: Found key " + obj.getKey().getValue(), //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
// Test all the values
for (org.mitre.cybox.objects.RegistryValueType stixRegValue : obj.getValues().getValues()) {
try {
for (RegistryValue valFromFile : result.getValueList()) {
// Test if the name field matches (if present)
boolean nameSuccess = true; // True if the name matches or isn't present
if (stixRegValue.getName() != null) {
try {
nameSuccess = compareStringObject(stixRegValue.getName(), valFromFile.getName());
} catch (UnsupportedEncodingException ex) {
nameSuccess = false;
}
}
boolean valueSuccess = true;
if (nameSuccess && (stixRegValue.getData() != null)) {
switch (valFromFile.getValueType()) {
case REG_SZ:
case REG_EXPAND_SZ:
try {
valueSuccess = compareStringObject(stixRegValue.getData(),
valFromFile.getValue().getAsString());
} catch (UnsupportedEncodingException ex) {
valueSuccess = false;
}
break;
case REG_DWORD:
case REG_BIG_ENDIAN:
case REG_QWORD:
// Only support "equals" for now.
if ((stixRegValue.getData().getCondition() == null)
|| (stixRegValue.getData().getCondition() == ConditionTypeEnum.EQUALS)) {
// Try to convert the STIX string to a long
try {
long stixValue = Long.decode(stixRegValue.getData().getValue().toString());
try {
valueSuccess = (stixValue == valFromFile.getValue().getAsNumber());
} catch (UnsupportedEncodingException ex) {
valueSuccess = false;
}
} catch (NumberFormatException ex) {
// We probably weren't looking at a numeric field to begin with,
// so getting this exception isn't really an error.
valueSuccess = false;
}
} else {
valueSuccess = false;
}
break;
default:
// Nothing to do here. These are the types we don't handle:
// REG_BIN, REG_FULL_RESOURCE_DESCRIPTOR, REG_LINK, REG_MULTI_SZ, REG_NONE,
// REG_RESOURCE_LIST, REG_RESOURCE_REQUIREMENTS_LIST
}
}
if (nameSuccess && valueSuccess) {
// Found a match for all values
List<StixArtifactData> artData = new ArrayList<>();
artData.add(new StixArtifactData(a_regInfo.getAbstractFile().getId(), id, "Registry")); //NON-NLS
return new ObservableResult(id, "RegistryObject: Found key " + obj.getKey().getValue() //NON-NLS
+ " and value " + stixRegValue.getName().getValue().toString() //NON-NLS
+ " = " + stixRegValue.getData().getValue().toString(),
spacing, ObservableResult.ObservableState.TRUE, artData);
}
}
} catch (Exception ex) {
// Broad catch here becase the registry parser can create all kinds of exceptions beyond what it reports.
return new ObservableResult(id, "RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
} catch (TskCoreException ex) {
return new ObservableResult(id, "RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
return new ObservableResult(id, "RegistryObject: Not done", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
public RegistryKey openRegistry(String hive) throws TskCoreException {
try {
RegistryHiveFile regFile = new RegistryHiveFile(new File(hive));
RegistryKey root = regFile.getRoot();
return root;
} catch (IOException ex) {
throw new TskCoreException("Error opening registry file - " + ex.getLocalizedMessage()); //NON-NLS
} catch (RegistryParseException ex) {
throw new TskCoreException("Error opening root node of registry - " + ex.getLocalizedMessage()); //NON-NLS
}
}
/**
* Go down the registry tree to find a key with the given name.
*
* @param root Root of the registry hive
* @param name Name of the subkey to seach for
*
* @return The matching subkey or null if not found
*/
public RegistryKey findKey(RegistryKey root, String name) {
RegistryKey currentKey = root;
// Split the key name into parts
String[] parts = name.split("\\\\");
for (String part : parts) {
if (part.length() > 0) {
try {
currentKey = currentKey.getSubkey(part);
} catch (Exception ex) {
// We get an exception if the value wasn't found (not a RegistryParseException).
// There doesn't seem to be a cleaner way to test for existance without cycling though
// everything ourselves. (Broad catch because things other than RegistryParseException
// can happen)
return null;
}
}
}
// If we make it this far, we've found it
return currentKey;
}
/**
* Copy all registry hives to the temp directory and return the list of
* created files.
*
* @return Paths to copied registry files.
*/
public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException {
// First get all the abstract files
List<AbstractFile> regFilesAbstract = findRegistryFiles();
// List to hold all the extracted file names plus their abstract file
List<RegistryFileInfo> regFilesLocal = new ArrayList<>();
// Make the temp directory
String tmpDir;
try {
tmpDir = Case.getCurrentCaseThrows().getTempDirectory() + File.separator + "STIX"; //NON-NLS
} catch (NoCurrentCaseException ex) {
throw new TskCoreException(ex.getLocalizedMessage());
}
File dir = new File(tmpDir);
if (dir.exists() == false) {
dir.mkdirs();
}
long index = 1;
for (AbstractFile regFile : regFilesAbstract) {
String regFileName = regFile.getName();
String regFileNameLocal = tmpDir + File.separator + regFileName + "_" + index;
File regFileNameLocalFile = new File(regFileNameLocal);
try {
// Don't save any unallocated versions
if (regFile.getMetaFlagsAsString().contains("Allocated")) { //NON-NLS
ContentUtils.writeToFile(regFile, regFileNameLocalFile);
regFilesLocal.add(new EvalRegistryObj().new RegistryFileInfo(regFile, regFileNameLocal));
}
} catch (IOException ex) {
throw new TskCoreException(ex.getLocalizedMessage());
}
index++;
}
return regFilesLocal;
}
/**
* Search for the registry hives on the system. Mostly copied from
* RecentActivity
*/
private static List<AbstractFile> findRegistryFiles() throws TskCoreException {
List<AbstractFile> registryFiles = new ArrayList<>();
Case openCase;
try {
openCase = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
throw new TskCoreException(ex.getLocalizedMessage());
}
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = openCase.getServices().getFileManager();
for (Content ds : openCase.getDataSources()) {
// find the user-specific ntuser-dat files
registryFiles.addAll(fileManager.findFiles(ds, "ntuser.dat")); //NON-NLS
// find the system hives
String[] regFileNames = new String[]{"system", "software", "security", "sam"}; //NON-NLS
for (String regFileName : regFileNames) {
List<AbstractFile> allRegistryFiles = fileManager.findFiles(ds, regFileName, "/system32/config"); //NON-NLS
for (AbstractFile regFile : allRegistryFiles) {
// Don't want anything from regback
if (!regFile.getParentPath().contains("RegBack")) { //NON-NLS
registryFiles.add(regFile);
}
}
}
}
return registryFiles;
}
private void setUnsupportedFieldWarnings() {
List<String> fieldNames = new ArrayList<>();
if (obj.getNumberValues() != null) {
fieldNames.add("Number_Values"); //NON-NLS
}
if (obj.getModifiedTime() != null) {
fieldNames.add("Modified_Time"); //NON-NLS
}
if (obj.getCreatorUsername() != null) {
fieldNames.add("Creator_Username"); //NON-NLS
}
if (obj.getHandleList() != null) {
fieldNames.add("Handle_List"); //NON-NLS
}
if (obj.getNumberSubkeys() != null) {
fieldNames.add("Number_Subkeys"); //NON-NLS
}
if (obj.getSubkeys() != null) {
fieldNames.add("Subkeys"); //NON-NLS
}
if (obj.getByteRuns() != null) {
fieldNames.add("Byte_Runs"); //NON-NLS
}
String warningStr = "";
for (String name : fieldNames) {
if (!warningStr.isEmpty()) {
warningStr += ", ";
}
warningStr += name;
}
addWarning("Unsupported field(s): " + warningStr); //NON-NLS
}
/**
* Class to keep track of the abstract file and temp file that goes with
* each registry hive.
*/
public class RegistryFileInfo {
private final AbstractFile abstractFile;
private final String tempFileName;
public RegistryFileInfo(AbstractFile a_abstractFile, String a_tempFileName) {
abstractFile = a_abstractFile;
tempFileName = a_tempFileName;
}
/**
* Get the AbstractFile for this RegistryFileInfo
*
* @return the abstractFile
*/
AbstractFile getAbstractFile() {
return abstractFile;
}
/**
* Get the Temporary file name for this RegistryFileInfo
*
* @return the tempFileName
*/
String getTempFileName() {
return tempFileName;
}
}
}

View File

@ -1,303 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.OSInfo;
import org.sleuthkit.datamodel.OSUtility;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.objects.SystemObjectType;
import org.mitre.cybox.objects.WindowsSystem;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalSystemObj extends EvaluatableObject {
private final SystemObjectType obj;
public EvalSystemObj(SystemObjectType a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
// For displaying what we were looking for in the results
String searchString = "";
// Check which fields are present and record them
boolean haveHostname = false;
// boolean haveDomain = false;
boolean haveProcArch = false;
boolean haveTempDir = false;
boolean haveProductName = false;
boolean haveSystemRoot = false;
boolean haveProductID = false;
boolean haveOwner = false;
boolean haveOrganization = false;
if (obj.getHostname() != null) {
haveHostname = true;
searchString = "Hostname \"" + obj.getHostname().getValue().toString() + "\""; //NON-NLS
}
if (obj.getProcessorArchitecture() != null) {
haveProcArch = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Processor architecture \"" + obj.getProcessorArchitecture().getValue().toString() + "\""; //NON-NLS
}
WindowsSystem winSysObj = null;
if (obj instanceof WindowsSystem) {
winSysObj = (WindowsSystem) obj;
if (winSysObj.getProductID() != null) {
haveProductID = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Product ID \"" + winSysObj.getProductID().getValue().toString() + "\""; //NON-NLS
}
if (winSysObj.getProductName() != null) {
haveProductName = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Product Name \"" + winSysObj.getProductName().getValue().toString() + "\""; //NON-NLS
}
if (winSysObj.getRegisteredOrganization() != null) {
haveOrganization = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Registered Org \"" + winSysObj.getRegisteredOrganization().getValue().toString() + "\""; //NON-NLS
}
if (winSysObj.getRegisteredOwner() != null) {
haveOwner = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Registered Owner \"" + winSysObj.getRegisteredOwner().getValue().toString() + "\""; //NON-NLS
}
if (winSysObj.getWindowsSystemDirectory() != null) {
haveSystemRoot = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "System root \"" + winSysObj.getWindowsSystemDirectory().getValue().toString() + "\""; //NON-NLS
}
if (winSysObj.getWindowsTempDirectory() != null) {
haveTempDir = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Temp dir \"" + winSysObj.getWindowsTempDirectory().getValue().toString() + "\""; //NON-NLS
}
}
// Return if we have nothing to search for
if (!(haveHostname || haveProcArch
|| haveTempDir || haveProductName || haveSystemRoot || haveProductID
|| haveOwner || haveOrganization)) {
return new ObservableResult(id, "SystemObject: No evaluatable fields found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
setUnsupportedFieldWarnings();
try {
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
List<OSInfo> osInfoList = OSUtility.getOSInfo(sleuthkitCase);
List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>();
if (!osInfoList.isEmpty()) {
for (OSInfo info : osInfoList) {
boolean foundHostnameMatch = false;
//boolean foundDomainMatch = false;
boolean foundProcArchMatch = false;
boolean foundTempDirMatch = false;
boolean foundProductNameMatch = false;
boolean foundSystemRootMatch = false;
boolean foundProductIDMatch = false;
boolean foundOwnerMatch = false;
boolean foundOrganizationMatch = false;
if (haveHostname) {
foundHostnameMatch = compareStringObject(obj.getHostname(), info.getCompName());
}
if (haveProcArch) {
foundProcArchMatch = compareStringObject(obj.getProcessorArchitecture().getValue().toString(),
obj.getProcessorArchitecture().getCondition(),
obj.getProcessorArchitecture().getApplyCondition(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE));
}
if (haveTempDir && (winSysObj != null)) {
foundTempDirMatch = compareStringObject(winSysObj.getWindowsTempDirectory(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEMP_DIR));
}
if (haveProductName && (winSysObj != null)) {
foundProductNameMatch = compareStringObject(winSysObj.getProductName(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME));
}
if (haveSystemRoot && (winSysObj != null)) {
foundSystemRootMatch = compareStringObject(winSysObj.getWindowsSystemDirectory(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH));
}
if (haveProductID && (winSysObj != null)) {
foundProductIDMatch = compareStringObject(winSysObj.getProductID(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PRODUCT_ID));
}
if (haveOwner && (winSysObj != null)) {
foundOwnerMatch = compareStringObject(winSysObj.getRegisteredOwner(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OWNER));
}
if (haveOrganization && (winSysObj != null)) {
foundOrganizationMatch = compareStringObject(winSysObj.getRegisteredOrganization(),
info.getAttributeValue(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ORGANIZATION));
}
if (((!haveHostname) || foundHostnameMatch)
&& ((!haveProcArch) || foundProcArchMatch)
&& ((!haveTempDir) || foundTempDirMatch)
&& ((!haveProductName) || foundProductNameMatch)
&& ((!haveSystemRoot) || foundSystemRootMatch)
&& ((!haveProductID) || foundProductIDMatch)
&& ((!haveOwner) || foundOwnerMatch)
&& ((!haveOrganization) || foundOrganizationMatch)) {
finalHits.addAll(info.getArtifacts());
}
}
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "System")); //NON-NLS
}
return new ObservableResult(id, "SystemObject: Found a match for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
// Didn't find any matches
return new ObservableResult(id, "SystemObject: No matches found for " + searchString, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} else {
return new ObservableResult(id, "SystemObject: No OS artifacts found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
} catch (TskCoreException | NoCurrentCaseException ex) {
return new ObservableResult(id, "SystemObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
/**
* Set up the warning for any fields in the object that aren't supported.
*/
private void setUnsupportedFieldWarnings() {
List<String> fieldNames = new ArrayList<String>();
if (obj.getAvailablePhysicalMemory() != null) {
fieldNames.add("Available_Physical_Memory"); //NON-NLS
}
if (obj.getBIOSInfo() != null) {
fieldNames.add("BIOS_Info"); //NON-NLS
}
if (obj.getDate() != null) {
fieldNames.add("Date"); //NON-NLS
}
if (obj.getLocalTime() != null) {
fieldNames.add("Local_Time"); //NON-NLS
}
if (obj.getNetworkInterfaceList() != null) {
fieldNames.add("Network_Interface_List"); //NON-NLS
}
if (obj.getOS() != null) {
fieldNames.add("OS"); //NON-NLS
}
if (obj.getProcessor() != null) {
fieldNames.add("Processor"); //NON-NLS
}
if (obj.getSystemTime() != null) {
fieldNames.add("System_Time"); //NON-NLS
}
if (obj.getTimezoneDST() != null) {
fieldNames.add("Timezone_DST"); //NON-NLS
}
if (obj.getTimezoneStandard() != null) {
fieldNames.add("Timezone_Standard"); //NON-NLS
}
if (obj.getTotalPhysicalMemory() != null) {
fieldNames.add("Total_Physical_Memory"); //NON-NLS
}
if (obj.getUptime() != null) {
fieldNames.add("Uptime"); //NON-NLS
}
if (obj.getUsername() != null) {
fieldNames.add("Username"); //NON-NLS
}
if (obj instanceof WindowsSystem) {
WindowsSystem winSysObj = (WindowsSystem) obj;
if (winSysObj.getDomains() != null) {
fieldNames.add("Domain"); //NON-NLS
}
if (winSysObj.getGlobalFlagList() != null) {
fieldNames.add("Global_Flag_List"); //NON-NLS
}
if (winSysObj.getNetBIOSName() != null) {
fieldNames.add("NetBIOS_Name"); //NON-NLS
}
if (winSysObj.getOpenHandleList() != null) {
fieldNames.add("Open_Handle_List"); //NON-NLS
}
if (winSysObj.getWindowsDirectory() != null) {
fieldNames.add("Windows_Directory"); //NON-NLS
}
}
String warningStr = "";
for (String name : fieldNames) {
if (!warningStr.isEmpty()) {
warningStr += ", ";
}
warningStr += name;
}
addWarning("Unsupported field(s): " + warningStr); //NON-NLS
}
}

View File

@ -1,158 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.common_2.ConditionApplicationEnum;
import org.mitre.cybox.objects.URIObjectType;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalURIObj extends EvaluatableObject {
private final URIObjectType obj;
public EvalURIObj(URIObjectType a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
if (obj.getValue() == null) {
return new ObservableResult(id, "URIObject: No URI value field found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
Case case1;
try {
case1 = Case.getCurrentCaseThrows();
} catch (NoCurrentCaseException ex) {
return new ObservableResult(id, "Exception while getting open case: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
}
String addressStr = obj.getValue().getValue().toString();
// Strip off http:// or https://
String modifiedAddressStr = addressStr.toLowerCase();
modifiedAddressStr = modifiedAddressStr.replaceAll("http(s)?://", ""); //NON-NLS
// Since we have single URL artifacts, ALL and NONE conditions probably don't make sense to test
if (!((obj.getValue().getApplyCondition() == null)
|| (obj.getValue().getApplyCondition() == ConditionApplicationEnum.ANY))) {
return new ObservableResult(id, "URIObject: Can not process apply condition " + obj.getValue().getApplyCondition().toString() //NON-NLS
+ " on URI object", spacing, ObservableResult.ObservableState.INDETERMINATE, null); //NON-NLS
}
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
try {
/*
* if ((obj.getValue().getCondition() == null) ||
* (obj.getValue().getCondition() == ConditionTypeEnum.EQUALS)) {
*
* // Old version - uses a database query but only works on full
* strings. // It will be faster to use this in the "equals" case
* String[] parts = addressStr.split("##comma##");
* List<BlackboardArtifact> arts = new
* ArrayList<BlackboardArtifact>(); for (String part : parts) {
* arts.addAll(sleuthkitCase.getBlackboardArtifacts(
* BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT,
* BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, part)); }
*
* if (!arts.isEmpty()) {
*
* List<StixArtifactData> artData = new
* ArrayList<StixArtifactData>(); for (BlackboardArtifact a : arts)
* { artData.add(new StixArtifactData(a.getObjectID(), id,
* "URIObject")); }
*
* return new ObservableResult(id, "URIObject: Found " + arts.size()
* + " matches for address = \"" + addressStr + "\"", spacing,
* ObservableResult.ObservableState.TRUE, artData);
*
* } else { return new ObservableResult(id, "URIObject: Found no
* matches for address = \"" + addressStr + "\"", spacing,
* ObservableResult.ObservableState.FALSE, null); } } else {
*/
// This is inefficient, but the easiest way to do it.
List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>();
// Get all the URL artifacts
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
for (BlackboardArtifact art : artList) {
for (BlackboardAttribute attr : art.getAttributes()) {
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
String modifiedAttrString = attr.getValueString();
if (modifiedAttrString != null) {
modifiedAttrString = modifiedAttrString.toLowerCase();
modifiedAttrString = modifiedAttrString.replaceAll("http(s)?://", ""); //NON-NLS
}
if (compareStringObject(modifiedAddressStr, obj.getValue().getCondition(),
obj.getValue().getApplyCondition(), modifiedAttrString)) {
finalHits.add(art);
}
}
}
}
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "UriObject")); //NON-NLS
}
return new ObservableResult(id, "UriObject: Found a match for " + addressStr, //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
return new ObservableResult(id, "URIObject: Found no matches for " + addressStr, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
/*
* }
*/
} catch (TskCoreException ex) {
return new ObservableResult(id, "URIObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
}

View File

@ -1,320 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.common_2.AnyURIObjectPropertyType;
import org.mitre.cybox.objects.URLHistory;
import org.mitre.cybox.objects.URLHistoryEntryType;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
/**
*
*/
class EvalURLHistoryObj extends EvaluatableObject {
private final URLHistory obj;
public EvalURLHistoryObj(URLHistory a_obj, String a_id, String a_spacing) {
obj = a_obj;
id = a_id;
spacing = a_spacing;
}
@Override
public synchronized ObservableResult evaluate() {
setWarnings("");
if ((obj.getBrowserInformation() == null) && (obj.getURLHistoryEntries() == null)) {
return new ObservableResult(id, "URLHistoryObject: No browser info or history entries found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// For displaying what we were looking for in the results
String baseSearchString = "";
String finalResultsStr = "";
// The browser info is the same for each entry
boolean haveBrowserName = false;
if (obj.getBrowserInformation() != null) {
if (obj.getBrowserInformation().getName() != null) {
haveBrowserName = true;
}
baseSearchString = "Browser \"" + obj.getBrowserInformation().getName() + "\""; //NON-NLS
}
// Matching artifacts
List<BlackboardArtifact> finalHits = new ArrayList<BlackboardArtifact>();
if (obj.getURLHistoryEntries() != null) {
for (URLHistoryEntryType entry : obj.getURLHistoryEntries()) {
boolean haveURL = false;
boolean haveHostname = false;
boolean haveReferrer = false;
boolean havePageTitle = false;
boolean haveUserProfile = false;
setUnsupportedEntryFieldWarnings(entry);
// At present, the search string doesn't get reported (because there could be different ones
// for multiple URL History Entries) but it's good for debugging.
String searchString = baseSearchString;
if ((entry.getURL() != null) && (entry.getURL().getValue() != null)) {
haveURL = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "URL \"" + entry.getURL().getValue().getValue() + "\""; //NON-NLS
}
if ((entry.getReferrerURL() != null) && (entry.getReferrerURL().getValue() != null)) {
haveReferrer = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Referrer \"" + entry.getReferrerURL().getValue().getValue() + "\""; //NON-NLS
}
if (entry.getUserProfileName() != null) {
haveUserProfile = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "UserProfile \"" + entry.getUserProfileName().getValue() + "\""; //NON-NLS
}
if (entry.getPageTitle() != null) {
havePageTitle = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Page title \"" + entry.getPageTitle().getValue() + "\""; //NON-NLS
}
if ((entry.getHostname() != null) && (entry.getHostname().getHostnameValue() != null)) {
haveHostname = true;
if (!searchString.isEmpty()) {
searchString += " and "; //NON-NLS
}
searchString += "Hostname \"" + entry.getHostname().getHostnameValue().getValue() + "\""; //NON-NLS
}
if (!finalResultsStr.isEmpty()) {
finalResultsStr += ", ";
}
finalResultsStr += searchString;
if (!(haveURL || haveHostname || haveReferrer
|| havePageTitle || haveUserProfile || haveBrowserName)) {
return new ObservableResult(id, "URLHistoryObject: No evaluatable fields found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
try {
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY);
for (BlackboardArtifact art : artList) {
boolean foundURLMatch = false;
boolean foundHostnameMatch = false;
boolean foundReferrerMatch = false;
boolean foundPageTitleMatch = false;
boolean foundUserProfileMatch = false;
boolean foundBrowserNameMatch = false;
for (BlackboardAttribute attr : art.getAttributes()) {
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID())
&& (haveURL)) {
if (entry.getURL().getValue() instanceof AnyURIObjectPropertyType) {
foundURLMatch = compareStringObject(entry.getURL().getValue().getValue().toString(),
entry.getURL().getValue().getCondition(),
entry.getURL().getValue().getApplyCondition(),
attr.getValueString());
} else {
addWarning("Non-AnyURIObjectPropertyType found in URL value field"); //NON-NLS
}
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID())
&& (haveHostname)) {
foundHostnameMatch = compareStringObject(entry.getHostname().getHostnameValue(),
attr.getValueString());
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID())
&& (haveReferrer)) {
if (entry.getReferrerURL().getValue() instanceof AnyURIObjectPropertyType) {
foundReferrerMatch = compareStringObject(entry.getReferrerURL().getValue().getValue().toString(),
entry.getURL().getValue().getCondition(),
entry.getURL().getValue().getApplyCondition(),
attr.getValueString());
} else {
addWarning("Non-AnyURIObjectPropertyType found in URL value field"); //NON-NLS
}
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID())
&& (havePageTitle)) {
foundPageTitleMatch = compareStringObject(entry.getPageTitle(),
attr.getValueString());
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())
&& (haveUserProfile)) {
foundUserProfileMatch = compareStringObject(entry.getUserProfileName(),
attr.getValueString());
}
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())
&& (haveBrowserName)) {
foundBrowserNameMatch = compareStringObject(obj.getBrowserInformation().getName(),
null, null, attr.getValueString());
}
}
if (((!haveURL) || foundURLMatch)
&& ((!haveHostname) || foundHostnameMatch)
&& ((!haveReferrer) || foundReferrerMatch)
&& ((!havePageTitle) || foundPageTitleMatch)
&& ((!haveUserProfile) || foundUserProfileMatch)
&& ((!haveBrowserName) || foundBrowserNameMatch)) {
finalHits.add(art);
}
}
} catch (TskCoreException | NoCurrentCaseException ex) {
return new ObservableResult(id, "URLHistoryObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "URLHistory")); //NON-NLS
}
return new ObservableResult(id, "URLHistoryObject: Found at least one match for " + finalResultsStr, //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
// Didn't find any matches
return new ObservableResult(id, "URLHistoryObject: No matches found for " + finalResultsStr, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} else if (haveBrowserName) {
// It doesn't seem too useful, but we can just search for the browser name
// if there aren't any URL entries
try {
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
List<BlackboardArtifact> artList
= sleuthkitCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY);
for (BlackboardArtifact art : artList) {
boolean foundBrowserNameMatch = false;
for (BlackboardAttribute attr : art.getAttributes()) {
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())
&& (haveBrowserName)) {
foundBrowserNameMatch = compareStringObject(obj.getBrowserInformation().getName(),
null, null, attr.getValueString());
}
}
if (foundBrowserNameMatch) {
finalHits.add(art);
}
}
if (!finalHits.isEmpty()) {
List<StixArtifactData> artData = new ArrayList<StixArtifactData>();
for (BlackboardArtifact a : finalHits) {
artData.add(new StixArtifactData(a.getObjectID(), id, "URLHistory")); //NON-NLS
}
return new ObservableResult(id, "URLHistoryObject: Found at least one match", //NON-NLS
spacing, ObservableResult.ObservableState.TRUE, artData);
}
// Didn't find any matches
return new ObservableResult(id, "URLHistoryObject: No matches found for " + baseSearchString, //NON-NLS
spacing, ObservableResult.ObservableState.FALSE, null);
} catch (TskCoreException | NoCurrentCaseException ex) {
return new ObservableResult(id, "URLHistoryObject: Exception during evaluation: " + ex.getLocalizedMessage(), //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
} else {
// Nothing to search for
return new ObservableResult(id, "URLHistoryObject: No evaluatable fields found", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
}
/**
* Set up the warning for any fields in the URL_History_Entry object that
* aren't supported.
*/
private void setUnsupportedEntryFieldWarnings(URLHistoryEntryType entry) {
List<String> fieldNames = new ArrayList<String>();
if (entry.getUserProfileName() != null) {
fieldNames.add("User_Profile_Name"); //NON-NLS
}
if (entry.getVisitCount() != null) {
fieldNames.add("Visit_Count"); //NON-NLS
}
if (entry.getManuallyEnteredCount() != null) {
fieldNames.add("Manually_Entered_Count"); //NON-NLS
}
if (entry.getModificationDateTime() != null) {
fieldNames.add("Modification_DateTime"); //NON-NLS
}
if (entry.getExpirationDateTime() != null) {
fieldNames.add("Expiration_DateTime"); //NON-NLS
}
if (entry.getFirstVisitDateTime() != null) {
fieldNames.add("First_Visit_DateTime"); //NON-NLS
}
if (entry.getLastVisitDateTime() != null) {
fieldNames.add("Last_Visit_DateTime"); //NON-NLS
}
String warningStr = "";
for (String name : fieldNames) {
if (!warningStr.isEmpty()) {
warningStr += ", ";
}
warningStr += name;
}
addWarning("Unsupported URL_History_Entry field(s): " + warningStr); //NON-NLS
}
}

View File

@ -1,261 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.util.ArrayList;
import java.util.List;
import org.mitre.cybox.common_2.ConditionApplicationEnum;
import org.mitre.cybox.common_2.ConditionTypeEnum;
import org.mitre.cybox.common_2.StringObjectPropertyType;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
*
*/
abstract class EvaluatableObject {
private String warnings;
protected String id;
protected String spacing;
abstract public ObservableResult evaluate();
/**
* Set the warnings string to the given value.
*
* @param a_warnings
*/
public void setWarnings(String a_warnings) {
warnings = a_warnings;
}
/**
* Get the warnings string. This should not be used to print the final
* version of the warnings.
*
* @return
*/
public String getWarnings() {
return warnings;
}
/**
* Add to the warnings string.
*
* @param a_newWarning
*/
public void addWarning(String a_newWarning) {
if ((warnings == null) || warnings.isEmpty()) {
warnings = a_newWarning;
return;
}
warnings = warnings + ", " + a_newWarning;
}
/**
* Find a list of artifacts with the given attribute type that contain the
* String Object. All comparisons will look for substrings of the Blackboard
* artifacts that match the String Object.
*
* @param item
* @param attrType
*
* @return
*
* @throws TskCoreException
*/
public List<BlackboardArtifact> findArtifactsBySubstring(StringObjectPropertyType item,
BlackboardAttribute.ATTRIBUTE_TYPE attrType) throws TskCoreException {
if (item.getValue() == null) {
throw new TskCoreException("Error: Value field is null"); //NON-NLS
}
if (item.getCondition() == null) {
addWarning("Warning: No condition given for " + attrType.getDisplayName() + " field, using substring comparison"); //NON-NLS
} else if (item.getCondition() != ConditionTypeEnum.CONTAINS) {
addWarning("Warning: Ignoring condition " + item.getCondition() + " for " //NON-NLS
+ attrType.getDisplayName() + " field and doing substring comparison"); //NON-NLS
}
List<BlackboardArtifact> hits = null;
try {
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
String[] parts = item.getValue().toString().split("##comma##"); //NON-NLS
if ((item.getApplyCondition() == null)
|| (item.getApplyCondition() == ConditionApplicationEnum.ANY)) {
for (String part : parts) {
if (hits == null) {
// Note that this searches for artifacts with "part" as a substring
hits = sleuthkitCase.getBlackboardArtifacts(
attrType,
part, false);
} else {
hits.addAll(sleuthkitCase.getBlackboardArtifacts(
attrType,
part, false));
}
}
} else if ((item.getApplyCondition() != null)
|| (item.getApplyCondition() == ConditionApplicationEnum.ALL)) {
boolean firstRound = true;
for (String part : parts) {
if (firstRound) {
hits = sleuthkitCase.getBlackboardArtifacts(
attrType,
part, false);
firstRound = false;
} else if (hits != null) {
hits.retainAll(sleuthkitCase.getBlackboardArtifacts(
attrType,
part, false));
} else {
// After first round; hits is still null
// I don't think this should happen but if it does we're done
return new ArrayList<BlackboardArtifact>();
}
}
} else {
throw new TskCoreException("Error: Can not apply NONE condition in search"); //NON-NLS
}
} catch (TskCoreException | NoCurrentCaseException ex) {
addWarning(ex.getLocalizedMessage());
}
return hits;
}
/**
* Compare a CybOX String Object with a given string.
*
* @param stringObj The CybOX String Object
* @param strField The string to compare against
*
* @return true if strField is a match for the CybOX object
*
* @throws TskCoreException
*/
public static boolean compareStringObject(StringObjectPropertyType stringObj, String strField)
throws TskCoreException {
if (stringObj.getValue() == null) {
throw new TskCoreException("Error: Value field is null"); //NON-NLS
}
String valueStr = stringObj.getValue().toString();
ConditionTypeEnum condition = stringObj.getCondition();
ConditionApplicationEnum applyCondition = stringObj.getApplyCondition();
return compareStringObject(valueStr, condition, applyCondition, strField);
}
/**
* Compare a string with CybOX conditions to a given string.
*
* @param valueStr The CybOX string
* @param condition EQUALS, CONTAINS, STARTS_WITH, etc
* @param applyCondition ANY, ALL, NONE
* @param strField The string to compare against
*
* @return true if strField is a match for the CybOX valueStr and conditions
*
* @throws TskCoreException
*/
public static boolean compareStringObject(String valueStr, ConditionTypeEnum condition,
ConditionApplicationEnum applyCondition, String strField)
throws TskCoreException {
if (valueStr == null) {
throw new TskCoreException("Error: Value field is null"); //NON-NLS
}
String[] parts = valueStr.split("##comma##"); //NON-NLS
String lowerFieldName = strField.toLowerCase();
for (String value : parts) {
boolean partialResult;
if ((condition == null)
|| (condition == ConditionTypeEnum.EQUALS)) {
partialResult = value.equalsIgnoreCase(strField);
} else if (condition == ConditionTypeEnum.DOES_NOT_EQUAL) {
partialResult = !value.equalsIgnoreCase(strField);
} else if (condition == ConditionTypeEnum.CONTAINS) {
partialResult = lowerFieldName.contains(value.toLowerCase());
} else if (condition == ConditionTypeEnum.DOES_NOT_CONTAIN) {
partialResult = !lowerFieldName.contains(value.toLowerCase());
} else if (condition == ConditionTypeEnum.STARTS_WITH) {
partialResult = lowerFieldName.startsWith(value.toLowerCase());
} else if (condition == ConditionTypeEnum.ENDS_WITH) {
partialResult = lowerFieldName.endsWith(value.toLowerCase());
} else {
throw new TskCoreException("Could not process condition " + condition.value() + " on " + value); //NON-NLS
}
// Do all the short-circuiting
if (applyCondition == ConditionApplicationEnum.NONE) {
if (partialResult == true) {
// Failed
return false;
}
} else if (applyCondition == ConditionApplicationEnum.ALL) {
if (partialResult == false) {
// Failed
return false;
}
} else {
// Default is "any"
if (partialResult == true) {
return true;
}
}
}
// At this point we're done and didn't short-circuit, so ALL or NONE conditions were true,
// and ANY was false
if ((applyCondition == ConditionApplicationEnum.NONE)
|| (applyCondition == ConditionApplicationEnum.ALL)) {
return true;
}
return false;
}
/**
* Format the warnings that will be printed. Basically, just put parentheses
* around them if the string isn't empty.
*
* @return
*/
public String getPrintableWarnings() {
String warningsToPrint = "";
if ((getWarnings() != null)
&& (!getWarnings().isEmpty())) {
warningsToPrint = " (" + getWarnings() + ")";
}
return warningsToPrint;
}
}

View File

@ -1,199 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.util.List;
import java.util.ArrayList;
import org.mitre.cybox.cybox_2.OperatorTypeEnum;
/**
*
*/
class ObservableResult {
public enum ObservableState {
TRUE("true "), //NON-NLS
FALSE("false "), //NON-NLS
INDETERMINATE("indeterminate"); //NON-NLS
private final String label;
private ObservableState(String s) {
label = s;
}
@Override
public String toString() {
return label;
}
}
private ObservableState state = null;
private String description = "";
private List<StixArtifactData> artifacts;
public ObservableResult(String a_id, String a_desc, String a_spacing,
ObservableState a_state, List<StixArtifactData> a_artifacts) {
state = a_state;
description = a_spacing + a_id + "\t" + a_state + "\t" + a_desc + "\r\n";
artifacts = a_artifacts;
}
public ObservableResult(OperatorTypeEnum a_operator, String a_spacing) {
state = ObservableState.INDETERMINATE;
description = a_spacing + a_operator + "\r\n";
artifacts = new ArrayList<StixArtifactData>();
}
public ObservableState getState() {
return state;
}
/**
* Returns true if the ObservableResult is currently true. Note: A false
* result here does not mean the state is false; it could also be
* indeterminate.
*
* @return true if the ObservableResult is true, false if it is false or
* indeterminate
*/
public boolean isTrue() {
return (state == ObservableState.TRUE);
}
/**
* Returns true if the ObservableResult is currently false. Note: A false
* result here does not mean the state is true; it could also be
* indeterminate.
*
* @return true if the ObservableResult is false, false if it is true or
* indeterminate
*/
public boolean isFalse() {
return (state == ObservableState.FALSE);
}
public String getDescription() {
return description;
}
public List<StixArtifactData> getArtifacts() {
return artifacts;
}
/**
* Add a new result to the current state
*
* @param a_result The new result to add
* @param a_operator AND or OR
*/
public void addResult(ObservableResult a_result, OperatorTypeEnum a_operator) {
addResult(a_result.getDescription(), a_result.getState(),
a_result.getArtifacts(), a_operator);
}
/**
* Add a new result to the current state.
*
* @param a_description Description of the observable and testing done
* @param a_state State of what we're adding (true, false, or
* indeterminate)
* @param a_operator AND or OR
*/
private void addResult(String a_description, ObservableState a_state,
List<StixArtifactData> a_artifacts, OperatorTypeEnum a_operator) {
addToDesc(a_description);
if (a_operator == OperatorTypeEnum.AND) {
if (a_state == ObservableState.FALSE) {
// If we now have a false, the whole thing is false regardless of previous state.
// Clear out any existing artifacts.
state = ObservableState.FALSE;
artifacts.clear();
} else if (a_state == ObservableState.INDETERMINATE) {
// Don't change the current state, and don't save the new artifacts
// (though there probably wouldn't be any)
} else {
if (state == ObservableState.FALSE) {
// Previous state false + new state true => stay false
} else if (state == ObservableState.TRUE) {
// Previous state true + new state true => stay true and add artifacts
if ((artifacts == null) && (a_artifacts != null)) {
artifacts = new ArrayList<StixArtifactData>();
}
if (a_artifacts != null) {
artifacts.addAll(a_artifacts);
}
} else {
// If the previous state was indeterminate, change it to true and add artifacts
state = ObservableState.TRUE;
if ((artifacts == null) && (a_artifacts != null)) {
artifacts = new ArrayList<StixArtifactData>();
}
if (a_artifacts != null) {
artifacts.addAll(a_artifacts);
}
}
}
} else {
if (a_state == ObservableState.TRUE) {
// If we now have a true, the whole thing is true regardless of previous state.
// Add the new artifacts.
state = ObservableState.TRUE;
if ((artifacts == null) && (a_artifacts != null)) {
artifacts = new ArrayList<StixArtifactData>();
}
if (a_artifacts != null) {
artifacts.addAll(a_artifacts);
}
} else if (a_state == ObservableState.INDETERMINATE) {
// Don't change the current state and don't record it to the
// description string (later we should save these in some way)
} else {
if (state == ObservableState.FALSE) {
// Previous state false + new state false => stay false
} else if (state == ObservableState.TRUE) {
// Previous state true + new state false => stay true
} else {
// Previous state indeterminate + new state false => change to false
state = ObservableState.FALSE;
}
}
}
}
/**
* Add to the description string. Mostly just to make things cleaner by not
* testing for null all over the place.
*
* @param a_desc New part of the description to add
*/
private void addToDesc(String a_desc) {
if (description == null) {
description = a_desc;
} else {
description += a_desc;
}
}
}

View File

@ -1,699 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 - 2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.JPanel;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import org.mitre.cybox.cybox_2.ObjectType;
import org.mitre.cybox.cybox_2.Observable;
import org.mitre.cybox.cybox_2.ObservableCompositionType;
import org.mitre.cybox.cybox_2.OperatorTypeEnum;
import org.mitre.cybox.objects.AccountObjectType;
import org.mitre.cybox.objects.Address;
import org.mitre.cybox.objects.DomainName;
import org.mitre.cybox.objects.EmailMessage;
import org.mitre.cybox.objects.FileObjectType;
import org.mitre.cybox.objects.SystemObjectType;
import org.mitre.cybox.objects.URIObjectType;
import org.mitre.cybox.objects.URLHistory;
import org.mitre.cybox.objects.WindowsNetworkShare;
import org.mitre.cybox.objects.WindowsRegistryKey;
import org.mitre.stix.common_1.IndicatorBaseType;
import org.mitre.stix.indicator_2.Indicator;
import org.mitre.stix.stix_1.STIXPackage;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.report.GeneralReportModule;
import org.sleuthkit.autopsy.report.GeneralReportSettings;
import org.sleuthkit.autopsy.report.NoReportModuleSettings;
import org.sleuthkit.autopsy.report.ReportModuleSettings;
import org.sleuthkit.autopsy.report.ReportProgressPanel;
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
import org.sleuthkit.datamodel.TskCoreException;
/**
*
*/
public class STIXReportModule implements GeneralReportModule {
private static final Logger logger = Logger.getLogger(STIXReportModule.class.getName());
private STIXReportModuleConfigPanel configPanel;
private static STIXReportModule instance = null;
private String reportPath;
private boolean reportAllResults;
private Map<String, ObjectType> idToObjectMap = new HashMap<>();
private Map<String, ObservableResult> idToResult = new HashMap<>();
private List<EvalRegistryObj.RegistryFileInfo> registryFileData = null;
private final boolean skipShortCircuit = true;
// Hidden constructor for the report
private STIXReportModule() {
}
// Get the default implementation of this report
public static synchronized STIXReportModule getDefault() {
if (instance == null) {
instance = new STIXReportModule();
}
return instance;
}
/**
* @param settings Report settings.
* @param progressPanel panel to update the report's progress
*/
@Override
@Messages({"STIXReportModule.srcModuleName.text=STIX Report"})
public void generateReport(GeneralReportSettings settings, ReportProgressPanel progressPanel) {
// Start the progress bar and setup the report
progressPanel.setIndeterminate(false);
progressPanel.start();
String baseReportDir = settings.getReportDirectoryPath();
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX"));
reportPath = baseReportDir + getRelativeFilePath();
File reportFile = new File(reportPath);
// Check if the user wants to display all output or just hits
reportAllResults = configPanel.getShowAllResults();
// Keep track of whether any errors occur during processing
boolean hadErrors = false;
// Process the file/directory name entry
String stixFileName = configPanel.getStixFile();
if (stixFileName == null) {
logger.log(Level.SEVERE, "STIXReportModuleConfigPanel.stixFile not initialized "); //NON-NLS
progressPanel.complete(ReportStatus.ERROR, NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided"));
new File(baseReportDir).delete();
return;
}
if (stixFileName.isEmpty()) {
logger.log(Level.SEVERE, "No STIX file/directory provided "); //NON-NLS
progressPanel.complete(ReportStatus.ERROR, NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided"));
new File(baseReportDir).delete();
return;
}
File stixFile = new File(stixFileName);
if (!stixFile.exists()) {
logger.log(Level.SEVERE, String.format("Unable to open STIX file/directory %s", stixFileName)); //NON-NLS
progressPanel.complete(ReportStatus.ERROR, NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
new File(baseReportDir).delete();
return;
}
try (BufferedWriter output = new BufferedWriter(new FileWriter(reportFile))) {
// Create array of stix file(s)
File[] stixFiles;
if (stixFile.isFile()) {
stixFiles = new File[1];
stixFiles[0] = stixFile;
} else {
stixFiles = stixFile.listFiles();
}
// Set the length of the progress bar - we increment twice for each file
progressPanel.setMaximumProgress(stixFiles.length * 2 + 1);
// Process each STIX file
for (File file : stixFiles) {
if (progressPanel.getStatus() == ReportStatus.CANCELED) {
return;
}
try {
processFile(file.getAbsolutePath(), progressPanel, output);
} catch (TskCoreException | JAXBException ex) {
String errMsg = String.format("Unable to process STIX file %s", file);
logger.log(Level.SEVERE, errMsg, ex); //NON-NLS
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), errMsg));
hadErrors = true;
break;
}
// Clear out the ID maps before loading the next file
idToObjectMap = new HashMap<>();
idToResult = new HashMap<>();
}
// Set the progress bar to done. If any errors occurred along the way, modify
// the "complete" message to indicate this.
Case.getCurrentCaseThrows().addReport(reportPath, Bundle.STIXReportModule_srcModuleName_text(), "");
if (hadErrors) {
progressPanel.complete(ReportStatus.ERROR, NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
} else {
progressPanel.complete(ReportStatus.COMPLETE);
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Unable to complete STIX report.", ex); //NON-NLS
progressPanel.complete(ReportStatus.ERROR, NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
} catch (TskCoreException | NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Unable to add report to database.", ex);
}
}
/**
* Process a STIX file.
*
* @param stixFile - Name of the file
* @param progressPanel - Progress panel (for updating)
* @param output
*
* @throws JAXBException
* @throws TskCoreException
*/
private void processFile(String stixFile, ReportProgressPanel progressPanel, BufferedWriter output) throws
JAXBException, TskCoreException {
// Load the STIX file
STIXPackage stix;
stix = loadSTIXFile(stixFile);
printFileHeader(stixFile, output);
// Save any observables listed up front
processObservables(stix);
progressPanel.increment();
// Make copies of the registry files
registryFileData = EvalRegistryObj.copyRegistryFiles();
// Process the indicators
processIndicators(stix, output, progressPanel);
progressPanel.increment();
}
/**
* Load a STIX-formatted XML file into a STIXPackage object.
*
* @param stixFileName Name of the STIX file to unmarshal
*
* @return Unmarshalled file contents
*
* @throws JAXBException
*/
private STIXPackage loadSTIXFile(String stixFileName) throws JAXBException {
// Create STIXPackage object from xml.
// See JIRA-6958 for details about class loading and jaxb.
ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(STIXReportModule.class.getClassLoader());
File file = new File(stixFileName);
JAXBContext jaxbContext = JAXBContext.newInstance("org.mitre.stix.stix_1:org.mitre.stix.common_1:org.mitre.stix.indicator_2:" //NON-NLS
+ "org.mitre.cybox.objects:org.mitre.cybox.cybox_2:org.mitre.cybox.common_2"); //NON-NLS
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
STIXPackage stix = (STIXPackage) jaxbUnmarshaller.unmarshal(file);
return stix;
} finally {
Thread.currentThread().setContextClassLoader(original);
}
}
/**
* Do the initial processing of the list of observables. For each
* observable, save it in a map using the ID as key.
*
* @param stix STIXPackage
*/
private void processObservables(STIXPackage stix) {
if (stix.getObservables() != null) {
List<Observable> obs = stix.getObservables().getObservables();
for (Observable o : obs) {
if (o.getId() != null) {
saveToObjectMap(o);
}
}
}
}
/**
* Process all STIX indicators and save results to output file and create
* artifacts.
*
* @param stix STIXPackage
* @param output
* @param progressPanel
*/
private void processIndicators(STIXPackage stix, BufferedWriter output, ReportProgressPanel progressPanel) throws TskCoreException {
if (stix.getIndicators() != null) {
List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
for (IndicatorBaseType t : s) {
if (t instanceof Indicator) {
Indicator ind = (Indicator) t;
if (ind.getObservable() != null) {
if (ind.getObservable().getObject() != null) {
ObservableResult result = evaluateSingleObservable(ind.getObservable(), "");
if (result.isTrue() || reportAllResults) {
writeResultsToFile(ind, result.getDescription(), result.isTrue(), output);
}
if (result.isTrue()) {
saveResultsAsArtifacts(ind, result, progressPanel);
}
} else if (ind.getObservable().getObservableComposition() != null) {
ObservableResult result = evaluateObservableComposition(ind.getObservable().getObservableComposition(), " ");
if (result.isTrue() || reportAllResults) {
writeResultsToFile(ind, result.getDescription(), result.isTrue(), output);
}
if (result.isTrue()) {
saveResultsAsArtifacts(ind, result, progressPanel);
}
}
}
}
}
}
}
/**
* Create the artifacts saved in the observable result.
*
* @param ind
* @param result
* @param progressPanel
*
* @throws TskCoreException
*/
private void saveResultsAsArtifacts(Indicator ind, ObservableResult result, ReportProgressPanel progressPanel) throws TskCoreException {
if (result.getArtifacts() == null) {
return;
}
// Count of how many artifacts have been created for this indicator.
int count = 0;
for (StixArtifactData s : result.getArtifacts()) {
// Figure out what name to use for this indicator. If it has a title,
// use that. Otherwise use the ID. If both are missing, use a
// generic heading.
if (ind.getTitle() != null) {
s.createArtifact(ind.getTitle());
} else if (ind.getId() != null) {
s.createArtifact(ind.getId().toString());
} else {
s.createArtifact("Unnamed indicator(s)"); //NON-NLS
}
// Trying to protect against the case where we end up with tons of artifacts
// for a single observable because the condition was not restrictive enough
count++;
if (count > 1000) {
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(),
"STIXReportModule.notifyMsg.tooManyArtifactsgt1000"));
break;
}
}
}
/**
* Write the full results string to the output file.
*
* @param ind - Used to get the title, ID, and description of the
* indicator
* @param resultStr - Full results for this indicator
* @param found - true if the indicator was found in datasource(s)
* @param output
*/
private void writeResultsToFile(Indicator ind, String resultStr, boolean found, BufferedWriter output) {
if (output != null) {
try {
if (found) {
output.write("----------------\r\n"
+ "Found indicator:\r\n"); //NON-NLS
} else {
output.write("-----------------------\r\n"
+ "Did not find indicator:\r\n"); //NON-NLS
}
if (ind.getTitle() != null) {
output.write("Title: " + ind.getTitle() + "\r\n"); //NON-NLS
} else {
output.write("\r\n");
}
if (ind.getId() != null) {
output.write("ID: " + ind.getId() + "\r\n"); //NON-NLS
}
if (ind.getDescription() != null) {
String desc = ind.getDescription().getValue();
desc = desc.trim();
output.write("Description: " + desc + "\r\n"); //NON-NLS
}
output.write("\r\nObservable results:\r\n" + resultStr + "\r\n\r\n"); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing to STIX report file %s", reportPath), ex); //NON-NLS
}
}
}
/**
* Write the a header for the current file to the output file.
*
* @param a_fileName
* @param output
*/
private void printFileHeader(String a_fileName, BufferedWriter output) {
if (output != null) {
try {
char[] chars = new char[a_fileName.length() + 8];
Arrays.fill(chars, '#');
String header = new String(chars);
output.write("\r\n" + header);
output.write("\r\n");
output.write("### " + a_fileName + " ###\r\n");
output.write(header + "\r\n\r\n");
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing to STIX report file %s", reportPath), ex); //NON-NLS
}
}
}
/**
* Use the ID or ID ref to create a key into the observable map.
*
* @param obs
*
* @return
*/
private String makeMapKey(Observable obs) {
QName idQ;
if (obs.getId() != null) {
idQ = obs.getId();
} else if (obs.getIdref() != null) {
idQ = obs.getIdref();
} else {
return "";
}
return idQ.getLocalPart();
}
/**
* Save an observable in the object map.
*
* @param obs
*/
private void saveToObjectMap(Observable obs) {
if (obs.getObject() != null) {
idToObjectMap.put(makeMapKey(obs), obs.getObject());
}
}
/**
* Evaluate an observable composition. Can be called recursively.
*
* @param comp The observable composition object to evaluate
* @param spacing Used to formatting the output
*
* @return The status of the composition
*
* @throws TskCoreException
*/
private ObservableResult evaluateObservableComposition(ObservableCompositionType comp, String spacing) throws TskCoreException {
if (comp.getOperator() == null) {
throw new TskCoreException("No operator found in composition"); //NON-NLS
}
if (comp.getObservables() != null) {
List<Observable> obsList = comp.getObservables();
// Split based on the type of composition (AND vs OR)
if (comp.getOperator() == OperatorTypeEnum.AND) {
ObservableResult result = new ObservableResult(OperatorTypeEnum.AND, spacing);
for (Observable o : obsList) {
ObservableResult newResult; // The combined result for the composition
if (o.getObservableComposition() != null) {
newResult = evaluateObservableComposition(o.getObservableComposition(), spacing + " ");
if (result == null) {
result = newResult;
} else {
result.addResult(newResult, OperatorTypeEnum.AND);
}
} else {
newResult = evaluateSingleObservable(o, spacing + " ");
if (result == null) {
result = newResult;
} else {
result.addResult(newResult, OperatorTypeEnum.AND);
}
}
if ((!skipShortCircuit) && !result.isFalse()) {
// For testing purposes (and maybe in general), may not want to short-circuit
return result;
}
}
// At this point, all comparisions should have been true (or indeterminate)
if (result == null) {
// This really shouldn't happen, but if we have an empty composition,
// indeterminate seems like a reasonable result
return new ObservableResult("", "", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
return result;
} else {
ObservableResult result = new ObservableResult(OperatorTypeEnum.OR, spacing);
for (Observable o : obsList) {
ObservableResult newResult;// The combined result for the composition
if (o.getObservableComposition() != null) {
newResult = evaluateObservableComposition(o.getObservableComposition(), spacing + " ");
if (result == null) {
result = newResult;
} else {
result.addResult(newResult, OperatorTypeEnum.OR);
}
} else {
newResult = evaluateSingleObservable(o, spacing + " ");
if (result == null) {
result = newResult;
} else {
result.addResult(newResult, OperatorTypeEnum.OR);
}
}
if ((!skipShortCircuit) && result.isTrue()) {
// For testing (and maybe in general), may not want to short-circuit
return result;
}
}
// At this point, all comparisions were false (or indeterminate)
if (result == null) {
// This really shouldn't happen, but if we have an empty composition,
// indeterminate seems like a reasonable result
return new ObservableResult("", "", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
return result;
}
} else {
throw new TskCoreException("No observables found in list"); //NON-NLS
}
}
/**
* Evaluate one observable and return the result. This is at the end of the
* observable composition tree and will not be called recursively.
*
* @param obs The observable object to evaluate
* @param spacing For formatting the output
*
* @return The status of the observable
*
* @throws TskCoreException
*/
private ObservableResult evaluateSingleObservable(Observable obs, String spacing) throws TskCoreException {
// If we've already calculated this one, return the saved value
if (idToResult.containsKey(makeMapKey(obs))) {
return idToResult.get(makeMapKey(obs));
}
if (obs.getIdref() == null) {
// We should have the object data right here (as opposed to elsewhere in the STIX file).
// Save it to the map.
if (obs.getId() != null) {
saveToObjectMap(obs);
}
if (obs.getObject() != null) {
ObservableResult result = evaluateObject(obs.getObject(), spacing, makeMapKey(obs));
idToResult.put(makeMapKey(obs), result);
return result;
}
}
if (idToObjectMap.containsKey(makeMapKey(obs))) {
ObservableResult result = evaluateObject(idToObjectMap.get(makeMapKey(obs)), spacing, makeMapKey(obs));
idToResult.put(makeMapKey(obs), result);
return result;
}
throw new TskCoreException("Error loading/finding object for observable " + obs.getIdref()); //NON-NLS
}
/**
* Evaluate a STIX object.
*
*
* @param obj The object to evaluate against the datasource(s)
* @param spacing For formatting the output
* @param id
*
* @return
*/
private ObservableResult evaluateObject(ObjectType obj, String spacing, String id) {
EvaluatableObject evalObj;
if (obj.getProperties() instanceof FileObjectType) {
evalObj = new EvalFileObj((FileObjectType) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof Address) {
evalObj = new EvalAddressObj((Address) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof URIObjectType) {
evalObj = new EvalURIObj((URIObjectType) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof EmailMessage) {
evalObj = new EvalEmailObj((EmailMessage) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof WindowsNetworkShare) {
evalObj = new EvalNetworkShareObj((WindowsNetworkShare) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof AccountObjectType) {
evalObj = new EvalAccountObj((AccountObjectType) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof SystemObjectType) {
evalObj = new EvalSystemObj((SystemObjectType) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof URLHistory) {
evalObj = new EvalURLHistoryObj((URLHistory) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof DomainName) {
evalObj = new EvalDomainObj((DomainName) obj.getProperties(), id, spacing);
} else if (obj.getProperties() instanceof WindowsRegistryKey) {
evalObj = new EvalRegistryObj((WindowsRegistryKey) obj.getProperties(), id, spacing, registryFileData);
} else {
// Try to get the object type as a string
String type = obj.getProperties().toString();
type = type.substring(0, type.indexOf("@"));
if ((type.lastIndexOf(".") + 1) < type.length()) {
type = type.substring(type.lastIndexOf(".") + 1);
}
return new ObservableResult(id, type + " not supported", //NON-NLS
spacing, ObservableResult.ObservableState.INDETERMINATE, null);
}
// Evalutate the object
return evalObj.evaluate();
}
@Override
public String getName() {
String name = NbBundle.getMessage(this.getClass(), "STIXReportModule.getName.text");
return name;
}
@Override
public String getRelativeFilePath() {
return "stix.txt"; //NON-NLS
}
@Override
public String getDescription() {
String desc = NbBundle.getMessage(this.getClass(), "STIXReportModule.getDesc.text");
return desc;
}
@Override
public JPanel getConfigurationPanel() {
initializePanel();
return configPanel;
}
private void initializePanel() {
if (configPanel == null) {
configPanel = new STIXReportModuleConfigPanel();
}
}
/**
* Get default configuration for this report module.
*
* @return Object which contains default report module settings.
*/
@Override
public ReportModuleSettings getDefaultConfiguration() {
return new STIXReportModuleSettings();
}
/**
* Get current configuration for this report module.
*
* @return Object which contains current report module settings.
*/
@Override
public ReportModuleSettings getConfiguration() {
initializePanel();
return configPanel.getConfiguration();
}
/**
* Set report module configuration.
*
* @param settings Object which contains report module settings.
*/
@Override
public void setConfiguration(ReportModuleSettings settings) {
initializePanel();
if (settings == null || settings instanceof NoReportModuleSettings) {
configPanel.setConfiguration((STIXReportModuleSettings) getDefaultConfiguration());
return;
}
if (settings instanceof STIXReportModuleSettings) {
configPanel.setConfiguration((STIXReportModuleSettings) settings);
return;
}
throw new IllegalArgumentException("Expected settings argument to be an instance of STIXReportModuleSettings");
}
}

View File

@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jStixFileTextField" min="-2" pref="292" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jButton1" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="73" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jStixFileTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jButton1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jCheckBox1" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="225" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/modules/stix/Bundle.properties" key="STIXReportModuleConfigPanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
</AuxValues>
</Component>
<Component class="javax.swing.JTextField" name="jStixFileTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/modules/stix/Bundle.properties" key="STIXReportModuleConfigPanel.jStixFileTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jStixFileTextFieldActionPerformed"/>
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="jStixFileTextFieldKeyReleased"/>
<EventHandler event="keyTyped" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="jStixFileTextFieldKeyTyped"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="jButton1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/modules/stix/Bundle.properties" key="STIXReportModuleConfigPanel.jButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
</AuxValues>
</Component>
<Component class="javax.swing.JCheckBox" name="jCheckBox1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/modules/stix/Bundle.properties" key="STIXReportModuleConfigPanel.jCheckBox1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBox1ActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
</AuxValues>
</Component>
</SubComponents>
</Form>

View File

@ -1,179 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.io.File;
import javax.swing.JFileChooser;
import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
/**
* Configuration panel for STIX report generation.
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class STIXReportModuleConfigPanel extends javax.swing.JPanel {
String stixFile = null;
boolean showAllResults;
private final JFileChooserFactory chooserHelper;
/**
* Creates new form STIXReportModuleConfigPanel
*/
public STIXReportModuleConfigPanel() {
initComponents();
showAllResults = false;
jCheckBox1.setSelected(false);
chooserHelper = new JFileChooserFactory();
}
void setConfiguration(STIXReportModuleSettings settings) {
jStixFileTextField.setText(settings.getStixFile());
showAllResults = settings.isShowAllResults();
jCheckBox1.setSelected(settings.isShowAllResults());
}
STIXReportModuleSettings getConfiguration() {
return new STIXReportModuleSettings(jStixFileTextField.getText(), jCheckBox1.isSelected());
}
String getStixFile() {
return stixFile;
}
boolean getShowAllResults() {
return showAllResults;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel2 = new javax.swing.JLabel();
jStixFileTextField = new javax.swing.JTextField();
jButton1 = new javax.swing.JButton();
jCheckBox1 = new javax.swing.JCheckBox();
jLabel2.setText(org.openide.util.NbBundle.getMessage(STIXReportModuleConfigPanel.class, "STIXReportModuleConfigPanel.jLabel2.text")); // NOI18N
jStixFileTextField.setText(org.openide.util.NbBundle.getMessage(STIXReportModuleConfigPanel.class, "STIXReportModuleConfigPanel.jStixFileTextField.text")); // NOI18N
jStixFileTextField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jStixFileTextFieldActionPerformed(evt);
}
});
jStixFileTextField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
jStixFileTextFieldKeyReleased(evt);
}
public void keyTyped(java.awt.event.KeyEvent evt) {
jStixFileTextFieldKeyTyped(evt);
}
});
jButton1.setText(org.openide.util.NbBundle.getMessage(STIXReportModuleConfigPanel.class, "STIXReportModuleConfigPanel.jButton1.text")); // NOI18N
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jCheckBox1.setText(org.openide.util.NbBundle.getMessage(STIXReportModuleConfigPanel.class, "STIXReportModuleConfigPanel.jCheckBox1.text")); // NOI18N
jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jCheckBox1ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addGroup(layout.createSequentialGroup()
.addComponent(jStixFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1))
.addComponent(jCheckBox1))
.addContainerGap(73, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jStixFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jButton1))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jCheckBox1)
.addContainerGap(225, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void jStixFileTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jStixFileTextFieldActionPerformed
}//GEN-LAST:event_jStixFileTextFieldActionPerformed
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
JFileChooser fileChooser = chooserHelper.getChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
File currentSelection = new File(jStixFileTextField.getText());
if (currentSelection.exists()) {
fileChooser.setCurrentDirectory(currentSelection);
}
int result = fileChooser.showOpenDialog(this);
if (result == JFileChooser.APPROVE_OPTION) {
stixFile = fileChooser.getSelectedFile().getAbsolutePath();
jStixFileTextField.setText(stixFile);
}
}//GEN-LAST:event_jButton1ActionPerformed
private void jStixFileTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jStixFileTextFieldKeyTyped
}//GEN-LAST:event_jStixFileTextFieldKeyTyped
private void jStixFileTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jStixFileTextFieldKeyReleased
stixFile = jStixFileTextField.getText();
}//GEN-LAST:event_jStixFileTextFieldKeyReleased
private void jCheckBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBox1ActionPerformed
showAllResults = jCheckBox1.isSelected();
}//GEN-LAST:event_jCheckBox1ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton jButton1;
private javax.swing.JCheckBox jCheckBox1;
private javax.swing.JLabel jLabel2;
private javax.swing.JTextField jStixFileTextField;
// End of variables declaration//GEN-END:variables
}

View File

@ -1,62 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import org.sleuthkit.autopsy.report.ReportModuleSettings;
/**
* Settings for the STIX report module.
*/
class STIXReportModuleSettings implements ReportModuleSettings {
private static final long serialVersionUID = 1L;
private final String stixFile;
private final boolean showAllResults;
STIXReportModuleSettings() {
stixFile = null;
showAllResults = false;
}
STIXReportModuleSettings(String stixFile, boolean showAllResults) {
this.stixFile = stixFile;
this.showAllResults = showAllResults;
}
@Override
public long getVersionNumber() {
return serialVersionUID;
}
/**
* @return the stixFile
*/
String getStixFile() {
return stixFile;
}
/**
* @return the showAllResults
*/
boolean isShowAllResults() {
return showAllResults;
}
}

View File

@ -1,107 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013-2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.report.modules.stix;
import java.util.Arrays;
import java.util.Collection;
import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE;
import org.sleuthkit.datamodel.Score;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
*
*/
class StixArtifactData {
private static final String MODULE_NAME = "Stix";
private AbstractFile file;
private final String observableId;
private final String objType;
private static final Logger logger = Logger.getLogger(StixArtifactData.class.getName());
StixArtifactData(AbstractFile a_file, String a_observableId, String a_objType) {
file = a_file;
observableId = a_observableId;
objType = a_objType;
}
StixArtifactData(long a_objId, String a_observableId, String a_objType) {
try {
Case case1 = Case.getCurrentCaseThrows();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
file = sleuthkitCase.getAbstractFileById(a_objId);
} catch (TskCoreException | NoCurrentCaseException ex) {
file = null;
}
observableId = a_observableId;
objType = a_objType;
}
@Messages({"StixArtifactData.indexError.message=Failed to index STIX interesting file hit artifact for keyword search.",
"StixArtifactData.noOpenCase.errMsg=No open case available."})
void createArtifact(String a_title) throws TskCoreException {
Blackboard blackboard;
try {
blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
return;
}
String setName = "STIX Indicator - " + StringUtils.defaultIfBlank(a_title, "(no title)"); //NON-NLS
Collection<BlackboardAttribute> attributes = Arrays.asList(
new BlackboardAttribute(TSK_SET_NAME, MODULE_NAME, setName),
new BlackboardAttribute(TSK_TITLE, MODULE_NAME, observableId),
new BlackboardAttribute(TSK_CATEGORY, MODULE_NAME, objType));
// Create artifact if it doesn't already exist.
if (!blackboard.artifactExists(file, TSK_INTERESTING_FILE_HIT, attributes)) {
BlackboardArtifact bba = file.newAnalysisResult(
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
null, setName, null,
attributes)
.getAnalysisResult();
try {
/*
* post the artifact which will index the artifact for keyword
* search, and fire an event to notify UI of this new artifact
*/
blackboard.postArtifact(bba, MODULE_NAME);
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -101,11 +101,6 @@ This report module generates a KML file from any GPS data in the case. This file
This report module generates a new Autopsy case that includes tagged and/or interesting items. See the \ref portable_case_page page for additional information.
\subsection report_stix STIX
The STIX module allows you to generate a report and Interesting File artifacts by running a STIX file (or files) against the data sources in the case.
For more information see the \ref stix_page page.
\subsection report_body_file TSK Body File
This module generates a <a href="https://wiki.sleuthkit.org/index.php?title=Body_file">TSK Body File</a> from the files in your case, which looks similar to the following:

View File

@ -1,104 +0,0 @@
/*! \page stix_page STIX
[TOC]
Overview
========
This document outlines the use of the STIX feature of Autopsy. This feature allows one or more Structured Threat Information Exchange (STIX) files to be run against a data source, reporting which indicators were found in the data source. More information about STIX can be found at https://stix.mitre.org/.
This document assumes basic familiarity with Autopsy.
Quick Start
===========
-# Create a case as normal and add a disk image (or folder of files) as a data source. To get the most out of the STIX module, ensure that the following ingest modules are selected:
- Recent Activity
- Hash Lookup (Check box to calculate MD5 hashes even with no database selected)
- File Type Identification
- Keyword Search (URL, IP, and Email addresses)
- Email Parser
- Extension Mismatch Detector
-# After the image has been added and ingest is complete, click the Report button then select STIX. Next choose either a single STIX file or a directory of STIX files to run against the image. It is possible to do this while ingest is running but the results will be incomplete.
-# Once the STIX report module is complete, there will be two sets of results:
- Entries will be created under Interesting Items in the Autopsy tree, under a subheading for each indicator.
- A log of which indicators/observables were found is generated by the report module (Follow the link on the Report Generation Progress window)
Supported CybOX Objects
=======================
- Address Object
- Address_Value
- Domain Name Object
- Value
- Email Message Object
- To
- CC
- From
- Subject
- File Object
- Size_In_Bytes
- File_Name
- File_Path
- File_Extension
- Modified_Time
- Accessed_Time
- Created_Time
- Hashes (MD5 only)
- File_Format
- is_masqueraded
- URI Object
- Value
- URL History Object
- Browser_Information (Name)
- URL
- Hostname
- Referrer_URL
- Page_Title
- User_Profile_Name
- User Account Object
- Home_Directory
- Username
- Win Executable File Object
- Time_Date_Stamp
- Windows Network Share Object
- Local_Path
- Netname
- Win Registry Key Object
- Key (Required)
- Hive
- Values
- System Object
- Hostname
- Processor_Architecture
- Win System Object
- Product_ID
- Product_Name
- Registered_Owner
- Registered_Organization
- Windows_System_Directory
- Windows_Temp_Directory
- Win User Account Object
- SID
See http://cybox.mitre.org for more information on CybOX Objects.
Limitations
===========
- As shown in the list above, not all CybOX objects/fields are currently supported. When an unsupported object/field is found in an observable, its status is set to "indeterminate" instead of true or false. These indeterminate fields will not change the result of the observable composition (i.e., if the rest is true, the overall result will stay as true).
- Not all ConditionTypeEnum values are supported. It varies by field, but generally on String fields the following work: EQUALS, DOES_NOT_EQUAL, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, ENDS_WITH. If a condition type is not supported there will be a warning in the log file.
- Related objects are not processed
*/