23 package org.sleuthkit.autopsy.recentactivity;
25 import java.io.BufferedReader;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileReader;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.StringReader;
33 import java.text.ParseException;
34 import java.text.SimpleDateFormat;
35 import java.util.logging.Level;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import org.openide.modules.InstalledFileLocator;
40 import org.openide.util.NbBundle;
48 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
49 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.Node;
53 import org.w3c.dom.NodeList;
54 import org.xml.sax.InputSource;
55 import org.xml.sax.SAXException;
56 import java.nio.file.Path;
57 import java.util.AbstractMap;
58 import java.util.ArrayList;
59 import java.util.List;
60 import java.util.Collection;
61 import java.util.HashMap;
63 import java.util.Scanner;
65 import java.util.HashSet;
66 import static java.util.TimeZone.getTimeZone;
67 import org.openide.util.Lookup;
75 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
86 "RegRipperNotFound=Autopsy RegRipper executable not found.",
87 "RegRipperFullNotFound=Full version RegRipper executable not found.",
88 "Progress_Message_Analyze_Registry=Analyzing Registry Files"
90 class ExtractRegistry extends Extract {
92 private static final String USERNAME_KEY =
"Username";
93 private static final String SID_KEY =
"SID";
94 private static final String RID_KEY =
"RID";
95 private static final String ACCOUNT_CREATED_KEY =
"Account Created";
96 private static final String LAST_LOGIN_KEY =
"Last Login Date";
97 private static final String LOGIN_COUNT_KEY =
"Login Count";
98 private static final String FULL_NAME_KEY =
"Full Name";
99 private static final String USER_COMMENT_KEY =
"User Comment";
100 private static final String ACCOUNT_TYPE_KEY =
"Account Type";
101 private static final String NAME_KEY =
"Name";
102 private static final String PWD_RESET_KEY =
"Pwd Rest Date";
103 private static final String PWD_FAILE_KEY =
"Pwd Fail Date";
104 private static final String INTERNET_NAME_KEY =
"InternetName";
105 private static final String PWD_DOES_NOT_EXPIRE_KEY =
"Password does not expire";
106 private static final String ACCOUNT_DISABLED_KEY =
"Account Disabled";
107 private static final String PWD_NOT_REQUIRED_KEY =
"Password not required";
108 private static final String NORMAL_ACCOUNT_KEY =
"Normal user account";
109 private static final String HOME_DIRECTORY_REQUIRED_KEY =
"Home directory required";
110 private static final String TEMPORARY_DUPLICATE_ACCOUNT =
"Temporary duplicate account";
111 private static final String MNS_LOGON_ACCOUNT_KEY =
"MNS logon user account";
112 private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY =
"Interdomain trust account";
113 private static final String WORKSTATION_TRUST_ACCOUNT =
"Workstation trust account";
114 private static final String SERVER_TRUST_ACCOUNT =
"Server trust account";
115 private static final String ACCOUNT_AUTO_LOCKED =
"Account auto locked";
116 private static final String PASSWORD_HINT =
"Password Hint";
118 private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
119 private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
120 private static final String[] ACCOUNT_TYPE_FLAGS = {NORMAL_ACCOUNT_KEY, SERVER_TRUST_ACCOUNT, WORKSTATION_TRUST_ACCOUNT, INTERDOMAIN_TRUST_ACCOUNT_KEY, MNS_LOGON_ACCOUNT_KEY, TEMPORARY_DUPLICATE_ACCOUNT};
122 final private static UsbDeviceIdMapper USB_MAPPER =
new UsbDeviceIdMapper();
123 final private static String RIP_EXE =
"rip.exe";
124 final private static String RIP_PL =
"rip.pl";
125 final private static int MS_IN_SEC = 1000;
126 final private static String NEVER_DATE =
"Never";
127 final private static String SECTION_DIVIDER =
"-------------------------";
128 final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
129 private final List<String> rrCmd =
new ArrayList<>();
130 private final List<String> rrFullCmd =
new ArrayList<>();
131 private final Path rrHome;
132 private final Path rrFullHome;
133 private Content dataSource;
134 private IngestJobContext context;
136 ExtractRegistry() throws IngestModuleException {
137 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
139 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
140 if (rrRoot == null) {
141 throw new IngestModuleException(Bundle.RegRipperNotFound());
144 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
145 if (rrFullRoot == null) {
146 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
149 String executableToRun = RIP_EXE;
150 if (!PlatformUtil.isWindowsOS()) {
151 executableToRun = RIP_PL;
153 rrHome = rrRoot.toPath();
154 String rrPath = rrHome.resolve(executableToRun).toString();
155 rrFullHome = rrFullRoot.toPath();
157 if (!(
new File(rrPath).exists())) {
158 throw new IngestModuleException(Bundle.RegRipperNotFound());
160 String rrFullPath = rrFullHome.resolve(executableToRun).toString();
161 if (!(
new File(rrFullPath).exists())) {
162 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
164 if (PlatformUtil.isWindowsOS()) {
166 rrFullCmd.add(rrFullPath);
169 File usrBin =
new File(
"/usr/bin/perl");
170 File usrLocalBin =
new File(
"/usr/local/bin/perl");
171 if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
172 perl =
"/usr/bin/perl";
173 }
else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
174 perl =
"/usr/local/bin/perl";
176 throw new IngestModuleException(
"perl not found in your system");
181 rrFullCmd.add(rrFullPath);
188 private List<AbstractFile> findRegistryFiles() {
189 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
194 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
195 }
catch (TskCoreException ex) {
196 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
200 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
201 for (String regFileName : regFileNames) {
203 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
204 }
catch (TskCoreException ex) {
205 String msg = NbBundle.getMessage(this.getClass(),
206 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
207 logger.log(Level.WARNING, msg);
208 this.addErrorMessage(this.getName() +
": " + msg);
211 return allRegistryFiles;
218 private void analyzeRegistryFiles() {
219 List<AbstractFile> allRegistryFiles = findRegistryFiles();
222 FileWriter logFile = null;
224 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator +
"regripper-info.txt");
225 }
catch (IOException ex) {
226 logger.log(Level.SEVERE, null, ex);
229 for (AbstractFile regFile : allRegistryFiles) {
230 String regFileName = regFile.getName();
231 long regFileId = regFile.getId();
232 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") + File.separator + regFileName;
233 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator + regFileName +
"-regripper-" + Long.toString(regFileId);
234 File regFileNameLocalFile =
new File(regFileNameLocal);
236 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
237 }
catch (ReadContentInputStreamException ex) {
238 logger.log(Level.WARNING, String.format(
"Error reading registry file '%s' (id=%d).",
239 regFile.getName(), regFileId), ex);
240 this.addErrorMessage(
241 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
242 this.getName(), regFileName));
244 }
catch (IOException ex) {
245 logger.log(Level.SEVERE, String.format(
"Error writing temp registry file '%s' for registry file '%s' (id=%d).",
246 regFileNameLocal, regFile.getName(), regFileId), ex);
247 this.addErrorMessage(
248 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
249 this.getName(), regFileName));
253 if (context.dataSourceIngestIsCancelled()) {
258 if (logFile != null) {
259 logFile.write(Long.toString(regFileId) +
"\t" + regFile.getUniquePath() +
"\n");
261 }
catch (TskCoreException | IOException ex) {
262 logger.log(Level.SEVERE, null, ex);
265 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
266 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
267 if (context.dataSourceIngestIsCancelled()) {
272 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
273 this.addErrorMessage(
274 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
275 this.getName(), regFileName));
279 if (!regOutputFiles.fullPlugins.isEmpty()) {
281 if (regFileNameLocal.toLowerCase().contains(
"sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) ==
false) {
282 this.addErrorMessage(
283 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
284 this.getName(), regFileName));
287 Report report = currentCase.addReport(regOutputFiles.fullPlugins,
288 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
289 "RegRipper " + regFile.getUniquePath(), regFile);
292 KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
293 if (null == searchService) {
294 logger.log(Level.WARNING,
"Keyword search service not found. Report will not be indexed");
296 searchService.index(report);
299 }
catch (TskCoreException e) {
300 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
304 regFileNameLocalFile.delete();
308 if (logFile != null) {
311 }
catch (IOException ex) {
312 logger.log(Level.SEVERE, null, ex);
323 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
324 String autopsyType =
"";
327 RegOutputFiles regOutputFiles =
new RegOutputFiles();
329 if (regFilePath.toLowerCase().contains(
"system")) {
330 autopsyType =
"autopsysystem";
332 }
else if (regFilePath.toLowerCase().contains(
"software")) {
333 autopsyType =
"autopsysoftware";
334 fullType =
"software";
335 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
336 autopsyType =
"autopsyntuser";
338 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
341 }
else if (regFilePath.toLowerCase().contains(
"security")) {
342 fullType =
"security";
344 return regOutputFiles;
348 if (!autopsyType.isEmpty()) {
349 regOutputFiles.autopsyPlugins = outFilePathBase +
"-autopsy.txt";
350 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
351 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins);
352 executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
354 if (context.dataSourceIngestIsCancelled()) {
355 return regOutputFiles;
359 if (!fullType.isEmpty()) {
360 regOutputFiles.fullPlugins = outFilePathBase +
"-full.txt";
361 String errFilePath = outFilePathBase +
"-full.err.txt";
362 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins);
363 executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
365 return regOutputFiles;
368 private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
370 List<String> commandLine =
new ArrayList<>();
371 for (String cmd : regRipperPath) {
372 commandLine.add(cmd);
374 commandLine.add(
"-r");
375 commandLine.add(hiveFilePath);
376 commandLine.add(
"-f");
377 commandLine.add(hiveFileType);
379 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
380 processBuilder.directory(regRipperHomeDir.toFile());
381 processBuilder.redirectOutput(
new File(outputFile));
382 processBuilder.redirectError(
new File(errFile));
383 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
384 }
catch (IOException ex) {
385 logger.log(Level.SEVERE,
"Unable to run RegRipper", ex);
386 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
399 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
400 FileInputStream fstream = null;
403 File regfile =
new File(regFilePath);
404 fstream =
new FileInputStream(regfile);
405 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
406 String startdoc =
"<?xml version=\"1.0\"?><document>";
407 String result = regString.replaceAll(
"----------------------------------------",
"");
408 result = result.replaceAll(
"\\n",
"");
409 result = result.replaceAll(
"\\r",
"");
410 result = result.replaceAll(
"'",
"'");
411 result = result.replaceAll(
"&",
"&");
412 result = result.replace(
'\0',
' ');
413 String enddoc =
"</document>";
414 String stringdoc = startdoc + result + enddoc;
415 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
416 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
419 Element oroot = doc.getDocumentElement();
420 NodeList children = oroot.getChildNodes();
421 int len = children.getLength();
422 for (
int i = 0; i < len; i++) {
424 if (context.dataSourceIngestIsCancelled()) {
428 Element tempnode = (Element) children.item(i);
430 String dataType = tempnode.getNodeName();
431 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
433 if (timenodes.getLength() > 0) {
434 Element timenode = (Element) timenodes.item(0);
435 String etime = timenode.getTextContent();
437 if (etime != null && !etime.isEmpty()) {
439 mtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
440 String Tempdate = mtime.toString();
441 mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
442 }
catch (ParseException ex) {
443 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.", ex);
448 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
449 if (artroots.getLength() == 0) {
454 Element artroot = (Element) artroots.item(0);
455 NodeList myartlist = artroot.getChildNodes();
456 String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
462 String systemRoot =
"";
463 String productId =
"";
464 String regOwner =
"";
466 Long installtime = null;
467 for (
int j = 0; j < myartlist.getLength(); j++) {
468 Node artchild = myartlist.item(j);
470 if (artchild.hasAttributes()) {
471 Element artnode = (Element) artchild;
473 String value = artnode.getTextContent();
475 value = value.trim();
477 String name = artnode.getAttribute(
"name");
487 version = version +
" " + value;
495 case "RegisteredOwner":
498 case "RegisteredOrganization":
502 if (value != null && !value.isEmpty()) {
504 installtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
505 String Tempdate = installtime.toString();
506 installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
507 }
catch (ParseException e) {
508 logger.log(Level.SEVERE,
"RegRipper::Conversion on DateTime -> ", e);
518 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
519 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
520 if (installtime != null) {
521 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
523 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
524 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
525 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
526 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
529 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
530 if (results.isEmpty()) {
531 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
532 bbart.addAttributes(bbattributes);
537 results.get(0).addAttributes(bbattributes);
540 }
catch (TskCoreException ex) {
541 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
546 String procArch =
"";
548 for (
int j = 0; j < myartlist.getLength(); j++) {
549 Node artchild = myartlist.item(j);
551 if (artchild.hasAttributes()) {
552 Element artnode = (Element) artchild;
554 String value = artnode.getTextContent().trim();
555 String name = artnode.getAttribute(
"name");
560 case "PROCESSOR_ARCHITECTURE":
563 case "PROCESSOR_IDENTIFIER":
574 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
575 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
576 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
577 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
580 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
581 if (results.isEmpty()) {
582 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
583 bbart.addAttributes(bbattributes);
588 results.get(0).addAttributes(bbattributes);
590 }
catch (TskCoreException ex) {
591 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
595 String compName =
"";
597 for (
int j = 0; j < myartlist.getLength(); j++) {
598 Node artchild = myartlist.item(j);
600 if (artchild.hasAttributes()) {
601 Element artnode = (Element) artchild;
603 String value = artnode.getTextContent().trim();
604 String name = artnode.getAttribute(
"name");
606 if (name.equals(
"ComputerName")) {
608 }
else if (name.equals(
"Domain")) {
614 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
615 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
616 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
619 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
620 if (results.isEmpty()) {
621 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
622 bbart.addAttributes(bbattributes);
627 results.get(0).addAttributes(bbattributes);
629 }
catch (TskCoreException ex) {
630 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
634 for (
int j = 0; j < myartlist.getLength(); j++) {
635 Node artchild = myartlist.item(j);
637 if (artchild.hasAttributes()) {
638 Element artnode = (Element) artchild;
640 String value = artnode.getTextContent().trim();
641 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
654 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
655 usbMtime = Long.valueOf(usbMtime.toString());
657 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
658 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
659 String dev = artnode.getAttribute(
"dev");
662 if (dev.toLowerCase().contains(
"vid")) {
663 USBInfo info = USB_MAPPER.parseAndLookup(dev);
664 if (info.getVendor() != null) {
665 make = info.getVendor();
667 if (info.getProduct() != null) {
668 model = info.getProduct();
671 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
672 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
673 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
674 bbart.addAttributes(bbattributes);
678 }
catch (TskCoreException ex) {
679 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.", ex);
683 Long itemMtime = null;
685 String mTimeAttr = artnode.getAttribute(
"mtime");
686 if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
687 itemMtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(mTimeAttr).getTime();
688 itemMtime /= MS_IN_SEC;
690 }
catch (ParseException ex) {
691 logger.log(Level.WARNING,
"Failed to parse epoch time for installed program artifact.", ex);
695 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
696 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
697 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
698 bbart.addAttributes(bbattributes);
702 }
catch (TskCoreException ex) {
703 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.", ex);
707 String officeName = artnode.getAttribute(
"name");
710 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
713 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
715 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
716 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
717 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
718 bbart.addAttributes(bbattributes);
722 }
catch (TskCoreException ex) {
723 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.", ex);
727 case "ProcessorArchitecture":
744 String homeDir = value;
745 String sid = artnode.getAttribute(
"sid");
746 String username = artnode.getAttribute(
"username");
747 BlackboardArtifact bbart = null;
750 ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
751 for (BlackboardArtifact artifact : existingArtifacts) {
752 if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
753 BlackboardAttribute attribute = artifact.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
754 if (attribute != null && attribute.getValueString().equals(sid)) {
760 }
catch (TskCoreException ex) {
761 logger.log(Level.WARNING,
"Error getting existing os account artifact", ex);
765 bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
766 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
767 parentModuleName, username));
768 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
769 parentModuleName, sid));
770 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
771 parentModuleName, homeDir));
774 BlackboardAttribute bbattr = bbart.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
776 if (bbattr == null) {
777 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
778 parentModuleName, username));
780 bbattr = bbart.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
781 if (bbattr == null) {
782 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
783 parentModuleName, homeDir));
786 bbart.addAttributes(bbattributes);
789 }
catch (TskCoreException ex) {
790 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.", ex);
794 case "NtuserNetwork":
796 String localPath = artnode.getAttribute(
"localPath");
797 String remoteName = value;
798 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
799 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
800 parentModuleName, localPath));
801 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
802 parentModuleName, remoteName));
803 bbart.addAttributes(bbattributes);
806 }
catch (TskCoreException ex) {
807 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.", ex);
811 String adapter = artnode.getAttribute(
"adapter");
813 Long lastWriteTime = Long.parseLong(artnode.getAttribute(
"writeTime"));
814 lastWriteTime = Long.valueOf(lastWriteTime.toString());
815 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
816 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
817 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
818 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
819 bbart.addAttributes(bbattributes);
822 }
catch (TskCoreException ex) {
823 logger.log(Level.SEVERE,
"Error adding SSID artifact to blackboard.", ex);
833 logger.log(Level.WARNING,
"Unrecognized node name: {0}", dataType);
842 }
catch (FileNotFoundException ex) {
843 logger.log(Level.SEVERE,
"Error finding the registry file.", ex);
844 }
catch (SAXException ex) {
845 logger.log(Level.SEVERE,
"Error parsing the registry XML.", ex);
846 }
catch (IOException ex) {
847 logger.log(Level.SEVERE,
"Error building the document parser.", ex);
848 }
catch (ParserConfigurationException ex) {
849 logger.log(Level.SEVERE,
"Error configuring the registry parser.", ex);
852 if (fstream != null) {
855 }
catch (IOException ex) {
870 private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
871 File regfile =
new File(regFilePath);
872 try (BufferedReader bufferedReader =
new BufferedReader(
new FileReader(regfile))) {
874 String userInfoSection =
"User Information";
875 String previousLine = null;
876 String line = bufferedReader.readLine();
877 Set<Map<String, String>> userSet =
new HashSet<>();
878 Map<String, List<String>> groupMap = null;
879 while (line != null) {
880 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
881 readUsers(bufferedReader, userSet);
884 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(
"Group Membership Information")) {
885 groupMap = readGroups(bufferedReader);
889 line = bufferedReader.readLine();
891 Map<String, Map<String, String>> userInfoMap =
new HashMap<>();
893 for (Map<String, String> userInfo : userSet) {
894 userInfoMap.put(userInfo.get(SID_KEY), userInfo);
897 List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
898 for (BlackboardArtifact osAccount : existingOsAccounts) {
900 if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
901 BlackboardAttribute existingUserId = osAccount.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
902 if (existingUserId != null) {
903 String userID = existingUserId.getValueString().trim();
904 Map<String, String> userInfo = userInfoMap.remove(userID);
906 if (userInfo != null) {
907 osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID),
true));
913 for (Map<String, String> userInfo : userInfoMap.values()) {
914 BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
915 bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)),
false));
921 }
catch (FileNotFoundException ex) {
922 logger.log(Level.SEVERE,
"Error finding the registry file.", ex);
923 }
catch (IOException ex) {
924 logger.log(Level.SEVERE,
"Error building the document parser: {0}", ex);
925 }
catch (ParseException ex) {
926 logger.log(Level.SEVERE,
"Error parsing the the date from the registry file", ex);
927 }
catch (TskCoreException ex) {
928 logger.log(Level.SEVERE,
"Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex);
944 Collection<BlackboardAttribute> getAttributesForAccount(Map<String, String> userInfo, List<String> groupList,
boolean existingUser)
throws ParseException {
945 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
947 SimpleDateFormat regRipperTimeFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'");
948 regRipperTimeFormat.setTimeZone(getTimeZone(
"GMT"));
951 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
952 getRAModuleName(), userInfo.get(SID_KEY)));
954 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
955 this.moduleName, userInfo.get(USERNAME_KEY)));
958 String value = userInfo.get(ACCOUNT_CREATED_KEY);
959 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
960 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
961 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
964 value = userInfo.get(LAST_LOGIN_KEY);
965 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
966 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
967 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
970 value = userInfo.get(LOGIN_COUNT_KEY);
971 if (value != null && !value.isEmpty()) {
972 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
973 getRAModuleName(), Integer.parseInt(value)));
976 value = userInfo.get(ACCOUNT_TYPE_KEY);
977 if (value != null && !value.isEmpty()) {
978 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE,
979 getRAModuleName(), value));
982 value = userInfo.get(USER_COMMENT_KEY);
983 if (value != null && !value.isEmpty()) {
984 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
985 getRAModuleName(), value));
988 value = userInfo.get(NAME_KEY);
989 if (value != null && !value.isEmpty()) {
990 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
991 getRAModuleName(), value));
994 value = userInfo.get(INTERNET_NAME_KEY);
995 if (value != null && !value.isEmpty()) {
996 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
997 getRAModuleName(), value));
1000 value = userInfo.get(FULL_NAME_KEY);
1001 if (value != null && !value.isEmpty()) {
1002 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME,
1003 getRAModuleName(), value));
1006 value = userInfo.get(PWD_RESET_KEY);
1007 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1008 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
1009 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1012 value = userInfo.get(PASSWORD_HINT);
1013 if (value != null && !value.isEmpty()) {
1014 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
1015 getRAModuleName(), value));
1018 value = userInfo.get(PWD_FAILE_KEY);
1019 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1020 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
1021 getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1024 String settingString =
"";
1025 for (String setting : PASSWORD_SETTINGS_FLAGS) {
1026 if (userInfo.containsKey(setting)) {
1027 settingString += setting +
", ";
1031 if (!settingString.isEmpty()) {
1032 settingString = settingString.substring(0, settingString.length() - 2);
1033 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
1034 getRAModuleName(), settingString));
1038 for (String setting : ACCOUNT_SETTINGS_FLAGS) {
1039 if (userInfo.containsKey(setting)) {
1040 settingString += setting +
", ";
1044 if (!settingString.isEmpty()) {
1045 settingString = settingString.substring(0, settingString.length() - 2);
1046 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
1047 getRAModuleName(), settingString));
1051 for (String setting : ACCOUNT_TYPE_FLAGS) {
1052 if (userInfo.containsKey(setting)) {
1053 settingString += setting +
", ";
1057 if (!settingString.isEmpty()) {
1058 settingString = settingString.substring(0, settingString.length() - 2);
1059 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
1060 getRAModuleName(), settingString));
1063 if (groupList != null && groupList.isEmpty()) {
1065 for (String group : groupList) {
1066 groups += group +
", ";
1069 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
1070 getRAModuleName(), groups.substring(0, groups.length() - 2)));
1073 return bbattributes;
1087 private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1088 String line = bufferedReader.readLine();
1090 String userName =
"";
1091 String user_rid =
"";
1092 while (line != null && !line.contains(SECTION_DIVIDER)) {
1094 if (line.contains(USERNAME_KEY)) {
1095 String regx = USERNAME_KEY +
"\\s*?:";
1096 String userNameAndIdString = line.replaceAll(regx,
"");
1097 userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf(
'[')).trim();
1098 user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf(
'['), userNameAndIdString.lastIndexOf(
']'));
1099 }
else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1100 Map.Entry<String, String> entry = getSAMKeyValue(line);
1102 HashMap<String, String> userInfo =
new HashMap<>();
1103 userInfo.put(USERNAME_KEY, userName);
1104 userInfo.put(RID_KEY, user_rid);
1105 userInfo.put(entry.getKey(), entry.getValue());
1108 line = bufferedReader.readLine();
1109 while (line != null && !line.isEmpty()) {
1110 entry = getSAMKeyValue(line);
1111 userInfo.put(entry.getKey(), entry.getValue());
1112 line = bufferedReader.readLine();
1114 users.add(userInfo);
1118 line = bufferedReader.readLine();
1131 Map<String, List<String>> readGroups(BufferedReader bufferedReader)
throws IOException {
1132 Map<String, List<String>> groupMap =
new HashMap<>();
1134 String line = bufferedReader.readLine();
1137 String groupName = null;
1139 while (line != null && !line.contains(SECTION_DIVIDER)) {
1141 if (line.contains(
"Group Name")) {
1142 String value = line.replaceAll(
"Group Name\\s*?:",
"").trim();
1143 groupName = (value.replaceAll(
"\\[\\d*?\\]",
"")).trim();
1144 int startIndex = value.indexOf(
'[');
1145 int endIndex = value.indexOf(
']');
1147 if (startIndex != -1 && endIndex != -1) {
1148 String countStr = value.substring(startIndex + 1, endIndex);
1149 userCount = Integer.parseInt(countStr);
1151 }
else if (line.matches(
"Users\\s*?:")) {
1152 for (
int i = 0; i < userCount; i++) {
1153 line = bufferedReader.readLine();
1155 String sid = line.trim();
1156 List<String> groupList = groupMap.get(sid);
1157 if (groupList == null) {
1158 groupList =
new ArrayList<>();
1159 groupMap.put(sid, groupList);
1161 groupList.add(groupName);
1166 line = bufferedReader.readLine();
1180 private Map.Entry<String, String> getSAMKeyValue(String line) {
1181 int index = line.indexOf(
':');
1182 Map.Entry<String, String> returnValue = null;
1184 String value = null;
1187 key = line.substring(0, index).trim();
1188 if (index + 1 < line.length()) {
1189 value = line.substring(index + 1).trim();
1194 }
else if (line.contains(
"-->")) {
1195 key = line.replace(
"-->",
"").trim();
1200 returnValue =
new AbstractMap.SimpleEntry<>(key, value);
1207 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
1208 this.dataSource = dataSource;
1209 this.context = context;
1211 progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
1212 analyzeRegistryFiles();
1221 public String autopsyPlugins =
"";
1222 public String fullPlugins =
"";