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;
62 "RegRipperNotFound=Autopsy RegRipper executable not found.",
63 "RegRipperFullNotFound=Full version RegRipper executable not found."
65 class ExtractRegistry extends Extract {
67 private final Logger logger = Logger.getLogger(this.getClass().getName());
68 private String RR_PATH;
69 private String RR_FULL_PATH;
71 private Path rrFullHome;
72 private Content dataSource;
73 private IngestJobContext context;
74 final private static UsbDeviceIdMapper USB_MAPPER =
new UsbDeviceIdMapper();
75 final private static String RIP_EXE =
"rip.exe";
76 final private static String RIP_PL =
"rip.pl";
77 final private static String PERL =
"perl ";
79 ExtractRegistry() throws IngestModuleException {
80 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
81 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
83 throw new IngestModuleException(Bundle.RegRipperNotFound());
86 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
87 if (rrFullRoot == null) {
88 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
91 String executableToRun = RIP_EXE;
92 if (!PlatformUtil.isWindowsOS()) {
93 executableToRun = RIP_PL;
95 rrHome = rrRoot.toPath();
96 RR_PATH = rrHome.resolve(executableToRun).toString();
97 rrFullHome = rrFullRoot.toPath();
98 RR_FULL_PATH = rrFullHome.resolve(executableToRun).toString();
100 if (!(
new File(RR_PATH).exists())) {
101 throw new IngestModuleException(Bundle.RegRipperNotFound());
103 if (!(
new File(RR_FULL_PATH).exists())) {
104 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
107 if (!PlatformUtil.isWindowsOS()) {
108 RR_PATH = PERL + RR_PATH;
109 RR_FULL_PATH = PERL + RR_FULL_PATH;
116 private List<AbstractFile> findRegistryFiles() {
117 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
122 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
123 }
catch (TskCoreException ex) {
124 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
128 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
129 for (String regFileName : regFileNames) {
131 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
132 }
catch (TskCoreException ex) {
133 String msg = NbBundle.getMessage(this.getClass(),
134 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
135 logger.log(Level.WARNING, msg);
136 this.addErrorMessage(this.getName() +
": " + msg);
139 return allRegistryFiles;
146 private void analyzeRegistryFiles() {
147 List<AbstractFile> allRegistryFiles = findRegistryFiles();
150 FileWriter logFile = null;
152 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator +
"regripper-info.txt");
153 }
catch (IOException ex) {
154 logger.log(Level.SEVERE, null, ex);
158 for (AbstractFile regFile : allRegistryFiles) {
159 String regFileName = regFile.getName();
160 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") + File.separator + regFileName;
161 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator + regFileName +
"-regripper-" + Integer.toString(j++);
162 File regFileNameLocalFile =
new File(regFileNameLocal);
164 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
165 }
catch (IOException ex) {
166 logger.log(Level.SEVERE,
"Error writing the temp registry file. {0}", ex);
167 this.addErrorMessage(
168 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
169 this.getName(), regFileName));
173 if (context.dataSourceIngestIsCancelled()) {
178 if (logFile != null) {
179 logFile.write(Integer.toString(j - 1) +
"\t" + regFile.getUniquePath() +
"\n");
181 }
catch (TskCoreException | IOException ex) {
182 logger.log(Level.SEVERE, null, ex);
185 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
186 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
187 if (context.dataSourceIngestIsCancelled()) {
192 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false) {
193 if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
194 this.addErrorMessage(
195 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
196 this.getName(), regFileName));
201 if (regOutputFiles.fullPlugins.isEmpty() ==
false) {
203 currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
"RegRipper " + regFile.getUniquePath());
204 }
catch (TskCoreException e) {
205 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
210 regFileNameLocalFile.delete();
214 if (logFile != null) {
217 }
catch (IOException ex) {
218 logger.log(Level.SEVERE, null, ex);
224 public String autopsyPlugins =
"";
225 public String fullPlugins =
"";
235 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
236 String autopsyType =
"";
241 if (regFilePath.toLowerCase().contains(
"system")) {
242 autopsyType =
"autopsysystem";
244 }
else if (regFilePath.toLowerCase().contains(
"software")) {
245 autopsyType =
"autopsysoftware";
246 fullType =
"software";
247 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
248 autopsyType =
"autopsyntuser";
250 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
252 }
else if (regFilePath.toLowerCase().contains(
"security")) {
253 fullType =
"security";
255 return regOutputFiles;
259 if (!autopsyType.isEmpty()) {
261 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
262 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.
autopsyPlugins);
263 executeRegRipper(RR_PATH, rrHome, regFilePath, autopsyType, regOutputFiles.
autopsyPlugins, errFilePath);
265 if (context.dataSourceIngestIsCancelled()) {
266 return regOutputFiles;
270 if (!fullType.isEmpty()) {
271 regOutputFiles.
fullPlugins = outFilePathBase +
"-full.txt";
272 String errFilePath = outFilePathBase +
"-full.err.txt";
273 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.
fullPlugins);
274 executeRegRipper(RR_FULL_PATH, rrFullHome, regFilePath, fullType, regOutputFiles.
fullPlugins, errFilePath);
276 return regOutputFiles;
279 private void executeRegRipper(String regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
281 List<String> commandLine =
new ArrayList<>();
282 commandLine.add(regRipperPath);
283 commandLine.add(
"-r");
284 commandLine.add(hiveFilePath);
285 commandLine.add(
"-f");
286 commandLine.add(hiveFileType);
288 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
289 processBuilder.directory(regRipperHomeDir.toFile());
290 processBuilder.redirectOutput(
new File(outputFile));
291 processBuilder.redirectError(
new File(errFile));
292 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
293 }
catch (IOException ex) {
294 logger.log(Level.SEVERE,
"Unable to run RegRipper", ex);
295 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
308 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
309 FileInputStream fstream = null;
311 SleuthkitCase tempDb = currentCase.getSleuthkitCase();
314 File regfile =
new File(regFilePath);
315 fstream =
new FileInputStream(regfile);
317 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
318 String startdoc =
"<?xml version=\"1.0\"?><document>";
319 String result = regString.replaceAll(
"----------------------------------------",
"");
320 result = result.replaceAll(
"\\n",
"");
321 result = result.replaceAll(
"\\r",
"");
322 result = result.replaceAll(
"'",
"'");
323 result = result.replaceAll(
"&",
"&");
324 result = result.replace(
'\0',
' ');
325 String enddoc =
"</document>";
326 String stringdoc = startdoc + result + enddoc;
327 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
328 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
331 Element oroot = doc.getDocumentElement();
332 NodeList children = oroot.getChildNodes();
333 int len = children.getLength();
334 for (
int i = 0; i < len; i++) {
335 Element tempnode = (Element) children.item(i);
337 String dataType = tempnode.getNodeName();
339 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
341 if (timenodes.getLength() > 0) {
342 Element timenode = (Element) timenodes.item(0);
343 String etime = timenode.getTextContent();
345 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
347 String Tempdate = mtime.toString();
348 mtime = Long.valueOf(Tempdate) / 1000;
349 }
catch (ParseException ex) {
350 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.");
354 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
355 if (artroots.getLength() == 0) {
360 Element artroot = (Element) artroots.item(0);
361 NodeList myartlist = artroot.getChildNodes();
362 String parentModuleName = NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace");
366 if (dataType.equals(
"WinVersion")) {
369 String systemRoot =
"";
370 String productId =
"";
371 String regOwner =
"";
373 Long installtime = null;
375 for (
int j = 0; j < myartlist.getLength(); j++) {
376 Node artchild = myartlist.item(j);
378 if (artchild.hasAttributes()) {
379 Element artnode = (Element) artchild;
381 String value = artnode.getTextContent().trim();
382 String name = artnode.getAttribute(
"name");
384 if (name.equals(
"ProductName")) {
386 }
else if (name.equals(
"CSDVersion")) {
388 version = version +
" " + value;
389 }
else if (name.equals(
"SystemRoot")) {
391 }
else if (name.equals(
"ProductId")) {
393 }
else if (name.equals(
"RegisteredOwner")) {
395 }
else if (name.equals(
"RegisteredOrganization")) {
397 }
else if (name.equals(
"InstallDate")) {
399 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
400 installtime = epochtime;
401 String Tempdate = installtime.toString();
402 installtime = Long.valueOf(Tempdate) / 1000;
403 }
catch (ParseException e) {
404 logger.log(Level.SEVERE,
"RegRipper::Conversion on DateTime -> ", e);
411 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
412 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
413 if (installtime != null) {
414 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
416 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
417 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
418 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
419 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
422 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
423 if (results.isEmpty()) {
424 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
425 bbart.addAttributes(bbattributes);
428 this.indexArtifact(bbart);
430 results.get(0).addAttributes(bbattributes);
433 }
catch (TskCoreException ex) {
434 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
436 }
else if (dataType.equals(
"Profiler")) {
439 String procArch =
"";
443 for (
int j = 0; j < myartlist.getLength(); j++) {
444 Node artchild = myartlist.item(j);
446 if (artchild.hasAttributes()) {
447 Element artnode = (Element) artchild;
449 String value = artnode.getTextContent().trim();
450 String name = artnode.getAttribute(
"name");
452 if (name.equals(
"OS")) {
454 }
else if (name.equals(
"PROCESSOR_ARCHITECTURE")) {
456 }
else if (name.equals(
"PROCESSOR_IDENTIFIER")) {
458 }
else if (name.equals(
"TEMP")) {
465 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
466 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
467 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
468 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
471 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
472 if (results.isEmpty()) {
473 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
474 bbart.addAttributes(bbattributes);
477 this.indexArtifact(bbart);
479 results.get(0).addAttributes(bbattributes);
481 }
catch (TskCoreException ex) {
482 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
484 }
else if (dataType.equals(
"CompName")) {
486 String compName =
"";
489 for (
int j = 0; j < myartlist.getLength(); j++) {
490 Node artchild = myartlist.item(j);
492 if (artchild.hasAttributes()) {
493 Element artnode = (Element) artchild;
495 String value = artnode.getTextContent().trim();
496 String name = artnode.getAttribute(
"name");
498 if (name.equals(
"ComputerName")) {
500 }
else if (name.equals(
"Domain")) {
507 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
508 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
509 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
512 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
513 if (results.isEmpty()) {
514 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
515 bbart.addAttributes(bbattributes);
518 this.indexArtifact(bbart);
520 results.get(0).addAttributes(bbattributes);
522 }
catch (TskCoreException ex) {
523 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
526 for (
int j = 0; j < myartlist.getLength(); j++) {
527 Node artchild = myartlist.item(j);
529 if (artchild.hasAttributes()) {
530 Element artnode = (Element) artchild;
532 String value = artnode.getTextContent().trim();
533 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
546 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
547 usbMtime = Long.valueOf(usbMtime.toString());
549 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
550 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
551 String dev = artnode.getAttribute(
"dev");
554 if (dev.toLowerCase().contains(
"vid")) {
555 USBInfo info = USB_MAPPER.parseAndLookup(dev);
556 if (info.getVendor() != null) {
557 make = info.getVendor();
559 if (info.getProduct() != null) {
560 model = info.getProduct();
563 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
564 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
565 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
566 bbart.addAttributes(bbattributes);
569 this.indexArtifact(bbart);
570 }
catch (TskCoreException ex) {
571 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.");
575 Long itemMtime = null;
577 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute(
"mtime")).getTime();
578 itemMtime = epochtime;
579 itemMtime = itemMtime / 1000;
580 }
catch (ParseException e) {
581 logger.log(Level.WARNING,
"Failed to parse epoch time for installed program artifact.");
585 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
586 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
587 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
588 bbart.addAttributes(bbattributes);
591 this.indexArtifact(bbart);
592 }
catch (TskCoreException ex) {
593 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
597 String officeName = artnode.getAttribute(
"name");
600 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
603 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
605 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
606 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
607 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
608 bbart.addAttributes(bbattributes);
611 this.indexArtifact(bbart);
612 }
catch (TskCoreException ex) {
613 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.");
617 case "ProcessorArchitecture":
635 String homeDir = value;
636 String sid = artnode.getAttribute(
"sid");
637 String username = artnode.getAttribute(
"username");
639 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
640 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
641 parentModuleName, username));
642 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
643 parentModuleName, sid));
644 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
645 parentModuleName, homeDir));
647 this.indexArtifact(bbart);
648 }
catch (TskCoreException ex) {
649 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.");
653 case "NtuserNetwork":
655 String localPath = artnode.getAttribute(
"localPath");
656 String remoteName = value;
657 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
658 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
659 parentModuleName, localPath));
660 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
661 parentModuleName, remoteName));
663 this.indexArtifact(bbart);
664 }
catch (TskCoreException ex) {
665 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.");
676 logger.log(Level.WARNING,
"Unrecognized node name: {0}", dataType);
684 }
catch (FileNotFoundException ex) {
685 logger.log(Level.SEVERE,
"Error finding the registry file.");
686 }
catch (SAXException ex) {
687 logger.log(Level.SEVERE,
"Error parsing the registry XML: {0}", ex);
688 }
catch (IOException ex) {
689 logger.log(Level.SEVERE,
"Error building the document parser: {0}", ex);
690 }
catch (ParserConfigurationException ex) {
691 logger.log(Level.SEVERE,
"Error configuring the registry parser: {0}", ex);
694 if (fstream != null) {
697 }
catch (IOException ex) {
704 public void process(Content dataSource, IngestJobContext context) {
705 this.dataSource = dataSource;
706 this.context = context;
707 analyzeRegistryFiles();