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;
62 class Chrome
extends Extract {
64 private static final String HISTORY_QUERY =
"SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
65 +
"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";
66 private static final String COOKIE_QUERY =
"SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies";
67 private static final String DOWNLOAD_QUERY =
"SELECT full_path, url, start_time, received_bytes FROM downloads";
68 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";
69 private static final String LOGIN_QUERY =
"SELECT origin_url, username_value, date_created, signon_realm from logins";
70 private static final String AUTOFILL_QUERY =
"SELECT name, value, count, date_created " +
71 " FROM autofill, autofill_dates " +
72 " WHERE autofill.pair_id = autofill_dates.pair_id"
74 private static final String AUTOFILL_QUERY_V8X =
"SELECT name, value, count, date_created, date_last_used from autofill";
75 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 " +
76 " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
77 " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
79 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" +
80 " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
81 " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
82 private final Logger logger = Logger.getLogger(this.getClass().getName());
83 private Content dataSource;
84 private IngestJobContext context;
87 "Progress_Message_Chrome_History=Chrome History",
88 "Progress_Message_Chrome_Bookmarks=Chrome Bookmarks",
89 "Progress_Message_Chrome_Cookies=Chrome Cookies",
90 "Progress_Message_Chrome_Downloads=Chrome Downloads",
91 "Progress_Message_Chrome_FormHistory=Chrome Form History",
92 "Progress_Message_Chrome_AutoFill=Chrome Auto Fill",
93 "Progress_Message_Chrome_Logins=Chrome Logins",
94 "Progress_Message_Chrome_Cache=Chrome Cache",
98 moduleName = NbBundle.getMessage(Chrome.class,
"Chrome.moduleName");
102 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
103 this.dataSource = dataSource;
104 this.context = context;
107 progressBar.progress(Bundle.Progress_Message_Chrome_History());
109 if (context.dataSourceIngestIsCancelled()) {
113 progressBar.progress(Bundle.Progress_Message_Chrome_Bookmarks());
115 if (context.dataSourceIngestIsCancelled()) {
119 progressBar.progress(Bundle.Progress_Message_Chrome_Cookies());
121 if (context.dataSourceIngestIsCancelled()) {
125 progressBar.progress(Bundle.Progress_Message_Chrome_Logins());
127 if (context.dataSourceIngestIsCancelled()) {
131 progressBar.progress(Bundle.Progress_Message_Chrome_AutoFill());
133 if (context.dataSourceIngestIsCancelled()) {
137 progressBar.progress(Bundle.Progress_Message_Chrome_Downloads());
139 if (context.dataSourceIngestIsCancelled()) {
143 progressBar.progress(Bundle.Progress_Message_Chrome_Cache());
144 ChromeCacheExtractor chromeCacheExtractor =
new ChromeCacheExtractor(dataSource, context, progressBar);
145 chromeCacheExtractor.getCaches();
151 private void getHistory() {
152 FileManager fileManager = currentCase.getServices().getFileManager();
153 List<AbstractFile> historyFiles;
155 historyFiles = fileManager.findFiles(dataSource,
"History",
"Chrome");
156 }
catch (TskCoreException ex) {
157 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.errGettingFiles");
158 logger.log(Level.SEVERE, msg, ex);
159 this.addErrorMessage(this.getName() +
": " + msg);
164 List<AbstractFile> allocatedHistoryFiles =
new ArrayList<>();
165 for (AbstractFile historyFile : historyFiles) {
166 if (historyFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
167 allocatedHistoryFiles.add(historyFile);
172 if (allocatedHistoryFiles.isEmpty()) {
173 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.couldntFindAnyFiles");
174 logger.log(Level.INFO, msg);
179 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
181 while (j < historyFiles.size()) {
182 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + historyFiles.get(j).getName() + j +
".db";
183 final AbstractFile historyFile = historyFiles.get(j++);
184 if (historyFile.getSize() == 0) {
188 ContentUtils.writeToFile(historyFile,
new File(temps), context::dataSourceIngestIsCancelled);
189 }
catch (ReadContentInputStreamException ex) {
190 logger.log(Level.WARNING, String.format(
"Error reading Chrome web history artifacts file '%s' (id=%d).",
191 historyFile.getName(), historyFile.getId()), ex);
192 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
193 this.getName(), historyFile.getName()));
195 }
catch (IOException ex) {
196 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).",
197 temps, historyFile.getName(), historyFile.getId()), ex);
198 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
199 this.getName(), historyFile.getName()));
202 File dbFile =
new File(temps);
203 if (context.dataSourceIngestIsCancelled()) {
207 List<HashMap<String, Object>> tempList;
208 tempList = this.dbConnect(temps, HISTORY_QUERY);
209 logger.log(Level.INFO,
"{0}- Now getting history from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
210 for (HashMap<String, Object> result : tempList) {
211 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
212 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
213 RecentActivityExtracterModuleFactory.getModuleName(),
214 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
215 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
216 RecentActivityExtracterModuleFactory.getModuleName(),
217 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
218 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
219 RecentActivityExtracterModuleFactory.getModuleName(),
220 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
221 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
222 RecentActivityExtracterModuleFactory.getModuleName(),
223 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
224 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
225 RecentActivityExtracterModuleFactory.getModuleName(),
226 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
227 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
228 RecentActivityExtracterModuleFactory.getModuleName(),
229 (NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
231 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
233 bbartifacts.add(bbart);
239 if( !bbartifacts.isEmpty() ){
240 postArtifacts(bbartifacts);
247 private void getBookmark() {
248 FileManager fileManager = currentCase.getServices().getFileManager();
249 List<AbstractFile> bookmarkFiles;
251 bookmarkFiles = fileManager.findFiles(dataSource,
"Bookmarks",
"Chrome");
252 }
catch (TskCoreException ex) {
253 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getBookmark.errMsg.errGettingFiles");
254 logger.log(Level.SEVERE, msg, ex);
255 this.addErrorMessage(this.getName() +
": " + msg);
259 if (bookmarkFiles.isEmpty()) {
260 logger.log(Level.INFO,
"Didn't find any Chrome bookmark files.");
265 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
268 while (j < bookmarkFiles.size()) {
269 AbstractFile bookmarkFile = bookmarkFiles.get(j++);
270 if (bookmarkFile.getSize() == 0) {
273 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + bookmarkFile.getName() + j +
".db";
275 ContentUtils.writeToFile(bookmarkFile,
new File(temps), context::dataSourceIngestIsCancelled);
276 }
catch (ReadContentInputStreamException ex) {
277 logger.log(Level.WARNING, String.format(
"Error reading Chrome bookmark artifacts file '%s' (id=%d).",
278 bookmarkFile.getName(), bookmarkFile.getId()), ex);
279 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
280 this.getName(), bookmarkFile.getName()));
282 }
catch (IOException ex) {
283 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).",
284 temps, bookmarkFile.getName(), bookmarkFile.getId()), ex);
285 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
286 this.getName(), bookmarkFile.getName()));
290 logger.log(Level.INFO,
"{0}- Now getting Bookmarks from {1}",
new Object[]{moduleName, temps});
291 File dbFile =
new File(temps);
292 if (context.dataSourceIngestIsCancelled()) {
297 FileReader tempReader;
299 tempReader =
new FileReader(temps);
300 }
catch (FileNotFoundException ex) {
301 logger.log(Level.WARNING,
"Error while trying to read into the Bookmarks for Chrome.", ex);
305 final JsonParser parser =
new JsonParser();
306 JsonElement jsonElement;
307 JsonObject jElement, jRoot, jBookmark;
308 JsonArray jBookmarkArray;
311 jsonElement = parser.parse(tempReader);
312 jElement = jsonElement.getAsJsonObject();
313 jRoot = jElement.get(
"roots").getAsJsonObject();
314 jBookmark = jRoot.get(
"bookmark_bar").getAsJsonObject();
315 jBookmarkArray = jBookmark.getAsJsonArray(
"children");
316 }
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
317 logger.log(Level.WARNING,
"Error parsing Json from Chrome Bookmark.", ex);
318 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile3",
319 this.getName(), bookmarkFile.getName()));
323 for (JsonElement result : jBookmarkArray) {
324 JsonObject address = result.getAsJsonObject();
325 if (address == null) {
328 JsonElement urlEl = address.get(
"url");
331 url = urlEl.getAsString();
336 JsonElement nameEl = address.get(
"name");
337 if (nameEl != null) {
338 name = nameEl.getAsString();
343 JsonElement dateEl = address.get(
"date_added");
344 if (dateEl != null) {
345 date = dateEl.getAsLong();
347 date = Long.valueOf(0);
349 String domain = NetworkUtils.extractDomain(url);
351 BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
352 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
354 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
355 RecentActivityExtracterModuleFactory.getModuleName(), url));
356 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
357 RecentActivityExtracterModuleFactory.getModuleName(), name));
358 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
359 RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf(
"11644473600")));
360 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
361 RecentActivityExtracterModuleFactory.getModuleName(),
362 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
363 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
364 RecentActivityExtracterModuleFactory.getModuleName(), domain));
365 bbart.addAttributes(bbattributes);
367 bbartifacts.add(bbart);
368 }
catch (TskCoreException ex) {
369 logger.log(Level.SEVERE,
"Error while trying to insert Chrome bookmark artifact{0}", ex);
370 this.addErrorMessage(
371 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile4",
372 this.getName(), bookmarkFile.getName()));
375 postArtifacts(bbartifacts);
383 private void getCookie() {
385 FileManager fileManager = currentCase.getServices().getFileManager();
386 List<AbstractFile> cookiesFiles;
388 cookiesFiles = fileManager.findFiles(dataSource,
"Cookies",
"Chrome");
389 }
catch (TskCoreException ex) {
390 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getCookie.errMsg.errGettingFiles");
391 logger.log(Level.SEVERE, msg, ex);
392 this.addErrorMessage(this.getName() +
": " + msg);
396 if (cookiesFiles.isEmpty()) {
397 logger.log(Level.INFO,
"Didn't find any Chrome cookies files.");
402 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
404 while (j < cookiesFiles.size()) {
405 AbstractFile cookiesFile = cookiesFiles.get(j++);
406 if (cookiesFile.getSize() == 0) {
409 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + cookiesFile.getName() + j +
".db";
411 ContentUtils.writeToFile(cookiesFile,
new File(temps), context::dataSourceIngestIsCancelled);
412 }
catch (ReadContentInputStreamException ex) {
413 logger.log(Level.WARNING, String.format(
"Error reading Chrome cookie artifacts file '%s' (id=%d).",
414 cookiesFile.getName(), cookiesFile.getId()), ex);
415 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile",
416 this.getName(), cookiesFile.getName()));
418 }
catch (IOException ex) {
419 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).",
420 temps, cookiesFile.getName(), cookiesFile.getId()), ex);
421 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile",
422 this.getName(), cookiesFile.getName()));
425 File dbFile =
new File(temps);
426 if (context.dataSourceIngestIsCancelled()) {
431 List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
432 logger.log(Level.INFO,
"{0}- Now getting cookies from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
433 for (HashMap<String, Object> result : tempList) {
434 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
435 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
436 RecentActivityExtracterModuleFactory.getModuleName(),
437 ((result.get(
"host_key").toString() != null) ? result.get(
"host_key").toString() :
"")));
438 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
439 RecentActivityExtracterModuleFactory.getModuleName(),
440 (Long.valueOf(result.get(
"last_access_utc").toString()) / 1000000) - Long.valueOf(
"11644473600")));
442 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
443 RecentActivityExtracterModuleFactory.getModuleName(),
444 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
445 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
446 RecentActivityExtracterModuleFactory.getModuleName(),
447 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
448 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
449 RecentActivityExtracterModuleFactory.getModuleName(),
450 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
451 String domain = result.get(
"host_key").toString();
452 domain = domain.replaceFirst(
"^\\.+(?!$)",
"");
453 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
454 RecentActivityExtracterModuleFactory.getModuleName(), domain));
456 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
458 bbartifacts.add(bbart);
465 if( !bbartifacts.isEmpty() ) {
466 postArtifacts(bbartifacts);
473 private void getDownload() {
474 FileManager fileManager = currentCase.getServices().getFileManager();
475 List<AbstractFile> downloadFiles;
477 downloadFiles = fileManager.findFiles(dataSource,
"History",
"Chrome");
478 }
catch (TskCoreException ex) {
479 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getDownload.errMsg.errGettingFiles");
480 logger.log(Level.SEVERE, msg, ex);
481 this.addErrorMessage(this.getName() +
": " + msg);
485 if (downloadFiles.isEmpty()) {
486 logger.log(Level.INFO,
"Didn't find any Chrome download files.");
491 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
493 while (j < downloadFiles.size()) {
494 AbstractFile downloadFile = downloadFiles.get(j++);
495 if (downloadFile.getSize() == 0) {
498 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + downloadFile.getName() + j +
".db";
500 ContentUtils.writeToFile(downloadFile,
new File(temps), context::dataSourceIngestIsCancelled);
501 }
catch (ReadContentInputStreamException ex) {
502 logger.log(Level.WARNING, String.format(
"Error reading Chrome download artifacts file '%s' (id=%d).",
503 downloadFile.getName(), downloadFile.getId()), ex);
504 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
505 this.getName(), downloadFile.getName()));
507 }
catch (IOException ex) {
508 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).",
509 temps, downloadFile.getName(), downloadFile.getId()), ex);
510 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
511 this.getName(), downloadFile.getName()));
514 File dbFile =
new File(temps);
515 if (context.dataSourceIngestIsCancelled()) {
520 List<HashMap<String, Object>> tempList;
522 if (isChromePreVersion30(temps)) {
523 tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
525 tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
528 logger.log(Level.INFO,
"{0}- Now getting downloads from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
529 for (HashMap<String, Object> result : tempList) {
530 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
531 String fullPath = result.get(
"full_path").toString();
532 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
533 RecentActivityExtracterModuleFactory.getModuleName(), fullPath));
534 long pathID = Util.findID(dataSource, fullPath);
536 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
537 NbBundle.getMessage(
this.getClass(),
538 "Chrome.parentModuleName"), pathID));
540 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
541 RecentActivityExtracterModuleFactory.getModuleName(),
542 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
544 Long time = (Long.valueOf(result.get(
"start_time").toString()) / 1000000) - Long.valueOf(
"11644473600");
548 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
549 RecentActivityExtracterModuleFactory.getModuleName(), time));
550 String domain = NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"");
551 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
552 RecentActivityExtracterModuleFactory.getModuleName(), domain));
553 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
554 RecentActivityExtracterModuleFactory.getModuleName(),
555 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
557 BlackboardArtifact webDownloadArtifact = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
558 if (webDownloadArtifact != null) {
559 bbartifacts.add(webDownloadArtifact);
563 for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
564 BlackboardArtifact associatedObjectArtifact = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
565 associatedObjectArtifact.addAttribute(
566 new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
567 RecentActivityExtracterModuleFactory.getModuleName(), webDownloadArtifact.getArtifactID()));
569 bbartifacts.add(associatedObjectArtifact);
572 }
catch (TskCoreException ex) {
573 logger.log(Level.SEVERE, String.format(
"Error creating associated object artifact for file '%s'", fullPath), ex);
581 if( !bbartifacts.isEmpty() ) {
582 postArtifacts(bbartifacts);
589 private void getLogins() {
591 FileManager fileManager = currentCase.getServices().getFileManager();
592 List<AbstractFile> loginDataFiles;
594 loginDataFiles = fileManager.findFiles(dataSource,
"Login Data",
"Chrome");
595 }
catch (TskCoreException ex) {
596 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getLogin.errMsg.errGettingFiles");
597 logger.log(Level.SEVERE, msg, ex);
598 this.addErrorMessage(this.getName() +
": " + msg);
602 if (loginDataFiles.isEmpty()) {
603 logger.log(Level.INFO,
"Didn't find any Chrome Login Data files.");
608 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
610 while (j < loginDataFiles.size()) {
611 AbstractFile loginDataFile = loginDataFiles.get(j++);
612 if (loginDataFile.getSize() == 0) {
615 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + loginDataFile.getName() + j +
".db";
617 ContentUtils.writeToFile(loginDataFile,
new File(temps), context::dataSourceIngestIsCancelled);
618 }
catch (ReadContentInputStreamException ex) {
619 logger.log(Level.WARNING, String.format(
"Error reading Chrome login artifacts file '%s' (id=%d).",
620 loginDataFile.getName(), loginDataFile.getId()), ex);
621 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
622 this.getName(), loginDataFile.getName()));
624 }
catch (IOException ex) {
625 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).",
626 temps, loginDataFile.getName(), loginDataFile.getId()), ex);
627 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
628 this.getName(), loginDataFile.getName()));
631 File dbFile =
new File(temps);
632 if (context.dataSourceIngestIsCancelled()) {
636 List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
637 logger.log(Level.INFO,
"{0}- Now getting login information from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
638 for (HashMap<String, Object> result : tempList) {
639 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
641 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
642 RecentActivityExtracterModuleFactory.getModuleName(),
643 ((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
"")));
646 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
647 RecentActivityExtracterModuleFactory.getModuleName(),
648 (Long.valueOf(result.get(
"date_created").toString()) / 1000000) - Long.valueOf(
"11644473600")));
650 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
651 RecentActivityExtracterModuleFactory.getModuleName(),
652 (NetworkUtils.extractDomain((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
""))));
654 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
655 RecentActivityExtracterModuleFactory.getModuleName(),
656 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
658 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
659 RecentActivityExtracterModuleFactory.getModuleName(),
660 ((result.get(
"signon_realm").toString() != null) ? result.get(
"signon_realm").toString() :
"")));
662 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes);
664 bbartifacts.add(bbart);
671 if( !bbartifacts.isEmpty() ) {
672 postArtifacts(bbartifacts);
680 private void getAutofill() {
682 FileManager fileManager = currentCase.getServices().getFileManager();
683 List<AbstractFile> webDataFiles;
685 webDataFiles = fileManager.findFiles(dataSource,
"Web Data",
"Chrome");
686 }
catch (TskCoreException ex) {
687 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getAutofills.errMsg.errGettingFiles");
688 logger.log(Level.SEVERE, msg, ex);
689 this.addErrorMessage(this.getName() +
": " + msg);
693 if (webDataFiles.isEmpty()) {
694 logger.log(Level.INFO,
"Didn't find any Chrome Web Data files.");
699 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
701 while (j < webDataFiles.size()) {
702 AbstractFile webDataFile = webDataFiles.get(j++);
703 if (webDataFile.getSize() == 0) {
706 String tempFilePath = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + webDataFile.getName() + j +
".db";
708 ContentUtils.writeToFile(webDataFile,
new File(tempFilePath), context::dataSourceIngestIsCancelled);
709 }
catch (ReadContentInputStreamException ex) {
710 logger.log(Level.WARNING, String.format(
"Error reading Chrome Autofill artifacts file '%s' (id=%d).",
711 webDataFile.getName(), webDataFile.getId()), ex);
712 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getAutofill.errMsg.errAnalyzingFiles",
713 this.getName(), webDataFile.getName()));
715 }
catch (IOException ex) {
716 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome Web data file '%s' (id=%d).",
717 tempFilePath, webDataFile.getName(), webDataFile.getId()), ex);
718 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
719 this.getName(), webDataFile.getName()));
722 File dbFile =
new File(tempFilePath);
723 if (context.dataSourceIngestIsCancelled()) {
729 boolean isSchemaV8X = Util.checkColumn(
"date_created",
"autofill", tempFilePath);
732 bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X));
734 bbartifacts.addAll(getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X));
739 if( !bbartifacts.isEmpty() ){
740 postArtifacts(bbartifacts);
753 private Collection<BlackboardArtifact> getFormAutofillArtifacts (AbstractFile webDataFile, String dbFilePath ,
boolean isSchemaV8X ) {
755 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
758 String autoFillquery = (isSchemaV8X) ? AUTOFILL_QUERY_V8X
761 List<HashMap<String, Object>> autofills = this.dbConnect(dbFilePath, autoFillquery);
762 logger.log(Level.INFO,
"{0}- Now getting Autofill information from {1} with {2}artifacts identified.",
new Object[]{moduleName, dbFilePath, autofills.size()});
763 for (HashMap<String, Object> result : autofills) {
764 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
767 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
768 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
769 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
771 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
772 RecentActivityExtracterModuleFactory.getModuleName(),
773 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
775 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
776 RecentActivityExtracterModuleFactory.getModuleName(),
777 (Integer.valueOf(result.get(
"count").toString()))));
779 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
780 RecentActivityExtracterModuleFactory.getModuleName(),
781 Long.valueOf(result.get(
"date_created").toString())));
785 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
786 RecentActivityExtracterModuleFactory.getModuleName(),
787 Long.valueOf(result.get(
"date_last_used").toString())));
791 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, webDataFile, bbattributes);
793 bbartifacts.add(bbart);
810 private Collection<BlackboardArtifact> getFormAddressArtifacts (AbstractFile webDataFile, String dbFilePath ,
boolean isSchemaV8X ) {
811 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
813 String webformAddressQuery = (isSchemaV8X) ? WEBFORM_ADDRESS_QUERY_V8X
814 : WEBFORM_ADDRESS_QUERY;
817 List<HashMap<String, Object>> addresses = this.dbConnect(dbFilePath, webformAddressQuery);
818 logger.log(Level.INFO,
"{0}- Now getting Web form addresses from {1} with {2}artifacts identified.",
new Object[]{moduleName, dbFilePath, addresses.size()});
819 for (HashMap<String, Object> result : addresses) {
820 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
823 String first_name = result.get(
"first_name").toString() != null ? result.get(
"first_name").toString() :
"";
824 String middle_name = result.get(
"middle_name").toString() != null ? result.get(
"middle_name").toString() :
"";
825 String last_name = result.get(
"last_name").toString() != null ? result.get(
"last_name").toString() :
"";
828 String email_Addr = result.get(
"email").toString() != null ? result.get(
"email").toString() :
"";
829 String phone_number = result.get(
"number").toString() != null ? result.get(
"number").toString() :
"";
832 String city = result.get(
"city").toString() != null ? result.get(
"city").toString() :
"";
833 String state = result.get(
"state").toString() != null ? result.get(
"state").toString() :
"";
834 String zipcode = result.get(
"zipcode").toString() != null ? result.get(
"zipcode").toString() :
"";
835 String country_code = result.get(
"country_code").toString() != null ? result.get(
"country_code").toString() :
"";
838 String full_name =
"";
839 String street_address =
"";
840 long date_modified = 0;
845 full_name = result.get(
"full_name").toString() != null ? result.get(
"full_name").toString() :
"";
846 street_address = result.get(
"street_address").toString() != null ? result.get(
"street_address").toString() :
"";
847 date_modified = result.get(
"date_modified").toString() != null ? Long.valueOf(result.get(
"date_modified").toString()) : 0;
848 use_count = result.get(
"use_count").toString() != null ? Integer.valueOf(result.get(
"use_count").toString()) : 0;
849 use_date = result.get(
"use_date").toString() != null ? Long.valueOf(result.get(
"use_date").toString()) : 0;
851 String address_line_1 = result.get(
"address_line_1").toString() != null ? result.get(
"street_address").toString() :
"";
852 String address_line_2 = result.get(
"address_line_2").toString() != null ? result.get(
"address_line_2").toString() :
"";
853 street_address = String.join(
" ", address_line_1, address_line_2);
857 if (email_Addr != null && !email_Addr.isEmpty()) {
859 Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.EMAIL, email_Addr, NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), webDataFile);
860 }
catch (NoCurrentCaseException | TskCoreException ex) {
861 logger.log(Level.SEVERE, String.format(
"Error creating email account instance for '%s' from Chrome WebData file '%s' .",
862 email_Addr, webDataFile.getName()), ex);
866 if (phone_number != null && !phone_number.isEmpty()) {
868 Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, phone_number, NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), webDataFile);
869 }
catch (NoCurrentCaseException | TskCoreException ex) {
870 logger.log(Level.SEVERE, String.format(
"Error creating phone account instance for '%s' from Chrome WebData file '%s' .",
871 phone_number, webDataFile.getName()), ex);
876 if (full_name == null || full_name.isEmpty()) {
877 full_name = String.join(
" ", first_name, middle_name, last_name);
879 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME_PERSON,
880 RecentActivityExtracterModuleFactory.getModuleName(),
883 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
884 RecentActivityExtracterModuleFactory.getModuleName(),
887 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
888 RecentActivityExtracterModuleFactory.getModuleName(),
891 String locationAddress = String.join(
", ", street_address, city, state, zipcode, country_code);
892 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCATION,
893 RecentActivityExtracterModuleFactory.getModuleName(),
896 if (date_modified > 0) {
897 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED,
898 RecentActivityExtracterModuleFactory.getModuleName(),
903 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
904 RecentActivityExtracterModuleFactory.getModuleName(),
909 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
910 RecentActivityExtracterModuleFactory.getModuleName(),
915 BlackboardArtifact bbart = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS, webDataFile, bbattributes);
917 bbartifacts.add(bbart);
924 private boolean isChromePreVersion30(String temps) {
925 String query =
"PRAGMA table_info(downloads)";
926 List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
927 for (HashMap<String, Object> col : columns) {
928 if (col.get(
"name").equals(
"url")) {