23 package org.sleuthkit.autopsy.recentactivity;
 
   27 import java.text.ParseException;
 
   28 import java.text.SimpleDateFormat;
 
   30 import java.util.logging.Level;
 
   31 import javax.xml.parsers.DocumentBuilder;
 
   32 import javax.xml.parsers.DocumentBuilderFactory;
 
   33 import javax.xml.parsers.ParserConfigurationException;
 
   34 import org.openide.modules.InstalledFileLocator;
 
   35 import org.openide.util.NbBundle;
 
   44 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
 
   45 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   46 import org.w3c.dom.Document;
 
   47 import org.w3c.dom.Element;
 
   48 import org.w3c.dom.Node;
 
   49 import org.w3c.dom.NodeList;
 
   50 import org.xml.sax.InputSource;
 
   51 import org.xml.sax.SAXException;
 
   52 import java.nio.file.Path;
 
   53 import static java.util.TimeZone.getTimeZone;
 
   54 import org.openide.util.Lookup;
 
   60 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
 
   69     "RegRipperNotFound=Autopsy RegRipper executable not found.",
 
   70     "RegRipperFullNotFound=Full version RegRipper executable not found.",
 
   71     "Progress_Message_Analyze_Registry=Analyzing Registry Files" 
   73 class ExtractRegistry extends Extract {
 
   75     private final Logger logger = Logger.getLogger(this.getClass().getName());
 
   76     private String RR_PATH;
 
   77     private String RR_FULL_PATH;
 
   79     private Path rrFullHome; 
 
   80     private Content dataSource;
 
   81     private IngestJobContext context;
 
   82     final private static UsbDeviceIdMapper USB_MAPPER = 
new UsbDeviceIdMapper();
 
   83     final private static String RIP_EXE = 
"rip.exe";
 
   84     final private static String RIP_PL = 
"rip.pl";
 
   85     final private static int MS_IN_SEC = 1000;
 
   86     final private static String NEVER_DATE = 
"Never";
 
   87     final private static String SECTION_DIVIDER = 
"-------------------------";
 
   88     private final List<String> rrCmd = 
new ArrayList<>();
 
   89     private final List<String> rrFullCmd = 
new ArrayList<>();
 
   91     ExtractRegistry() throws IngestModuleException {
 
   92         moduleName = NbBundle.getMessage(ExtractIE.class, 
"ExtractRegistry.moduleName.text");
 
   94         final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(), 
false); 
 
   96             throw new IngestModuleException(Bundle.RegRipperNotFound());
 
   99         final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(), 
false); 
 
  100         if (rrFullRoot == null) {
 
  101             throw new IngestModuleException(Bundle.RegRipperFullNotFound());
 
  104         String executableToRun = RIP_EXE;
 
  105         if (!PlatformUtil.isWindowsOS()) {
 
  106             executableToRun = RIP_PL;
 
  108         rrHome = rrRoot.toPath();
 
  109         RR_PATH = rrHome.resolve(executableToRun).toString();
 
  110         rrFullHome = rrFullRoot.toPath();
 
  111         RR_FULL_PATH = rrFullHome.resolve(executableToRun).toString();
 
  113         if (!(
new File(RR_PATH).exists())) {
 
  114             throw new IngestModuleException(Bundle.RegRipperNotFound());
 
  116         if (!(
new File(RR_FULL_PATH).exists())) {
 
  117             throw new IngestModuleException(Bundle.RegRipperFullNotFound());
 
  119         if (PlatformUtil.isWindowsOS()) {
 
  121             rrFullCmd.add(RR_FULL_PATH);
 
  124             File usrBin = 
new File(
"/usr/bin/perl");
 
  125             File usrLocalBin = 
new File(
"/usr/local/bin/perl");
 
  126             if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
 
  127                 perl = 
"/usr/bin/perl";
 
  128             } 
else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
 
  129                 perl = 
"/usr/local/bin/perl";
 
  131                 throw new IngestModuleException(
"perl not found in your system");
 
  136             rrFullCmd.add(RR_FULL_PATH);
 
  143     private List<AbstractFile> findRegistryFiles() {
 
  144         List<AbstractFile> allRegistryFiles = 
new ArrayList<>();
 
  149             allRegistryFiles.addAll(fileManager.findFiles(dataSource, 
"ntuser.dat")); 
 
  150         } 
catch (TskCoreException ex) {
 
  151             logger.log(Level.WARNING, 
"Error fetching 'ntuser.dat' file."); 
 
  155         String[] regFileNames = 
new String[]{
"system", 
"software", 
"security", 
"sam"}; 
 
  156         for (String regFileName : regFileNames) {
 
  158                 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, 
"/system32/config")); 
 
  159             } 
catch (TskCoreException ex) {
 
  160                 String msg = NbBundle.getMessage(this.getClass(),
 
  161                         "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
 
  162                 logger.log(Level.WARNING, msg);
 
  163                 this.addErrorMessage(this.getName() + 
": " + msg);
 
  166         return allRegistryFiles;
 
  173     private void analyzeRegistryFiles() {
 
  174         List<AbstractFile> allRegistryFiles = findRegistryFiles();
 
  177         FileWriter logFile = null;
 
  179             logFile = 
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, 
"reg") + File.separator + 
"regripper-info.txt"); 
 
  180         } 
catch (IOException ex) {
 
  181             logger.log(Level.SEVERE, null, ex);
 
  184         for (AbstractFile regFile : allRegistryFiles) {
 
  185             String regFileName = regFile.getName();
 
  186             long regFileId = regFile.getId();
 
  187             String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, 
"reg") + File.separator + regFileName;
 
  188             String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, 
"reg") + File.separator + regFileName + 
"-regripper-" + Long.toString(regFileId); 
 
  189             File regFileNameLocalFile = 
new File(regFileNameLocal);
 
  191                 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
 
  192             } 
catch (ReadContentInputStreamException ex) {
 
  193                 logger.log(Level.WARNING, String.format(
"Error reading registry file '%s' (id=%d).",
 
  194                         regFile.getName(), regFileId), ex); 
 
  195                 this.addErrorMessage(
 
  196                         NbBundle.getMessage(
this.getClass(), 
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
 
  197                                 this.getName(), regFileName));
 
  199             } 
catch (IOException ex) {
 
  200                 logger.log(Level.SEVERE, String.format(
"Error writing temp registry file '%s' for registry file '%s' (id=%d).",
 
  201                         regFileNameLocal, regFile.getName(), regFileId), ex); 
 
  202                 this.addErrorMessage(
 
  203                         NbBundle.getMessage(
this.getClass(), 
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
 
  204                                 this.getName(), regFileName));
 
  208             if (context.dataSourceIngestIsCancelled()) {
 
  213                 if (logFile != null) {
 
  214                     logFile.write(Long.toString(regFileId) + 
"\t" + regFile.getUniquePath() + 
"\n");
 
  216             } 
catch (TskCoreException | IOException ex) {
 
  217                 logger.log(Level.SEVERE, null, ex);
 
  220             logger.log(Level.INFO, 
"{0}- Now getting registry information from {1}", 
new Object[]{moduleName, regFileNameLocal}); 
 
  221             RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
 
  222             if (context.dataSourceIngestIsCancelled()) {
 
  227             if (regOutputFiles.autopsyPlugins.isEmpty() == 
false) {
 
  228                 if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == 
false) {
 
  229                     this.addErrorMessage(
 
  230                             NbBundle.getMessage(
this.getClass(), 
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
 
  231                                     this.getName(), regFileName));
 
  236             if (!regOutputFiles.fullPlugins.isEmpty()) {
 
  238                 if (regFileNameLocal.toLowerCase().contains(
"sam")) {
 
  239                     if (parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == 
false) {
 
  240                         this.addErrorMessage(
 
  241                                 NbBundle.getMessage(
this.getClass(), 
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
 
  242                                         this.getName(), regFileName));
 
  246                     Report report = currentCase.addReport(regOutputFiles.fullPlugins,
 
  247                             NbBundle.getMessage(
this.getClass(), 
"ExtractRegistry.parentModuleName.noSpace"),
 
  248                             "RegRipper " + regFile.getUniquePath(), regFile); 
 
  251                     KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
 
  252                     if (null == searchService) {
 
  253                         logger.log(Level.WARNING, 
"Keyword search service not found. Report will not be indexed");
 
  255                         searchService.index(report);
 
  257                 } 
catch (TskCoreException e) {
 
  258                     this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); 
 
  263             regFileNameLocalFile.delete();
 
  267             if (logFile != null) {
 
  270         } 
catch (IOException ex) {
 
  271             logger.log(Level.SEVERE, null, ex);
 
  277         public String autopsyPlugins = 
"";
 
  278         public String fullPlugins = 
"";
 
  288     private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
 
  289         String autopsyType = 
"";    
 
  294         if (regFilePath.toLowerCase().contains(
"system")) { 
 
  295             autopsyType = 
"autopsysystem"; 
 
  297         } 
else if (regFilePath.toLowerCase().contains(
"software")) { 
 
  298             autopsyType = 
"autopsysoftware"; 
 
  299             fullType = 
"software"; 
 
  300         } 
else if (regFilePath.toLowerCase().contains(
"ntuser")) { 
 
  301             autopsyType = 
"autopsyntuser"; 
 
  303         } 
else if (regFilePath.toLowerCase().contains(
"sam")) { 
 
  306         } 
else if (regFilePath.toLowerCase().contains(
"security")) { 
 
  307             fullType = 
"security"; 
 
  309             return regOutputFiles;
 
  313         if (!autopsyType.isEmpty()) {
 
  315             String errFilePath = outFilePathBase + 
"-autopsy.err.txt"; 
 
  316             logger.log(Level.INFO, 
"Writing RegRipper results to: {0}", regOutputFiles.
autopsyPlugins); 
 
  317             executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.
autopsyPlugins, errFilePath);
 
  319         if (context.dataSourceIngestIsCancelled()) {
 
  320             return regOutputFiles;
 
  324         if (!fullType.isEmpty()) {
 
  325             regOutputFiles.
fullPlugins = outFilePathBase + 
"-full.txt"; 
 
  326             String errFilePath = outFilePathBase + 
"-full.err.txt"; 
 
  327             logger.log(Level.INFO, 
"Writing Full RegRipper results to: {0}", regOutputFiles.
fullPlugins); 
 
  328             executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.
fullPlugins, errFilePath);
 
  330         return regOutputFiles;
 
  333     private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
 
  335             List<String> commandLine = 
new ArrayList<>();
 
  336             for (String cmd : regRipperPath) {
 
  337                 commandLine.add(cmd);
 
  339             commandLine.add(
"-r"); 
 
  340             commandLine.add(hiveFilePath);
 
  341             commandLine.add(
"-f"); 
 
  342             commandLine.add(hiveFileType);
 
  344             ProcessBuilder processBuilder = 
new ProcessBuilder(commandLine);
 
  345             processBuilder.directory(regRipperHomeDir.toFile()); 
 
  346             processBuilder.redirectOutput(
new File(outputFile));
 
  347             processBuilder.redirectError(
new File(errFile));
 
  348             ExecUtil.execute(processBuilder, 
new DataSourceIngestModuleProcessTerminator(context));
 
  349         } 
catch (IOException ex) {
 
  350             logger.log(Level.SEVERE, 
"Unable to run RegRipper", ex); 
 
  351             this.addErrorMessage(NbBundle.getMessage(
this.getClass(), 
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
 
  364     private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
 
  365         FileInputStream fstream = null;
 
  368             File regfile = 
new File(regFilePath);
 
  369             fstream = 
new FileInputStream(regfile);
 
  370             String regString = 
new Scanner(fstream, 
"UTF-8").useDelimiter(
"\\Z").next(); 
 
  371             String startdoc = 
"<?xml version=\"1.0\"?><document>"; 
 
  372             String result = regString.replaceAll(
"----------------------------------------", 
"");
 
  373             result = result.replaceAll(
"\\n", 
""); 
 
  374             result = result.replaceAll(
"\\r", 
""); 
 
  375             result = result.replaceAll(
"'", 
"'"); 
 
  376             result = result.replaceAll(
"&", 
"&"); 
 
  377             result = result.replace(
'\0', 
' '); 
 
  378             String enddoc = 
"</document>"; 
 
  379             String stringdoc = startdoc + result + enddoc;
 
  380             DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 
  381             Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
 
  384             Element oroot = doc.getDocumentElement();
 
  385             NodeList children = oroot.getChildNodes();
 
  386             int len = children.getLength();
 
  389             Collection<BlackboardArtifact> usbBBartifacts = 
new ArrayList<>();
 
  392             Collection<BlackboardArtifact> wifiBBartifacts = 
new ArrayList<>();
 
  393             for (
int i = 0; i < len; i++) {
 
  394                 Element tempnode = (Element) children.item(i);
 
  396                 String dataType = tempnode.getNodeName();
 
  397                 NodeList timenodes = tempnode.getElementsByTagName(
"mtime"); 
 
  399                 if (timenodes.getLength() > 0) {
 
  400                     Element timenode = (Element) timenodes.item(0);
 
  401                     String etime = timenode.getTextContent();
 
  403                         Long epochtime = 
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
 
  405                         String Tempdate = mtime.toString();
 
  406                         mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
 
  407                     } 
catch (ParseException ex) {
 
  408                         logger.log(Level.WARNING, 
"Failed to parse epoch time when parsing the registry."); 
 
  412                 NodeList artroots = tempnode.getElementsByTagName(
"artifacts"); 
 
  413                 if (artroots.getLength() == 0) {
 
  418                 Element artroot = (Element) artroots.item(0);
 
  419                 NodeList myartlist = artroot.getChildNodes();
 
  420                 String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
 
  427                         String systemRoot = 
"";
 
  428                         String productId = 
"";
 
  429                         String regOwner = 
"";
 
  431                         Long installtime = null;
 
  432                         for (
int j = 0; j < myartlist.getLength(); j++) {
 
  433                             Node artchild = myartlist.item(j);
 
  435                             if (artchild.hasAttributes()) {
 
  436                                 Element artnode = (Element) artchild;
 
  438                                 String value = artnode.getTextContent().trim();
 
  439                                 String name = artnode.getAttribute(
"name"); 
 
  446                                         version = version + 
" " + value;
 
  454                                     case "RegisteredOwner": 
 
  457                                     case "RegisteredOrganization": 
 
  462                                             Long epochtime = 
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
 
  463                                             installtime = epochtime;
 
  464                                             String Tempdate = installtime.toString();
 
  465                                             installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
 
  466                                         } 
catch (ParseException e) {
 
  467                                             logger.log(Level.SEVERE, 
"RegRipper::Conversion on DateTime -> ", e); 
 
  476                             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  477                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
 
  478                             if (installtime != null) {
 
  479                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
 
  481                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
 
  482                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
 
  483                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
 
  484                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
 
  487                             ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
 
  488                             if (results.isEmpty()) {
 
  489                                 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
 
  490                                 bbart.addAttributes(bbattributes);
 
  493                                 this.indexArtifact(bbart);
 
  495                                 results.get(0).addAttributes(bbattributes);
 
  498                         } 
catch (TskCoreException ex) {
 
  499                             logger.log(Level.SEVERE, 
"Error adding installed program artifact to blackboard."); 
 
  504                         String procArch = 
"";
 
  507                         for (
int j = 0; j < myartlist.getLength(); j++) {
 
  508                             Node artchild = myartlist.item(j);
 
  510                             if (artchild.hasAttributes()) {
 
  511                                 Element artnode = (Element) artchild;
 
  513                                 String value = artnode.getTextContent().trim();
 
  514                                 String name = artnode.getAttribute(
"name"); 
 
  519                                     case "PROCESSOR_ARCHITECTURE": 
 
  522                                     case "PROCESSOR_IDENTIFIER": 
 
  534                             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  535                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
 
  536                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
 
  537                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
 
  540                             ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
 
  541                             if (results.isEmpty()) {
 
  542                                 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
 
  543                                 bbart.addAttributes(bbattributes);
 
  546                                 this.indexArtifact(bbart);
 
  548                                 results.get(0).addAttributes(bbattributes);
 
  550                         } 
catch (TskCoreException ex) {
 
  551                             logger.log(Level.SEVERE, 
"Error adding os info artifact to blackboard."); 
 
  555                         String compName = 
"";
 
  557                         for (
int j = 0; j < myartlist.getLength(); j++) {
 
  558                             Node artchild = myartlist.item(j);
 
  560                             if (artchild.hasAttributes()) {
 
  561                                 Element artnode = (Element) artchild;
 
  563                                 String value = artnode.getTextContent().trim();
 
  564                                 String name = artnode.getAttribute(
"name"); 
 
  566                                 if (name.equals(
"ComputerName")) { 
 
  568                                 } 
else if (name.equals(
"Domain")) { 
 
  574                             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  575                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
 
  576                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
 
  579                             ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
 
  580                             if (results.isEmpty()) {
 
  581                                 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
 
  582                                 bbart.addAttributes(bbattributes);
 
  585                                 this.indexArtifact(bbart);
 
  587                                 results.get(0).addAttributes(bbattributes);
 
  589                         } 
catch (TskCoreException ex) {
 
  590                             logger.log(Level.SEVERE, 
"Error adding os info artifact to blackboard."); 
 
  594                         for (
int j = 0; j < myartlist.getLength(); j++) {
 
  595                             Node artchild = myartlist.item(j);
 
  597                             if (artchild.hasAttributes()) {
 
  598                                 Element artnode = (Element) artchild;
 
  600                                 String value = artnode.getTextContent().trim();
 
  601                                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  614                                             Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime")); 
 
  615                                             usbMtime = Long.valueOf(usbMtime.toString());
 
  617                                             BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
 
  618                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
 
  619                                             String dev = artnode.getAttribute(
"dev"); 
 
  622                                             if (dev.toLowerCase().contains(
"vid")) { 
 
  623                                                 USBInfo info = USB_MAPPER.parseAndLookup(dev);
 
  624                                                 if (info.getVendor() != null) {
 
  625                                                     make = info.getVendor();
 
  627                                                 if (info.getProduct() != null) {
 
  628                                                     model = info.getProduct();
 
  631                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
 
  632                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
 
  633                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
 
  634                                             bbart.addAttributes(bbattributes);
 
  637                                             this.indexArtifact(bbart);
 
  639                                             usbBBartifacts.add(bbart);
 
  640                                         } 
catch (TskCoreException ex) {
 
  641                                             logger.log(Level.SEVERE, 
"Error adding device attached artifact to blackboard."); 
 
  645                                         Long itemMtime = null;
 
  647                                             Long epochtime = 
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute(
"mtime")).getTime(); 
 
  648                                             itemMtime = epochtime;
 
  649                                             itemMtime = itemMtime / MS_IN_SEC;
 
  650                                         } 
catch (ParseException e) {
 
  651                                             logger.log(Level.WARNING, 
"Failed to parse epoch time for installed program artifact."); 
 
  655                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
 
  656                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
 
  657                                             BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
 
  658                                             bbart.addAttributes(bbattributes);
 
  661                                             this.indexArtifact(bbart);
 
  662                                         } 
catch (TskCoreException ex) {
 
  663                                             logger.log(Level.SEVERE, 
"Error adding installed program artifact to blackboard."); 
 
  667                                         String officeName = artnode.getAttribute(
"name"); 
 
  670                                             BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
 
  673                                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
 
  675                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
 
  676                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
 
  677                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
 
  678                                             bbart.addAttributes(bbattributes);
 
  681                                             this.indexArtifact(bbart);
 
  682                                         } 
catch (TskCoreException ex) {
 
  683                                             logger.log(Level.SEVERE, 
"Error adding recent object artifact to blackboard."); 
 
  687                                     case "ProcessorArchitecture": 
 
  704                                             String homeDir = value;
 
  705                                             String sid = artnode.getAttribute(
"sid"); 
 
  706                                             String username = artnode.getAttribute(
"username"); 
 
  707                                             BlackboardArtifact bbart = null;
 
  710                                                 ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
 
  711                                                 for (BlackboardArtifact artifact : existingArtifacts) {
 
  712                                                     if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
 
  713                                                         BlackboardAttribute attribute = artifact.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
 
  714                                                         if (attribute != null && attribute.getValueString().equals(sid)) {
 
  720                                             } 
catch (TskCoreException ex) {
 
  721                                                 logger.log(Level.WARNING, 
"Error getting existing os account artifact", ex);
 
  725                                                 bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
 
  726                                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
 
  727                                                         parentModuleName, username));
 
  728                                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
 
  729                                                         parentModuleName, sid));
 
  730                                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
 
  731                                                         parentModuleName, homeDir));
 
  734                                                 BlackboardAttribute bbattr = bbart.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
 
  736                                                 if (bbattr == null) {
 
  737                                                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
 
  738                                                             parentModuleName, username));
 
  740                                                 bbattr = bbart.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
 
  741                                                 if (bbattr == null) {
 
  742                                                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
 
  743                                                             parentModuleName, homeDir));
 
  746                                             bbart.addAttributes(bbattributes);
 
  748                                             this.indexArtifact(bbart);
 
  749                                         } 
catch (TskCoreException ex) {
 
  750                                             logger.log(Level.SEVERE, 
"Error adding account artifact to blackboard."); 
 
  754                                     case "NtuserNetwork": 
 
  756                                             String localPath = artnode.getAttribute(
"localPath"); 
 
  757                                             String remoteName = value;
 
  758                                             BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
 
  759                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
 
  760                                                     parentModuleName, localPath));
 
  761                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
 
  762                                                     parentModuleName, remoteName));
 
  763                                             bbart.addAttributes(bbattributes);
 
  765                                             this.indexArtifact(bbart);
 
  766                                         } 
catch (TskCoreException ex) {
 
  767                                             logger.log(Level.SEVERE, 
"Error adding network artifact to blackboard."); 
 
  771                                         String adapter = artnode.getAttribute(
"adapter"); 
 
  773                                             Long lastWriteTime = Long.parseLong(artnode.getAttribute(
"writeTime")); 
 
  774                                             lastWriteTime = Long.valueOf(lastWriteTime.toString());
 
  775                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
 
  776                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
 
  777                                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
 
  778                                             BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
 
  779                                             bbart.addAttributes(bbattributes);
 
  781                                             this.indexArtifact(bbart);
 
  782                                             wifiBBartifacts.add(bbart);
 
  783                                         } 
catch (TskCoreException ex) {
 
  784                                             logger.log(Level.SEVERE, 
"Error adding SSID artifact to blackboard."); 
 
  794                                         logger.log(Level.WARNING, 
"Unrecognized node name: {0}", dataType); 
 
  802             if (!usbBBartifacts.isEmpty()) {
 
  803                 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts));
 
  805             if (!wifiBBartifacts.isEmpty()) {
 
  806                 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK, wifiBBartifacts));
 
  809         } 
catch (FileNotFoundException ex) {
 
  810             logger.log(Level.SEVERE, 
"Error finding the registry file.", ex); 
 
  811         } 
catch (SAXException ex) {
 
  812             logger.log(Level.SEVERE, 
"Error parsing the registry XML: {0}", ex); 
 
  813         } 
catch (IOException ex) {
 
  814             logger.log(Level.SEVERE, 
"Error building the document parser: {0}", ex); 
 
  815         } 
catch (ParserConfigurationException ex) {
 
  816             logger.log(Level.SEVERE, 
"Error configuring the registry parser: {0}", ex); 
 
  819                 if (fstream != null) {
 
  822             } 
catch (IOException ex) {
 
  837     private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
 
  838         File regfile = 
new File(regFilePath);
 
  839         String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
 
  840         SimpleDateFormat regRipperTimeFormat = 
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'");
 
  841         regRipperTimeFormat.setTimeZone(getTimeZone(
"GMT"));
 
  842         try (BufferedReader bufferedReader = 
new BufferedReader(
new FileReader(regfile))) {
 
  844             String userInfoSection = 
"User Information";
 
  845             String previousLine = null;
 
  846             String line = bufferedReader.readLine();
 
  847             Set<UserInfo> userSet = 
new HashSet<>();
 
  848             while (line != null) {
 
  849                 if (line.contains(SECTION_DIVIDER) && previousLine != null) {
 
  850                     if (previousLine.contains(userInfoSection)) {
 
  851                         readUsers(bufferedReader, userSet);
 
  855                 line = bufferedReader.readLine();
 
  857             Map<String, UserInfo> userInfoMap = 
new HashMap<>();
 
  859             for (UserInfo userInfo : userSet) {
 
  860                 userInfoMap.put(userInfo.getUserSid(), userInfo);
 
  863             List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
 
  864             for (BlackboardArtifact osAccount : existingOsAccounts) {
 
  866                 if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
 
  867                     BlackboardAttribute existingUserId = osAccount.getAttribute(
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
 
  868                     if (existingUserId != null) {
 
  869                         UserInfo userInfo = userInfoMap.remove(existingUserId.getValueString().trim());
 
  871                         if (userInfo != null) {
 
  872                             Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  873                             if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) {
 
  874                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  875                                         parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC));
 
  877                             if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) {
 
  878                                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  879                                         parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC));
 
  881                             bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
 
  882                                     parentModuleName, userInfo.getLoginCount()));
 
  883                             osAccount.addAttributes(bbattributes);
 
  889             for (String userId : userInfoMap.keySet()) {
 
  890                 UserInfo userInfo = userInfoMap.get(userId);
 
  891                 Collection<BlackboardAttribute> bbattributes = 
new ArrayList<>();
 
  892                 BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
 
  893                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
 
  894                         parentModuleName, userInfo.getUserName()));
 
  895                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
 
  896                         parentModuleName, userId));
 
  897                 if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) {
 
  898                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
 
  899                             parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC));
 
  901                 if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) {
 
  902                     bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
 
  903                             parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC));
 
  905                 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
 
  906                         parentModuleName, userInfo.getLoginCount()));
 
  907                 bbart.addAttributes(bbattributes);
 
  909                 this.indexArtifact(bbart);
 
  913         } 
catch (FileNotFoundException ex) {
 
  914             logger.log(Level.SEVERE, 
"Error finding the registry file.", ex); 
 
  915         } 
catch (IOException ex) {
 
  916             logger.log(Level.SEVERE, 
"Error building the document parser: {0}", ex); 
 
  917         } 
catch (ParseException ex) {
 
  918             logger.log(Level.SEVERE, 
"Error parsing the the date from the registry file", ex); 
 
  919         } 
catch (TskCoreException ex) {
 
  920              logger.log(Level.SEVERE, 
"Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); 
 
  936     private void readUsers(BufferedReader bufferedReader, Set<UserInfo> users) 
throws IOException {
 
  937         String userNameLabel = 
"Username        :";
 
  938         String sidLabel = 
"SID             :";
 
  939         String accountCreatedLabel = 
"Account Created :";
 
  940         String loginCountLabel = 
"Login Count     :";
 
  941         String lastLoginLabel = 
"Last Login Date :";
 
  942         String line = bufferedReader.readLine();
 
  944         String userName = 
"";
 
  945         while (line != null && !line.contains(SECTION_DIVIDER)) {
 
  947             if (line.contains(userNameLabel)) {
 
  948                 String userNameAndIdString = line.replace(userNameLabel, 
"");
 
  949                 userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf(
'[')).trim();
 
  951             else if (line.contains(sidLabel) && !userName.isEmpty()){
 
  952                 String sid = line.replace(sidLabel, 
"").trim();
 
  953                 UserInfo userInfo = 
new UserInfo(userName, sid);
 
  955                 line = bufferedReader.readLine();
 
  956                 while (line != null && !line.isEmpty()) {
 
  957                     if (line.contains(accountCreatedLabel)) {
 
  958                         userInfo.setAccountCreatedDate(line.replace(accountCreatedLabel, 
"").trim());
 
  959                     } 
else if (line.contains(loginCountLabel)) {
 
  960                         userInfo.setLoginCount(Integer.parseInt(line.replace(loginCountLabel, 
"").trim()));
 
  961                     } 
else if (line.contains(lastLoginLabel)) {
 
  962                         userInfo.setLastLoginDate(line.replace(lastLoginLabel, 
"").trim());
 
  964                     line = bufferedReader.readLine();
 
  969             line = bufferedReader.readLine();
 
  974     public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
 
  975         this.dataSource = dataSource;
 
  976         this.context = context;
 
  978         progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
 
  979         analyzeRegistryFiles();
 
  993         private int loginCount = 0;
 
 1003             userSid = userSidString;
 
 1011         String getUserName() {
 
 1020         String getUserSid() {
 
 1029         String getLastLoginDate() {
 
 1030             return lastLoginDate;
 
 1038         void setLastLoginDate(String lastLoginDate) {
 
 1039             this.lastLoginDate = lastLoginDate;
 
 1047         String getAccountCreatedDate() {
 
 1048             return accountCreatedDate;
 
 1056         void setAccountCreatedDate(String accountCreatedDate) {
 
 1057             this.accountCreatedDate = accountCreatedDate;
 
 1065         int getLoginCount() {
 
 1074         void setLoginCount(
int loginCount) {
 
 1075             this.loginCount = loginCount;