19 package org.sleuthkit.autopsy.modules.stix;
 
   27 import java.util.List;
 
   28 import java.util.ArrayList;
 
   29 import java.io.IOException;
 
   30 import java.io.UnsupportedEncodingException;
 
   32 import java.util.regex.Pattern;
 
   33 import java.util.regex.Matcher;
 
   35 import org.mitre.cybox.objects.WindowsRegistryKey;
 
   36 import org.mitre.cybox.common_2.ConditionTypeEnum;
 
   37 import com.williballenthin.rejistry.*;
 
   42 class EvalRegistryObj 
extends EvaluatableObject {
 
   44     private final WindowsRegistryKey obj;
 
   45     private final List<RegistryFileInfo> regFiles = 
new ArrayList<RegistryFileInfo>();
 
   47     public EvalRegistryObj(WindowsRegistryKey a_obj, String a_id, String a_spacing, List<RegistryFileInfo> a_regFiles) {
 
   51         regFiles.addAll(a_regFiles);
 
   54     private EvalRegistryObj() {
 
   61     public synchronized ObservableResult evaluate() {
 
   66         if (obj.getKey() == null) {
 
   67             return new ObservableResult(
id, 
"RegistryObject: No key found", 
 
   68                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
   72         if (!((obj.getKey().getCondition() == null)
 
   73                 || (obj.getKey().getCondition() == ConditionTypeEnum.EQUALS))) {
 
   74             return new ObservableResult(
id, 
"RegistryObject: Can not support condition " + obj.getKey().getCondition() 
 
   76                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
   79         setUnsupportedFieldWarnings();
 
   82         List<RegistryFileInfo> hiveList = 
new ArrayList<RegistryFileInfo>();
 
   83         if (obj.getHive() == null) {
 
   85             hiveList.addAll(regFiles);
 
   86         } 
else if (obj.getHive().getValue().toString().startsWith(
"HKEY")) { 
 
   89             for (RegistryFileInfo regFile : regFiles) {
 
   90                 if (regFile.abstractFile.getParentPath() != null) {
 
   91                     Pattern pattern = Pattern.compile(
"system32", Pattern.CASE_INSENSITIVE);
 
   92                     Matcher matcher = pattern.matcher(regFile.abstractFile.getParentPath());
 
   95                         if (obj.getHive().getValue().toString().equalsIgnoreCase(
"HKEY_LOCAL_MACHINE")) { 
 
   96                             hiveList.add(regFile);
 
  100                         if (!obj.getHive().getValue().toString().equalsIgnoreCase(
"HKEY_LOCAL_MACHINE")) { 
 
  101                             hiveList.add(regFile);
 
  108             String stixHiveName = obj.getHive().getValue().toString();
 
  111             Pattern pattern = Pattern.compile(
"Temp.STIX." + stixHiveName, Pattern.CASE_INSENSITIVE);
 
  113             for (RegistryFileInfo hive : regFiles) {
 
  114                 Matcher matcher = pattern.matcher(hive.tempFileName);
 
  115                 if (matcher.find()) {
 
  121             if (hiveList.isEmpty()) {
 
  122                 hiveList.addAll(regFiles);
 
  127         if (hiveList.isEmpty()) {
 
  128             return new ObservableResult(
id, 
"RegistryObject: No matching registry hives found", 
 
  129                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  132         for (RegistryFileInfo hive : hiveList) {
 
  134                 ObservableResult result = testRegistryFile(hive);
 
  135                 if (result.isTrue()) {
 
  138             } 
catch (Exception ex) {
 
  142                 addWarning(
"Error processing registry file " + hive); 
 
  146         if (obj.getHive() == null) {
 
  147             return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue(), 
 
  148                     spacing, ObservableResult.ObservableState.FALSE, null);
 
  150         return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue() 
 
  151                 + 
" in hive " + obj.getHive().getValue(), 
 
  152                 spacing, ObservableResult.ObservableState.FALSE, null);
 
  162     private ObservableResult testRegistryFile(RegistryFileInfo a_regInfo) {
 
  164             RegistryKey root = openRegistry(a_regInfo.tempFileName);
 
  165             RegistryKey result = findKey(root, obj.getKey().getValue().toString());
 
  167             if (result == null) {
 
  172                 if((obj.getHive() != null) 
 
  173                     && obj.getHive().getValue().toString().startsWith(
"HKEY")){ 
 
  174                     String[] parts = obj.getKey().getValue().toString().split(
"\\\\");
 
  176                     for (
int i = 1; i < parts.length; i++) {
 
  177                         if (newKey.length() > 0) {
 
  182                     result = findKey(root, newKey);
 
  185                 if (result == null) {
 
  186                     return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue(), 
 
  187                             spacing, ObservableResult.ObservableState.FALSE, null);
 
  191             if ((obj.getValues() == null) || (obj.getValues().getValues().isEmpty())) {
 
  193                 List<StixArtifactData> artData = 
new ArrayList<StixArtifactData>();
 
  194                 artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id, 
"Registry")); 
 
  195                 return new ObservableResult(
id, 
"RegistryObject: Found key " + obj.getKey().getValue(), 
 
  196                         spacing, ObservableResult.ObservableState.TRUE, artData);
 
  200             for (
org.mitre.cybox.objects.RegistryValueType stixRegValue : obj.getValues().getValues()) {
 
  202                     for (RegistryValue valFromFile : result.getValueList()) {
 
  205                         boolean nameSuccess = 
true; 
 
  206                         if (stixRegValue.getName() != null) {
 
  208                                 nameSuccess = compareStringObject(stixRegValue.getName(), valFromFile.getName());
 
  209                             } 
catch (UnsupportedEncodingException ex) {
 
  214                         boolean valueSuccess = 
true;
 
  215                         if (nameSuccess && (stixRegValue.getData() != null)) {
 
  216                             switch (valFromFile.getValueType()) {
 
  221                                         valueSuccess = compareStringObject(stixRegValue.getData(),
 
  222                                                 valFromFile.getValue().getAsString());
 
  223                                     } 
catch (UnsupportedEncodingException ex) {
 
  224                                         valueSuccess = 
false;
 
  232                                     if ((stixRegValue.getData().getCondition() == null)
 
  233                                             || (stixRegValue.getData().getCondition() == ConditionTypeEnum.EQUALS)) {
 
  237                                             long stixValue = Long.decode(stixRegValue.getData().getValue().toString());
 
  240                                                 valueSuccess = (stixValue == valFromFile.getValue().getAsNumber());
 
  241                                             } 
catch (UnsupportedEncodingException ex) {
 
  242                                                 valueSuccess = 
false;
 
  244                                         } 
catch (NumberFormatException ex) {
 
  247                                             valueSuccess = 
false;
 
  250                                         valueSuccess = 
false;
 
  261                         if (nameSuccess && valueSuccess) {
 
  263                             List<StixArtifactData> artData = 
new ArrayList<StixArtifactData>();
 
  264                             artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id, 
"Registry")); 
 
  265                             return new ObservableResult(
id, 
"RegistryObject: Found key " + obj.getKey().getValue() 
 
  266                                     + 
" and value " + stixRegValue.getName().getValue().toString() 
 
  267                                     + 
" = " + stixRegValue.getData().getValue().toString(),
 
  268                                     spacing, ObservableResult.ObservableState.TRUE, artData);
 
  271                 } 
catch (Exception ex) {
 
  273                     return new ObservableResult(
id, 
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), 
 
  274                             spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  277         } 
catch (TskCoreException ex) {
 
  278             return new ObservableResult(
id, 
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), 
 
  279                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  282         return new ObservableResult(
id, 
"RegistryObject: Not done", 
 
  283                 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  286     public RegistryKey openRegistry(String hive) 
throws TskCoreException {
 
  289             RegistryHiveFile regFile = 
new RegistryHiveFile(
new File(hive));
 
  290             RegistryKey root = regFile.getRoot();
 
  292         } 
catch (IOException ex) {
 
  293             throw new TskCoreException(
"Error opening registry file - " + ex.getLocalizedMessage()); 
 
  294         } 
catch (RegistryParseException ex) {
 
  295             throw new TskCoreException(
"Error opening root node of registry - " + ex.getLocalizedMessage()); 
 
  306     public RegistryKey findKey(RegistryKey root, String name) {
 
  308         RegistryKey currentKey = root;
 
  311         String[] parts = name.split(
"\\\\");
 
  312         for (String part : parts) {
 
  314             if (part.length() > 0) {
 
  316                     currentKey = currentKey.getSubkey(part);
 
  317                 } 
catch (Exception ex) {
 
  337     public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException {
 
  340         List<AbstractFile> regFilesAbstract = findRegistryFiles();
 
  343         List<RegistryFileInfo> regFilesLocal = 
new ArrayList<RegistryFileInfo>();
 
  346         String tmpDir = Case.getCurrentCase().getTempDirectory() + File.separator + 
"STIX"; 
 
  347         File dir = 
new File(tmpDir);
 
  348         if (dir.exists() == 
false) {
 
  353         for (AbstractFile regFile : regFilesAbstract) {
 
  354             String regFileName = regFile.getName();
 
  355             String regFileNameLocal = tmpDir + File.separator + regFileName + 
"_" + index;
 
  356             File regFileNameLocalFile = 
new File(regFileNameLocal);
 
  359                 if (regFile.getMetaFlagsAsString().contains(
"Allocated")) { 
 
  360                     ContentUtils.writeToFile(regFile, regFileNameLocalFile);
 
  361                     regFilesLocal.add(
new EvalRegistryObj().
new RegistryFileInfo(regFile, regFileNameLocal));
 
  363             } 
catch (IOException ex) {
 
  364                 throw new TskCoreException(ex.getLocalizedMessage());
 
  369         return regFilesLocal;
 
  376     private static List<AbstractFile> findRegistryFiles() throws TskCoreException {
 
  377         List<AbstractFile> registryFiles = 
new ArrayList<AbstractFile>();
 
  380         for (Content ds : Case.getCurrentCase().getDataSources()) {
 
  383             registryFiles.addAll(fileManager.findFiles(ds, 
"ntuser.dat")); 
 
  386             String[] regFileNames = 
new String[]{
"system", 
"software", 
"security", 
"sam"}; 
 
  387             for (String regFileName : regFileNames) {
 
  388                 List<AbstractFile> allRegistryFiles = fileManager.
findFiles(ds, regFileName, 
"/system32/config"); 
 
  389                 for (AbstractFile regFile : allRegistryFiles) {
 
  391                     if (!regFile.getParentPath().contains(
"RegBack")) { 
 
  392                         registryFiles.add(regFile);
 
  398         return registryFiles;
 
  401     private void setUnsupportedFieldWarnings() {
 
  402         List<String> fieldNames = 
new ArrayList<String>();
 
  404         if (obj.getNumberValues() != null) {
 
  405             fieldNames.add(
"Number_Values"); 
 
  407         if (obj.getModifiedTime() != null) {
 
  408             fieldNames.add(
"Modified_Time"); 
 
  410         if (obj.getCreatorUsername() != null) {
 
  411             fieldNames.add(
"Creator_Username"); 
 
  413         if (obj.getHandleList() != null) {
 
  414             fieldNames.add(
"Handle_List"); 
 
  416         if (obj.getNumberSubkeys() != null) {
 
  417             fieldNames.add(
"Number_Subkeys"); 
 
  419         if (obj.getSubkeys() != null) {
 
  420             fieldNames.add(
"Subkeys"); 
 
  422         if (obj.getByteRuns() != null) {
 
  423             fieldNames.add(
"Byte_Runs"); 
 
  426         String warningStr = 
"";
 
  427         for (String name : fieldNames) {
 
  428             if (!warningStr.isEmpty()) {
 
  434         addWarning(
"Unsupported field(s): " + warningStr); 
 
  447             abstractFile = a_abstractFile;
 
  448             tempFileName = a_tempFileName;
 
final String tempFileName
synchronized List< AbstractFile > findFiles(Content dataSource, String fileName)
final AbstractFile abstractFile
RegistryFileInfo(AbstractFile a_abstractFile, String a_tempFileName)