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;
59 class ExtractRegistry
extends Extract {
61 private Logger logger = Logger.getLogger(this.getClass().getName());
62 private String RR_PATH;
63 private String RR_FULL_PATH;
64 private String rrHome;
65 private String rrFullHome;
66 private boolean rrFound =
false;
67 private boolean rrFullFound =
false;
68 private Content dataSource;
69 private IngestJobContext context;
70 final private static UsbDeviceIdMapper usbMapper =
new UsbDeviceIdMapper();
73 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
74 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
76 logger.log(Level.SEVERE,
"RegRipper not found");
83 rrHome = rrRoot.getAbsolutePath();
84 logger.log(Level.INFO,
"RegRipper home: {0}", rrHome);
86 if (PlatformUtil.isWindowsOS()) {
87 RR_PATH = rrHome + File.separator +
"rip.exe";
89 RR_PATH =
"perl " + rrHome + File.separator +
"rip.pl";
92 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
93 if (rrFullRoot == null) {
94 logger.log(Level.SEVERE,
"RegRipper Full not found");
100 if (rrFullRoot != null) {
101 rrFullHome = rrFullRoot.getAbsolutePath();
105 logger.log(Level.INFO,
"RegRipper Full home: {0}", rrFullHome);
107 if (PlatformUtil.isWindowsOS()) {
108 RR_FULL_PATH = rrFullHome + File.separator +
"rip.exe";
110 RR_FULL_PATH =
"perl " + rrFullHome + File.separator +
"rip.pl";
117 private List<AbstractFile> findRegistryFiles() {
118 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
123 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
124 }
catch (TskCoreException ex) {
125 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
129 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
130 for (String regFileName : regFileNames) {
132 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
133 }
catch (TskCoreException ex) {
134 String msg = NbBundle.getMessage(this.getClass(),
135 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
136 logger.log(Level.WARNING, msg);
137 this.addErrorMessage(this.getName() +
": " + msg);
140 return allRegistryFiles;
147 private void analyzeRegistryFiles() {
148 List<AbstractFile> allRegistryFiles = findRegistryFiles();
151 FileWriter logFile = null;
153 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator +
"regripper-info.txt");
154 }
catch (IOException ex) {
155 logger.log(Level.SEVERE, null, ex);
159 for (AbstractFile regFile : allRegistryFiles) {
160 String regFileName = regFile.getName();
161 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") + File.separator + regFileName;
162 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") + File.separator + regFileName +
"-regripper-" + Integer.toString(j++);
163 File regFileNameLocalFile =
new File(regFileNameLocal);
165 ContentUtils.writeToFile(regFile, regFileNameLocalFile);
166 }
catch (IOException ex) {
167 logger.log(Level.SEVERE,
"Error writing the temp registry file. {0}", ex);
168 this.addErrorMessage(
169 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
170 this.getName(), regFileName));
174 if (context.dataSourceIngestIsCancelled()) {
179 if (logFile != null) {
180 logFile.write(Integer.toString(j - 1) +
"\t" + regFile.getUniquePath() +
"\n");
182 }
catch (TskCoreException | IOException ex) {
183 logger.log(Level.SEVERE, null, ex);
186 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
187 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
188 if (context.dataSourceIngestIsCancelled()) {
193 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false) {
194 if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
195 this.addErrorMessage(
196 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
197 this.getName(), regFileName));
202 if (regOutputFiles.fullPlugins.isEmpty() ==
false) {
204 currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
"RegRipper " + regFile.getUniquePath());
205 }
catch (TskCoreException e) {
206 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
211 regFileNameLocalFile.delete();
215 if (logFile != null) {
218 }
catch (IOException ex) {
219 logger.log(Level.SEVERE, null, ex);
236 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
237 String autopsyType =
"";
242 if (regFilePath.toLowerCase().contains(
"system")) {
243 autopsyType =
"autopsysystem";
245 }
else if (regFilePath.toLowerCase().contains(
"software")) {
246 autopsyType =
"autopsysoftware";
247 fullType =
"software";
248 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
249 autopsyType =
"autopsyntuser";
251 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
253 }
else if (regFilePath.toLowerCase().contains(
"security")) {
254 fullType =
"security";
256 return regOutputFiles;
260 if (!autopsyType.isEmpty() && rrFound) {
262 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
263 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.
autopsyPlugins);
264 executeRegRipper(RR_PATH, rrHome, regFilePath, autopsyType, regOutputFiles.
autopsyPlugins, errFilePath);
266 if (context.dataSourceIngestIsCancelled()) {
267 return regOutputFiles;
271 if (!fullType.isEmpty() && rrFullFound) {
272 regOutputFiles.
fullPlugins = outFilePathBase +
"-full.txt";
273 String errFilePath = outFilePathBase +
"-full.err.txt";
274 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.
fullPlugins);
275 executeRegRipper(RR_FULL_PATH, rrFullHome, regFilePath, fullType, regOutputFiles.
fullPlugins, errFilePath);
277 return regOutputFiles;
280 private void executeRegRipper(String regRipperPath, String regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
282 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", outputFile);
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(
new File(regRipperHomeDir));
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();
336 for (
int i = 0; i < len; i++) {
337 Element tempnode = (Element) children.item(i);
339 String dataType = tempnode.getNodeName();
341 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
343 if (timenodes.getLength() > 0) {
344 Element timenode = (Element) timenodes.item(0);
345 String etime = timenode.getTextContent();
347 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
349 String Tempdate = mtime.toString();
350 mtime = Long.valueOf(Tempdate) / 1000;
351 }
catch (ParseException ex) {
352 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.");
356 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
357 if (artroots.getLength() == 0) {
362 Element artroot = (Element) artroots.item(0);
363 NodeList myartlist = artroot.getChildNodes();
364 String parentModuleName = NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace");
368 if (dataType.equals(
"WinVersion")) {
371 String systemRoot =
"";
372 String productId =
"";
373 String regOwner =
"";
375 Long installtime = null;
377 for (
int j = 0; j < myartlist.getLength(); j++) {
378 Node artchild = myartlist.item(j);
380 if (artchild.hasAttributes()) {
381 Element artnode = (Element) artchild;
383 String value = artnode.getTextContent().trim();
384 String name = artnode.getAttribute(
"name");
386 if (name.equals(
"ProductName")) {
388 }
else if (name.equals(
"CSDVersion")) {
390 version = version +
" " + value;
391 }
else if (name.equals(
"SystemRoot")) {
393 }
else if (name.equals(
"ProductId")) {
395 }
else if (name.equals(
"RegisteredOwner")) {
397 }
else if (name.equals(
"RegisteredOrganization")) {
399 }
else if (name.equals(
"InstallDate")) {
401 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
402 installtime = epochtime;
403 String Tempdate = installtime.toString();
404 installtime = Long.valueOf(Tempdate) / 1000;
405 }
catch (ParseException e) {
406 logger.log(Level.SEVERE,
"RegRipper::Conversion on DateTime -> ", e);
413 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
414 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
415 if (installtime != null) {
416 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
418 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
419 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
420 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
421 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
424 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
425 if (results.isEmpty()) {
426 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
427 bbart.addAttributes(bbattributes);
430 this.indexArtifact(bbart);
432 results.get(0).addAttributes(bbattributes);
435 }
catch (TskCoreException ex) {
436 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
438 }
else if (dataType.equals(
"Profiler")) {
441 String procArch =
"";
445 for (
int j = 0; j < myartlist.getLength(); j++) {
446 Node artchild = myartlist.item(j);
448 if (artchild.hasAttributes()) {
449 Element artnode = (Element) artchild;
451 String value = artnode.getTextContent().trim();
452 String name = artnode.getAttribute(
"name");
454 if (name.equals(
"OS")) {
456 }
else if (name.equals(
"PROCESSOR_ARCHITECTURE")) {
458 }
else if (name.equals(
"PROCESSOR_IDENTIFIER")) {
460 }
else if (name.equals(
"TEMP")) {
467 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
468 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
469 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
470 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
473 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
474 if (results.isEmpty()) {
475 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
476 bbart.addAttributes(bbattributes);
479 this.indexArtifact(bbart);
481 results.get(0).addAttributes(bbattributes);
483 }
catch (TskCoreException ex) {
484 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
486 }
else if (dataType.equals(
"CompName")) {
488 String compName =
"";
491 for (
int j = 0; j < myartlist.getLength(); j++) {
492 Node artchild = myartlist.item(j);
494 if (artchild.hasAttributes()) {
495 Element artnode = (Element) artchild;
497 String value = artnode.getTextContent().trim();
498 String name = artnode.getAttribute(
"name");
500 if (name.equals(
"ComputerName")) {
502 }
else if (name.equals(
"Domain")) {
509 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
510 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
511 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
514 ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
515 if (results.isEmpty()) {
516 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
517 bbart.addAttributes(bbattributes);
520 this.indexArtifact(bbart);
522 results.get(0).addAttributes(bbattributes);
524 }
catch (TskCoreException ex) {
525 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
528 for (
int j = 0; j < myartlist.getLength(); j++) {
529 Node artchild = myartlist.item(j);
531 if (artchild.hasAttributes()) {
532 Element artnode = (Element) artchild;
534 String value = artnode.getTextContent().trim();
535 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
548 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
549 usbMtime = Long.valueOf(usbMtime.toString());
551 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
552 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
553 String dev = artnode.getAttribute(
"dev");
556 if (dev.toLowerCase().contains(
"vid")) {
557 USBInfo info = usbMapper.parseAndLookup(dev);
558 if (info.getVendor() != null) {
559 make = info.getVendor();
561 if (info.getProduct() != null) {
562 model = info.getProduct();
565 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
566 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
567 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
568 bbart.addAttributes(bbattributes);
571 this.indexArtifact(bbart);
572 }
catch (TskCoreException ex) {
573 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.");
577 Long itemMtime = null;
579 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute(
"mtime")).getTime();
580 itemMtime = epochtime;
581 itemMtime = itemMtime / 1000;
582 }
catch (ParseException e) {
583 logger.log(Level.WARNING,
"Failed to parse epoch time for installed program artifact.");
587 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
588 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
589 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
590 bbart.addAttributes(bbattributes);
593 this.indexArtifact(bbart);
594 }
catch (TskCoreException ex) {
595 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
599 String officeName = artnode.getAttribute(
"name");
602 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
605 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
607 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
608 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
609 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
610 bbart.addAttributes(bbattributes);
613 this.indexArtifact(bbart);
614 }
catch (TskCoreException ex) {
615 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.");
619 case "ProcessorArchitecture":
637 String homeDir = value;
638 String sid = artnode.getAttribute(
"sid");
639 String username = artnode.getAttribute(
"username");
641 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
642 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
643 parentModuleName, username));
644 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
645 parentModuleName, sid));
646 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
647 parentModuleName, homeDir));
649 this.indexArtifact(bbart);
650 }
catch (TskCoreException ex) {
651 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.");
655 case "NtuserNetwork":
657 String localPath = artnode.getAttribute(
"localPath");
658 String remoteName = value;
659 BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
660 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
661 parentModuleName, localPath));
662 bbart.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
663 parentModuleName, remoteName));
665 this.indexArtifact(bbart);
666 }
catch (TskCoreException ex) {
667 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.");
678 logger.log(Level.WARNING,
"Unrecognized node name: {0}", dataType);
686 }
catch (FileNotFoundException ex) {
687 logger.log(Level.SEVERE,
"Error finding the registry file.");
688 }
catch (SAXException ex) {
689 logger.log(Level.SEVERE,
"Error parsing the registry XML: {0}", ex);
690 }
catch (IOException ex) {
691 logger.log(Level.SEVERE,
"Error building the document parser: {0}", ex);
692 }
catch (ParserConfigurationException ex) {
693 logger.log(Level.SEVERE,
"Error configuring the registry parser: {0}", ex);
696 if (fstream != null) {
699 }
catch (IOException ex) {
706 public void process(Content dataSource, IngestJobContext context) {
707 this.dataSource = dataSource;
708 this.context = context;
709 analyzeRegistryFiles();