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)