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;
48 import org.w3c.dom.Document;
49 import org.w3c.dom.Element;
50 import org.w3c.dom.Node;
51 import org.w3c.dom.NodeList;
52 import org.xml.sax.InputSource;
53 import org.xml.sax.SAXException;
61 class ExtractRegistry
extends Extract {
63 private Logger logger = Logger.getLogger(this.getClass().getName());
64 private String RR_PATH;
65 private String RR_FULL_PATH;
66 private String rrHome;
67 private String rrFullHome;
68 private boolean rrFound =
false;
69 private boolean rrFullFound =
false;
71 private IngestJobContext context;
72 final private static UsbDeviceIdMapper usbMapper =
new UsbDeviceIdMapper();
75 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text");
76 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
78 logger.log(Level.SEVERE,
"RegRipper not found");
85 rrHome = rrRoot.getAbsolutePath();
86 logger.log(Level.INFO,
"RegRipper home: {0}", rrHome);
88 if (PlatformUtil.isWindowsOS()) {
89 RR_PATH = rrHome +
File.separator +
"rip.exe";
91 RR_PATH =
"perl " + rrHome +
File.separator +
"rip.pl";
94 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
95 if (rrFullRoot == null) {
96 logger.log(Level.SEVERE,
"RegRipper Full not found");
102 if (rrFullRoot != null) {
103 rrFullHome = rrFullRoot.getAbsolutePath();
107 logger.log(Level.INFO,
"RegRipper Full home: {0}", rrFullHome);
109 if (PlatformUtil.isWindowsOS()) {
110 RR_FULL_PATH = rrFullHome +
File.separator +
"rip.exe";
112 RR_FULL_PATH =
"perl " + rrFullHome +
File.separator +
"rip.pl";
119 private List<AbstractFile> findRegistryFiles() {
120 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
125 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
127 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
131 String[] regFileNames =
new String[]{
"system",
"software",
"security",
"sam"};
132 for (String regFileName : regFileNames) {
134 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
136 String msg = NbBundle.getMessage(this.getClass(),
137 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
138 logger.log(Level.WARNING, msg);
139 this.addErrorMessage(this.getName() +
": " + msg);
142 return allRegistryFiles;
149 private void analyzeRegistryFiles() {
150 List<AbstractFile> allRegistryFiles = findRegistryFiles();
153 FileWriter logFile = null;
155 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg") +
File.separator +
"regripper-info.txt");
156 }
catch (IOException ex) {
157 logger.log(Level.SEVERE, null, ex);
162 String regFileName = regFile.getName();
163 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg") +
File.separator + regFileName;
164 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg") +
File.separator + regFileName +
"-regripper-" + Integer.
toString(j++);
165 File regFileNameLocalFile =
new File(regFileNameLocal);
167 ContentUtils.writeToFile(regFile, regFileNameLocalFile);
168 }
catch (IOException ex) {
169 logger.log(Level.SEVERE,
"Error writing the temp registry file. {0}", ex);
170 this.addErrorMessage(
171 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
172 this.getName(), regFileName));
176 if (context.dataSourceIngestIsCancelled()) {
181 if (logFile != null) {
182 logFile.write(Integer.toString(j - 1) +
"\t" + regFile.getUniquePath() +
"\n");
185 logger.log(Level.SEVERE, null, ex);
188 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{moduleName, regFileNameLocal});
189 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
190 if (context.dataSourceIngestIsCancelled()) {
195 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false) {
196 if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
197 this.addErrorMessage(
198 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
199 this.getName(), regFileName));
204 if (regOutputFiles.fullPlugins.isEmpty() ==
false) {
206 currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
"RegRipper " + regFile.getUniquePath());
208 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
213 regFileNameLocalFile.delete();
217 if (logFile != null) {
220 }
catch (IOException ex) {
221 logger.log(Level.SEVERE, null, ex);
238 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
239 String autopsyType =
"";
244 if (regFilePath.toLowerCase().contains(
"system")) {
245 autopsyType =
"autopsysystem";
247 }
else if (regFilePath.toLowerCase().contains(
"software")) {
248 autopsyType =
"autopsysoftware";
249 fullType =
"software";
250 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
251 autopsyType =
"autopsyntuser";
253 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
255 }
else if (regFilePath.toLowerCase().contains(
"security")) {
256 fullType =
"security";
258 return regOutputFiles;
262 if (!autopsyType.isEmpty() && rrFound) {
264 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
265 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.
autopsyPlugins);
266 executeRegRipper(RR_PATH, rrHome, regFilePath, autopsyType, regOutputFiles.
autopsyPlugins, errFilePath);
268 if (context.dataSourceIngestIsCancelled()) {
269 return regOutputFiles;
273 if (!fullType.isEmpty() && rrFullFound) {
274 regOutputFiles.
fullPlugins = outFilePathBase +
"-full.txt";
275 String errFilePath = outFilePathBase +
"-full.err.txt";
276 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.
fullPlugins);
277 executeRegRipper(RR_FULL_PATH, rrFullHome, regFilePath, fullType, regOutputFiles.
fullPlugins, errFilePath);
279 return regOutputFiles;
282 private void executeRegRipper(String regRipperPath, String regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
284 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", outputFile);
285 List<String> commandLine =
new ArrayList<>();
286 commandLine.add(regRipperPath);
287 commandLine.add(
"-r");
288 commandLine.add(hiveFilePath);
289 commandLine.add(
"-f");
290 commandLine.add(hiveFileType);
292 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
293 processBuilder.directory(
new File(regRipperHomeDir));
294 processBuilder.redirectOutput(
new File(outputFile));
295 processBuilder.redirectError(
new File(errFile));
296 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
297 }
catch (IOException ex) {
298 logger.log(Level.SEVERE,
"Unable to run RegRipper", ex);
299 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
311 private boolean parseAutopsyPluginOutput(String regFilePath,
AbstractFile regFile) {
312 FileInputStream fstream = null;
317 File regfile =
new File(regFilePath);
318 fstream =
new FileInputStream(regfile);
320 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
321 String startdoc =
"<?xml version=\"1.0\"?><document>";
322 String result = regString.replaceAll(
"----------------------------------------",
"");
323 result = result.replaceAll(
"\\n",
"");
324 result = result.replaceAll(
"\\r",
"");
325 result = result.replaceAll(
"'",
"'");
326 result = result.replaceAll(
"&",
"&");
327 result = result.replace(
'\0',
' ');
328 String enddoc =
"</document>";
329 String stringdoc = startdoc + result + enddoc;
330 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
331 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
334 Element oroot = doc.getDocumentElement();
335 NodeList children = oroot.getChildNodes();
336 int len = children.getLength();
337 for (
int i = 0; i < len; i++) {
338 Element tempnode = (Element) children.item(i);
340 String dataType = tempnode.getNodeName();
342 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
344 if (timenodes.getLength() > 0) {
345 Element timenode = (Element) timenodes.item(0);
346 String etime = timenode.getTextContent();
348 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
350 String Tempdate = mtime.toString();
351 mtime = Long.valueOf(Tempdate) / 1000;
352 }
catch (ParseException ex) {
353 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.");
357 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
358 if (artroots.getLength() == 0) {
363 Element artroot = (Element) artroots.item(0);
364 NodeList myartlist = artroot.getChildNodes();
365 String parentModuleName = NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace");
369 if (dataType.equals(
"WinVersion")) {
372 String systemRoot =
"";
373 String productId =
"";
374 String regOwner =
"";
376 Long installtime = null;
378 for (
int j = 0; j < myartlist.getLength(); j++) {
379 Node artchild = myartlist.item(j);
381 if (artchild.hasAttributes()) {
382 Element artnode = (Element) artchild;
384 String value = artnode.getTextContent().trim();
385 String name = artnode.getAttribute(
"name");
387 if (name.equals(
"ProductName")) {
389 }
else if (name.equals(
"CSDVersion")) {
391 version = version +
" " + value;
392 }
else if (name.equals(
"SystemRoot")) {
394 }
else if (name.equals(
"ProductId")) {
396 }
else if (name.equals(
"RegisteredOwner")) {
398 }
else if (name.equals(
"RegisteredOrganization")) {
400 }
else if (name.equals(
"InstallDate")) {
402 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
403 installtime = epochtime;
404 String Tempdate = installtime.toString();
405 installtime = Long.valueOf(Tempdate) / 1000;
406 }
catch (ParseException e) {
407 logger.log(Level.SEVERE,
"RegRipper::Conversion on DateTime -> ", e);
414 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
415 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), parentModuleName, version));
416 if (installtime != null) {
417 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), parentModuleName, installtime));
419 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), parentModuleName, systemRoot));
420 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID.getTypeID(), parentModuleName, productId));
421 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER.getTypeID(), parentModuleName, regOwner));
422 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION.getTypeID(), parentModuleName, regOrg));
426 if (results.isEmpty()) {
430 results.get(0).addAttributes(bbattributes);
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.getTypeID(), parentModuleName, os));
467 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, procArch));
468 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR.getTypeID(), parentModuleName, tempDir));
472 if (results.isEmpty()) {
476 results.get(0).addAttributes(bbattributes);
479 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
481 }
else if (dataType.equals(
"CompName")) {
483 String compName =
"";
486 for (
int j = 0; j < myartlist.getLength(); j++) {
487 Node artchild = myartlist.item(j);
489 if (artchild.hasAttributes()) {
490 Element artnode = (Element) artchild;
492 String value = artnode.getTextContent().trim();
493 String name = artnode.getAttribute(
"name");
495 if (name.equals(
"ComputerName")) {
497 }
else if (name.equals(
"Domain")) {
504 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
505 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), parentModuleName, compName));
506 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), parentModuleName, domain));
510 if (results.isEmpty()) {
514 results.get(0).addAttributes(bbattributes);
517 logger.log(Level.SEVERE,
"Error adding os info artifact to blackboard.");
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 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
540 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
541 usbMtime = Long.valueOf(usbMtime.toString());
544 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), parentModuleName, usbMtime));
545 String dev = artnode.getAttribute(
"dev");
548 if (dev.toLowerCase().contains(
"vid")) {
549 USBInfo info = usbMapper.parseAndLookup(dev);
550 if (info.getVendor() != null) {
551 make = info.getVendor();
553 if (info.getProduct() != null) {
554 model = info.getProduct();
557 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE.getTypeID(), parentModuleName, make));
558 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL.getTypeID(), parentModuleName, model));
559 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID.getTypeID(), parentModuleName, value));
562 logger.log(Level.SEVERE,
"Error adding device attached artifact to blackboard.");
566 Long itemMtime = null;
568 Long epochtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute(
"mtime")).getTime();
569 itemMtime = epochtime;
570 itemMtime = itemMtime / 1000;
571 }
catch (ParseException e) {
572 logger.log(Level.WARNING,
"Failed to parse epoch time for installed program artifact.");
576 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), parentModuleName, value));
577 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), parentModuleName, itemMtime));
581 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.");
585 String officeName = artnode.getAttribute(
"name");
591 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), parentModuleName, mtime));
593 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), parentModuleName, officeName));
594 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), parentModuleName, value));
595 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), parentModuleName, artnode.getNodeName()));
598 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.");
602 case "ProcessorArchitecture":
620 String homeDir = value;
621 String sid = artnode.getAttribute(
"sid");
622 String username = artnode.getAttribute(
"username");
626 parentModuleName, username));
628 parentModuleName, sid));
630 parentModuleName, homeDir));
632 logger.log(Level.SEVERE,
"Error adding account artifact to blackboard.");
636 case "NtuserNetwork":
638 String localPath = artnode.getAttribute(
"localPath");
639 String remoteName = value;
642 parentModuleName, localPath));
644 parentModuleName, remoteName));
647 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.");
652 logger.log(Level.WARNING,
"Unrecognized node name: {0}", dataType);
660 }
catch (FileNotFoundException ex) {
661 logger.log(Level.SEVERE,
"Error finding the registry file.");
662 }
catch (SAXException ex) {
663 logger.log(Level.SEVERE,
"Error parsing the registry XML: {0}", ex);
664 }
catch (IOException ex) {
665 logger.log(Level.SEVERE,
"Error building the document parser: {0}", ex);
666 }
catch (ParserConfigurationException ex) {
667 logger.log(Level.SEVERE,
"Error configuring the registry parser: {0}", ex);
670 if (fstream != null) {
673 }
catch (IOException ex) {
680 public void process(
Content dataSource, IngestJobContext context) {
681 this.dataSource = dataSource;
682 this.context = context;
683 analyzeRegistryFiles();
ArrayList< BlackboardArtifact > getBlackboardArtifacts(int artifactTypeID)
void addAttributes(Collection< BlackboardAttribute > attributes)
void addAttribute(BlackboardAttribute attr)
BlackboardArtifact newArtifact(int artifactTypeID)
String toString(boolean preserveState)