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);
162 private ObservableResult testRegistryFile(RegistryFileInfo a_regInfo) {
164 RegistryKey root = openRegistry(a_regInfo.tempFileName);
165 RegistryKey result = findKey(root, obj.getKey().getValue().toString());
167 if (result == null) {
172 if((obj.getHive() != null)
173 && obj.getHive().getValue().toString().startsWith(
"HKEY")){
174 String[] parts = obj.getKey().getValue().toString().split(
"\\\\");
176 for (
int i = 1; i < parts.length; i++) {
177 if (newKey.length() > 0) {
182 result = findKey(root, newKey);
185 if (result == null) {
186 return new ObservableResult(
id,
"RegistryObject: Could not find key " + obj.getKey().getValue(),
187 spacing, ObservableResult.ObservableState.FALSE, null);
191 if ((obj.getValues() == null) || (obj.getValues().getValues().isEmpty())) {
193 List<StixArtifactData> artData =
new ArrayList<StixArtifactData>();
194 artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id,
"Registry"));
195 return new ObservableResult(
id,
"RegistryObject: Found key " + obj.getKey().getValue(),
196 spacing, ObservableResult.ObservableState.TRUE, artData);
200 for (
org.mitre.cybox.objects.RegistryValueType stixRegValue : obj.getValues().getValues()) {
202 for (RegistryValue valFromFile : result.getValueList()) {
205 boolean nameSuccess =
true;
206 if (stixRegValue.getName() != null) {
208 nameSuccess = compareStringObject(stixRegValue.getName(), valFromFile.getName());
209 }
catch (UnsupportedEncodingException ex) {
214 boolean valueSuccess =
true;
215 if (nameSuccess && (stixRegValue.getData() != null)) {
216 switch (valFromFile.getValueType()) {
221 valueSuccess = compareStringObject(stixRegValue.getData(),
222 valFromFile.getValue().getAsString());
223 }
catch (UnsupportedEncodingException ex) {
224 valueSuccess =
false;
232 if ((stixRegValue.getData().getCondition() == null)
233 || (stixRegValue.getData().getCondition() == ConditionTypeEnum.EQUALS)) {
237 long stixValue = Long.decode(stixRegValue.getData().getValue().toString());
240 valueSuccess = (stixValue == valFromFile.getValue().getAsNumber());
241 }
catch (UnsupportedEncodingException ex) {
242 valueSuccess =
false;
244 }
catch (NumberFormatException ex) {
247 valueSuccess =
false;
250 valueSuccess =
false;
261 if (nameSuccess && valueSuccess) {
263 List<StixArtifactData> artData =
new ArrayList<StixArtifactData>();
264 artData.add(
new StixArtifactData(a_regInfo.abstractFile.getId(), id,
"Registry"));
265 return new ObservableResult(
id,
"RegistryObject: Found key " + obj.getKey().getValue()
266 +
" and value " + stixRegValue.getName().getValue().toString()
267 +
" = " + stixRegValue.getData().getValue().toString(),
268 spacing, ObservableResult.ObservableState.TRUE, artData);
271 }
catch (Exception ex) {
273 return new ObservableResult(
id,
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(),
274 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
277 }
catch (TskCoreException ex) {
278 return new ObservableResult(
id,
"RegistryObject: Exception during evaluation: " + ex.getLocalizedMessage(),
279 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
282 return new ObservableResult(
id,
"RegistryObject: Not done",
283 spacing, ObservableResult.ObservableState.INDETERMINATE, null);
286 public RegistryKey openRegistry(String hive)
throws TskCoreException {
289 RegistryHiveFile regFile =
new RegistryHiveFile(
new File(hive));
290 RegistryKey root = regFile.getRoot();
292 }
catch (IOException ex) {
293 throw new TskCoreException(
"Error opening registry file - " + ex.getLocalizedMessage());
294 }
catch (RegistryParseException ex) {
295 throw new TskCoreException(
"Error opening root node of registry - " + ex.getLocalizedMessage());
306 public RegistryKey findKey(RegistryKey root, String name) {
308 RegistryKey currentKey = root;
311 String[] parts = name.split(
"\\\\");
312 for (String part : parts) {
314 if (part.length() > 0) {
316 currentKey = currentKey.getSubkey(part);
317 }
catch (Exception ex) {
337 public static List<RegistryFileInfo> copyRegistryFiles() throws TskCoreException {
340 List<AbstractFile> regFilesAbstract = findRegistryFiles();
343 List<RegistryFileInfo> regFilesLocal =
new ArrayList<RegistryFileInfo>();
346 String tmpDir = Case.getCurrentCase().getTempDirectory() + File.separator +
"STIX";
347 File dir =
new File(tmpDir);
348 if (dir.exists() ==
false) {
353 for (AbstractFile regFile : regFilesAbstract) {
354 String regFileName = regFile.getName();
355 String regFileNameLocal = tmpDir + File.separator + regFileName +
"_" + index;
356 File regFileNameLocalFile =
new File(regFileNameLocal);
359 if (regFile.getMetaFlagsAsString().contains(
"Allocated")) {
360 ContentUtils.writeToFile(regFile, regFileNameLocalFile);
361 regFilesLocal.add(
new EvalRegistryObj().
new RegistryFileInfo(regFile, regFileNameLocal));
363 }
catch (IOException ex) {
364 throw new TskCoreException(ex.getLocalizedMessage());
369 return regFilesLocal;
376 private static List<AbstractFile> findRegistryFiles() throws TskCoreException {
377 List<AbstractFile> registryFiles =
new ArrayList<AbstractFile>();
380 for (Content ds : Case.getCurrentCase().getDataSources()) {
383 registryFiles.addAll(fileManager.findFiles(ds,
"ntuser.dat"));
386 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
387 for (String regFileName : regFileNames) {
388 List<AbstractFile> allRegistryFiles = fileManager.
findFiles(ds, regFileName,
"/system32/config");
389 for (AbstractFile regFile : allRegistryFiles) {
391 if (!regFile.getParentPath().contains(
"RegBack")) {
392 registryFiles.add(regFile);
398 return registryFiles;
401 private void setUnsupportedFieldWarnings() {
402 List<String> fieldNames =
new ArrayList<String>();
404 if (obj.getNumberValues() != null) {
405 fieldNames.add(
"Number_Values");
407 if (obj.getModifiedTime() != null) {
408 fieldNames.add(
"Modified_Time");
410 if (obj.getCreatorUsername() != null) {
411 fieldNames.add(
"Creator_Username");
413 if (obj.getHandleList() != null) {
414 fieldNames.add(
"Handle_List");
416 if (obj.getNumberSubkeys() != null) {
417 fieldNames.add(
"Number_Subkeys");
419 if (obj.getSubkeys() != null) {
420 fieldNames.add(
"Subkeys");
422 if (obj.getByteRuns() != null) {
423 fieldNames.add(
"Byte_Runs");
426 String warningStr =
"";
427 for (String name : fieldNames) {
428 if (!warningStr.isEmpty()) {
434 addWarning(
"Unsupported field(s): " + warningStr);
447 abstractFile = a_abstractFile;
448 tempFileName = a_tempFileName;
final String tempFileName
synchronized List< AbstractFile > findFiles(Content dataSource, String fileName)
final AbstractFile abstractFile
RegistryFileInfo(AbstractFile a_abstractFile, String a_tempFileName)