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.*;
 
   43 class EvalRegistryObj 
extends EvaluatableObject {
 
   45     private final WindowsRegistryKey obj;
 
   46     private final List<RegistryFileInfo> regFiles = 
new ArrayList<RegistryFileInfo>();
 
   48     public EvalRegistryObj(WindowsRegistryKey a_obj, String a_id, String a_spacing, List<RegistryFileInfo> a_regFiles) {
 
   52         regFiles.addAll(a_regFiles);
 
   55     private EvalRegistryObj() {
 
   62     public synchronized ObservableResult evaluate() {
 
   67         if (obj.getKey() == null) {
 
   68             return new ObservableResult(
id, 
"RegistryObject: No key found", 
 
   69                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
   73         if (!((obj.getKey().getCondition() == null)
 
   74                 || (obj.getKey().getCondition() == ConditionTypeEnum.EQUALS))) {
 
   75             return new ObservableResult(
id, 
"RegistryObject: Can not support condition " + obj.getKey().getCondition() 
 
   77                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
   80         setUnsupportedFieldWarnings();
 
   83         List<RegistryFileInfo> hiveList = 
new ArrayList<RegistryFileInfo>();
 
   84         if (obj.getHive() == null) {
 
   86             hiveList.addAll(regFiles);
 
   87         } 
else if (obj.getHive().getValue().toString().startsWith(
"HKEY")) { 
 
   90             for (RegistryFileInfo regFile : regFiles) {
 
   91                 if (regFile.abstractFile.getParentPath() != null) {
 
   92                     Pattern pattern = Pattern.compile(
"system32", Pattern.CASE_INSENSITIVE);
 
   93                     Matcher matcher = pattern.matcher(regFile.abstractFile.getParentPath());
 
   96                         if (obj.getHive().getValue().toString().equalsIgnoreCase(
"HKEY_LOCAL_MACHINE")) { 
 
   97                             hiveList.add(regFile);
 
  101                         if (!obj.getHive().getValue().toString().equalsIgnoreCase(
"HKEY_LOCAL_MACHINE")) { 
 
  102                             hiveList.add(regFile);
 
  109             String stixHiveName = obj.getHive().getValue().toString();
 
  112             Pattern pattern = Pattern.compile(
"Temp.STIX." + stixHiveName, Pattern.CASE_INSENSITIVE);
 
  114             for (RegistryFileInfo hive : regFiles) {
 
  115                 Matcher matcher = pattern.matcher(hive.tempFileName);
 
  116                 if (matcher.find()) {
 
  122             if (hiveList.isEmpty()) {
 
  123                 hiveList.addAll(regFiles);
 
  128         if (hiveList.isEmpty()) {
 
  129             return new ObservableResult(
id, 
"RegistryObject: No matching registry hives found", 
 
  130                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  133         for (RegistryFileInfo hive : hiveList) {
 
  135                 ObservableResult result = testRegistryFile(hive);
 
  136                 if (result.isTrue()) {
 
  139             } 
catch (Exception ex) {
 
  143                 addWarning(
"Error processing registry file " + hive); 
 
  147         if (obj.getHive() == null) {
 
  148             return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue(), 
 
  149                     spacing, ObservableResult.ObservableState.FALSE, null);
 
  151         return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue() 
 
  152                 + 
" in hive " + obj.getHive().getValue(), 
 
  153                 spacing, ObservableResult.ObservableState.FALSE, null);
 
  164     private ObservableResult testRegistryFile(RegistryFileInfo a_regInfo) {
 
  166             RegistryKey root = openRegistry(a_regInfo.tempFileName);
 
  167             RegistryKey result = findKey(root, obj.getKey().getValue().toString());
 
  169             if (result == null) {
 
  174                 if ((obj.getHive() != null)
 
  175                         && obj.getHive().getValue().toString().startsWith(
"HKEY")) { 
 
  176                     String[] parts = obj.getKey().getValue().toString().split(
"\\\\");
 
  178                     for (
int i = 1; i < parts.length; i++) {
 
  179                         if (newKey.length() > 0) {
 
  184                     result = findKey(root, newKey);
 
  187                 if (result == null) {
 
  188                     return new ObservableResult(
id, 
"RegistryObject: Could not find key " + obj.getKey().getValue(), 
 
  189                             spacing, ObservableResult.ObservableState.FALSE, null);
 
  193             if ((obj.getValues() == null) || (obj.getValues().getValues().isEmpty())) {
 
  195                 List<StixArtifactData> artData = 
new ArrayList<StixArtifactData>();
 
  196                 artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id, 
"Registry")); 
 
  197                 return new ObservableResult(
id, 
"RegistryObject: Found key " + obj.getKey().getValue(), 
 
  198                         spacing, ObservableResult.ObservableState.TRUE, artData);
 
  202             for (
org.mitre.cybox.objects.RegistryValueType stixRegValue : obj.getValues().getValues()) {
 
  204                     for (RegistryValue valFromFile : result.getValueList()) {
 
  207                         boolean nameSuccess = 
true; 
 
  208                         if (stixRegValue.getName() != null) {
 
  210                                 nameSuccess = compareStringObject(stixRegValue.getName(), valFromFile.getName());
 
  211                             } 
catch (UnsupportedEncodingException ex) {
 
  216                         boolean valueSuccess = 
true;
 
  217                         if (nameSuccess && (stixRegValue.getData() != null)) {
 
  218                             switch (valFromFile.getValueType()) {
 
  223                                         valueSuccess = compareStringObject(stixRegValue.getData(),
 
  224                                                 valFromFile.getValue().getAsString());
 
  225                                     } 
catch (UnsupportedEncodingException ex) {
 
  226                                         valueSuccess = 
false;
 
  234                                     if ((stixRegValue.getData().getCondition() == null)
 
  235                                             || (stixRegValue.getData().getCondition() == ConditionTypeEnum.EQUALS)) {
 
  239                                             long stixValue = Long.decode(stixRegValue.getData().getValue().toString());
 
  242                                                 valueSuccess = (stixValue == valFromFile.getValue().getAsNumber());
 
  243                                             } 
catch (UnsupportedEncodingException ex) {
 
  244                                                 valueSuccess = 
false;
 
  246                                         } 
catch (NumberFormatException ex) {
 
  249                                             valueSuccess = 
false;
 
  252                                         valueSuccess = 
false;
 
  263                         if (nameSuccess && valueSuccess) {
 
  265                             List<StixArtifactData> artData = 
new ArrayList<StixArtifactData>();
 
  266                             artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id, 
"Registry")); 
 
  267                             return new ObservableResult(
id, 
"RegistryObject: Found key " + obj.getKey().getValue() 
 
  268                                     + 
" and value " + stixRegValue.getName().getValue().toString() 
 
  269                                     + 
" = " + stixRegValue.getData().getValue().toString(),
 
  270                                     spacing, ObservableResult.ObservableState.TRUE, artData);
 
  273                 } 
catch (Exception ex) {
 
  275                     return new ObservableResult(
id, 
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), 
 
  276                             spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  279         } 
catch (TskCoreException ex) {
 
  280             return new ObservableResult(
id, 
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(), 
 
  281                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  284         return new ObservableResult(
id, 
"RegistryObject: Not done", 
 
  285                 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  288     public RegistryKey openRegistry(String hive) 
throws TskCoreException {
 
  291             RegistryHiveFile regFile = 
new RegistryHiveFile(
new File(hive));
 
  292             RegistryKey root = regFile.getRoot();
 
  294         } 
catch (IOException ex) {
 
  295             throw new TskCoreException(
"Error opening registry file - " + ex.getLocalizedMessage()); 
 
  296         } 
catch (RegistryParseException ex) {
 
  297             throw new TskCoreException(
"Error opening root node of registry - " + ex.getLocalizedMessage()); 
 
  309     public RegistryKey findKey(RegistryKey root, String name) {
 
  311         RegistryKey currentKey = root;
 
  314         String[] parts = name.split(
"\\\\");
 
  315         for (String part : parts) {
 
  317             if (part.length() > 0) {
 
  319                     currentKey = currentKey.getSubkey(part);
 
  320                 } 
catch (Exception ex) {
 
  340     public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException {
 
  343         List<AbstractFile> regFilesAbstract = findRegistryFiles();
 
  346         List<RegistryFileInfo> regFilesLocal = 
new ArrayList<RegistryFileInfo>();
 
  351            tmpDir = Case.getCurrentCaseThrows().getTempDirectory() + File.separator + 
"STIX"; 
 
  352         } 
catch (NoCurrentCaseException ex) { 
 
  353             throw new TskCoreException(ex.getLocalizedMessage());
 
  355         File dir = 
new File(tmpDir);
 
  356         if (dir.exists() == 
false) {
 
  361         for (AbstractFile regFile : regFilesAbstract) {
 
  362             String regFileName = regFile.getName();
 
  363             String regFileNameLocal = tmpDir + File.separator + regFileName + 
"_" + index;
 
  364             File regFileNameLocalFile = 
new File(regFileNameLocal);
 
  367                 if (regFile.getMetaFlagsAsString().contains(
"Allocated")) { 
 
  368                     ContentUtils.writeToFile(regFile, regFileNameLocalFile);
 
  369                     regFilesLocal.add(
new EvalRegistryObj().
new RegistryFileInfo(regFile, regFileNameLocal));
 
  371             } 
catch (IOException ex) {
 
  372                 throw new TskCoreException(ex.getLocalizedMessage());
 
  377         return regFilesLocal;
 
  384     private static List<AbstractFile> findRegistryFiles() throws TskCoreException {
 
  385         List<AbstractFile> registryFiles = 
new ArrayList<AbstractFile>();
 
  388             openCase = Case.getCurrentCaseThrows();
 
  389         } 
catch (NoCurrentCaseException ex) { 
 
  390             throw new TskCoreException(ex.getLocalizedMessage());
 
  394         for (Content ds : openCase.getDataSources()) {
 
  397             registryFiles.addAll(fileManager.findFiles(ds, 
"ntuser.dat")); 
 
  400             String[] regFileNames = 
new String[]{
"system", 
"software", 
"security", 
"sam"}; 
 
  401             for (String regFileName : regFileNames) {
 
  402                 List<AbstractFile> allRegistryFiles = fileManager.
findFiles(ds, regFileName, 
"/system32/config"); 
 
  403                 for (AbstractFile regFile : allRegistryFiles) {
 
  405                     if (!regFile.getParentPath().contains(
"RegBack")) { 
 
  406                         registryFiles.add(regFile);
 
  412         return registryFiles;
 
  415     private void setUnsupportedFieldWarnings() {
 
  416         List<String> fieldNames = 
new ArrayList<String>();
 
  418         if (obj.getNumberValues() != null) {
 
  419             fieldNames.add(
"Number_Values"); 
 
  421         if (obj.getModifiedTime() != null) {
 
  422             fieldNames.add(
"Modified_Time"); 
 
  424         if (obj.getCreatorUsername() != null) {
 
  425             fieldNames.add(
"Creator_Username"); 
 
  427         if (obj.getHandleList() != null) {
 
  428             fieldNames.add(
"Handle_List"); 
 
  430         if (obj.getNumberSubkeys() != null) {
 
  431             fieldNames.add(
"Number_Subkeys"); 
 
  433         if (obj.getSubkeys() != null) {
 
  434             fieldNames.add(
"Subkeys"); 
 
  436         if (obj.getByteRuns() != null) {
 
  437             fieldNames.add(
"Byte_Runs"); 
 
  440         String warningStr = 
"";
 
  441         for (String name : fieldNames) {
 
  442             if (!warningStr.isEmpty()) {
 
  448         addWarning(
"Unsupported field(s): " + warningStr); 
 
  461             abstractFile = a_abstractFile;
 
  462             tempFileName = a_tempFileName;
 
final String tempFileName
synchronized List< AbstractFile > findFiles(String fileName)
final AbstractFile abstractFile
RegistryFileInfo(AbstractFile a_abstractFile, String a_tempFileName)