23 package org.sleuthkit.autopsy.recentactivity;
25 import java.io.BufferedReader;
27 import org.openide.util.NbBundle;
30 import java.io.FileInputStream;
31 import java.io.FileNotFoundException;
32 import java.io.IOException;
33 import java.io.InputStreamReader;
34 import java.text.ParseException;
35 import java.text.SimpleDateFormat;
36 import java.util.ArrayList;
37 import java.util.List;
39 import java.util.HashSet;
40 import java.util.logging.Level;
42 import java.util.Collection;
43 import java.util.Scanner;
44 import org.openide.modules.InstalledFileLocator;
50 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
52 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
63 class ExtractIE
extends Extract {
65 private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
66 private IngestServices services = IngestServices.getInstance();
67 private String moduleTempResultsDir;
68 private String PASCO_LIB_PATH;
69 private String JAVA_PATH;
70 private static final SimpleDateFormat dateFormatter =
new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
71 private Content dataSource;
72 private IngestJobContext context;
75 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractIE.moduleName.text");
76 moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(),
"IE") + File.separator +
"results";
77 JAVA_PATH = PlatformUtil.getJavaPath();
81 public void process(Content dataSource, IngestJobContext context) {
82 this.dataSource = dataSource;
83 this.context = context;
93 private void getBookmark() {
95 List<AbstractFile> favoritesFiles;
97 favoritesFiles = fileManager.
findFiles(dataSource,
"%.url",
"Favorites");
98 }
catch (TskCoreException ex) {
99 logger.log(Level.WARNING,
"Error fetching 'url' files for Internet Explorer bookmarks.", ex);
100 this.addErrorMessage(
101 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getBookmark.errMsg.errGettingBookmarks",
106 if (favoritesFiles.isEmpty()) {
107 logger.log(Level.INFO,
"Didn't find any IE bookmark files.");
112 for (AbstractFile fav : favoritesFiles) {
113 if (fav.getSize() == 0) {
117 if (context.dataSourceIngestIsCancelled()) {
121 String url = getURLFromIEBookmarkFile(fav);
123 String name = fav.getName();
124 Long datetime = fav.getCrtime();
125 String Tempdate = datetime.toString();
126 datetime = Long.valueOf(Tempdate);
127 String domain = Util.extractDomain(url);
129 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
130 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
131 NbBundle.getMessage(
this.getClass(),
132 "ExtractIE.parentModuleName.noSpace"), url));
133 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
134 NbBundle.getMessage(
this.getClass(),
135 "ExtractIE.parentModuleName.noSpace"), name));
136 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
137 NbBundle.getMessage(
this.getClass(),
138 "ExtractIE.parentModuleName.noSpace"), datetime));
139 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
140 NbBundle.getMessage(
this.getClass(),
141 "ExtractIE.parentModuleName.noSpace"),
142 NbBundle.getMessage(
this.getClass(),
"ExtractIE.moduleName.text")));
143 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
144 NbBundle.getMessage(
this.getClass(),
145 "ExtractIE.parentModuleName.noSpace"), domain));
146 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
148 services.fireModuleDataEvent(
new ModuleDataEvent(
149 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
152 private String getURLFromIEBookmarkFile(AbstractFile fav) {
153 BufferedReader reader =
new BufferedReader(
new InputStreamReader(
new ReadContentInputStream(fav)));
154 String line, url =
"";
156 while ((line = reader.readLine()) != null) {
159 if (line.startsWith(
"URL")) {
160 url = line.substring(line.indexOf(
"=") + 1);
164 }
catch (IOException ex) {
165 logger.log(Level.WARNING,
"Failed to read from content: " + fav.getName(), ex);
166 this.addErrorMessage(
167 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
169 }
catch (IndexOutOfBoundsException ex) {
170 logger.log(Level.WARNING,
"Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.getName(), ex);
171 this.addErrorMessage(
172 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
177 }
catch (IOException ex) {
178 logger.log(Level.WARNING,
"Failed to close reader.", ex);
188 private void getCookie() {
190 List<AbstractFile> cookiesFiles;
192 cookiesFiles = fileManager.
findFiles(dataSource,
"%.txt",
"Cookies");
193 }
catch (TskCoreException ex) {
194 logger.log(Level.WARNING,
"Error getting cookie files for IE");
195 this.addErrorMessage(
196 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
200 if (cookiesFiles.isEmpty()) {
201 logger.log(Level.INFO,
"Didn't find any IE cookies files.");
206 for (AbstractFile cookiesFile : cookiesFiles) {
207 if (context.dataSourceIngestIsCancelled()) {
210 if (cookiesFile.getSize() == 0) {
214 byte[] t =
new byte[(int) cookiesFile.getSize()];
216 final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
217 }
catch (TskCoreException ex) {
218 logger.log(Level.SEVERE,
"Error reading bytes of Internet Explorer cookie.", ex);
219 this.addErrorMessage(
220 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getCookie.errMsg.errReadingIECookie",
221 this.getName(), cookiesFile.getName()));
224 String cookieString =
new String(t);
225 String[] values = cookieString.split(
"\n");
226 String url = values.length > 2 ? values[2] :
"";
227 String value = values.length > 1 ? values[1] :
"";
228 String name = values.length > 0 ? values[0] :
"";
229 Long datetime = cookiesFile.getCrtime();
230 String tempDate = datetime.toString();
231 datetime = Long.valueOf(tempDate);
232 String domain = Util.extractDomain(url);
234 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
235 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
236 NbBundle.getMessage(
this.getClass(),
237 "ExtractIE.parentModuleName.noSpace"), url));
238 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
239 NbBundle.getMessage(
this.getClass(),
240 "ExtractIE.parentModuleName.noSpace"), datetime));
241 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
242 NbBundle.getMessage(
this.getClass(),
243 "ExtractIE.parentModuleName.noSpace"), (name != null) ? name :
""));
244 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
245 NbBundle.getMessage(
this.getClass(),
246 "ExtractIE.parentModuleName.noSpace"), value));
247 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
248 NbBundle.getMessage(
this.getClass(),
249 "ExtractIE.parentModuleName.noSpace"),
250 NbBundle.getMessage(
this.getClass(),
"ExtractIE.moduleName.text")));
251 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
252 NbBundle.getMessage(
this.getClass(),
253 "ExtractIE.parentModuleName.noSpace"), domain));
254 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
256 services.fireModuleDataEvent(
new ModuleDataEvent(
257 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE));
263 private void getHistory() {
264 logger.log(Level.INFO,
"Pasco results path: {0}", moduleTempResultsDir);
265 boolean foundHistory =
false;
267 final File pascoRoot = InstalledFileLocator.getDefault().locate(
"pasco2", ExtractIE.class.getPackage().getName(),
false);
268 if (pascoRoot == null) {
269 this.addErrorMessage(
270 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.unableToGetHist", this.getName()));
271 logger.log(Level.SEVERE,
"Error finding pasco program ");
275 final String pascoHome = pascoRoot.getAbsolutePath();
276 logger.log(Level.INFO,
"Pasco2 home: {0}", pascoHome);
278 PASCO_LIB_PATH = pascoHome + File.separator +
"pasco2.jar" + File.pathSeparator
279 + pascoHome + File.separator +
"*";
281 File resultsDir =
new File(moduleTempResultsDir);
286 List<AbstractFile> indexFiles;
288 indexFiles = fileManager.
findFiles(dataSource,
"index.dat");
289 }
catch (TskCoreException ex) {
290 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errGettingHistFiles",
292 logger.log(Level.WARNING,
"Error fetching 'index.data' files for Internet Explorer history.");
296 if (indexFiles.isEmpty()) {
297 String msg = NbBundle.getMessage(this.getClass(),
"ExtractIE.getHistory.errMsg.noHistFiles");
298 logger.log(Level.INFO, msg);
304 String indexFileName;
305 for (AbstractFile indexFile : indexFiles) {
311 indexFileName =
"index" + Integer.toString((
int) indexFile.getId()) +
".dat";
313 temps = RAImageIngestModule.getRATempPath(currentCase,
"IE") + File.separator + indexFileName;
314 File datFile =
new File(temps);
315 if (context.dataSourceIngestIsCancelled()) {
319 ContentUtils.writeToFile(indexFile, datFile);
320 }
catch (IOException e) {
321 logger.log(Level.SEVERE,
"Error while trying to write index.dat file " + datFile.getAbsolutePath(), e);
322 this.addErrorMessage(
323 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
324 datFile.getAbsolutePath()));
328 String filename =
"pasco2Result." + indexFile.getId() +
".txt";
329 boolean bPascProcSuccess = executePasco(temps, filename);
330 if (context.dataSourceIngestIsCancelled()) {
336 if (bPascProcSuccess) {
337 parsePascoOutput(indexFile, filename);
343 logger.log(Level.WARNING,
"pasco execution failed on: {0}",
this.getName());
344 this.addErrorMessage(
345 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
350 services.fireModuleDataEvent(
new ModuleDataEvent(
351 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName"), BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
363 private boolean executePasco(String indexFilePath, String outputFileName) {
364 boolean success =
true;
366 final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
367 final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName +
".err";
368 logger.log(Level.INFO,
"Writing pasco results to: {0}", outputFileFullPath);
369 List<String> commandLine =
new ArrayList<>();
370 commandLine.add(JAVA_PATH);
371 commandLine.add(
"-cp");
372 commandLine.add(PASCO_LIB_PATH);
373 commandLine.add(
"isi.pasco2.Main");
374 commandLine.add(
"-T");
375 commandLine.add(
"history");
376 commandLine.add(indexFilePath);
377 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
378 processBuilder.redirectOutput(
new File(outputFileFullPath));
379 processBuilder.redirectError(
new File(errFileFullPath));
380 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
382 }
catch (IOException ex) {
384 logger.log(Level.SEVERE,
"Unable to execute Pasco to process Internet Explorer web history.", ex);
396 private void parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
398 String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
400 File file =
new File(fnAbs);
401 if (file.exists() ==
false) {
402 this.addErrorMessage(
403 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
405 logger.log(Level.WARNING,
"Pasco Output not found: {0}", file.getPath());
411 if (file.length() == 0) {
417 fileScanner =
new Scanner(
new FileInputStream(file.toString()));
418 }
catch (FileNotFoundException ex) {
419 this.addErrorMessage(
420 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
422 logger.log(Level.WARNING,
"Unable to find the Pasco file at " + file.getPath(), ex);
427 Set<String> reportedUserAccounts =
new HashSet<String>();
429 while (fileScanner.hasNext()) {
430 String line = fileScanner.nextLine();
431 if (!line.startsWith(
"URL")) {
435 String[] lineBuff = line.split(
"\\t");
437 if (lineBuff.length < 4) {
438 logger.log(Level.INFO,
"Found unrecognized IE history format.");
442 String ddtime = lineBuff[2];
443 String actime = lineBuff[3];
444 Long ftime = (long) 0;
453 if (lineBuff[1].contains(
"@")) {
454 String url[] = lineBuff[1].split(
"@", 2);
456 user = user.replace(
"Visited:",
"");
457 user = user.replace(
":Host:",
"");
458 user = user.replaceAll(
"(:)(.*?)(:)",
"");
461 realurl = realurl.replace(
"Visited:",
"");
462 realurl = realurl.replaceAll(
":(.*?):",
"");
463 realurl = realurl.replace(
":Host:",
"");
464 realurl = realurl.trim();
467 realurl = lineBuff[1].trim();
470 domain = Util.extractDomain(realurl);
472 if (!ddtime.isEmpty()) {
473 ddtime = ddtime.replace(
"T",
" ");
474 ddtime = ddtime.substring(ddtime.length() - 5);
477 if (!actime.isEmpty()) {
479 Long epochtime = dateFormatter.parse(actime).getTime();
480 ftime = epochtime.longValue();
481 ftime = ftime / 1000;
482 }
catch (ParseException e) {
483 this.addErrorMessage(
484 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
486 logger.log(Level.SEVERE,
"Error parsing Pasco results.", e);
491 BlackboardArtifact bbart = origFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
492 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
493 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
494 NbBundle.getMessage(
this.getClass(),
495 "ExtractIE.parentModuleName.noSpace"), realurl));
498 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
499 NbBundle.getMessage(
this.getClass(),
500 "ExtractIE.parentModuleName.noSpace"), ftime));
501 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
502 NbBundle.getMessage(
this.getClass(),
503 "ExtractIE.parentModuleName.noSpace"),
""));
505 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
506 NbBundle.getMessage(
this.getClass(),
507 "ExtractIE.parentModuleName.noSpace"),
508 NbBundle.getMessage(
this.getClass(),
509 "ExtractIE.moduleName.text")));
510 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
511 NbBundle.getMessage(
this.getClass(),
512 "ExtractIE.parentModuleName.noSpace"), domain));
513 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
514 NbBundle.getMessage(
this.getClass(),
515 "ExtractIE.parentModuleName.noSpace"), user));
516 bbart.addAttributes(bbattributes);
519 this.indexArtifact(bbart);
521 if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
522 BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
523 osAttr.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
524 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parentModuleName.noSpace"), user));
527 this.indexArtifact(osAttr);
529 reportedUserAccounts.add(user);
531 }
catch (TskCoreException ex) {
532 logger.log(Level.SEVERE,
"Error writing Internet Explorer web history artifact to the blackboard.", ex);
synchronized List< AbstractFile > findFiles(String fileName)