23 package org.sleuthkit.autopsy.recentactivity;
25 import java.io.BufferedReader;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileReader;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.InputStreamReader;
33 import java.io.StringReader;
34 import java.nio.charset.StandardCharsets;
35 import java.text.ParseException;
36 import java.text.SimpleDateFormat;
37 import java.util.logging.Level;
38 import javax.xml.parsers.DocumentBuilder;
39 import javax.xml.parsers.DocumentBuilderFactory;
40 import javax.xml.parsers.ParserConfigurationException;
41 import org.apache.commons.io.FilenameUtils;
42 import org.openide.modules.InstalledFileLocator;
43 import org.openide.util.NbBundle;
51 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
52 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
53 import org.w3c.dom.Document;
54 import org.w3c.dom.Element;
55 import org.w3c.dom.Node;
56 import org.w3c.dom.NodeList;
57 import org.xml.sax.InputSource;
58 import org.xml.sax.SAXException;
59 import java.nio.file.Path;
60 import java.util.AbstractMap;
61 import java.util.ArrayList;
62 import java.util.List;
63 import java.util.Collection;
64 import java.util.Collections;
65 import java.util.Date;
66 import java.util.HashMap;
68 import java.util.Scanner;
70 import java.util.HashSet;
71 import static java.util.Locale.US;
72 import java.util.Optional;
73 import static java.util.TimeZone.getTimeZone;
74 import java.util.stream.Collectors;
75 import org.openide.util.Lookup;
82 import org.
sleuthkit.datamodel.Blackboard.BlackboardException;
85 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT;
86 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
87 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
88 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
89 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED;
90 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID;
91 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
92 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
93 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HOME_DIR;
100 import org.
sleuthkit.datamodel.OsAccount.OsAccountAttribute;
103 import org.
sleuthkit.datamodel.OsAccountManager.NotUserSIDException;
104 import org.
sleuthkit.datamodel.OsAccountManager.OsAccountUpdateResult;
106 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
118 "RegRipperNotFound=Autopsy RegRipper executable not found.",
119 "RegRipperFullNotFound=Full version RegRipper executable not found.",
120 "Progress_Message_Analyze_Registry=Analyzing Registry Files",
121 "Shellbag_Artifact_Display_Name=Shell Bags",
122 "Shellbag_Key_Attribute_Display_Name=Key",
123 "Shellbag_Last_Write_Attribute_Display_Name=Last Write",
124 "Recently_Used_Artifacts_Office_Trustrecords=Stored in TrustRecords because Office security exception was granted",
125 "Recently_Used_Artifacts_ArcHistory=Recently opened by 7Zip",
126 "Recently_Used_Artifacts_Applets=Recently opened according to Applets registry key",
127 "Recently_Used_Artifacts_Mmc=Recently opened according to Windows Management Console MRU",
128 "Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU",
129 "Recently_Used_Artifacts_Officedocs=Recently opened according to Office MRU",
130 "Recently_Used_Artifacts_Adobe=Recently opened according to Adobe MRU",
131 "Recently_Used_Artifacts_Mediaplayer=Recently opened according to Media Player MRU",
132 "Registry_System_Bam=Recently Executed according to Background Activity Moderator (BAM)"
134 class ExtractRegistry extends Extract {
136 private static final String USERNAME_KEY =
"Username";
137 private static final String SID_KEY =
"SID";
138 private static final String RID_KEY =
"RID";
139 private static final String ACCOUNT_CREATED_KEY =
"Account Created";
140 private static final String LAST_LOGIN_KEY =
"Last Login Date";
141 private static final String LOGIN_COUNT_KEY =
"Login Count";
142 private static final String FULL_NAME_KEY =
"Full Name";
143 private static final String USER_COMMENT_KEY =
"User Comment";
144 private static final String ACCOUNT_TYPE_KEY =
"Account Type";
145 private static final String NAME_KEY =
"Name";
146 private static final String PWD_RESET_KEY =
"Pwd Rest Date";
147 private static final String PWD_FAILE_KEY =
"Pwd Fail Date";
148 private static final String INTERNET_NAME_KEY =
"InternetName";
149 private static final String PWD_DOES_NOT_EXPIRE_KEY =
"Password does not expire";
150 private static final String ACCOUNT_DISABLED_KEY =
"Account Disabled";
151 private static final String PWD_NOT_REQUIRED_KEY =
"Password not required";
152 private static final String NORMAL_ACCOUNT_KEY =
"Normal user account";
153 private static final String HOME_DIRECTORY_REQUIRED_KEY =
"Home directory required";
154 private static final String TEMPORARY_DUPLICATE_ACCOUNT =
"Temporary duplicate account";
155 private static final String MNS_LOGON_ACCOUNT_KEY =
"MNS logon user account";
156 private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY =
"Interdomain trust account";
157 private static final String WORKSTATION_TRUST_ACCOUNT =
"Workstation trust account";
158 private static final String SERVER_TRUST_ACCOUNT =
"Server trust account";
159 private static final String ACCOUNT_AUTO_LOCKED =
"Account auto locked";
160 private static final String PASSWORD_HINT =
"Password Hint";
162 private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
163 private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
164 private static final String[] ACCOUNT_TYPE_FLAGS = {NORMAL_ACCOUNT_KEY, SERVER_TRUST_ACCOUNT, WORKSTATION_TRUST_ACCOUNT, INTERDOMAIN_TRUST_ACCOUNT_KEY, MNS_LOGON_ACCOUNT_KEY, TEMPORARY_DUPLICATE_ACCOUNT};
166 final private static UsbDeviceIdMapper USB_MAPPER =
new UsbDeviceIdMapper();
167 final private static String RIP_EXE =
"rip.exe";
168 final private static String RIP_PL =
"rip.pl";
169 final private static String RIP_PL_INCLUDE_FLAG =
"-I";
170 final private static int MS_IN_SEC = 1000;
171 final private static String NEVER_DATE =
"Never";
172 final private static String SECTION_DIVIDER =
"-------------------------";
173 final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
174 private final List<String> rrCmd =
new ArrayList<>();
175 private final List<String> rrFullCmd =
new ArrayList<>();
176 private final Path rrHome;
177 private final Path rrFullHome;
178 private Content dataSource;
179 private IngestJobContext context;
180 private Map<String, String> userNameMap;
182 private String compName =
"";
183 private String domainName =
"";
185 private static final String SHELLBAG_ARTIFACT_NAME =
"RA_SHELL_BAG";
186 private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE =
"RA_SHELL_BAG_LAST_WRITE";
187 private static final String SHELLBAG_ATTRIBUTE_KEY =
"RA_SHELL_BAG_KEY";
189 private static final SimpleDateFormat REG_RIPPER_TIME_FORMAT =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'", US);
191 private BlackboardArtifact.Type shellBagArtifactType = null;
192 private BlackboardAttribute.Type shellBagKeyAttributeType = null;
193 private BlackboardAttribute.Type shellBagLastWriteAttributeType = null;
196 REG_RIPPER_TIME_FORMAT.setTimeZone(getTimeZone(
"GMT"));
199 ExtractRegistry() throws IngestModuleException {
200 super(NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text"));
202 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
203 if (rrRoot == null) {
204 throw new IngestModuleException(Bundle.RegRipperNotFound());
207 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
208 if (rrFullRoot == null) {
209 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
212 String executableToRun = RIP_EXE;
213 if (!PlatformUtil.isWindowsOS()) {
214 executableToRun = RIP_PL;
216 rrHome = rrRoot.toPath();
217 String rrPath = rrHome.resolve(executableToRun).toString();
218 rrFullHome = rrFullRoot.toPath();
220 if (!(
new File(rrPath).exists())) {
221 throw new IngestModuleException(Bundle.RegRipperNotFound());
223 String rrFullPath = rrFullHome.resolve(executableToRun).toString();
224 if (!(
new File(rrFullPath).exists())) {
225 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
227 if (PlatformUtil.isWindowsOS()) {
229 rrFullCmd.add(rrFullPath);
232 File usrBin =
new File(
"/usr/bin/perl");
233 File usrLocalBin =
new File(
"/usr/local/bin/perl");
234 if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
235 perl =
"/usr/bin/perl";
236 }
else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
237 perl =
"/usr/local/bin/perl";
239 throw new IngestModuleException(
"perl not found in your system");
242 rrCmd.add(RIP_PL_INCLUDE_FLAG);
243 rrCmd.add(rrHome.toString());
246 rrFullCmd.add(RIP_PL_INCLUDE_FLAG);
247 rrFullCmd.add(rrFullHome.toString());
248 rrFullCmd.add(rrFullPath);
255 private List<AbstractFile> findRegistryFiles() {
256 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
261 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"sam",
"/system32/config"));
262 }
catch (TskCoreException ex) {
263 String msg = NbBundle.getMessage(this.getClass(),
264 "ExtractRegistry.findRegFiles.errMsg.errReadingFile",
"sam");
265 logger.log(Level.WARNING, msg, ex);
266 this.addErrorMessage(this.getName() +
": " + msg);
271 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
272 }
catch (TskCoreException ex) {
273 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
278 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"usrclass.dat"));
279 }
catch (TskCoreException ex) {
280 logger.log(Level.WARNING, String.format(
"Error finding 'usrclass.dat' files."), ex);
284 String[] regFileNames =
new String[]{
"system",
"software",
"security"};
285 for (String regFileName : regFileNames) {
287 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
288 }
catch (TskCoreException ex) {
289 String msg = NbBundle.getMessage(this.getClass(),
290 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
291 logger.log(Level.WARNING, msg, ex);
292 this.addErrorMessage(this.getName() +
": " + msg);
295 return allRegistryFiles;
303 private void analyzeRegistryFiles(
long ingestJobId) {
304 List<AbstractFile> allRegistryFiles = findRegistryFiles();
307 FileWriter logFile = null;
309 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg", ingestJobId) + File.separator +
"regripper-info.txt");
310 }
catch (IOException ex) {
311 logger.log(Level.SEVERE, null, ex);
314 for (AbstractFile regFile : allRegistryFiles) {
315 if (context.dataSourceIngestIsCancelled()) {
319 String regFileName = regFile.getName();
320 long regFileId = regFile.getId();
321 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg", ingestJobId) + File.separator + regFileName;
322 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg", ingestJobId) + File.separator + regFileName +
"-regripper-" + Long.toString(regFileId);
323 File regFileNameLocalFile =
new File(regFileNameLocal);
325 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
326 }
catch (ReadContentInputStreamException ex) {
327 logger.log(Level.WARNING, String.format(
"Error reading registry file '%s' (id=%d).",
328 regFile.getName(), regFileId), ex);
329 this.addErrorMessage(
330 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
331 this.getName(), regFileName));
333 }
catch (IOException ex) {
334 logger.log(Level.SEVERE, String.format(
"Error writing temp registry file '%s' for registry file '%s' (id=%d).",
335 regFileNameLocal, regFile.getName(), regFileId), ex);
336 this.addErrorMessage(
337 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
338 this.getName(), regFileName));
342 if (context.dataSourceIngestIsCancelled()) {
347 if (logFile != null) {
348 logFile.write(Long.toString(regFileId) +
"\t" + regFile.getUniquePath() +
"\n");
350 }
catch (TskCoreException | IOException ex) {
351 logger.log(Level.SEVERE, null, ex);
354 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{getName(), regFileNameLocal});
355 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
356 if (context.dataSourceIngestIsCancelled()) {
361 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
362 this.addErrorMessage(
363 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
364 this.getName(), regFileName));
367 if (context.dataSourceIngestIsCancelled()) {
372 if (!regOutputFiles.fullPlugins.isEmpty()) {
374 if (regFileNameLocal.toLowerCase().contains(
"sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile, ingestJobId) ==
false) {
375 this.addErrorMessage(
376 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
377 this.getName(), regFileName));
378 }
else if (regFileNameLocal.toLowerCase().contains(
"ntuser") || regFileNameLocal.toLowerCase().contains(
"usrclass")) {
380 List<ShellBag> shellbags = ShellBagParser.parseShellbagOutput(regOutputFiles.fullPlugins);
381 createShellBagArtifacts(regFile, shellbags);
382 createRecentlyUsedArtifacts(regOutputFiles.fullPlugins, regFile);
383 }
catch (IOException | TskCoreException ex) {
384 logger.log(Level.WARNING, String.format(
"Unable to get shell bags from file %s", regOutputFiles.fullPlugins), ex);
386 }
else if (regFileNameLocal.toLowerCase().contains(
"system") && parseSystemPluginOutput(regOutputFiles.fullPlugins, regFile) ==
false) {
387 this.addErrorMessage(
388 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
389 this.getName(), regFileName));
392 if (context.dataSourceIngestIsCancelled()) {
397 Report report = currentCase.addReport(regOutputFiles.fullPlugins,
398 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
399 "RegRipper " + regFile.getUniquePath(), regFile);
402 KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
403 if (null == searchService) {
404 logger.log(Level.WARNING,
"Keyword search service not found. Report will not be indexed");
406 searchService.index(report);
409 }
catch (TskCoreException e) {
410 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
414 regFileNameLocalFile.delete();
418 if (logFile != null) {
421 }
catch (IOException ex) {
422 logger.log(Level.SEVERE, null, ex);
433 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
434 String autopsyType =
"";
437 RegOutputFiles regOutputFiles =
new RegOutputFiles();
439 if (regFilePath.toLowerCase().contains(
"system")) {
440 autopsyType =
"autopsysystem";
442 }
else if (regFilePath.toLowerCase().contains(
"software")) {
443 autopsyType =
"autopsysoftware";
444 fullType =
"software";
445 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
446 autopsyType =
"autopsyntuser";
448 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
451 }
else if (regFilePath.toLowerCase().contains(
"security")) {
452 fullType =
"security";
453 }
else if (regFilePath.toLowerCase().contains(
"usrclass")) {
454 fullType =
"usrclass";
456 return regOutputFiles;
460 if (!autopsyType.isEmpty()) {
461 regOutputFiles.autopsyPlugins = outFilePathBase +
"-autopsy.txt";
462 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
463 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins);
464 executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
466 if (context.dataSourceIngestIsCancelled()) {
467 return regOutputFiles;
471 if (!fullType.isEmpty()) {
472 regOutputFiles.fullPlugins = outFilePathBase +
"-full.txt";
473 String errFilePath = outFilePathBase +
"-full.err.txt";
474 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins);
475 executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
477 scanErrorLogs(errFilePath);
478 }
catch (IOException ex) {
479 logger.log(Level.SEVERE, String.format(
"Unable to run RegRipper on %s", regFilePath), ex);
480 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName(), regFilePath));
483 return regOutputFiles;
486 private void scanErrorLogs(String errFilePath)
throws IOException {
487 File regfile =
new File(errFilePath);
488 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
489 String line = reader.readLine();
490 while (line != null) {
492 if (line.toLowerCase().contains(
"error") || line.toLowerCase().contains(
"@inc")) {
493 logger.log(Level.WARNING,
"Regripper file {0} contains errors from run", errFilePath);
496 line = reader.readLine();
501 private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
503 List<String> commandLine =
new ArrayList<>();
504 for (String cmd : regRipperPath) {
505 commandLine.add(cmd);
507 commandLine.add(
"-r");
508 commandLine.add(hiveFilePath);
509 commandLine.add(
"-f");
510 commandLine.add(hiveFileType);
512 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
513 processBuilder.directory(regRipperHomeDir.toFile());
514 processBuilder.redirectOutput(
new File(outputFile));
515 processBuilder.redirectError(
new File(errFile));
516 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context,
true));
517 }
catch (IOException ex) {
518 logger.log(Level.SEVERE, String.format(
"Error running RegRipper on %s", hiveFilePath), ex);
519 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName(), hiveFilePath));
532 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
533 FileInputStream fstream = null;
534 List<BlackboardArtifact> newArtifacts =
new ArrayList<>();
537 File regfile =
new File(regFilePath);
538 fstream =
new FileInputStream(regfile);
539 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
540 String startdoc =
"<?xml version=\"1.0\"?><document>";
541 String result = regString.replaceAll(
"----------------------------------------",
"");
542 result = result.replaceAll(
"\\n",
"");
543 result = result.replaceAll(
"\\r",
"");
544 result = result.replaceAll(
"'",
"'");
545 result = result.replaceAll(
"&",
"&");
546 result = result.replace(
'\0',
' ');
547 String enddoc =
"</document>";
548 String stringdoc = startdoc + result + enddoc;
549 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
550 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
553 Element oroot = doc.getDocumentElement();
554 NodeList children = oroot.getChildNodes();
555 int len = children.getLength();
556 for (
int i = 0; i < len; i++) {
558 if (context.dataSourceIngestIsCancelled()) {
562 Element tempnode = (Element) children.item(i);
564 String dataType = tempnode.getNodeName();
565 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
567 if (timenodes.getLength() > 0) {
568 Element timenode = (Element) timenodes.item(0);
569 String etime = timenode.getTextContent();
571 if (etime != null && !etime.isEmpty()) {
573 mtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy", US).parse(etime).getTime();
574 String Tempdate = mtime.toString();
575 mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
576 }
catch (ParseException ex) {
577 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.", ex);
582 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
583 if (artroots.getLength() == 0) {
588 Element artroot = (Element) artroots.item(0);
589 NodeList myartlist = artroot.getChildNodes();
590 String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
596 String systemRoot =
"";
597 String productId =
"";
598 String regOwner =
"";
600 Long installtime = null;
601 for (
int j = 0; j < myartlist.getLength(); j++) {
602 Node artchild = myartlist.item(j);
604 if (artchild.hasAttributes()) {
605 Element artnode = (Element) artchild;
607 String value = artnode.getTextContent();
609 value = value.trim();
611 String name = artnode.getAttribute(
"name");
621 version = version +
" " + value;
629 case "RegisteredOwner":
632 case "RegisteredOrganization":
636 if (value != null && !value.isEmpty()) {
638 installtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyyZ", US).parse(value+
"+0000").getTime();
639 String Tempdate = installtime.toString();
640 installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
641 }
catch (ParseException e) {
642 logger.log(Level.WARNING,
"RegRipper::Conversion on DateTime -> ", e);
652 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
653 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
654 if (installtime != null) {
655 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
657 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
658 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
659 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
660 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
663 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
664 if (results.isEmpty()) {
665 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_OS_INFO, regFile, bbattributes));
667 results.get(0).addAttributes(bbattributes);
670 }
catch (TskCoreException ex) {
671 logger.log(Level.SEVERE, String.format(
"Error adding installed program artifact to blackboard for file %d.", regFile.getId()), ex);
676 String procArch =
"";
678 for (
int j = 0; j < myartlist.getLength(); j++) {
679 Node artchild = myartlist.item(j);
681 if (artchild.hasAttributes()) {
682 Element artnode = (Element) artchild;
684 String value = artnode.getTextContent().trim();
685 String name = artnode.getAttribute(
"name");
690 case "PROCESSOR_ARCHITECTURE":
693 case "PROCESSOR_IDENTIFIER":
704 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
705 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
706 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
707 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
710 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
711 if (results.isEmpty()) {
712 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_OS_INFO, regFile, bbattributes));
714 results.get(0).addAttributes(bbattributes);
716 }
catch (TskCoreException ex) {
717 logger.log(Level.SEVERE, String.format(
"Error adding installed os_info to blackboard for file %d.", regFile.getId()), ex);
721 for (
int j = 0; j < myartlist.getLength(); j++) {
722 Node artchild = myartlist.item(j);
724 if (artchild.hasAttributes()) {
725 Element artnode = (Element) artchild;
727 String value = artnode.getTextContent().trim();
728 String name = artnode.getAttribute(
"name");
730 if (name.equals(
"ComputerName")) {
732 }
else if (name.equals(
"Domain")) {
738 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
739 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
740 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domainName));
743 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
744 if (results.isEmpty()) {
745 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_OS_INFO, regFile, bbattributes));
747 results.get(0).addAttributes(bbattributes);
749 for (Map.Entry<String, String> userMap : getUserNameMap().entrySet()) {
752 sid = userMap.getKey();
753 String userName = userMap.getValue();
755 createOrUpdateOsAccount(regFile, sid, userName, null, null, OsAccountRealm.RealmScope.LOCAL);
756 }
catch(TskCoreException | TskDataException | NotUserSIDException ex) {
757 logger.log(Level.WARNING, String.format(
"Failed to update Domain for existing OsAccount: %s, sid: %s", regFile.getId(), sid), ex);
760 }
catch (TskCoreException ex) {
761 logger.log(Level.SEVERE, String.format(
"Error adding os_info artifact to blackboard for file %d.", regFile.getId()), ex);
765 for (
int j = 0; j < myartlist.getLength(); j++) {
766 Node artchild = myartlist.item(j);
768 if (artchild.hasAttributes()) {
769 Element artnode = (Element) artchild;
771 String value = artnode.getTextContent().trim();
772 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
785 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
786 usbMtime = Long.valueOf(usbMtime.toString());
787 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
788 String dev = artnode.getAttribute(
"dev");
791 if (dev.toLowerCase().contains(
"vid")) {
792 USBInfo info = USB_MAPPER.parseAndLookup(dev);
793 if (info.getVendor() != null) {
794 make = info.getVendor();
796 if (info.getProduct() != null) {
797 model = info.getProduct();
800 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
801 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
802 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
803 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, regFile, bbattributes));
804 }
catch (TskCoreException ex) {
805 logger.log(Level.SEVERE, String.format(
"Error adding device_attached artifact to blackboard for file %d.", regFile.getId()), ex);
809 Long itemMtime = null;
811 String mTimeAttr = artnode.getAttribute(
"mtime");
812 if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
813 itemMtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy", US).parse(mTimeAttr).getTime();
814 itemMtime /= MS_IN_SEC;
816 }
catch (ParseException ex) {
817 logger.log(Level.SEVERE,
"Failed to parse epoch time for installed program artifact.", ex);
821 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
822 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
823 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG), bbattributes);
824 newArtifacts.add(bbart);
825 }
catch (TskCoreException ex) {
826 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.", ex);
830 String officeName = artnode.getAttribute(
"name");
835 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
837 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
838 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
839 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
840 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_RECENT_OBJECT), bbattributes);
842 newArtifacts.add(bbart);
843 }
catch (TskCoreException ex) {
844 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.", ex);
848 case "ProcessorArchitecture":
864 String homeDir = value;
865 String sid = artnode.getAttribute(
"sid");
866 String username = artnode.getAttribute(
"username");
867 String domName = domainName;
871 OsAccountRealm.RealmScope scope = OsAccountRealm.RealmScope.DOMAIN;
872 if(knownMachineSID(sid)) {
874 scope = OsAccountRealm.RealmScope.LOCAL;
878 createOrUpdateOsAccount(regFile, sid, username, homeDir, domName, scope);
879 }
catch(TskCoreException | TskDataException | NotUserSIDException ex) {
880 logger.log(Level.SEVERE, String.format(
"Failed to create OsAccount for file: %s, sid: %s", regFile.getId(), sid), ex);
884 case "NtuserNetwork":
886 String localPath = artnode.getAttribute(
"localPath");
887 String remoteName = value;
889 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
890 parentModuleName, localPath));
891 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
892 parentModuleName, remoteName));
893 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_REMOTE_DRIVE), bbattributes);
894 newArtifacts.add(bbart);
895 }
catch (TskCoreException ex) {
896 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.", ex);
900 String adapter = artnode.getAttribute(
"adapter");
902 Long lastWriteTime = Long.parseLong(artnode.getAttribute(
"writeTime"));
903 lastWriteTime = Long.valueOf(lastWriteTime.toString());
904 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
905 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
906 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
907 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WIFI_NETWORK), bbattributes);
908 newArtifacts.add(bbart);
909 }
catch (TskCoreException ex) {
910 logger.log(Level.SEVERE,
"Error adding SSID artifact to blackboard.", ex);
920 logger.log(Level.SEVERE,
"Unrecognized node name: {0}", dataType);
929 }
catch (FileNotFoundException ex) {
930 logger.log(Level.WARNING, String.format(
"Error finding the registry file: %s", regFilePath), ex);
931 }
catch (SAXException ex) {
932 logger.log(Level.WARNING, String.format(
"Error parsing the registry XML: %s", regFilePath), ex);
933 }
catch (IOException ex) {
934 logger.log(Level.WARNING, String.format(
"Error building the document parser: %s", regFilePath), ex);
935 }
catch (ParserConfigurationException ex) {
936 logger.log(Level.WARNING, String.format(
"Error configuring the registry parser: %s", regFilePath), ex);
939 if (fstream != null) {
942 }
catch (IOException ex) {
945 if (!context.dataSourceIngestIsCancelled()) {
946 postArtifacts(newArtifacts);
952 private boolean parseSystemPluginOutput(String regfilePath, AbstractFile regAbstractFile) {
953 File regfile =
new File(regfilePath);
954 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
955 String line = reader.readLine();
956 while (line != null) {
959 if (line.toLowerCase().matches(
"^bam v.*")) {
960 parseBamKey(regAbstractFile, reader, Bundle.Registry_System_Bam());
961 }
else if (line.toLowerCase().matches(
"^bthport v..*")) {
962 parseBlueToothDevices(regAbstractFile, reader);
964 line = reader.readLine();
967 }
catch (FileNotFoundException ex) {
968 logger.log(Level.WARNING,
"Error finding the registry file.", ex);
969 }
catch (IOException ex) {
970 logger.log(Level.WARNING,
"Error reading the system hive: {0}", ex);
989 private void parseBlueToothDevices(AbstractFile regFile, BufferedReader reader)
throws FileNotFoundException, IOException {
990 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
991 String line = reader.readLine();
992 while ((line != null) && (!line.contains(SECTION_DIVIDER))) {
993 line = reader.readLine();
999 if ((line != null) && (line.toLowerCase().contains(
"device unique id"))) {
1003 while (line != null && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.toLowerCase().contains(
"radio support not found")) {
1004 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1005 addBlueToothAttribute(line, attributes, TSK_DEVICE_ID);
1006 line = reader.readLine();
1008 if ((line != null) && (line.toLowerCase().contains(
"name"))) {
1009 addBlueToothAttribute(line, attributes, TSK_NAME);
1010 line = reader.readLine();
1012 addBlueToothAttribute(line, attributes, TSK_DATETIME);
1013 line = reader.readLine();
1014 addBlueToothAttribute(line, attributes, TSK_DATETIME_ACCESSED);
1017 bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING, regFile, attributes));
1018 }
catch (TskCoreException ex) {
1019 logger.log(Level.SEVERE, String.format(
"Failed to create bluetooth_pairing artifact for file %d", regFile.getId()), ex);
1023 line = reader.readLine();
1032 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1033 postArtifacts(bbartifacts);
1037 private void addBlueToothAttribute(String line, Collection<BlackboardAttribute> attributes, ATTRIBUTE_TYPE attributeType) {
1042 String tokens[] = line.split(
": ");
1043 if (tokens.length > 1 && !tokens[1].isEmpty()) {
1044 String tokenString = tokens[1];
1045 if (attributeType.getDisplayName().toLowerCase().contains(
"date")) {
1046 String dateString = tokenString.toLowerCase().replace(
" z",
"");
1048 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy", US);
1049 Long dateLong = Long.valueOf(0);
1051 Date newDate = dateFormat.parse(dateString);
1052 dateLong = newDate.getTime() / 1000;
1053 }
catch (ParseException ex) {
1056 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for Bluetooth Last Seen attribute.", dateString), ex);
1058 attributes.add(
new BlackboardAttribute(attributeType, getName(), dateLong));
1060 attributes.add(
new BlackboardAttribute(attributeType, getName(), tokenString));
1075 private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile,
long ingestJobId) {
1077 File regfile =
new File(regFilePath);
1078 List<BlackboardArtifact> newArtifacts =
new ArrayList<>();
1079 try (BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
new FileInputStream(regfile), StandardCharsets.UTF_8))) {
1081 String userInfoSection =
"User Information";
1082 String previousLine = null;
1083 String line = bufferedReader.readLine();
1084 Set<Map<String, String>> userSet =
new HashSet<>();
1085 Map<String, List<String>> groupMap = null;
1086 while (line != null) {
1087 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
1088 readUsers(bufferedReader, userSet);
1091 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(
"Group Membership Information")) {
1092 groupMap = readGroups(bufferedReader);
1095 previousLine = line;
1096 line = bufferedReader.readLine();
1098 Map<String, Map<String, String>> userInfoMap =
new HashMap<>();
1100 for (Map<String, String> userInfo : userSet) {
1101 userInfoMap.put(userInfo.get(SID_KEY), userInfo);
1105 OsAccountManager accountMgr = tskCase.getOsAccountManager();
1106 HostManager hostMrg = tskCase.getHostManager();
1107 Host host = hostMrg.getHostByDataSource((DataSource)dataSource);
1109 List<OsAccount> existingAccounts = accountMgr.getOsAccounts(host);
1110 for(OsAccount osAccount: existingAccounts) {
1111 Optional<String> optional = osAccount.getAddr();
1112 if(!optional.isPresent()) {
1116 String sid = optional.get();
1117 Map<String, String> userInfo = userInfoMap.remove(sid);
1118 if(userInfo != null) {
1119 addAccountInstance(accountMgr, osAccount, (DataSource)dataSource);
1120 updateOsAccount(osAccount, userInfo, groupMap.get(sid), regAbstractFile);
1125 for (Map<String, String> userInfo : userInfoMap.values()) {
1126 OsAccount osAccount = accountMgr.newWindowsOsAccount(userInfo.get(SID_KEY), null, null, host, OsAccountRealm.RealmScope.LOCAL);
1127 accountMgr.newOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
1128 updateOsAccount(osAccount, userInfo, groupMap.get(userInfo.get(SID_KEY)), regAbstractFile);
1131 }
catch (FileNotFoundException ex) {
1132 logger.log(Level.WARNING,
"Error finding the registry file.", ex);
1133 }
catch (IOException ex) {
1134 logger.log(Level.WARNING,
"Error building the document parser: {0}", ex);
1135 }
catch (TskDataException | TskCoreException ex) {
1136 logger.log(Level.WARNING,
"Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex);
1137 }
catch (OsAccountManager.NotUserSIDException ex) {
1138 logger.log(Level.WARNING,
"Error creating OS Account, input SID is not a user SID.", ex);
1141 if (!context.dataSourceIngestIsCancelled()) {
1142 postArtifacts(newArtifacts);
1159 private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1160 String line = bufferedReader.readLine();
1162 String userName =
"";
1163 String user_rid =
"";
1164 while (line != null && !line.contains(SECTION_DIVIDER)) {
1166 if (line.contains(USERNAME_KEY)) {
1167 String regx = USERNAME_KEY +
"\\s*?:";
1168 String userNameAndIdString = line.replaceAll(regx,
"");
1169 userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf(
'[')).trim();
1170 user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf(
'['), userNameAndIdString.lastIndexOf(
']'));
1171 }
else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1172 Map.Entry<String, String> entry = getSAMKeyValue(line);
1174 HashMap<String, String> userInfo =
new HashMap<>();
1175 userInfo.put(USERNAME_KEY, userName);
1176 userInfo.put(RID_KEY, user_rid);
1177 userInfo.put(entry.getKey(), entry.getValue());
1180 line = bufferedReader.readLine();
1181 while (line != null && !line.isEmpty()) {
1182 entry = getSAMKeyValue(line);
1183 if (entry != null) {
1184 userInfo.put(entry.getKey(), entry.getValue());
1186 line = bufferedReader.readLine();
1188 users.add(userInfo);
1192 line = bufferedReader.readLine();
1205 private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile)
throws FileNotFoundException, IOException {
1206 File regfile =
new File(regFileName);
1207 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
1208 String line = reader.readLine();
1209 while (line != null) {
1212 if (line.matches(
"^adoberdr v.*")) {
1213 parseAdobeMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Adobe());
1214 }
else if (line.matches(
"^mpmru v.*")) {
1215 parseMediaPlayerMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mediaplayer());
1216 }
else if (line.matches(
"^trustrecords v.*")) {
1217 parseOfficeTrustRecords(regFile, reader, Bundle.Recently_Used_Artifacts_Office_Trustrecords());
1218 }
else if (line.matches(
"^ArcHistory:")) {
1219 parse7ZipMRU(regFile, reader, Bundle.Recently_Used_Artifacts_ArcHistory());
1220 }
else if (line.matches(
"^applets v.*")) {
1221 parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Applets());
1222 }
else if (line.matches(
"^mmc v.*")) {
1223 parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mmc());
1224 }
else if (line.matches(
"^winrar v.*")) {
1225 parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar());
1226 }
else if (line.matches(
"^officedocs2010 v.*")) {
1227 parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs());
1229 line = reader.readLine();
1245 private void parseBamKey(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1246 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1247 String line = reader.readLine();
1249 while (!line.contains(SECTION_DIVIDER)) {
1250 line = reader.readLine();
1253 line = reader.readLine();
1255 while (!line.contains(SECTION_DIVIDER)) {
1258 String tokens[] = line.split(
"\\|");
1259 Long progRunDateTime = Long.valueOf(tokens[0]);
1262 String fileNameSid[] = tokens[4].split(
"\\s+\\(S-");
1263 String userSid =
"S-" + fileNameSid[1].substring(0, fileNameSid[1].length() - 1);
1264 String userName = getUserNameMap().get(userSid);
1265 if (userName == null) {
1268 String fileName = fileNameSid[0];
1269 if (fileName.startsWith(
"\\Device\\HarddiskVolume")) {
1271 int fileNameStart = fileName.indexOf(
'\\', 16);
1272 fileName = fileName.substring(fileNameStart, fileName.length());
1275 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1276 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(), fileName));
1277 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, getName(), userName));
1278 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), progRunDateTime));
1279 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, getName(), comment));
1282 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_PROG_RUN, regFile, attributes);
1283 bbartifacts.add(bba);
1284 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1286 bbartifacts.add(bba);
1288 }
catch (TskCoreException ex) {
1289 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_PROG_RUN artifact for file %d", regFile.getId()), ex);
1291 line = reader.readLine();
1293 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1294 postArtifacts(bbartifacts);
1309 private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1310 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1311 String line = reader.readLine();
1312 SimpleDateFormat adobePluginDateFormat =
new SimpleDateFormat(
"yyyyMMddHHmmssZ", US);
1313 Long adobeUsedTime = Long.valueOf(0);
1314 while (!line.contains(SECTION_DIVIDER)) {
1315 line = reader.readLine();
1317 if (line.matches(
"^Key name,file name,sDate,uFileSize,uPageCount")) {
1318 line = reader.readLine();
1321 while (!line.contains(SECTION_DIVIDER)) {
1324 String tokens[] = line.split(
",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
1325 String fileName = tokens[1].substring(0, tokens[1].length() - 1);
1326 fileName = fileName.replace(
"\"",
"");
1327 if (fileName.charAt(0) ==
'/') {
1328 fileName = fileName.substring(1, fileName.length() - 1);
1329 fileName = fileName.replaceFirst(
"/",
":/");
1332 if (tokens.length > 2) {
1335 String fileUsedTime = tokens[2].replaceAll(
"'",
"");
1336 Date usedDate = adobePluginDateFormat.parse(fileUsedTime);
1337 adobeUsedTime = usedDate.getTime() / 1000;
1338 }
catch (ParseException ex) {
1341 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex);
1344 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1345 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1346 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getName(), adobeUsedTime));
1347 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1349 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1351 bbartifacts.add(bba);
1352 fileName = fileName.replace(
"\0",
"");
1353 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1355 bbartifacts.add(bba);
1358 }
catch(TskCoreException ex) {
1359 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1361 line = reader.readLine();
1366 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1367 postArtifacts(bbartifacts);
1383 private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1384 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1385 String line = reader.readLine();
1386 while (!line.contains(SECTION_DIVIDER)) {
1387 line = reader.readLine();
1389 if (line.contains(
"LastWrite")) {
1390 line = reader.readLine();
1393 while (!line.contains(SECTION_DIVIDER) && !line.contains(
"RecentFileList has no values.")) {
1395 String tokens[] = line.split(
"> ");
1396 String fileName = tokens[1];
1397 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1398 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1399 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1401 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1403 bbartifacts.add(bba);
1404 bba = createAssociatedArtifact(fileName, bba);
1406 bbartifacts.add(bba);
1407 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1409 bbartifacts.add(bba);
1413 }
catch(TskCoreException ex) {
1414 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1416 line = reader.readLine();
1421 if (!bbartifacts.isEmpty()&& !context.dataSourceIngestIsCancelled()) {
1422 postArtifacts(bbartifacts);
1438 private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1439 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1440 String line = reader.readLine();
1441 while (!line.contains(SECTION_DIVIDER)) {
1442 line = reader.readLine();
1444 if (line.contains(
"LastWrite")) {
1445 line = reader.readLine();
1448 while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains(
"Applets")
1449 && !line.contains((
"Recent File List"))) {
1451 String tokens[] = line.split(
"> ");
1452 if (tokens.length > 1) {
1453 String fileName = tokens[1];
1454 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1455 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1456 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1458 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1460 bbartifacts.add(bba);
1461 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1463 bbartifacts.add(bba);
1466 }
catch(TskCoreException ex) {
1467 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1470 line = reader.readLine();
1475 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1476 postArtifacts(bbartifacts);
1492 private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1493 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1494 String line = reader.readLine();
1495 while (!line.contains(SECTION_DIVIDER)) {
1496 line = reader.readLine();
1498 if (line.contains(
"LastWrite")) {
1499 line = reader.readLine();
1502 if (!line.isEmpty()) {
1503 while (!line.contains(SECTION_DIVIDER)) {
1505 String tokens[] = line.split(
"> ");
1506 String fileName = tokens[1];
1507 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1508 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1509 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1511 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1512 bbartifacts.add(bba);
1513 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1515 bbartifacts.add(bba);
1517 }
catch(TskCoreException ex) {
1518 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1520 line = reader.readLine();
1526 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1527 postArtifacts(bbartifacts);
1543 private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1544 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1545 String line = reader.readLine();
1547 if (!line.contains(
"PathHistory:")) {
1548 while (!line.contains(
"PathHistory:") && !line.isEmpty()) {
1551 String fileName = line;
1552 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1553 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1554 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1556 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1557 bbartifacts.add(bba);
1558 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1560 bbartifacts.add(bba);
1563 }
catch(TskCoreException ex) {
1564 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1566 line = reader.readLine();
1570 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1571 postArtifacts(bbartifacts);
1587 private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1588 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1589 String line = reader.readLine();
1593 while (!line.contains(SECTION_DIVIDER)) {
1594 line = reader.readLine();
1596 line = reader.readLine();
1597 while (!line.contains(SECTION_DIVIDER)) {
1600 String tokens[] = line.split(
"\\|");
1601 Long docDate = Long.valueOf(tokens[0]);
1602 String fileNameTokens[] = tokens[4].split(
" - ");
1603 String fileName = fileNameTokens[1];
1604 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1605 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1606 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getName(), docDate));
1607 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1609 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1610 bbartifacts.add(bba);
1611 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1613 bbartifacts.add(bba);
1615 }
catch(TskCoreException ex) {
1616 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1618 line = reader.readLine();
1621 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1622 postArtifacts(bbartifacts);
1638 private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1639 String userProfile = regFile.getParentPath();
1640 userProfile = userProfile.substring(0, userProfile.length() - 1);
1641 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1642 SimpleDateFormat pluginDateFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy", US);
1643 Long usedTime = Long.valueOf(0);
1644 String line = reader.readLine();
1645 while (!line.contains(SECTION_DIVIDER)) {
1646 line = reader.readLine();
1648 usedTime = Long.valueOf(0);
1649 if (!line.contains(
"**") && !line.contains(
"----------") && !line.contains(
"LastWrite")
1650 && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains(
"TrustRecords")
1651 && !line.contains(
"VBAWarnings =")) {
1655 String fileName = null;
1656 String tokens[] = line.split(
" : ");
1657 fileName = tokens[1];
1658 fileName = fileName.replace(
"%USERPROFILE%", userProfile);
1661 String fileUsedTime = tokens[0].replaceAll(
" Z",
"");
1662 Date usedDate = pluginDateFormat.parse(fileUsedTime);
1663 usedTime = usedDate.getTime() / 1000;
1664 }
catch (ParseException ex) {
1667 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex);
1669 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1670 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1671 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getName(), usedTime));
1672 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1674 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1675 bbartifacts.add(bba);
1676 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1678 bbartifacts.add(bba);
1680 }
catch(TskCoreException ex) {
1681 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1686 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1687 postArtifacts(bbartifacts);
1701 private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) {
1702 String fileName = FilenameUtils.getName(filePathName);
1703 String filePath = FilenameUtils.getPath(filePathName);
1704 List<AbstractFile> sourceFiles;
1706 sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath);
1707 if (!sourceFiles.isEmpty()) {
1708 return createAssociatedArtifact(sourceFiles.get(0), bba);
1710 }
catch (TskCoreException ex) {
1713 logger.log(Level.WARNING, String.format(
"Error finding actual file %s. file may not exist", filePathName));
1729 private Map<String, String> makeUserNameMap(Content dataSource)
throws TskCoreException {
1730 Map<String, String> map =
new HashMap<>();
1732 for(OsAccount account: tskCase.getOsAccountManager().getOsAccounts(((DataSource)dataSource).getHost())) {
1733 Optional<String> userName = account.getLoginName();
1735 map.put(account.getName(), userName.isPresent() ? userName.get() :
"");
1749 private String getMachineSID(String osAccountSID) {
1752 int index = osAccountSID.lastIndexOf(
"-");
1753 return osAccountSID.substring(0, index);
1756 private final List<String> machineSIDs =
new ArrayList<>();
1766 private boolean knownMachineSID(String osAccountSID) {
1767 if (machineSIDs.isEmpty()) {
1768 Map<String, String> userMap = getUserNameMap();
1769 for (String str : userMap.keySet()) {
1770 String temp = getMachineSID(str);
1771 if (!machineSIDs.contains(temp)) {
1772 machineSIDs.add(temp);
1776 String machineSID = getMachineSID(osAccountSID);
1777 return machineSIDs.contains(machineSID);
1785 private Map<String, String> getUserNameMap() {
1786 if(userNameMap == null) {
1790 userNameMap = makeUserNameMap(dataSource);
1791 }
catch (TskCoreException ex) {
1792 logger.log(Level.WARNING,
"Unable to create OS Account user name map", ex);
1795 userNameMap =
new HashMap<>();
1812 private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
1813 return artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID())));
1824 void createShellBagArtifacts(AbstractFile regFile, List<ShellBag> shellbags)
throws TskCoreException {
1825 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1826 List<DataArtifact> dataArtifacts =
new ArrayList<>();
1828 for (ShellBag bag : shellbags) {
1829 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1830 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), bag.getResource()));
1831 attributes.add(
new BlackboardAttribute(getKeyAttribute(), getName(), bag.getKey()));
1834 time = bag.getLastWrite();
1836 attributes.add(
new BlackboardAttribute(getLastWriteAttribute(), getName(), time));
1839 time = bag.getModified();
1841 attributes.add(
new BlackboardAttribute(TSK_DATETIME_MODIFIED, getName(), time));
1844 time = bag.getCreated();
1846 attributes.add(
new BlackboardAttribute(TSK_DATETIME_CREATED, getName(), time));
1849 time = bag.getAccessed();
1851 attributes.add(
new BlackboardAttribute(TSK_DATETIME_ACCESSED, getName(), time));
1854 BlackboardArtifact artifact = createArtifactWithAttributes(getShellBagArtifact(), regFile, attributes);
1855 artifacts.add(artifact);
1856 dataArtifacts.add((DataArtifact)artifact);
1859 if(!context.dataSourceIngestIsCancelled()) {
1860 postArtifacts(artifacts);
1861 context.addDataArtifactsToJob(dataArtifacts);
1874 private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException {
1875 if (shellBagArtifactType == null) {
1877 shellBagArtifactType = tskCase.getBlackboard().getOrAddArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name());
1878 }
catch (BlackboardException ex) {
1879 throw new TskCoreException(String.format(
"Failed to get shell bag artifact type", SHELLBAG_ARTIFACT_NAME), ex);
1883 return shellBagArtifactType;
1894 private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException {
1895 if (shellBagLastWriteAttributeType == null) {
1897 shellBagLastWriteAttributeType = tskCase.getBlackboard().getOrAddAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE,
1898 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME,
1899 Bundle.Shellbag_Last_Write_Attribute_Display_Name());
1900 }
catch (BlackboardException ex) {
1902 throw new TskCoreException(String.format(
"Failed to get custom attribute %s", SHELLBAG_ATTRIBUTE_LAST_WRITE), ex);
1905 return shellBagLastWriteAttributeType;
1916 private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException {
1917 if (shellBagKeyAttributeType == null) {
1919 shellBagKeyAttributeType = tskCase.getBlackboard().getOrAddAttributeType(SHELLBAG_ATTRIBUTE_KEY,
1920 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
1921 Bundle.Shellbag_Key_Attribute_Display_Name());
1922 }
catch (BlackboardException ex) {
1923 throw new TskCoreException(String.format(
"Failed to get key attribute %s", SHELLBAG_ATTRIBUTE_KEY), ex);
1926 return shellBagKeyAttributeType;
1938 Map<String, List<String>> readGroups(BufferedReader bufferedReader)
throws IOException {
1939 Map<String, List<String>> groupMap =
new HashMap<>();
1941 String line = bufferedReader.readLine();
1944 String groupName = null;
1946 while (line != null && !line.contains(SECTION_DIVIDER)) {
1948 if (line.contains(
"Group Name")) {
1949 String value = line.replaceAll(
"Group Name\\s*?:",
"").trim();
1950 groupName = (value.replaceAll(
"\\[\\d*?\\]",
"")).trim();
1951 int startIndex = value.indexOf(
" [") + 1;
1952 int endIndex = value.indexOf(
']');
1954 if (startIndex != -1 && endIndex != -1) {
1955 String countStr = value.substring(startIndex + 1, endIndex);
1956 userCount = Integer.parseInt(countStr);
1958 }
else if (line.matches(
"Users\\s*?:")) {
1959 for (
int i = 0; i < userCount; i++) {
1960 line = bufferedReader.readLine();
1962 String sid = line.trim();
1963 List<String> groupList = groupMap.get(sid);
1964 if (groupList == null) {
1965 groupList =
new ArrayList<>();
1966 groupMap.put(sid, groupList);
1968 groupList.add(groupName);
1973 line = bufferedReader.readLine();
1986 private Map.Entry<String, String> getSAMKeyValue(String line) {
1987 int index = line.indexOf(
':');
1988 Map.Entry<String, String> returnValue = null;
1990 String value = null;
1993 key = line.substring(0, index).trim();
1994 if (index + 1 < line.length()) {
1995 value = line.substring(index + 1).trim();
2000 }
else if (line.contains(
"-->")) {
2001 key = line.replace(
"-->",
"").trim();
2006 returnValue =
new AbstractMap.SimpleEntry<>(key, value);
2013 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
2014 this.dataSource = dataSource;
2015 this.context = context;
2017 progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
2018 analyzeRegistryFiles(context.getJobId());
2027 public String autopsyPlugins =
"";
2028 public String fullPlugins =
"";
2043 private void createOrUpdateOsAccount(AbstractFile file, String sid, String userName, String homeDir, String domainName, OsAccountRealm.RealmScope realmScope) throws TskCoreException, TskDataException, NotUserSIDException {
2044 OsAccountManager accountMgr = tskCase.getOsAccountManager();
2045 HostManager hostMrg = tskCase.getHostManager();
2046 Host host = hostMrg.getHostByDataSource((DataSource)dataSource);
2048 Optional<OsAccount> optional = accountMgr.getWindowsOsAccount(sid, null, null, host);
2049 OsAccount osAccount;
2050 if (!optional.isPresent()) {
2051 osAccount = accountMgr.newWindowsOsAccount(sid, userName != null && userName.isEmpty() ? null : userName, domainName, host, realmScope);
2052 accountMgr.newOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
2054 osAccount = optional.get();
2055 addAccountInstance(accountMgr, osAccount, (DataSource)dataSource);
2056 if (userName != null && !userName.isEmpty()) {
2057 OsAccountUpdateResult updateResult= accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, userName, (domainName == null || domainName.isEmpty()) ? null : domainName, host);
2058 osAccount = updateResult.getUpdatedAccount().orElse(osAccount);
2062 if (homeDir != null && !homeDir.isEmpty()) {
2063 List<OsAccountAttribute> attributes =
new ArrayList<>();
2064 String dir = homeDir.replaceFirst(
"^(%\\w*%)",
"");
2065 dir = dir.replace(
"\\",
"/");
2066 attributes.add(createOsAccountAttribute(TSK_HOME_DIR, dir, osAccount, host, file));
2067 accountMgr.addExtendedOsAccountAttributes(osAccount, attributes);
2078 private void addEmailAccount(AbstractFile regFile, String emailAddress) {
2080 currentCase.getSleuthkitCase()
2081 .getCommunicationsManager()
2082 .createAccountFileInstance(Account.Type.EMAIL,
2083 emailAddress, getRAModuleName(), regFile);
2084 }
catch (TskCoreException ex) {
2085 logger.log(Level.SEVERE,
2086 String.format(
"Error adding email account with value "
2087 +
"%s, to the case database for file %s [objId=%d]",
2088 emailAddress, regFile.getName(), regFile.getId()), ex);
2100 private Long parseRegRipTime(String value) {
2102 return REG_RIPPER_TIME_FORMAT.parse(value).getTime() / MS_IN_SEC;
2103 }
catch (ParseException ex) {
2104 logger.log(Level.SEVERE, String.format(
"Failed to parse reg rip time: %s", value));
2120 private void updateOsAccount(OsAccount osAccount, Map<String, String> userInfo, List<String> groupList, AbstractFile regFile)
throws TskDataException, TskCoreException, NotUserSIDException {
2121 Host host = ((DataSource)dataSource).getHost();
2123 SimpleDateFormat regRipperTimeFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'", US);
2124 regRipperTimeFormat.setTimeZone(getTimeZone(
"GMT"));
2126 List<OsAccountAttribute> attributes =
new ArrayList<>();
2128 Long creationTime = null;
2130 String value = userInfo.get(ACCOUNT_CREATED_KEY);
2131 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2132 creationTime = parseRegRipTime(value);
2135 value = userInfo.get(LAST_LOGIN_KEY);
2136 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2137 Long time = parseRegRipTime(value);
2139 attributes.add(createOsAccountAttribute(TSK_DATETIME_ACCESSED,
2140 parseRegRipTime(value),
2141 osAccount, host, regFile));
2145 String loginName = null;
2146 value = userInfo.get(USERNAME_KEY);
2147 if (value != null && !value.isEmpty()) {
2151 value = userInfo.get(LOGIN_COUNT_KEY);
2152 if (value != null && !value.isEmpty()) {
2153 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
2154 Integer.parseInt(value),
2155 osAccount, host, regFile));
2161 value = userInfo.get(ACCOUNT_TYPE_KEY);
2162 if (value != null && !value.isEmpty() && value.toLowerCase().contains(
"admin")) {
2163 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_IS_ADMIN,
2164 1, osAccount, host, regFile));
2167 value = userInfo.get(USER_COMMENT_KEY);
2168 if (value != null && !value.isEmpty()) {
2169 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
2170 value, osAccount, host, regFile));
2173 value = userInfo.get(INTERNET_NAME_KEY);
2174 if (value != null && !value.isEmpty()) {
2175 addEmailAccount(regFile, value);
2177 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
2178 value, osAccount, host, regFile));
2182 String fullName = null;
2183 value = userInfo.get(FULL_NAME_KEY);
2184 if (value != null && !value.isEmpty()) {
2187 value = userInfo.get(NAME_KEY);
2188 if (value != null && !value.isEmpty()) {
2193 value = userInfo.get(PWD_RESET_KEY);
2194 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2195 Long time = parseRegRipTime(value);
2197 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
2198 time, osAccount, host, regFile));
2202 value = userInfo.get(PASSWORD_HINT);
2203 if (value != null && !value.isEmpty()) {
2204 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
2205 value, osAccount, host, regFile));
2208 value = userInfo.get(PWD_FAILE_KEY);
2209 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2210 Long time = parseRegRipTime(value);
2212 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
2213 time, osAccount, host, regFile));
2217 String settingString = getSettingsFromMap(PASSWORD_SETTINGS_FLAGS, userInfo);
2218 if (!settingString.isEmpty()) {
2219 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
2220 settingString, osAccount, host, regFile));
2223 settingString = getSettingsFromMap(ACCOUNT_SETTINGS_FLAGS, userInfo);
2224 if (!settingString.isEmpty()) {
2225 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
2226 settingString, osAccount, host, regFile));
2229 settingString = getSettingsFromMap(ACCOUNT_TYPE_FLAGS, userInfo);
2230 if (!settingString.isEmpty()) {
2231 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
2232 settingString, osAccount, host, regFile));
2235 if (groupList != null && groupList.isEmpty()) {
2236 String groups = groupList.stream()
2237 .map(String::valueOf)
2238 .collect(Collectors.joining(
", "));
2240 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
2241 groups, osAccount, host, regFile));
2245 OsAccountManager accountMgr = tskCase.getOsAccountManager();
2246 accountMgr.addExtendedOsAccountAttributes(osAccount, attributes);
2249 accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, loginName, null, host);
2252 accountMgr.updateStandardOsAccountAttributes(osAccount, fullName, null, null, creationTime);
2265 private String getSettingsFromMap(String[] keys, Map<String, String> map) {
2266 List<String> settingsList =
new ArrayList<>();
2267 for (String setting : keys) {
2268 if (map.containsKey(setting)) {
2269 settingsList.add(setting);
2273 if (!settingsList.isEmpty()) {
2274 return settingsList.stream()
2275 .map(String::valueOf)
2276 .collect(Collectors.joining(
", "));
2293 private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, String value, OsAccount osAccount, Host host, AbstractFile file) {
2294 return osAccount.new OsAccountAttribute(
new BlackboardAttribute.Type(type), value, osAccount, host, file);
2308 private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, Long value, OsAccount osAccount, Host host, AbstractFile file) {
2309 return osAccount.new OsAccountAttribute(
new BlackboardAttribute.Type(type), value, osAccount, host, file);
2323 private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, Integer value, OsAccount osAccount, Host host, AbstractFile file) {
2324 return osAccount.new OsAccountAttribute(
new BlackboardAttribute.Type(type), value, osAccount, host, file);
2336 private void addAccountInstance(OsAccountManager accountMgr, OsAccount osAccount, DataSource dataSource)
throws TskCoreException {
2337 accountMgr.newOsAccountInstance(osAccount, dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);