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 private List<String> rrCmd =
new ArrayList<>();
80 private List<String> rrFullCmd=
new ArrayList<>();
83 ExtractRegistry() throws IngestModuleException {
84 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
86 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
88 throw new IngestModuleException(Bundle.RegRipperNotFound());
91 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
92 if (rrFullRoot == null) {
93 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
96 String executableToRun = RIP_EXE;
97 if (!PlatformUtil.isWindowsOS()) {
98 executableToRun = RIP_PL;
100 rrHome = rrRoot.toPath();
101 RR_PATH = rrHome.resolve(executableToRun).toString();
102 rrFullHome = rrFullRoot.toPath();
103 RR_FULL_PATH = rrFullHome.resolve(executableToRun).toString();
105 if (!(
new File(RR_PATH).exists())) {
106 throw new IngestModuleException(Bundle.RegRipperNotFound());
108 if (!(
new File(RR_FULL_PATH).exists())) {
109 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
111 if(PlatformUtil.isWindowsOS()){
113 rrFullCmd.add(RR_FULL_PATH);
116 File usrBin =
new File(
"/usr/bin/perl");
117 File usrLocalBin =
new File(
"/usr/local/bin/perl");
118 if(usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()){
119 perl =
"/usr/bin/perl";
120 }
else if(usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()){
121 perl =
"/usr/local/bin/perl";
123 throw new IngestModuleException(
"perl not found in your system");
128 rrFullCmd.add(RR_FULL_PATH);
134 private List<AbstractFile> findRegistryFiles() {
135 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
140 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
141 }
catch (TskCoreException ex) {
142 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
146 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
147 for (String regFileName : regFileNames) {
149 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
150 }
catch (TskCoreException ex) {
151 String msg = NbBundle.getMessage(this.getClass(),
152 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
153 logger.log(Level.WARNING, msg);
154 this.addErrorMessage(this.getName() +
": " + msg);
157 return allRegistryFiles;
164 private void analyzeRegistryFiles() {
165 List<AbstractFile> allRegistryFiles = findRegistryFiles();
168 FileWriter logFile = null;
170 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator +
"regripper-info.txt");
171 }
catch (IOException ex) {
172 logger.log(Level.SEVERE, null, ex);
176 for (AbstractFile regFile : allRegistryFiles) {
177 String regFileName = regFile.getName();
178 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") + File.separator + regFileName;
179 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator + regFileName +
"-regripper-" + Integer.toString(j++);
180 File regFileNameLocalFile =
new File(regFileNameLocal);
182 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
183 }
catch (IOException ex) {
184 logger.log(Level.SEVERE,
"Error writing the temp registry file. {0}", ex);
185 this.addErrorMessage(
186 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
187 this.getName(), regFileName));
191 if (context.dataSourceIngestIsCancelled()) {
196 if (logFile != null) {
197 logFile.write(Integer.toString(j - 1) +
"\t" + regFile.getUniquePath() +
"\n");
199 }
catch (TskCoreException | IOException ex) {
200 logger.log(Level.SEVERE, null, ex);
203 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
204 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
205 if (context.dataSourceIngestIsCancelled()) {
210 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false) {
211 if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
212 this.addErrorMessage(
213 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
214 this.getName(), regFileName));
219 if (!regOutputFiles.fullPlugins.isEmpty()) {
221 currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
"RegRipper " + regFile.getUniquePath());
222 }
catch (TskCoreException e) {
223 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
228 regFileNameLocalFile.delete();
232 if (logFile != null) {
235 }
catch (IOException ex) {
236 logger.log(Level.SEVERE, null, ex);
242 public String autopsyPlugins =
"";
243 public String fullPlugins =
"";
253 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
254 String autopsyType =
"";
259 if (regFilePath.toLowerCase().contains(
"system")) {
260 autopsyType =
"autopsysystem";
262 }
else if (regFilePath.toLowerCase().contains(
"software")) {
263 autopsyType =
"autopsysoftware";
264 fullType =
"software";
265 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
266 autopsyType =
"autopsyntuser";
268 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
270 }
else if (regFilePath.toLowerCase().contains(
"security")) {
271 fullType =
"security";
273 return regOutputFiles;
277 if (!autopsyType.isEmpty()) {
279 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
280 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.
autopsyPlugins);
281 executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.
autopsyPlugins, errFilePath);
283 if (context.dataSourceIngestIsCancelled()) {
284 return regOutputFiles;
288 if (!fullType.isEmpty()) {
289 regOutputFiles.
fullPlugins = outFilePathBase +
"-full.txt";
290 String errFilePath = outFilePathBase +
"-full.err.txt";
291 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.
fullPlugins);
292 executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.
fullPlugins, errFilePath);
294 return regOutputFiles;
297 private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
299 List<String> commandLine =
new ArrayList<>();
300 for(String cmd: regRipperPath){
301 commandLine.add(cmd);
303 commandLine.add(
"-r");
304 commandLine.add(hiveFilePath);
305 commandLine.add(
"-f");
306 commandLine.add(hiveFileType);
308 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
309 processBuilder.directory(regRipperHomeDir.toFile());
310 processBuilder.redirectOutput(
new File(outputFile));
311 processBuilder.redirectError(
new File(errFile));
312 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
313 }
catch (IOException ex) {
314 logger.log(Level.SEVERE,
"Unable to run RegRipper", ex);
315 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
328 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
329 FileInputStream fstream = null;
331 SleuthkitCase tempDb = currentCase.getSleuthkitCase();
334 File regfile =
new File(regFilePath);
335 fstream =
new FileInputStream(regfile);
337 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
338 String startdoc =
"<?xml version=\"1.0\"?><document>";
339 String result = regString.replaceAll(
"----------------------------------------",
"");
340 result = result.replaceAll(
"\\n",
"");
341 result = result.replaceAll(
"\\r",
"");
342 result = result.replaceAll(
"'",
"'");
343 result = result.replaceAll(
"&",
"&");
344 result = result.replace(
'\0',
' ');
345 String enddoc =
"</document>";
346 String stringdoc = startdoc + result + enddoc;
347 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
348 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
351 Element oroot = doc.getDocumentElement();
352 NodeList children = oroot.getChildNodes();
353 int len = children.getLength();
356 Collection<BlackboardArtifact> usbBBartifacts =
new ArrayList<>();
358 for (
int i = 0; i < len; i++) {
359 Element tempnode = (Element) children.item(i);
361 String dataType = tempnode.getNodeName();
363 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
365 if (timenodes.getLength() > 0) {
366 Element timenode = (Element) timenodes.item(0);
367 String etime = timenode.getTextContent();
369 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
371 String Tempdate = mtime.toString();
372 mtime = Long.valueOf(Tempdate) / 1000;
373 }
catch (ParseException ex) {
374 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.");
378 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
379 if (artroots.getLength() == 0) {
384 Element artroot = (Element) artroots.item(0);
385 NodeList myartlist = artroot.getChildNodes();
386 String parentModuleName = NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace");
393 String systemRoot =
"";
394 String productId =
"";
395 String regOwner =
"";
397 Long installtime = null;
398 for (
int j = 0; j < myartlist.getLength(); j++) {
399 Node artchild = myartlist.item(j);
401 if (artchild.hasAttributes()) {
402 Element artnode = (Element) artchild;
404 String value = artnode.getTextContent().trim();
405 String name = artnode.getAttribute(
"name");
412 version = version +
" " + value;
420 case "RegisteredOwner":
423 case "RegisteredOrganization":
428 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
429 installtime = epochtime;
430 String Tempdate = installtime.toString();
431 installtime = Long.valueOf(Tempdate) / 1000;
432 }
catch (ParseException e) {
433 logger.log(Level.SEVERE,
"RegRipper::Conversion on DateTime -> ", e);
440 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
441 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
442 if (installtime != null) {
443 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
445 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
446 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
447 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
448 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
451 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
452 if (results.isEmpty()) {
453 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
454 bbart.addAttributes(bbattributes);
457 this.indexArtifact(bbart);
459 results.get(0).addAttributes(bbattributes);
462 }
catch (TskCoreException ex) {
463 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
468 String procArch =
"";
471 for (
int j = 0; j < myartlist.getLength(); j++) {
472 Node artchild = myartlist.item(j);
474 if (artchild.hasAttributes()) {
475 Element artnode = (Element) artchild;
477 String value = artnode.getTextContent().trim();
478 String name = artnode.getAttribute(
"name");
483 case "PROCESSOR_ARCHITECTURE":
486 case "PROCESSOR_IDENTIFIER":
497 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
498 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
499 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
500 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
503 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
504 if (results.isEmpty()) {
505 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
506 bbart.addAttributes(bbattributes);
509 this.indexArtifact(bbart);
511 results.get(0).addAttributes(bbattributes);
513 }
catch (TskCoreException ex) {
514 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
518 String compName =
"";
520 for (
int j = 0; j < myartlist.getLength(); j++) {
521 Node artchild = myartlist.item(j);
523 if (artchild.hasAttributes()) {
524 Element artnode = (Element) artchild;
526 String value = artnode.getTextContent().trim();
527 String name = artnode.getAttribute(
"name");
529 if (name.equals(
"ComputerName")) {
531 }
else if (name.equals(
"Domain")) {
536 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
537 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
538 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
541 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
542 if (results.isEmpty()) {
543 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
544 bbart.addAttributes(bbattributes);
547 this.indexArtifact(bbart);
549 results.get(0).addAttributes(bbattributes);
551 }
catch (TskCoreException ex) {
552 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
556 for (
int j = 0; j < myartlist.getLength(); j++) {
557 Node artchild = myartlist.item(j);
559 if (artchild.hasAttributes()) {
560 Element artnode = (Element) artchild;
562 String value = artnode.getTextContent().trim();
563 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
576 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
577 usbMtime = Long.valueOf(usbMtime.toString());
579 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
580 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
581 String dev = artnode.getAttribute(
"dev");
584 if (dev.toLowerCase().contains(
"vid")) {
585 USBInfo info = USB_MAPPER.parseAndLookup(dev);
586 if (info.getVendor() != null) {
587 make = info.getVendor();
589 if (info.getProduct() != null) {
590 model = info.getProduct();
593 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
594 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
595 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
596 bbart.addAttributes(bbattributes);
599 this.indexArtifact(bbart);
601 usbBBartifacts.add(bbart);
602 }
catch (TskCoreException ex) {
603 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.");
607 Long itemMtime = null;
609 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute(
"mtime")).getTime();
610 itemMtime = epochtime;
611 itemMtime = itemMtime / 1000;
612 }
catch (ParseException e) {
613 logger.log(Level.WARNING,
"Failed to parse epoch time for installed program artifact.");
617 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
618 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
619 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
620 bbart.addAttributes(bbattributes);
623 this.indexArtifact(bbart);
624 }
catch (TskCoreException ex) {
625 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
629 String officeName = artnode.getAttribute(
"name");
632 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
635 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
637 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
638 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
639 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
640 bbart.addAttributes(bbattributes);
643 this.indexArtifact(bbart);
644 }
catch (TskCoreException ex) {
645 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.");
649 case "ProcessorArchitecture":
667 String homeDir = value;
668 String sid = artnode.getAttribute(
"sid");
669 String username = artnode.getAttribute(
"username");
670 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
671 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
672 parentModuleName, username));
673 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
674 parentModuleName, sid));
675 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
676 parentModuleName, homeDir));
678 bbart.addAttributes(bbattributes);
680 this.indexArtifact(bbart);
681 }
catch (TskCoreException ex) {
682 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.");
686 case "NtuserNetwork":
688 String localPath = artnode.getAttribute(
"localPath");
689 String remoteName = value;
690 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
691 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
692 parentModuleName, localPath));
693 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
694 parentModuleName, remoteName));
695 bbart.addAttributes(bbattributes);
697 this.indexArtifact(bbart);
698 }
catch (TskCoreException ex) {
699 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.");
710 logger.log(Level.WARNING,
"Unrecognized node name: {0}", dataType);
718 if (!usbBBartifacts.isEmpty()) {
719 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts));
722 }
catch (FileNotFoundException ex) {
723 logger.log(Level.SEVERE,
"Error finding the registry file.");
724 }
catch (SAXException ex) {
725 logger.log(Level.SEVERE,
"Error parsing the registry XML: {0}", ex);
726 }
catch (IOException ex) {
727 logger.log(Level.SEVERE,
"Error building the document parser: {0}", ex);
728 }
catch (ParserConfigurationException ex) {
729 logger.log(Level.SEVERE,
"Error configuring the registry parser: {0}", ex);
732 if (fstream != null) {
735 }
catch (IOException ex) {
742 public void process(Content dataSource, IngestJobContext context) {
743 this.dataSource = dataSource;
744 this.context = context;
745 analyzeRegistryFiles();