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)