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);
 
  163     private ObservableResult testRegistryFile(RegistryFileInfo a_regInfo) {
 
  165             RegistryKey root = openRegistry(a_regInfo.tempFileName);
 
  166             RegistryKey result = findKey(root, obj.getKey().getValue().toString());
 
  168             if (result == null) {
 
  173                 if ((obj.getHive() != null)
 
  174                         && obj.getHive().getValue().toString().startsWith(
"HKEY")) { 
 
  175                     String[] parts = obj.getKey().getValue().toString().split(
"\\\\");
 
  177                     for (
int i = 1; i < parts.length; i++) {
 
  178                         if (newKey.length() > 0) {
 
  183                     result = findKey(root, newKey);
 
  186                 if (result == null) {
 
  187                     return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue(), 
 
  188                             spacing, ObservableResult.ObservableState.FALSE, null);
 
  192             if ((obj.getValues() == null) || (obj.getValues().getValues().isEmpty())) {
 
  194                 List<StixArtifactData> artData = 
new ArrayList<StixArtifactData>();
 
  195                 artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id, 
"Registry")); 
 
  196                 return new ObservableResult(
id, 
"RegistryObject: Found key " + obj.getKey().getValue(), 
 
  197                         spacing, ObservableResult.ObservableState.TRUE, artData);
 
  201             for (
org.mitre.cybox.objects.RegistryValueType stixRegValue : obj.getValues().getValues()) {
 
  203                     for (RegistryValue valFromFile : result.getValueList()) {
 
  206                         boolean nameSuccess = 
true; 
 
  207                         if (stixRegValue.getName() != null) {
 
  209                                 nameSuccess = compareStringObject(stixRegValue.getName(), valFromFile.getName());
 
  210                             } 
catch (UnsupportedEncodingException ex) {
 
  215                         boolean valueSuccess = 
true;
 
  216                         if (nameSuccess && (stixRegValue.getData() != null)) {
 
  217                             switch (valFromFile.getValueType()) {
 
  222                                         valueSuccess = compareStringObject(stixRegValue.getData(),
 
  223                                                 valFromFile.getValue().getAsString());
 
  224                                     } 
catch (UnsupportedEncodingException ex) {
 
  225                                         valueSuccess = 
false;
 
  233                                     if ((stixRegValue.getData().getCondition() == null)
 
  234                                             || (stixRegValue.getData().getCondition() == ConditionTypeEnum.EQUALS)) {
 
  238                                             long stixValue = Long.decode(stixRegValue.getData().getValue().toString());
 
  241                                                 valueSuccess = (stixValue == valFromFile.getValue().getAsNumber());
 
  242                                             } 
catch (UnsupportedEncodingException ex) {
 
  243                                                 valueSuccess = 
false;
 
  245                                         } 
catch (NumberFormatException ex) {
 
  248                                             valueSuccess = 
false;
 
  251                                         valueSuccess = 
false;
 
  262                         if (nameSuccess && valueSuccess) {
 
  264                             List<StixArtifactData> artData = 
new ArrayList<StixArtifactData>();
 
  265                             artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id, 
"Registry")); 
 
  266                             return new ObservableResult(
id, 
"RegistryObject: Found key " + obj.getKey().getValue() 
 
  267                                     + 
" and value " + stixRegValue.getName().getValue().toString() 
 
  268                                     + 
" = " + stixRegValue.getData().getValue().toString(),
 
  269                                     spacing, ObservableResult.ObservableState.TRUE, artData);
 
  272                 } 
catch (Exception ex) {
 
  274                     return new ObservableResult(
id, 
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), 
 
  275                             spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  278         } 
catch (TskCoreException ex) {
 
  279             return new ObservableResult(
id, 
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), 
 
  280                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  283         return new ObservableResult(
id, 
"RegistryObject: Not done", 
 
  284                 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  287     public RegistryKey openRegistry(String hive) 
throws TskCoreException {
 
  290             RegistryHiveFile regFile = 
new RegistryHiveFile(
new File(hive));
 
  291             RegistryKey root = regFile.getRoot();
 
  293         } 
catch (IOException ex) {
 
  294             throw new TskCoreException(
"Error opening registry file - " + ex.getLocalizedMessage()); 
 
  295         } 
catch (RegistryParseException ex) {
 
  296             throw new TskCoreException(
"Error opening root node of registry - " + ex.getLocalizedMessage()); 
 
  308     public RegistryKey findKey(RegistryKey root, String name) {
 
  310         RegistryKey currentKey = root;
 
  313         String[] parts = name.split(
"\\\\");
 
  314         for (String part : parts) {
 
  316             if (part.length() > 0) {
 
  318                     currentKey = currentKey.getSubkey(part);
 
  319                 } 
catch (Exception ex) {
 
  339     public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException {
 
  342         List<AbstractFile> regFilesAbstract = findRegistryFiles();
 
  345         List<RegistryFileInfo> regFilesLocal = 
new ArrayList<RegistryFileInfo>();
 
  348         String tmpDir = Case.getCurrentCase().getTempDirectory() + File.separator + 
"STIX"; 
 
  349         File dir = 
new File(tmpDir);
 
  350         if (dir.exists() == 
false) {
 
  355         for (AbstractFile regFile : regFilesAbstract) {
 
  356             String regFileName = regFile.getName();
 
  357             String regFileNameLocal = tmpDir + File.separator + regFileName + 
"_" + index;
 
  358             File regFileNameLocalFile = 
new File(regFileNameLocal);
 
  361                 if (regFile.getMetaFlagsAsString().contains(
"Allocated")) { 
 
  362                     ContentUtils.writeToFile(regFile, regFileNameLocalFile);
 
  363                     regFilesLocal.add(
new EvalRegistryObj().
new RegistryFileInfo(regFile, regFileNameLocal));
 
  365             } 
catch (IOException ex) {
 
  366                 throw new TskCoreException(ex.getLocalizedMessage());
 
  371         return regFilesLocal;
 
  378     private static List<AbstractFile> findRegistryFiles() throws TskCoreException {
 
  379         List<AbstractFile> registryFiles = 
new ArrayList<AbstractFile>();
 
  382         for (Content ds : Case.getCurrentCase().getDataSources()) {
 
  385             registryFiles.addAll(fileManager.findFiles(ds, 
"ntuser.dat")); 
 
  388             String[] regFileNames = 
new String[]{
"system", 
"software", 
"security", 
"sam"}; 
 
  389             for (String regFileName : regFileNames) {
 
  390                 List<AbstractFile> allRegistryFiles = fileManager.
findFiles(ds, regFileName, 
"/system32/config"); 
 
  391                 for (AbstractFile regFile : allRegistryFiles) {
 
  393                     if (!regFile.getParentPath().contains(
"RegBack")) { 
 
  394                         registryFiles.add(regFile);
 
  400         return registryFiles;
 
  403     private void setUnsupportedFieldWarnings() {
 
  404         List<String> fieldNames = 
new ArrayList<String>();
 
  406         if (obj.getNumberValues() != null) {
 
  407             fieldNames.add(
"Number_Values"); 
 
  409         if (obj.getModifiedTime() != null) {
 
  410             fieldNames.add(
"Modified_Time"); 
 
  412         if (obj.getCreatorUsername() != null) {
 
  413             fieldNames.add(
"Creator_Username"); 
 
  415         if (obj.getHandleList() != null) {
 
  416             fieldNames.add(
"Handle_List"); 
 
  418         if (obj.getNumberSubkeys() != null) {
 
  419             fieldNames.add(
"Number_Subkeys"); 
 
  421         if (obj.getSubkeys() != null) {
 
  422             fieldNames.add(
"Subkeys"); 
 
  424         if (obj.getByteRuns() != null) {
 
  425             fieldNames.add(
"Byte_Runs"); 
 
  428         String warningStr = 
"";
 
  429         for (String name : fieldNames) {
 
  430             if (!warningStr.isEmpty()) {
 
  436         addWarning(
"Unsupported field(s): " + warningStr); 
 
  449             abstractFile = a_abstractFile;
 
  450             tempFileName = a_tempFileName;
 
final String tempFileName
synchronized List< AbstractFile > findFiles(String fileName)
final AbstractFile abstractFile
RegistryFileInfo(AbstractFile a_abstractFile, String a_tempFileName)