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.FileWriter;
33 import java.io.IOException;
34 import java.io.InputStreamReader;
35 import java.io.Writer;
36 import java.text.ParseException;
37 import java.text.SimpleDateFormat;
38 import java.util.ArrayList;
39 import java.util.List;
41 import java.util.HashSet;
42 import java.util.logging.Level;
44 import java.util.Collection;
45 import java.util.Scanner;
46 import org.openide.modules.InstalledFileLocator;
65 class ExtractIE
extends Extract {
67 private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
68 private IngestServices services = IngestServices.getInstance();
69 private String moduleTempResultsDir;
70 private String PASCO_LIB_PATH;
71 private String JAVA_PATH;
72 private static final SimpleDateFormat dateFormatter =
new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
74 private IngestJobContext context;
77 moduleName = NbBundle.getMessage(ExtractIE.class,
"ExtractIE.moduleName.text");
78 moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(),
"IE") +
File.separator +
"results";
79 JAVA_PATH = PlatformUtil.getJavaPath();
83 public void process(
Content dataSource, IngestJobContext context) {
84 this.dataSource = dataSource;
85 this.context = context;
95 private void getBookmark() {
97 List<AbstractFile> favoritesFiles;
99 favoritesFiles = fileManager.
findFiles(dataSource,
"%.url",
"Favorites");
101 logger.log(Level.WARNING,
"Error fetching 'url' files for Internet Explorer bookmarks.", ex);
102 this.addErrorMessage(
103 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getBookmark.errMsg.errGettingBookmarks",
108 if (favoritesFiles.isEmpty()) {
109 logger.log(Level.INFO,
"Didn't find any IE bookmark files.");
115 if (fav.getSize() == 0) {
119 if (context.dataSourceIngestIsCancelled()) {
123 String url = getURLFromIEBookmarkFile(fav);
125 String name = fav.getName();
126 Long datetime = fav.getCrtime();
127 String Tempdate = datetime.toString();
128 datetime = Long.valueOf(Tempdate);
129 String domain = Util.extractDomain(url);
131 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
133 NbBundle.getMessage(this.getClass(),
134 "ExtractIE.parentModuleName.noSpace"), url));
136 NbBundle.getMessage(this.getClass(),
137 "ExtractIE.parentModuleName.noSpace"), name));
139 NbBundle.getMessage(this.getClass(),
140 "ExtractIE.parentModuleName.noSpace"), datetime));
142 NbBundle.getMessage(this.getClass(),
143 "ExtractIE.parentModuleName.noSpace"),
144 NbBundle.getMessage(this.getClass(),
"ExtractIE.moduleName.text")));
146 NbBundle.getMessage(this.getClass(),
147 "ExtractIE.parentModuleName.noSpace"), domain));
148 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
150 services.fireModuleDataEvent(
new ModuleDataEvent(
154 private String getURLFromIEBookmarkFile(
AbstractFile fav) {
156 String line, url =
"";
158 while ((line = reader.readLine()) != null) {
161 if (line.startsWith(
"URL")) {
162 url = line.substring(line.indexOf(
"=") + 1);
166 }
catch (IOException ex) {
167 logger.log(Level.WARNING,
"Failed to read from content: " + fav.
getName(), ex);
168 this.addErrorMessage(
169 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
171 }
catch (IndexOutOfBoundsException ex) {
172 logger.log(Level.WARNING,
"Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.
getName(), ex);
173 this.addErrorMessage(
174 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
179 }
catch (IOException ex) {
180 logger.log(Level.WARNING,
"Failed to close reader.", ex);
190 private void getCookie() {
192 List<AbstractFile> cookiesFiles;
194 cookiesFiles = fileManager.
findFiles(dataSource,
"%.txt",
"Cookies");
196 logger.log(Level.WARNING,
"Error getting cookie files for IE");
197 this.addErrorMessage(
198 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
202 if (cookiesFiles.isEmpty()) {
203 logger.log(Level.INFO,
"Didn't find any IE cookies files.");
209 if (context.dataSourceIngestIsCancelled()) {
212 if (cookiesFile.getSize() == 0) {
216 byte[] t =
new byte[(int) cookiesFile.getSize()];
218 final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
220 logger.log(Level.SEVERE,
"Error reading bytes of Internet Explorer cookie.", ex);
221 this.addErrorMessage(
222 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getCookie.errMsg.errReadingIECookie",
223 this.getName(), cookiesFile.getName()));
226 String cookieString =
new String(t);
227 String[] values = cookieString.split(
"\n");
228 String url = values.length > 2 ? values[2] :
"";
229 String value = values.length > 1 ? values[1] :
"";
230 String name = values.length > 0 ? values[0] :
"";
231 Long datetime = cookiesFile.getCrtime();
232 String tempDate = datetime.toString();
233 datetime = Long.valueOf(tempDate);
234 String domain = Util.extractDomain(url);
236 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
238 NbBundle.getMessage(this.getClass(),
239 "ExtractIE.parentModuleName.noSpace"), url));
241 NbBundle.getMessage(this.getClass(),
242 "ExtractIE.parentModuleName.noSpace"), datetime));
244 NbBundle.getMessage(this.getClass(),
245 "ExtractIE.parentModuleName.noSpace"), (name != null) ? name :
""));
247 NbBundle.getMessage(this.getClass(),
248 "ExtractIE.parentModuleName.noSpace"), value));
250 NbBundle.getMessage(this.getClass(),
251 "ExtractIE.parentModuleName.noSpace"),
252 NbBundle.getMessage(this.getClass(),
"ExtractIE.moduleName.text")));
254 NbBundle.getMessage(this.getClass(),
255 "ExtractIE.parentModuleName.noSpace"), domain));
256 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
258 services.fireModuleDataEvent(
new ModuleDataEvent(
265 private void getHistory() {
266 logger.log(Level.INFO,
"Pasco results path: {0}", moduleTempResultsDir);
267 boolean foundHistory =
false;
269 final File pascoRoot = InstalledFileLocator.getDefault().locate(
"pasco2", ExtractIE.class.getPackage().getName(),
false);
270 if (pascoRoot == null) {
271 this.addErrorMessage(
272 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.unableToGetHist", this.getName()));
273 logger.log(Level.SEVERE,
"Error finding pasco program ");
277 final String pascoHome = pascoRoot.getAbsolutePath();
278 logger.log(Level.INFO,
"Pasco2 home: {0}", pascoHome);
280 PASCO_LIB_PATH = pascoHome +
File.separator +
"pasco2.jar" +
File.pathSeparator
281 + pascoHome +
File.separator +
"*";
283 File resultsDir =
new File(moduleTempResultsDir);
288 List<AbstractFile> indexFiles;
290 indexFiles = fileManager.
findFiles(dataSource,
"index.dat");
292 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errGettingHistFiles",
294 logger.log(Level.WARNING,
"Error fetching 'index.data' files for Internet Explorer history.");
298 if (indexFiles.isEmpty()) {
299 String msg = NbBundle.getMessage(this.getClass(),
"ExtractIE.getHistory.errMsg.noHistFiles");
300 logger.log(Level.INFO, msg);
306 String indexFileName;
313 indexFileName =
"index" + Integer.toString((
int) indexFile.getId()) +
".dat";
315 temps = RAImageIngestModule.getRATempPath(currentCase,
"IE") +
File.separator + indexFileName;
317 if (context.dataSourceIngestIsCancelled()) {
321 ContentUtils.writeToFile(indexFile, datFile);
322 }
catch (IOException e) {
323 logger.log(Level.SEVERE,
"Error while trying to write index.dat file " + datFile.getAbsolutePath(), e);
324 this.addErrorMessage(
325 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
326 datFile.getAbsolutePath()));
330 String filename =
"pasco2Result." + indexFile.getId() +
".txt";
331 boolean bPascProcSuccess = executePasco(temps, filename);
332 if (context.dataSourceIngestIsCancelled()) {
338 if (bPascProcSuccess) {
339 parsePascoOutput(indexFile, filename);
345 logger.log(Level.WARNING,
"pasco execution failed on: {0}",
this.getName());
346 this.addErrorMessage(
347 NbBundle.getMessage(
this.getClass(),
"ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
352 services.fireModuleDataEvent(
new ModuleDataEvent(
364 private boolean executePasco(String indexFilePath, String outputFileName) {
365 boolean success =
true;
367 final String outputFileFullPath = moduleTempResultsDir +
File.separator + outputFileName;
368 final String errFileFullPath = moduleTempResultsDir +
File.separator + outputFileName +
".err";
369 logger.log(Level.INFO,
"Writing pasco results to: {0}", outputFileFullPath);
370 List<String> commandLine =
new ArrayList<>();
371 commandLine.add(JAVA_PATH);
372 commandLine.add(
"-cp");
373 commandLine.add(PASCO_LIB_PATH);
374 commandLine.add(
"isi.pasco2.Main");
375 commandLine.add(
"-T");
376 commandLine.add(
"history");
377 commandLine.add(indexFilePath);
378 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
379 processBuilder.redirectOutput(
new File(outputFileFullPath));
380 processBuilder.redirectError(
new File(errFileFullPath));
381 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context));
383 }
catch (IOException ex) {
385 logger.log(Level.SEVERE,
"Unable to execute Pasco to process Internet Explorer web history.", ex);
397 private void parsePascoOutput(
AbstractFile origFile, String pascoOutputFileName) {
399 String fnAbs = moduleTempResultsDir +
File.separator + pascoOutputFileName;
402 if (file.
exists() ==
false) {
403 this.addErrorMessage(
404 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
406 logger.log(Level.WARNING,
"Pasco Output not found: {0}", file.getPath());
412 if (file.length() == 0) {
418 fileScanner =
new Scanner(
new FileInputStream(file.
toString()));
419 }
catch (FileNotFoundException ex) {
420 this.addErrorMessage(
421 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
423 logger.log(Level.WARNING,
"Unable to find the Pasco file at " + file.getPath(), ex);
428 Set<String> reportedUserAccounts =
new HashSet<String>();
430 while (fileScanner.hasNext()) {
431 String line = fileScanner.nextLine();
432 if (!line.startsWith(
"URL")) {
436 String[] lineBuff = line.split(
"\\t");
438 if (lineBuff.length < 4) {
439 logger.log(Level.INFO,
"Found unrecognized IE history format.");
443 String ddtime = lineBuff[2];
444 String actime = lineBuff[3];
445 Long ftime = (long) 0;
454 if (lineBuff[1].contains(
"@")) {
455 String url[] = lineBuff[1].split(
"@", 2);
457 user = user.replace(
"Visited:",
"");
458 user = user.replace(
":Host:",
"");
459 user = user.replaceAll(
"(:)(.*?)(:)",
"");
462 realurl = realurl.replace(
"Visited:",
"");
463 realurl = realurl.replaceAll(
":(.*?):",
"");
464 realurl = realurl.replace(
":Host:",
"");
465 realurl = realurl.trim();
468 realurl = lineBuff[1].trim();
471 domain = Util.extractDomain(realurl);
473 if (!ddtime.isEmpty()) {
474 ddtime = ddtime.replace(
"T",
" ");
475 ddtime = ddtime.substring(ddtime.length() - 5);
478 if (!actime.isEmpty()) {
480 Long epochtime = dateFormatter.parse(actime).getTime();
481 ftime = epochtime.longValue();
482 ftime = ftime / 1000;
483 }
catch (ParseException e) {
484 this.addErrorMessage(
485 NbBundle.getMessage(
this.getClass(),
"ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
487 logger.log(Level.SEVERE,
"Error parsing Pasco results.", e);
493 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
495 NbBundle.getMessage(this.getClass(),
496 "ExtractIE.parentModuleName.noSpace"), realurl));
500 NbBundle.getMessage(this.getClass(),
501 "ExtractIE.parentModuleName.noSpace"), ftime));
503 NbBundle.getMessage(this.getClass(),
504 "ExtractIE.parentModuleName.noSpace"),
""));
507 NbBundle.getMessage(this.getClass(),
508 "ExtractIE.parentModuleName.noSpace"),
509 NbBundle.getMessage(this.getClass(),
510 "ExtractIE.moduleName.text")));
512 NbBundle.getMessage(this.getClass(),
513 "ExtractIE.parentModuleName.noSpace"), domain));
515 NbBundle.getMessage(this.getClass(),
516 "ExtractIE.parentModuleName.noSpace"), user));
519 if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
522 NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), user));
523 reportedUserAccounts.add(user);
526 logger.log(Level.SEVERE,
"Error writing Internet Explorer web history artifact to the blackboard.", ex);
void addAttributes(Collection< BlackboardAttribute > attributes)
synchronized List< AbstractFile > findFiles(Content dataSource, String fileName)
void addAttribute(BlackboardAttribute attr)
BlackboardArtifact newArtifact(int artifactTypeID)
String toString(boolean preserveState)