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;
64 "RegRipperNotFound=Autopsy RegRipper executable not found.",
65 "RegRipperFullNotFound=Full version RegRipper executable not found."
67 class ExtractRegistry extends Extract {
69 private final Logger logger = Logger.getLogger(this.getClass().getName());
70 private String RR_PATH;
71 private String RR_FULL_PATH;
73 private Path rrFullHome;
74 private Content dataSource;
75 private IngestJobContext context;
76 final private static UsbDeviceIdMapper USB_MAPPER =
new UsbDeviceIdMapper();
77 final private static String RIP_EXE =
"rip.exe";
78 final private static String RIP_PL =
"rip.pl";
79 final private static String PERL =
"perl ";
81 ExtractRegistry() throws IngestModuleException {
82 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
83 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
85 throw new IngestModuleException(Bundle.RegRipperNotFound());
88 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
89 if (rrFullRoot == null) {
90 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
93 String executableToRun = RIP_EXE;
94 if (!PlatformUtil.isWindowsOS()) {
95 executableToRun = RIP_PL;
97 rrHome = rrRoot.toPath();
98 RR_PATH = rrHome.resolve(executableToRun).toString();
99 rrFullHome = rrFullRoot.toPath();
100 RR_FULL_PATH = rrFullHome.resolve(executableToRun).toString();
102 if (!(
new File(RR_PATH).exists())) {
103 throw new IngestModuleException(Bundle.RegRipperNotFound());
105 if (!(
new File(RR_FULL_PATH).exists())) {
106 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
109 if (!PlatformUtil.isWindowsOS()) {
110 RR_PATH = PERL + RR_PATH;
111 RR_FULL_PATH = PERL + RR_FULL_PATH;
118 private List<AbstractFile> findRegistryFiles() {
119 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
124 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
125 }
catch (TskCoreException ex) {
126 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
130 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
131 for (String regFileName : regFileNames) {
133 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
134 }
catch (TskCoreException ex) {
135 String msg = NbBundle.getMessage(this.getClass(),
136 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
137 logger.log(Level.WARNING, msg);
138 this.addErrorMessage(this.getName() +
": " + msg);
141 return allRegistryFiles;
148 private void analyzeRegistryFiles() {
149 List<AbstractFile> allRegistryFiles = findRegistryFiles();
152 FileWriter logFile = null;
154 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator +
"regripper-info.txt");
155 }
catch (IOException ex) {
156 logger.log(Level.SEVERE, null, ex);
160 for (AbstractFile regFile : allRegistryFiles) {
161 String regFileName = regFile.getName();
162 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") + File.separator + regFileName;
163 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator + regFileName +
"-regripper-" + Integer.toString(j++);
164 File regFileNameLocalFile =
new File(regFileNameLocal);
166 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
167 }
catch (IOException ex) {
168 logger.log(Level.SEVERE,
"Error writing the temp registry file. {0}", ex);
169 this.addErrorMessage(
170 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
171 this.getName(), regFileName));
175 if (context.dataSourceIngestIsCancelled()) {
180 if (logFile != null) {
181 logFile.write(Integer.toString(j - 1) +
"\t" + regFile.getUniquePath() +
"\n");
183 }
catch (TskCoreException | IOException ex) {
184 logger.log(Level.SEVERE, null, ex);
187 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
188 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
189 if (context.dataSourceIngestIsCancelled()) {
194 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false) {
195 if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
196 this.addErrorMessage(
197 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
198 this.getName(), regFileName));
203 if (!regOutputFiles.fullPlugins.isEmpty()) {
205 currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
"RegRipper " + regFile.getUniquePath());
206 }
catch (TskCoreException e) {
207 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
212 regFileNameLocalFile.delete();
216 if (logFile != null) {
219 }
catch (IOException ex) {
220 logger.log(Level.SEVERE, null, ex);
226 public String autopsyPlugins =
"";
227 public String fullPlugins =
"";
237 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
238 String autopsyType =
"";
243 if (regFilePath.toLowerCase().contains(
"system")) {
244 autopsyType =
"autopsysystem";
246 }
else if (regFilePath.toLowerCase().contains(
"software")) {
247 autopsyType =
"autopsysoftware";
248 fullType =
"software";
249 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
250 autopsyType =
"autopsyntuser";
252 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
254 }
else if (regFilePath.toLowerCase().contains(
"security")) {
255 fullType =
"security";
257 return regOutputFiles;
261 if (!autopsyType.isEmpty()) {
263 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
264 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.
autopsyPlugins);
265 executeRegRipper(RR_PATH, rrHome, regFilePath, autopsyType, regOutputFiles.
autopsyPlugins, errFilePath);
267 if (context.dataSourceIngestIsCancelled()) {
268 return regOutputFiles;
272 if (!fullType.isEmpty()) {
273 regOutputFiles.
fullPlugins = outFilePathBase +
"-full.txt";
274 String errFilePath = outFilePathBase +
"-full.err.txt";
275 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.
fullPlugins);
276 executeRegRipper(RR_FULL_PATH, rrFullHome, regFilePath, fullType, regOutputFiles.
fullPlugins, errFilePath);
278 return regOutputFiles;
281 private void executeRegRipper(String regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
283 List<String> commandLine =
new ArrayList<>();
284 commandLine.add(regRipperPath);
285 commandLine.add(
"-r");
286 commandLine.add(hiveFilePath);
287 commandLine.add(
"-f");
288 commandLine.add(hiveFileType);
290 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
291 processBuilder.directory(regRipperHomeDir.toFile());
292 processBuilder.redirectOutput(
new File(outputFile));
293 processBuilder.redirectError(
new File(errFile));
294 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
295 }
catch (IOException ex) {
296 logger.log(Level.SEVERE,
"Unable to run RegRipper", ex);
297 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
310 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
311 FileInputStream fstream = null;
313 SleuthkitCase tempDb = currentCase.getSleuthkitCase();
316 File regfile =
new File(regFilePath);
317 fstream =
new FileInputStream(regfile);
319 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
320 String startdoc =
"<?xml version=\"1.0\"?><document>";
321 String result = regString.replaceAll(
"----------------------------------------",
"");
322 result = result.replaceAll(
"\\n",
"");
323 result = result.replaceAll(
"\\r",
"");
324 result = result.replaceAll(
"'",
"'");
325 result = result.replaceAll(
"&",
"&");
326 result = result.replace(
'\0',
' ');
327 String enddoc =
"</document>";
328 String stringdoc = startdoc + result + enddoc;
329 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
330 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
333 Element oroot = doc.getDocumentElement();
334 NodeList children = oroot.getChildNodes();
335 int len = children.getLength();
338 Collection<BlackboardArtifact> usbBBartifacts =
new ArrayList<>();
340 for (
int i = 0; i < len; i++) {
341 Element tempnode = (Element) children.item(i);
343 String dataType = tempnode.getNodeName();
345 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
347 if (timenodes.getLength() > 0) {
348 Element timenode = (Element) timenodes.item(0);
349 String etime = timenode.getTextContent();
351 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
353 String Tempdate = mtime.toString();
354 mtime = Long.valueOf(Tempdate) / 1000;
355 }
catch (ParseException ex) {
356 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.");
360 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
361 if (artroots.getLength() == 0) {
366 Element artroot = (Element) artroots.item(0);
367 NodeList myartlist = artroot.getChildNodes();
368 String parentModuleName = NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace");
375 String systemRoot =
"";
376 String productId =
"";
377 String regOwner =
"";
379 Long installtime = null;
380 for (
int j = 0; j < myartlist.getLength(); j++) {
381 Node artchild = myartlist.item(j);
383 if (artchild.hasAttributes()) {
384 Element artnode = (Element) artchild;
386 String value = artnode.getTextContent().trim();
387 String name = artnode.getAttribute(
"name");
394 version = version +
" " + value;
402 case "RegisteredOwner":
405 case "RegisteredOrganization":
410 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
411 installtime = epochtime;
412 String Tempdate = installtime.toString();
413 installtime = Long.valueOf(Tempdate) / 1000;
414 }
catch (ParseException e) {
415 logger.log(Level.SEVERE,
"RegRipper::Conversion on DateTime -> ", e);
422 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
423 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
424 if (installtime != null) {
425 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
427 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
428 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
429 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
430 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
433 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
434 if (results.isEmpty()) {
435 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
436 bbart.addAttributes(bbattributes);
439 this.indexArtifact(bbart);
441 results.get(0).addAttributes(bbattributes);
444 }
catch (TskCoreException ex) {
445 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
450 String procArch =
"";
453 for (
int j = 0; j < myartlist.getLength(); j++) {
454 Node artchild = myartlist.item(j);
456 if (artchild.hasAttributes()) {
457 Element artnode = (Element) artchild;
459 String value = artnode.getTextContent().trim();
460 String name = artnode.getAttribute(
"name");
465 case "PROCESSOR_ARCHITECTURE":
468 case "PROCESSOR_IDENTIFIER":
479 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
480 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
481 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
482 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
485 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
486 if (results.isEmpty()) {
487 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
488 bbart.addAttributes(bbattributes);
491 this.indexArtifact(bbart);
493 results.get(0).addAttributes(bbattributes);
495 }
catch (TskCoreException ex) {
496 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
500 String compName =
"";
502 for (
int j = 0; j < myartlist.getLength(); j++) {
503 Node artchild = myartlist.item(j);
505 if (artchild.hasAttributes()) {
506 Element artnode = (Element) artchild;
508 String value = artnode.getTextContent().trim();
509 String name = artnode.getAttribute(
"name");
511 if (name.equals(
"ComputerName")) {
513 }
else if (name.equals(
"Domain")) {
518 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
519 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
520 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
523 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
524 if (results.isEmpty()) {
525 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
526 bbart.addAttributes(bbattributes);
529 this.indexArtifact(bbart);
531 results.get(0).addAttributes(bbattributes);
533 }
catch (TskCoreException ex) {
534 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
538 for (
int j = 0; j < myartlist.getLength(); j++) {
539 Node artchild = myartlist.item(j);
541 if (artchild.hasAttributes()) {
542 Element artnode = (Element) artchild;
544 String value = artnode.getTextContent().trim();
545 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
558 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
559 usbMtime = Long.valueOf(usbMtime.toString());
561 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
562 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
563 String dev = artnode.getAttribute(
"dev");
566 if (dev.toLowerCase().contains(
"vid")) {
567 USBInfo info = USB_MAPPER.parseAndLookup(dev);
568 if (info.getVendor() != null) {
569 make = info.getVendor();
571 if (info.getProduct() != null) {
572 model = info.getProduct();
575 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
576 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
577 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
578 bbart.addAttributes(bbattributes);
581 this.indexArtifact(bbart);
583 usbBBartifacts.add(bbart);
584 }
catch (TskCoreException ex) {
585 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.");
589 Long itemMtime = null;
591 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute(
"mtime")).getTime();
592 itemMtime = epochtime;
593 itemMtime = itemMtime / 1000;
594 }
catch (ParseException e) {
595 logger.log(Level.WARNING,
"Failed to parse epoch time for installed program artifact.");
599 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
600 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
601 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
602 bbart.addAttributes(bbattributes);
605 this.indexArtifact(bbart);
606 }
catch (TskCoreException ex) {
607 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
611 String officeName = artnode.getAttribute(
"name");
614 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
617 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
619 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
620 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
621 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
622 bbart.addAttributes(bbattributes);
625 this.indexArtifact(bbart);
626 }
catch (TskCoreException ex) {
627 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.");
631 case "ProcessorArchitecture":
649 String homeDir = value;
650 String sid = artnode.getAttribute(
"sid");
651 String username = artnode.getAttribute(
"username");
653 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
654 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
655 parentModuleName, username));
656 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
657 parentModuleName, sid));
658 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
659 parentModuleName, homeDir));
661 this.indexArtifact(bbart);
662 }
catch (TskCoreException ex) {
663 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.");
667 case "NtuserNetwork":
669 String localPath = artnode.getAttribute(
"localPath");
670 String remoteName = value;
671 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
672 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
673 parentModuleName, localPath));
674 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
675 parentModuleName, remoteName));
677 this.indexArtifact(bbart);
678 }
catch (TskCoreException ex) {
679 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.");
690 logger.log(Level.WARNING,
"Unrecognized node name: {0}", dataType);
698 if (!usbBBartifacts.isEmpty()) {
699 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts));
702 }
catch (FileNotFoundException ex) {
703 logger.log(Level.SEVERE,
"Error finding the registry file.");
704 }
catch (SAXException ex) {
705 logger.log(Level.SEVERE,
"Error parsing the registry XML: {0}", ex);
706 }
catch (IOException ex) {
707 logger.log(Level.SEVERE,
"Error building the document parser: {0}", ex);
708 }
catch (ParserConfigurationException ex) {
709 logger.log(Level.SEVERE,
"Error configuring the registry parser: {0}", ex);
712 if (fstream != null) {
715 }
catch (IOException ex) {
722 public void process(Content dataSource, IngestJobContext context) {
723 this.dataSource = dataSource;
724 this.context = context;
725 analyzeRegistryFiles();