23 package org.sleuthkit.autopsy.recentactivity;
25 import com.google.gson.JsonArray;
26 import com.google.gson.JsonElement;
27 import com.google.gson.JsonIOException;
28 import com.google.gson.JsonObject;
29 import com.google.gson.JsonParser;
30 import com.google.gson.JsonSyntaxException;
31 import org.openide.util.NbBundle;
33 import java.util.logging.Level;
36 import java.io.FileNotFoundException;
37 import java.io.FileReader;
38 import java.io.IOException;
39 import org.apache.commons.io.FilenameUtils;
40 import org.openide.util.NbBundle.Messages;
51 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
53 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
55 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
58 import org.
sleuthkit.datamodel.blackboardutils.WebBrowserArtifactsHelper;
63 class Chrome
extends Extract {
65 private static final String HISTORY_QUERY =
"SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
66 +
"last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url";
67 private static final String COOKIE_QUERY =
"SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies";
68 private static final String DOWNLOAD_QUERY =
"SELECT full_path, url, start_time, received_bytes FROM downloads";
69 private static final String DOWNLOAD_QUERY_V30 =
"SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id";
70 private static final String LOGIN_QUERY =
"SELECT origin_url, username_value, date_created, signon_realm from logins";
71 private static final String AUTOFILL_QUERY =
"SELECT name, value, count, date_created " +
72 " FROM autofill, autofill_dates " +
73 " WHERE autofill.pair_id = autofill_dates.pair_id"
75 private static final String AUTOFILL_QUERY_V8X =
"SELECT name, value, count, date_created, date_last_used from autofill";
76 private static final String WEBFORM_ADDRESS_QUERY =
"SELECT first_name, middle_name, last_name, address_line_1, address_line_2, city, state, zipcode, country_code, number, email, date_modified " +
77 " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
78 " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
80 private static final String WEBFORM_ADDRESS_QUERY_V8X =
"SELECT first_name, middle_name, last_name, full_name, street_address, city, state, zipcode, country_code, number, email, date_modified, use_date, use_count" +
81 " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
82 " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
83 private final Logger logger = Logger.getLogger(this.getClass().getName());
84 private Content dataSource;
85 private IngestJobContext context;
88 "Progress_Message_Chrome_History=Chrome History",
89 "Progress_Message_Chrome_Bookmarks=Chrome Bookmarks",
90 "Progress_Message_Chrome_Cookies=Chrome Cookies",
91 "Progress_Message_Chrome_Downloads=Chrome Downloads",
92 "Progress_Message_Chrome_FormHistory=Chrome Form History",
93 "Progress_Message_Chrome_AutoFill=Chrome Auto Fill",
94 "Progress_Message_Chrome_Logins=Chrome Logins",
95 "Progress_Message_Chrome_Cache=Chrome Cache",
99 moduleName = NbBundle.getMessage(Chrome.class,
"Chrome.moduleName");
103 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
104 this.dataSource = dataSource;
105 this.context = context;
108 progressBar.progress(Bundle.Progress_Message_Chrome_History());
110 if (context.dataSourceIngestIsCancelled()) {
114 progressBar.progress(Bundle.Progress_Message_Chrome_Bookmarks());
116 if (context.dataSourceIngestIsCancelled()) {
120 progressBar.progress(Bundle.Progress_Message_Chrome_Cookies());
122 if (context.dataSourceIngestIsCancelled()) {
126 progressBar.progress(Bundle.Progress_Message_Chrome_Logins());
128 if (context.dataSourceIngestIsCancelled()) {
132 progressBar.progress(Bundle.Progress_Message_Chrome_AutoFill());
134 if (context.dataSourceIngestIsCancelled()) {
138 progressBar.progress(Bundle.Progress_Message_Chrome_Downloads());
140 if (context.dataSourceIngestIsCancelled()) {
144 progressBar.progress(Bundle.Progress_Message_Chrome_Cache());
145 ChromeCacheExtractor chromeCacheExtractor =
new ChromeCacheExtractor(dataSource, context, progressBar);
146 chromeCacheExtractor.processCaches();
152 private void getHistory() {
153 FileManager fileManager = currentCase.getServices().getFileManager();
154 List<AbstractFile> historyFiles;
156 historyFiles = fileManager.findFiles(dataSource,
"History",
"Chrome");
157 }
catch (TskCoreException ex) {
158 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.errGettingFiles");
159 logger.log(Level.SEVERE, msg, ex);
160 this.addErrorMessage(this.getName() +
": " + msg);
165 List<AbstractFile> allocatedHistoryFiles =
new ArrayList<>();
166 for (AbstractFile historyFile : historyFiles) {
167 if (historyFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
168 allocatedHistoryFiles.add(historyFile);
173 if (allocatedHistoryFiles.isEmpty()) {
174 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.couldntFindAnyFiles");
175 logger.log(Level.INFO, msg);
180 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
182 while (j < historyFiles.size()) {
183 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + historyFiles.get(j).getName() + j +
".db";
184 final AbstractFile historyFile = historyFiles.get(j++);
185 if (historyFile.getSize() == 0) {
189 ContentUtils.writeToFile(historyFile,
new File(temps), context::dataSourceIngestIsCancelled);
190 }
catch (ReadContentInputStreamException ex) {
191 logger.log(Level.WARNING, String.format(
"Error reading Chrome web history artifacts file '%s' (id=%d).",
192 historyFile.getName(), historyFile.getId()), ex);
193 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
194 this.getName(), historyFile.getName()));
196 }
catch (IOException ex) {
197 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).",
198 temps, historyFile.getName(), historyFile.getId()), ex);
199 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
200 this.getName(), historyFile.getName()));
203 File dbFile =
new File(temps);
204 if (context.dataSourceIngestIsCancelled()) {
208 List<HashMap<String, Object>> tempList;
209 tempList = this.dbConnect(temps, HISTORY_QUERY);
210 logger.log(Level.INFO,
"{0}- Now getting history from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
211 for (HashMap<String, Object> result : tempList) {
212 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
213 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
214 RecentActivityExtracterModuleFactory.getModuleName(),
215 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
216 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
217 RecentActivityExtracterModuleFactory.getModuleName(),
218 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
219 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
220 RecentActivityExtracterModuleFactory.getModuleName(),
221 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
222 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
223 RecentActivityExtracterModuleFactory.getModuleName(),
224 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
225 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
226 RecentActivityExtracterModuleFactory.getModuleName(),
227 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
228 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
229 RecentActivityExtracterModuleFactory.getModuleName(),
230 (NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
232 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
234 bbartifacts.add(bbart);
240 if( !bbartifacts.isEmpty() ){
241 postArtifacts(bbartifacts);
248 private void getBookmark() {
249 FileManager fileManager = currentCase.getServices().getFileManager();
250 List<AbstractFile> bookmarkFiles;
252 bookmarkFiles = fileManager.findFiles(dataSource,
"Bookmarks",
"Chrome");
253 }
catch (TskCoreException ex) {
254 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getBookmark.errMsg.errGettingFiles");
255 logger.log(Level.SEVERE, msg, ex);
256 this.addErrorMessage(this.getName() +
": " + msg);
260 if (bookmarkFiles.isEmpty()) {
261 logger.log(Level.INFO,
"Didn't find any Chrome bookmark files.");
266 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
269 while (j < bookmarkFiles.size()) {
270 AbstractFile bookmarkFile = bookmarkFiles.get(j++);
271 if (bookmarkFile.getSize() == 0) {
274 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + bookmarkFile.getName() + j +
".db";
276 ContentUtils.writeToFile(bookmarkFile,
new File(temps), context::dataSourceIngestIsCancelled);
277 }
catch (ReadContentInputStreamException ex) {
278 logger.log(Level.WARNING, String.format(
"Error reading Chrome bookmark artifacts file '%s' (id=%d).",
279 bookmarkFile.getName(), bookmarkFile.getId()), ex);
280 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
281 this.getName(), bookmarkFile.getName()));
283 }
catch (IOException ex) {
284 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).",
285 temps, bookmarkFile.getName(), bookmarkFile.getId()), ex);
286 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
287 this.getName(), bookmarkFile.getName()));
291 logger.log(Level.INFO,
"{0}- Now getting Bookmarks from {1}",
new Object[]{moduleName, temps});
292 File dbFile =
new File(temps);
293 if (context.dataSourceIngestIsCancelled()) {
298 FileReader tempReader;
300 tempReader =
new FileReader(temps);
301 }
catch (FileNotFoundException ex) {
302 logger.log(Level.WARNING,
"Error while trying to read into the Bookmarks for Chrome.", ex);
306 final JsonParser parser =
new JsonParser();
307 JsonElement jsonElement;
308 JsonObject jElement, jRoot, jBookmark;
309 JsonArray jBookmarkArray;
312 jsonElement = parser.parse(tempReader);
313 jElement = jsonElement.getAsJsonObject();
314 jRoot = jElement.get(
"roots").getAsJsonObject();
315 jBookmark = jRoot.get(
"bookmark_bar").getAsJsonObject();
316 jBookmarkArray = jBookmark.getAsJsonArray(
"children");
317 }
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
318 logger.log(Level.WARNING,
"Error parsing Json from Chrome Bookmark.", ex);
319 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile3",
320 this.getName(), bookmarkFile.getName()));
324 for (JsonElement result : jBookmarkArray) {
325 JsonObject address = result.getAsJsonObject();
326 if (address == null) {
329 JsonElement urlEl = address.get(
"url");
332 url = urlEl.getAsString();
337 JsonElement nameEl = address.get(
"name");
338 if (nameEl != null) {
339 name = nameEl.getAsString();
344 JsonElement dateEl = address.get(
"date_added");
345 if (dateEl != null) {
346 date = dateEl.getAsLong();
348 date = Long.valueOf(0);
350 String domain = NetworkUtils.extractDomain(url);
352 BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
353 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
355 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
356 RecentActivityExtracterModuleFactory.getModuleName(), url));
357 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
358 RecentActivityExtracterModuleFactory.getModuleName(), name));
359 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
360 RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf(
"11644473600")));
361 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
362 RecentActivityExtracterModuleFactory.getModuleName(),
363 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
364 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
365 RecentActivityExtracterModuleFactory.getModuleName(), domain));
366 bbart.addAttributes(bbattributes);
368 bbartifacts.add(bbart);
369 }
catch (TskCoreException ex) {
370 logger.log(Level.SEVERE,
"Error while trying to insert Chrome bookmark artifact{0}", ex);
371 this.addErrorMessage(
372 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile4",
373 this.getName(), bookmarkFile.getName()));
376 postArtifacts(bbartifacts);
384 private void getCookie() {
386 FileManager fileManager = currentCase.getServices().getFileManager();
387 List<AbstractFile> cookiesFiles;
389 cookiesFiles = fileManager.findFiles(dataSource,
"Cookies",
"Chrome");
390 }
catch (TskCoreException ex) {
391 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getCookie.errMsg.errGettingFiles");
392 logger.log(Level.SEVERE, msg, ex);
393 this.addErrorMessage(this.getName() +
": " + msg);
397 if (cookiesFiles.isEmpty()) {
398 logger.log(Level.INFO,
"Didn't find any Chrome cookies files.");
403 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
405 while (j < cookiesFiles.size()) {
406 AbstractFile cookiesFile = cookiesFiles.get(j++);
407 if (cookiesFile.getSize() == 0) {
410 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + cookiesFile.getName() + j +
".db";
412 ContentUtils.writeToFile(cookiesFile,
new File(temps), context::dataSourceIngestIsCancelled);
413 }
catch (ReadContentInputStreamException ex) {
414 logger.log(Level.WARNING, String.format(
"Error reading Chrome cookie artifacts file '%s' (id=%d).",
415 cookiesFile.getName(), cookiesFile.getId()), ex);
416 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile",
417 this.getName(), cookiesFile.getName()));
419 }
catch (IOException ex) {
420 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).",
421 temps, cookiesFile.getName(), cookiesFile.getId()), ex);
422 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile",
423 this.getName(), cookiesFile.getName()));
426 File dbFile =
new File(temps);
427 if (context.dataSourceIngestIsCancelled()) {
432 List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
433 logger.log(Level.INFO,
"{0}- Now getting cookies from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
434 for (HashMap<String, Object> result : tempList) {
435 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
436 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
437 RecentActivityExtracterModuleFactory.getModuleName(),
438 ((result.get(
"host_key").toString() != null) ? result.get(
"host_key").toString() :
"")));
439 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
440 RecentActivityExtracterModuleFactory.getModuleName(),
441 (Long.valueOf(result.get(
"last_access_utc").toString()) / 1000000) - Long.valueOf(
"11644473600")));
443 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
444 RecentActivityExtracterModuleFactory.getModuleName(),
445 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
446 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
447 RecentActivityExtracterModuleFactory.getModuleName(),
448 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
449 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
450 RecentActivityExtracterModuleFactory.getModuleName(),
451 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
452 String domain = result.get(
"host_key").toString();
453 domain = domain.replaceFirst(
"^\\.+(?!$)",
"");
454 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
455 RecentActivityExtracterModuleFactory.getModuleName(), domain));
457 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
459 bbartifacts.add(bbart);
466 if( !bbartifacts.isEmpty() ) {
467 postArtifacts(bbartifacts);
474 private void getDownload() {
475 FileManager fileManager = currentCase.getServices().getFileManager();
476 List<AbstractFile> downloadFiles;
478 downloadFiles = fileManager.findFiles(dataSource,
"History",
"Chrome");
479 }
catch (TskCoreException ex) {
480 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getDownload.errMsg.errGettingFiles");
481 logger.log(Level.SEVERE, msg, ex);
482 this.addErrorMessage(this.getName() +
": " + msg);
486 if (downloadFiles.isEmpty()) {
487 logger.log(Level.INFO,
"Didn't find any Chrome download files.");
492 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
494 while (j < downloadFiles.size()) {
495 AbstractFile downloadFile = downloadFiles.get(j++);
496 if (downloadFile.getSize() == 0) {
499 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + downloadFile.getName() + j +
".db";
501 ContentUtils.writeToFile(downloadFile,
new File(temps), context::dataSourceIngestIsCancelled);
502 }
catch (ReadContentInputStreamException ex) {
503 logger.log(Level.WARNING, String.format(
"Error reading Chrome download artifacts file '%s' (id=%d).",
504 downloadFile.getName(), downloadFile.getId()), ex);
505 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
506 this.getName(), downloadFile.getName()));
508 }
catch (IOException ex) {
509 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).",
510 temps, downloadFile.getName(), downloadFile.getId()), ex);
511 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
512 this.getName(), downloadFile.getName()));
515 File dbFile =
new File(temps);
516 if (context.dataSourceIngestIsCancelled()) {
521 List<HashMap<String, Object>> tempList;
523 if (isChromePreVersion30(temps)) {
524 tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
526 tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
529 logger.log(Level.INFO,
"{0}- Now getting downloads from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
530 for (HashMap<String, Object> result : tempList) {
531 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
532 String fullPath = result.get(
"full_path").toString();
533 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
534 RecentActivityExtracterModuleFactory.getModuleName(), fullPath));
535 long pathID = Util.findID(dataSource, fullPath);
537 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
538 NbBundle.getMessage(
this.getClass(),
539 "Chrome.parentModuleName"), pathID));
541 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
542 RecentActivityExtracterModuleFactory.getModuleName(),
543 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
545 Long time = (Long.valueOf(result.get(
"start_time").toString()) / 1000000) - Long.valueOf(
"11644473600");
549 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
550 RecentActivityExtracterModuleFactory.getModuleName(), time));
551 String domain = NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"");
552 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
553 RecentActivityExtracterModuleFactory.getModuleName(), domain));
554 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
555 RecentActivityExtracterModuleFactory.getModuleName(),
556 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
558 BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
559 if (webDownloadArtifact != null) {
560 bbartifacts.add(webDownloadArtifact);
564 String normalizedFullPath = FilenameUtils.normalize(fullPath,
true);
565 for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(normalizedFullPath), FilenameUtils.getPath(normalizedFullPath))) {
566 BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
567 associatedObjectArtifact.addAttribute(
568 new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
569 RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
571 bbartifacts.add(associatedObjectArtifact);
574 }
catch (TskCoreException ex) {
575 logger.log(Level.SEVERE, String.format(
"Error creating associated object artifact for file '%s'", fullPath), ex);
583 if( !bbartifacts.isEmpty() ) {
584 postArtifacts(bbartifacts);
591 private void getLogins() {
593 FileManager fileManager = currentCase.getServices().getFileManager();
594 List<AbstractFile> loginDataFiles;
596 loginDataFiles = fileManager.findFiles(dataSource,
"Login Data",
"Chrome");
597 }
catch (TskCoreException ex) {
598 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getLogin.errMsg.errGettingFiles");
599 logger.log(Level.SEVERE, msg, ex);
600 this.addErrorMessage(this.getName() +
": " + msg);
604 if (loginDataFiles.isEmpty()) {
605 logger.log(Level.INFO,
"Didn't find any Chrome Login Data files.");
610 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
612 while (j < loginDataFiles.size()) {
613 AbstractFile loginDataFile = loginDataFiles.get(j++);
614 if (loginDataFile.getSize() == 0) {
617 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + loginDataFile.getName() + j +
".db";
619 ContentUtils.writeToFile(loginDataFile,
new File(temps), context::dataSourceIngestIsCancelled);
620 }
catch (ReadContentInputStreamException ex) {
621 logger.log(Level.WARNING, String.format(
"Error reading Chrome login artifacts file '%s' (id=%d).",
622 loginDataFile.getName(), loginDataFile.getId()), ex);
623 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
624 this.getName(), loginDataFile.getName()));
626 }
catch (IOException ex) {
627 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).",
628 temps, loginDataFile.getName(), loginDataFile.getId()), ex);
629 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
630 this.getName(), loginDataFile.getName()));
633 File dbFile =
new File(temps);
634 if (context.dataSourceIngestIsCancelled()) {
638 List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
639 logger.log(Level.INFO,
"{0}- Now getting login information from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
640 for (HashMap<String, Object> result : tempList) {
641 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
643 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
644 RecentActivityExtracterModuleFactory.getModuleName(),
645 ((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
"")));
648 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
649 RecentActivityExtracterModuleFactory.getModuleName(),
650 (Long.valueOf(result.get(
"date_created").toString()) / 1000000) - Long.valueOf(
"11644473600")));
652 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
653 RecentActivityExtracterModuleFactory.getModuleName(),
654 (NetworkUtils.extractDomain((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
""))));
656 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
657 RecentActivityExtracterModuleFactory.getModuleName(),
658 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
660 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
661 RecentActivityExtracterModuleFactory.getModuleName(),
662 ((result.get(
"signon_realm").toString() != null) ? result.get(
"signon_realm").toString() :
"")));
664 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes);
666 bbartifacts.add(bbart);
673 if( !bbartifacts.isEmpty() ) {
674 postArtifacts(bbartifacts);
682 private void getAutofill() {
684 FileManager fileManager = currentCase.getServices().getFileManager();
685 List<AbstractFile> webDataFiles;
687 webDataFiles = fileManager.findFiles(dataSource,
"Web Data",
"Chrome");
688 }
catch (TskCoreException ex) {
689 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getAutofills.errMsg.errGettingFiles");
690 logger.log(Level.SEVERE, msg, ex);
691 this.addErrorMessage(this.getName() +
": " + msg);
695 if (webDataFiles.isEmpty()) {
696 logger.log(Level.INFO,
"Didn't find any Chrome Web Data files.");
701 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
703 while (j < webDataFiles.size()) {
704 AbstractFile webDataFile = webDataFiles.get(j++);
705 if (webDataFile.getSize() == 0) {
708 String tempFilePath = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + webDataFile.getName() + j +
".db";
710 ContentUtils.writeToFile(webDataFile,
new File(tempFilePath), context::dataSourceIngestIsCancelled);
711 }
catch (ReadContentInputStreamException ex) {
712 logger.log(Level.WARNING, String.format(
"Error reading Chrome Autofill artifacts file '%s' (id=%d).",
713 webDataFile.getName(), webDataFile.getId()), ex);
714 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getAutofill.errMsg.errAnalyzingFiles",
715 this.getName(), webDataFile.getName()));
717 }
catch (IOException ex) {
718 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome Web data file '%s' (id=%d).",
719 tempFilePath, webDataFile.getName(), webDataFile.getId()), ex);
720 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
721 this.getName(), webDataFile.getName()));
724 File dbFile =
new File(tempFilePath);
725 if (context.dataSourceIngestIsCancelled()) {
731 boolean isSchemaV8X = Util.checkColumn(
"date_created",
"autofill", tempFilePath);
734 bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X));
737 getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X);
738 }
catch (NoCurrentCaseException | TskCoreException | Blackboard.BlackboardException ex) {
739 logger.log(Level.SEVERE, String.format(
"Error adding artifacts to the case database "
740 +
"for chrome file %s [objId=%d]", webDataFile.getName(), webDataFile.getId()), ex);
746 if( !bbartifacts.isEmpty() ){
747 postArtifacts(bbartifacts);
760 private Collection<BlackboardArtifact> getFormAutofillArtifacts (AbstractFile webDataFile, String dbFilePath ,
boolean isSchemaV8X ) {
762 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
765 String autoFillquery = (isSchemaV8X) ? AUTOFILL_QUERY_V8X
768 List<HashMap<String, Object>> autofills = this.dbConnect(dbFilePath, autoFillquery);
769 logger.log(Level.INFO,
"{0}- Now getting Autofill information from {1} with {2}artifacts identified.",
new Object[]{moduleName, dbFilePath, autofills.size()});
770 for (HashMap<String, Object> result : autofills) {
771 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
774 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
775 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
776 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
778 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
779 RecentActivityExtracterModuleFactory.getModuleName(),
780 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
782 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
783 RecentActivityExtracterModuleFactory.getModuleName(),
784 (Integer.valueOf(result.get(
"count").toString()))));
786 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
787 RecentActivityExtracterModuleFactory.getModuleName(),
788 Long.valueOf(result.get(
"date_created").toString())));
792 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
793 RecentActivityExtracterModuleFactory.getModuleName(),
794 Long.valueOf(result.get(
"date_last_used").toString())));
798 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, webDataFile, bbattributes);
800 bbartifacts.add(bbart);
817 private void getFormAddressArtifacts (AbstractFile webDataFile, String dbFilePath ,
boolean isSchemaV8X )
throws NoCurrentCaseException,
818 TskCoreException, Blackboard.BlackboardException {
820 String webformAddressQuery = (isSchemaV8X) ? WEBFORM_ADDRESS_QUERY_V8X
821 : WEBFORM_ADDRESS_QUERY;
824 WebBrowserArtifactsHelper helper =
new WebBrowserArtifactsHelper(
825 Case.getCurrentCaseThrows().getSleuthkitCase(),
826 NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"),
831 List<HashMap<String, Object>> addresses = this.dbConnect(dbFilePath, webformAddressQuery);
832 logger.log(Level.INFO,
"{0}- Now getting Web form addresses from {1} with {2}artifacts identified.",
new Object[]{moduleName, dbFilePath, addresses.size()});
833 for (HashMap<String, Object> result : addresses) {
836 String first_name = result.get(
"first_name").toString() != null ? result.get(
"first_name").toString() :
"";
837 String middle_name = result.get(
"middle_name").toString() != null ? result.get(
"middle_name").toString() :
"";
838 String last_name = result.get(
"last_name").toString() != null ? result.get(
"last_name").toString() :
"";
841 String email_Addr = result.get(
"email").toString() != null ? result.get(
"email").toString() :
"";
842 String phone_number = result.get(
"number").toString() != null ? result.get(
"number").toString() :
"";
845 String city = result.get(
"city").toString() != null ? result.get(
"city").toString() :
"";
846 String state = result.get(
"state").toString() != null ? result.get(
"state").toString() :
"";
847 String zipcode = result.get(
"zipcode").toString() != null ? result.get(
"zipcode").toString() :
"";
848 String country_code = result.get(
"country_code").toString() != null ? result.get(
"country_code").toString() :
"";
851 String full_name =
"";
852 String street_address =
"";
853 long date_modified = 0;
858 full_name = result.get(
"full_name").toString() != null ? result.get(
"full_name").toString() :
"";
859 street_address = result.get(
"street_address").toString() != null ? result.get(
"street_address").toString() :
"";
860 date_modified = result.get(
"date_modified").toString() != null ? Long.valueOf(result.get(
"date_modified").toString()) : 0;
861 use_count = result.get(
"use_count").toString() != null ? Integer.valueOf(result.get(
"use_count").toString()) : 0;
862 use_date = result.get(
"use_date").toString() != null ? Long.valueOf(result.get(
"use_date").toString()) : 0;
864 String address_line_1 = result.get(
"address_line_1").toString() != null ? result.get(
"street_address").toString() :
"";
865 String address_line_2 = result.get(
"address_line_2").toString() != null ? result.get(
"address_line_2").toString() :
"";
866 street_address = String.join(
" ", address_line_1, address_line_2);
870 if (full_name == null || full_name.isEmpty()) {
871 full_name = String.join(
" ", first_name, middle_name, last_name);
874 String locationAddress = String.join(
", ", street_address, city, state, zipcode, country_code);
876 List<BlackboardAttribute> otherAttributes =
new ArrayList<>();
877 if (date_modified > 0) {
878 otherAttributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED,
879 RecentActivityExtracterModuleFactory.getModuleName(),
883 helper.addWebFormAddress(
884 full_name, email_Addr, phone_number,
885 locationAddress, 0, use_date,
886 use_count, otherAttributes);
890 private boolean isChromePreVersion30(String temps) {
891 String query =
"PRAGMA table_info(downloads)";
892 List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
893 for (HashMap<String, Object> col : columns) {
894 if (col.get(
"name").equals(
"url")) {