@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<RegistryFileInfo>(); 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.abstractFile.getParentPath() != null) { Pattern pattern = Pattern.compile("system32", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(regFile.abstractFile.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.tempFileName); 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.tempFileName); 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<StixArtifactData>(); artData.add( new StixArtifactData(a_regInfo.abstractFile.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<StixArtifactData>(); artData.add( new StixArtifactData(a_regInfo.abstractFile.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); }