19 package org.sleuthkit.autopsy.report.modules.stix;
21 import com.williballenthin.rejistry.RegistryHiveFile;
22 import com.williballenthin.rejistry.RegistryKey;
23 import com.williballenthin.rejistry.RegistryParseException;
24 import com.williballenthin.rejistry.RegistryValue;
30 import java.util.List;
31 import java.util.ArrayList;
32 import java.io.IOException;
33 import java.io.UnsupportedEncodingException;
35 import java.util.regex.Pattern;
36 import java.util.regex.Matcher;
37 import org.mitre.cybox.objects.WindowsRegistryKey;
38 import org.mitre.cybox.common_2.ConditionTypeEnum;
44 class EvalRegistryObj
extends EvaluatableObject {
46 private final WindowsRegistryKey obj;
47 private final List<RegistryFileInfo> regFiles =
new ArrayList<>();
49 EvalRegistryObj(WindowsRegistryKey a_obj, String a_id, String a_spacing, List<RegistryFileInfo> a_regFiles) {
53 regFiles.addAll(a_regFiles);
56 private EvalRegistryObj() {
63 public synchronized ObservableResult evaluate() {
68 if (obj.getKey() == null) {
69 return new ObservableResult(
id,
"RegistryObject: No key found",
70 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
74 if (!((obj.getKey().getCondition() == null)
75 || (obj.getKey().getCondition() == ConditionTypeEnum.EQUALS))) {
76 return new ObservableResult(
id,
"RegistryObject: Can not support condition " + obj.getKey().getCondition()
78 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
81 setUnsupportedFieldWarnings();
84 List<RegistryFileInfo> hiveList =
new ArrayList<>();
85 if (obj.getHive() == null) {
87 hiveList.addAll(regFiles);
88 }
else if (obj.getHive().getValue().toString().startsWith(
"HKEY")) {
91 for (RegistryFileInfo regFile : regFiles) {
92 if (regFile.getAbstractFile().getParentPath() != null) {
93 Pattern pattern = Pattern.compile(
"system32", Pattern.CASE_INSENSITIVE);
94 Matcher matcher = pattern.matcher(regFile.getAbstractFile().getParentPath());
97 if (obj.getHive().getValue().toString().equalsIgnoreCase(
"HKEY_LOCAL_MACHINE")) {
98 hiveList.add(regFile);
102 if (!obj.getHive().getValue().toString().equalsIgnoreCase(
"HKEY_LOCAL_MACHINE")) {
103 hiveList.add(regFile);
110 String stixHiveName = obj.getHive().getValue().toString();
113 Pattern pattern = Pattern.compile(
"Temp.STIX." + stixHiveName, Pattern.CASE_INSENSITIVE);
115 for (RegistryFileInfo hive : regFiles) {
116 Matcher matcher = pattern.matcher(hive.getTempFileName());
117 if (matcher.find()) {
123 if (hiveList.isEmpty()) {
124 hiveList.addAll(regFiles);
129 if (hiveList.isEmpty()) {
130 return new ObservableResult(
id,
"RegistryObject: No matching registry hives found",
131 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
134 for (RegistryFileInfo hive : hiveList) {
136 ObservableResult result = testRegistryFile(hive);
137 if (result.isTrue()) {
140 }
catch (Exception ex) {
144 addWarning(
"Error processing registry file " + hive);
148 if (obj.getHive() == null) {
149 return new ObservableResult(
id,
"RegistryObject: Could not find key " + obj.getKey().getValue(),
150 spacing, ObservableResult.ObservableState.FALSE, null);
152 return new ObservableResult(
id,
"RegistryObject: Could not find key " + obj.getKey().getValue()
153 +
" in hive " + obj.getHive().getValue(),
154 spacing, ObservableResult.ObservableState.FALSE, null);
165 private ObservableResult testRegistryFile(RegistryFileInfo a_regInfo) {
167 RegistryKey root = openRegistry(a_regInfo.getTempFileName());
168 RegistryKey result = findKey(root, obj.getKey().getValue().toString());
170 if (result == null) {
175 if ((obj.getHive() != null)
176 && obj.getHive().getValue().toString().startsWith(
"HKEY")) {
177 String[] parts = obj.getKey().getValue().toString().split(
"\\\\");
179 for (
int i = 1; i < parts.length; i++) {
180 if (newKey.length() > 0) {
185 result = findKey(root, newKey);
188 if (result == null) {
189 return new ObservableResult(
id,
"RegistryObject: Could not find key " + obj.getKey().getValue(),
190 spacing, ObservableResult.ObservableState.FALSE, null);
194 if ((obj.getValues() == null) || (obj.getValues().getValues().isEmpty())) {
196 List<StixArtifactData> artData =
new ArrayList<>();
197 artData.add(
new StixArtifactData(a_regInfo.getAbstractFile().getId(), id,
"Registry"));
198 return new ObservableResult(
id,
"RegistryObject: Found key " + obj.getKey().getValue(),
199 spacing, ObservableResult.ObservableState.TRUE, artData);
203 for (
org.mitre.cybox.objects.RegistryValueType stixRegValue : obj.getValues().getValues()) {
205 for (RegistryValue valFromFile : result.getValueList()) {
208 boolean nameSuccess =
true;
209 if (stixRegValue.getName() != null) {
211 nameSuccess = compareStringObject(stixRegValue.getName(), valFromFile.getName());
212 }
catch (UnsupportedEncodingException ex) {
217 boolean valueSuccess =
true;
218 if (nameSuccess && (stixRegValue.getData() != null)) {
219 switch (valFromFile.getValueType()) {
224 valueSuccess = compareStringObject(stixRegValue.getData(),
225 valFromFile.getValue().getAsString());
226 }
catch (UnsupportedEncodingException ex) {
227 valueSuccess =
false;
235 if ((stixRegValue.getData().getCondition() == null)
236 || (stixRegValue.getData().getCondition() == ConditionTypeEnum.EQUALS)) {
240 long stixValue = Long.decode(stixRegValue.getData().getValue().toString());
243 valueSuccess = (stixValue == valFromFile.getValue().getAsNumber());
244 }
catch (UnsupportedEncodingException ex) {
245 valueSuccess =
false;
247 }
catch (NumberFormatException ex) {
250 valueSuccess =
false;
253 valueSuccess =
false;
264 if (nameSuccess && valueSuccess) {
266 List<StixArtifactData> artData =
new ArrayList<>();
267 artData.add(
new StixArtifactData(a_regInfo.getAbstractFile().getId(), id,
"Registry"));
268 return new ObservableResult(
id,
"RegistryObject: Found key " + obj.getKey().getValue()
269 +
" and value " + stixRegValue.getName().getValue().toString()
270 +
" = " + stixRegValue.getData().getValue().toString(),
271 spacing, ObservableResult.ObservableState.TRUE, artData);
274 }
catch (Exception ex) {
276 return new ObservableResult(
id,
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(),
277 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
280 }
catch (TskCoreException ex) {
281 return new ObservableResult(
id,
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(),
282 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
285 return new ObservableResult(
id,
"RegistryObject: Not done",
286 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
289 public RegistryKey openRegistry(String hive)
throws TskCoreException {
292 RegistryHiveFile regFile =
new RegistryHiveFile(
new File(hive));
293 RegistryKey root = regFile.getRoot();
295 }
catch (IOException ex) {
296 throw new TskCoreException(
"Error opening registry file - " + ex.getLocalizedMessage());
297 }
catch (RegistryParseException ex) {
298 throw new TskCoreException(
"Error opening root node of registry - " + ex.getLocalizedMessage());
310 public RegistryKey findKey(RegistryKey root, String name) {
312 RegistryKey currentKey = root;
315 String[] parts = name.split(
"\\\\");
316 for (String part : parts) {
318 if (part.length() > 0) {
320 currentKey = currentKey.getSubkey(part);
321 }
catch (Exception ex) {
341 public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException {
344 List<AbstractFile> regFilesAbstract = findRegistryFiles();
347 List<RegistryFileInfo> regFilesLocal =
new ArrayList<>();
352 tmpDir = Case.getCurrentCaseThrows().getTempDirectory() + File.separator +
"STIX";
353 }
catch (NoCurrentCaseException ex) {
354 throw new TskCoreException(ex.getLocalizedMessage());
356 File dir =
new File(tmpDir);
357 if (dir.exists() ==
false) {
362 for (AbstractFile regFile : regFilesAbstract) {
363 String regFileName = regFile.getName();
364 String regFileNameLocal = tmpDir + File.separator + regFileName +
"_" + index;
365 File regFileNameLocalFile =
new File(regFileNameLocal);
368 if (regFile.getMetaFlagsAsString().contains(
"Allocated")) {
369 ContentUtils.writeToFile(regFile, regFileNameLocalFile);
370 regFilesLocal.add(
new EvalRegistryObj().
new RegistryFileInfo(regFile, regFileNameLocal));
372 }
catch (IOException ex) {
373 throw new TskCoreException(ex.getLocalizedMessage());
378 return regFilesLocal;
385 private static List<AbstractFile> findRegistryFiles() throws TskCoreException {
386 List<AbstractFile> registryFiles =
new ArrayList<>();
389 openCase = Case.getCurrentCaseThrows();
390 }
catch (NoCurrentCaseException ex) {
391 throw new TskCoreException(ex.getLocalizedMessage());
395 for (Content ds : openCase.getDataSources()) {
398 registryFiles.addAll(fileManager.findFiles(ds,
"ntuser.dat"));
401 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
402 for (String regFileName : regFileNames) {
403 List<AbstractFile> allRegistryFiles = fileManager.
findFiles(ds, regFileName,
"/system32/config");
404 for (AbstractFile regFile : allRegistryFiles) {
406 if (!regFile.getParentPath().contains(
"RegBack")) {
407 registryFiles.add(regFile);
413 return registryFiles;
416 private void setUnsupportedFieldWarnings() {
417 List<String> fieldNames =
new ArrayList<>();
419 if (obj.getNumberValues() != null) {
420 fieldNames.add(
"Number_Values");
422 if (obj.getModifiedTime() != null) {
423 fieldNames.add(
"Modified_Time");
425 if (obj.getCreatorUsername() != null) {
426 fieldNames.add(
"Creator_Username");
428 if (obj.getHandleList() != null) {
429 fieldNames.add(
"Handle_List");
431 if (obj.getNumberSubkeys() != null) {
432 fieldNames.add(
"Number_Subkeys");
434 if (obj.getSubkeys() != null) {
435 fieldNames.add(
"Subkeys");
437 if (obj.getByteRuns() != null) {
438 fieldNames.add(
"Byte_Runs");
441 String warningStr =
"";
442 for (String name : fieldNames) {
443 if (!warningStr.isEmpty()) {
449 addWarning(
"Unsupported field(s): " + warningStr);
462 abstractFile = a_abstractFile;
463 tempFileName = a_tempFileName;
471 AbstractFile getAbstractFile() {
480 String getTempFileName() {
RegistryFileInfo(AbstractFile a_abstractFile, String a_tempFileName)
final AbstractFile abstractFile
synchronized List< AbstractFile > findFiles(String fileName)
final String tempFileName