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;
34 import java.util.logging.Level;
37 import java.io.FileNotFoundException;
38 import java.io.FileReader;
39 import java.io.IOException;
40 import org.apache.commons.io.FilenameUtils;
41 import org.openide.util.NbBundle.Messages;
53 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
55 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
57 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
64 class Chrome
extends Extract {
66 private static final String HISTORY_QUERY =
"SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
67 +
"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";
68 private static final String COOKIE_QUERY =
"SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies";
69 private static final String DOWNLOAD_QUERY =
"SELECT full_path, url, start_time, received_bytes FROM downloads";
70 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";
71 private static final String LOGIN_QUERY =
"SELECT origin_url, username_value, date_created, signon_realm from logins";
72 private static final String AUTOFILL_QUERY =
"SELECT name, value, count, date_created " +
73 " FROM autofill, autofill_dates " +
74 " WHERE autofill.pair_id = autofill_dates.pair_id"
76 private static final String AUTOFILL_QUERY_V8X =
"SELECT name, value, count, date_created, date_last_used from autofill";
77 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 " +
78 " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
79 " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
81 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" +
82 " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" +
83 " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid";
84 private final Logger logger = Logger.getLogger(this.getClass().getName());
85 private Content dataSource;
86 private IngestJobContext context;
89 "Progress_Message_Chrome_History=Chrome History",
90 "Progress_Message_Chrome_Bookmarks=Chrome Bookmarks",
91 "Progress_Message_Chrome_Cookies=Chrome Cookies",
92 "Progress_Message_Chrome_Downloads=Chrome Downloads",
93 "Progress_Message_Chrome_FormHistory=Chrome Form History",
94 "Progress_Message_Chrome_AutoFill=Chrome Auto Fill",
95 "Progress_Message_Chrome_Logins=Chrome Logins",
96 "Progress_Message_Chrome_Cache=Chrome Cache",
100 moduleName = NbBundle.getMessage(Chrome.class,
"Chrome.moduleName");
104 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
105 this.dataSource = dataSource;
106 this.context = context;
109 progressBar.progress(Bundle.Progress_Message_Chrome_History());
112 progressBar.progress(Bundle.Progress_Message_Chrome_Bookmarks());
115 progressBar.progress(Bundle.Progress_Message_Chrome_Cookies());
118 progressBar.progress(Bundle.Progress_Message_Chrome_Logins());
121 progressBar.progress(Bundle.Progress_Message_Chrome_AutoFill());
124 progressBar.progress(Bundle.Progress_Message_Chrome_Downloads());
127 progressBar.progress(Bundle.Progress_Message_Chrome_Cache());
128 ChromeCacheExtractor chromeCacheExtractor =
new ChromeCacheExtractor(dataSource, context, progressBar);
129 chromeCacheExtractor.getCaches();
135 private void getHistory() {
136 FileManager fileManager = currentCase.getServices().getFileManager();
137 List<AbstractFile> historyFiles;
139 historyFiles = fileManager.findFiles(dataSource,
"History",
"Chrome");
140 }
catch (TskCoreException ex) {
141 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.errGettingFiles");
142 logger.log(Level.SEVERE, msg, ex);
143 this.addErrorMessage(this.getName() +
": " + msg);
148 List<AbstractFile> allocatedHistoryFiles =
new ArrayList<>();
149 for (AbstractFile historyFile : historyFiles) {
150 if (historyFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
151 allocatedHistoryFiles.add(historyFile);
156 if (allocatedHistoryFiles.isEmpty()) {
157 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.couldntFindAnyFiles");
158 logger.log(Level.INFO, msg);
163 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
165 while (j < historyFiles.size()) {
166 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + historyFiles.get(j).getName() + j +
".db";
167 final AbstractFile historyFile = historyFiles.get(j++);
168 if (historyFile.getSize() == 0) {
172 ContentUtils.writeToFile(historyFile,
new File(temps), context::dataSourceIngestIsCancelled);
173 }
catch (ReadContentInputStreamException ex) {
174 logger.log(Level.WARNING, String.format(
"Error reading Chrome web history artifacts file '%s' (id=%d).",
175 historyFile.getName(), historyFile.getId()), ex);
176 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
177 this.getName(), historyFile.getName()));
179 }
catch (IOException ex) {
180 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).",
181 temps, historyFile.getName(), historyFile.getId()), ex);
182 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
183 this.getName(), historyFile.getName()));
186 File dbFile =
new File(temps);
187 if (context.dataSourceIngestIsCancelled()) {
191 List<HashMap<String, Object>> tempList;
192 tempList = this.dbConnect(temps, HISTORY_QUERY);
193 logger.log(Level.INFO,
"{0}- Now getting history from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
194 for (HashMap<String, Object> result : tempList) {
195 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
196 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
197 RecentActivityExtracterModuleFactory.getModuleName(),
198 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
199 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
200 RecentActivityExtracterModuleFactory.getModuleName(),
201 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
202 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
203 RecentActivityExtracterModuleFactory.getModuleName(),
204 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
205 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
206 RecentActivityExtracterModuleFactory.getModuleName(),
207 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
208 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
209 RecentActivityExtracterModuleFactory.getModuleName(),
210 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
211 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
212 RecentActivityExtracterModuleFactory.getModuleName(),
213 (NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
215 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
217 bbartifacts.add(bbart);
223 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
224 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
225 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
231 private void getBookmark() {
232 FileManager fileManager = currentCase.getServices().getFileManager();
233 List<AbstractFile> bookmarkFiles;
235 bookmarkFiles = fileManager.findFiles(dataSource,
"Bookmarks",
"Chrome");
236 }
catch (TskCoreException ex) {
237 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getBookmark.errMsg.errGettingFiles");
238 logger.log(Level.SEVERE, msg, ex);
239 this.addErrorMessage(this.getName() +
": " + msg);
243 if (bookmarkFiles.isEmpty()) {
244 logger.log(Level.INFO,
"Didn't find any Chrome bookmark files.");
249 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
252 while (j < bookmarkFiles.size()) {
253 AbstractFile bookmarkFile = bookmarkFiles.get(j++);
254 if (bookmarkFile.getSize() == 0) {
257 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + bookmarkFile.getName() + j +
".db";
259 ContentUtils.writeToFile(bookmarkFile,
new File(temps), context::dataSourceIngestIsCancelled);
260 }
catch (ReadContentInputStreamException ex) {
261 logger.log(Level.WARNING, String.format(
"Error reading Chrome bookmark artifacts file '%s' (id=%d).",
262 bookmarkFile.getName(), bookmarkFile.getId()), ex);
263 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
264 this.getName(), bookmarkFile.getName()));
266 }
catch (IOException ex) {
267 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).",
268 temps, bookmarkFile.getName(), bookmarkFile.getId()), ex);
269 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
270 this.getName(), bookmarkFile.getName()));
274 logger.log(Level.INFO,
"{0}- Now getting Bookmarks from {1}",
new Object[]{moduleName, temps});
275 File dbFile =
new File(temps);
276 if (context.dataSourceIngestIsCancelled()) {
281 FileReader tempReader;
283 tempReader =
new FileReader(temps);
284 }
catch (FileNotFoundException ex) {
285 logger.log(Level.SEVERE,
"Error while trying to read into the Bookmarks for Chrome.", ex);
286 this.addErrorMessage(
287 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzeFile", this.getName(),
288 bookmarkFile.getName()));
292 final JsonParser parser =
new JsonParser();
293 JsonElement jsonElement;
294 JsonObject jElement, jRoot, jBookmark;
295 JsonArray jBookmarkArray;
298 jsonElement = parser.parse(tempReader);
299 jElement = jsonElement.getAsJsonObject();
300 jRoot = jElement.get(
"roots").getAsJsonObject();
301 jBookmark = jRoot.get(
"bookmark_bar").getAsJsonObject();
302 jBookmarkArray = jBookmark.getAsJsonArray(
"children");
303 }
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
304 logger.log(Level.WARNING,
"Error parsing Json from Chrome Bookmark.", ex);
305 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile3",
306 this.getName(), bookmarkFile.getName()));
310 for (JsonElement result : jBookmarkArray) {
311 JsonObject address = result.getAsJsonObject();
312 if (address == null) {
315 JsonElement urlEl = address.get(
"url");
318 url = urlEl.getAsString();
323 JsonElement nameEl = address.get(
"name");
324 if (nameEl != null) {
325 name = nameEl.getAsString();
330 JsonElement dateEl = address.get(
"date_added");
331 if (dateEl != null) {
332 date = dateEl.getAsLong();
334 date = Long.valueOf(0);
336 String domain = NetworkUtils.extractDomain(url);
338 BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
339 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
341 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
342 RecentActivityExtracterModuleFactory.getModuleName(), url));
343 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
344 RecentActivityExtracterModuleFactory.getModuleName(), name));
345 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
346 RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf(
"11644473600")));
347 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
348 RecentActivityExtracterModuleFactory.getModuleName(),
349 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
350 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
351 RecentActivityExtracterModuleFactory.getModuleName(), domain));
352 bbart.addAttributes(bbattributes);
355 this.indexArtifact(bbart);
356 bbartifacts.add(bbart);
357 }
catch (TskCoreException ex) {
358 logger.log(Level.SEVERE,
"Error while trying to insert Chrome bookmark artifact{0}", ex);
359 this.addErrorMessage(
360 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile4",
361 this.getName(), bookmarkFile.getName()));
367 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
368 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
369 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
375 private void getCookie() {
377 FileManager fileManager = currentCase.getServices().getFileManager();
378 List<AbstractFile> cookiesFiles;
380 cookiesFiles = fileManager.findFiles(dataSource,
"Cookies",
"Chrome");
381 }
catch (TskCoreException ex) {
382 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getCookie.errMsg.errGettingFiles");
383 logger.log(Level.SEVERE, msg, ex);
384 this.addErrorMessage(this.getName() +
": " + msg);
388 if (cookiesFiles.isEmpty()) {
389 logger.log(Level.INFO,
"Didn't find any Chrome cookies files.");
394 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
396 while (j < cookiesFiles.size()) {
397 AbstractFile cookiesFile = cookiesFiles.get(j++);
398 if (cookiesFile.getSize() == 0) {
401 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + cookiesFile.getName() + j +
".db";
403 ContentUtils.writeToFile(cookiesFile,
new File(temps), context::dataSourceIngestIsCancelled);
404 }
catch (ReadContentInputStreamException ex) {
405 logger.log(Level.WARNING, String.format(
"Error reading Chrome cookie artifacts file '%s' (id=%d).",
406 cookiesFile.getName(), cookiesFile.getId()), ex);
407 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile",
408 this.getName(), cookiesFile.getName()));
410 }
catch (IOException ex) {
411 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).",
412 temps, cookiesFile.getName(), cookiesFile.getId()), ex);
413 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile",
414 this.getName(), cookiesFile.getName()));
417 File dbFile =
new File(temps);
418 if (context.dataSourceIngestIsCancelled()) {
423 List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
424 logger.log(Level.INFO,
"{0}- Now getting cookies from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
425 for (HashMap<String, Object> result : tempList) {
426 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
427 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
428 RecentActivityExtracterModuleFactory.getModuleName(),
429 ((result.get(
"host_key").toString() != null) ? result.get(
"host_key").toString() :
"")));
430 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
431 RecentActivityExtracterModuleFactory.getModuleName(),
432 (Long.valueOf(result.get(
"last_access_utc").toString()) / 1000000) - Long.valueOf(
"11644473600")));
434 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
435 RecentActivityExtracterModuleFactory.getModuleName(),
436 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
437 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
438 RecentActivityExtracterModuleFactory.getModuleName(),
439 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
440 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
441 RecentActivityExtracterModuleFactory.getModuleName(),
442 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
443 String domain = result.get(
"host_key").toString();
444 domain = domain.replaceFirst(
"^\\.+(?!$)",
"");
445 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
446 RecentActivityExtracterModuleFactory.getModuleName(), domain));
448 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
450 bbartifacts.add(bbart);
457 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
458 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
459 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
465 private void getDownload() {
466 FileManager fileManager = currentCase.getServices().getFileManager();
467 List<AbstractFile> downloadFiles;
469 downloadFiles = fileManager.findFiles(dataSource,
"History",
"Chrome");
470 }
catch (TskCoreException ex) {
471 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getDownload.errMsg.errGettingFiles");
472 logger.log(Level.SEVERE, msg, ex);
473 this.addErrorMessage(this.getName() +
": " + msg);
477 if (downloadFiles.isEmpty()) {
478 logger.log(Level.INFO,
"Didn't find any Chrome download files.");
483 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
485 while (j < downloadFiles.size()) {
486 AbstractFile downloadFile = downloadFiles.get(j++);
487 if (downloadFile.getSize() == 0) {
490 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + downloadFile.getName() + j +
".db";
492 ContentUtils.writeToFile(downloadFile,
new File(temps), context::dataSourceIngestIsCancelled);
493 }
catch (ReadContentInputStreamException ex) {
494 logger.log(Level.WARNING, String.format(
"Error reading Chrome download artifacts file '%s' (id=%d).",
495 downloadFile.getName(), downloadFile.getId()), ex);
496 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
497 this.getName(), downloadFile.getName()));
499 }
catch (IOException ex) {
500 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).",
501 temps, downloadFile.getName(), downloadFile.getId()), ex);
502 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
503 this.getName(), downloadFile.getName()));
506 File dbFile =
new File(temps);
507 if (context.dataSourceIngestIsCancelled()) {
512 List<HashMap<String, Object>> tempList;
514 if (isChromePreVersion30(temps)) {
515 tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
517 tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
520 logger.log(Level.INFO,
"{0}- Now getting downloads from {1} with {2} artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
521 for (HashMap<String, Object> result : tempList) {
522 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
523 String fullPath = result.get(
"full_path").toString();
524 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
525 RecentActivityExtracterModuleFactory.getModuleName(), fullPath));
526 long pathID = Util.findID(dataSource, fullPath);
528 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
529 NbBundle.getMessage(
this.getClass(),
530 "Chrome.parentModuleName"), pathID));
532 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
533 RecentActivityExtracterModuleFactory.getModuleName(),
534 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
536 Long time = (Long.valueOf(result.get(
"start_time").toString()) / 1000000) - Long.valueOf(
"11644473600");
540 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
541 RecentActivityExtracterModuleFactory.getModuleName(), time));
542 String domain = NetworkUtils.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"");
543 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
544 RecentActivityExtracterModuleFactory.getModuleName(), domain));
545 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
546 RecentActivityExtracterModuleFactory.getModuleName(),
547 NbBundle.getMessage(this.getClass(),
"Chrome.moduleName")));
549 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
551 bbartifacts.add(bbart);
556 for (AbstractFile downloadedFile : fileManager.findFiles(dataSource, FilenameUtils.getName(fullPath), FilenameUtils.getPath(fullPath))) {
557 BlackboardArtifact downloadSourceArt = downloadedFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE);
558 downloadSourceArt.addAttributes(createDownloadSourceAttributes(result.get(
"url").toString()));
560 bbartifacts.add(downloadSourceArt);
563 }
catch (TskCoreException ex) {
564 logger.log(Level.SEVERE, String.format(
"Error creating download source artifact for file '%s'", fullPath), ex);
571 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
572 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
573 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
579 private void getLogins() {
581 FileManager fileManager = currentCase.getServices().getFileManager();
582 List<AbstractFile> loginDataFiles;
584 loginDataFiles = fileManager.findFiles(dataSource,
"Login Data",
"Chrome");
585 }
catch (TskCoreException ex) {
586 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getLogin.errMsg.errGettingFiles");
587 logger.log(Level.SEVERE, msg, ex);
588 this.addErrorMessage(this.getName() +
": " + msg);
592 if (loginDataFiles.isEmpty()) {
593 logger.log(Level.INFO,
"Didn't find any Chrome Login Data files.");
598 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
600 while (j < loginDataFiles.size()) {
601 AbstractFile loginDataFile = loginDataFiles.get(j++);
602 if (loginDataFile.getSize() == 0) {
605 String temps = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + loginDataFile.getName() + j +
".db";
607 ContentUtils.writeToFile(loginDataFile,
new File(temps), context::dataSourceIngestIsCancelled);
608 }
catch (ReadContentInputStreamException ex) {
609 logger.log(Level.WARNING, String.format(
"Error reading Chrome login artifacts file '%s' (id=%d).",
610 loginDataFile.getName(), loginDataFile.getId()), ex);
611 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
612 this.getName(), loginDataFile.getName()));
614 }
catch (IOException ex) {
615 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).",
616 temps, loginDataFile.getName(), loginDataFile.getId()), ex);
617 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
618 this.getName(), loginDataFile.getName()));
621 File dbFile =
new File(temps);
622 if (context.dataSourceIngestIsCancelled()) {
626 List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
627 logger.log(Level.INFO,
"{0}- Now getting login information from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
628 for (HashMap<String, Object> result : tempList) {
629 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
631 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
632 RecentActivityExtracterModuleFactory.getModuleName(),
633 ((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
"")));
636 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
637 RecentActivityExtracterModuleFactory.getModuleName(),
638 (Long.valueOf(result.get(
"date_created").toString()) / 1000000) - Long.valueOf(
"11644473600")));
640 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
641 RecentActivityExtracterModuleFactory.getModuleName(),
642 (NetworkUtils.extractDomain((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
""))));
644 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
645 RecentActivityExtracterModuleFactory.getModuleName(),
646 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
648 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
649 RecentActivityExtracterModuleFactory.getModuleName(),
650 ((result.get(
"signon_realm").toString() != null) ? result.get(
"signon_realm").toString() :
"")));
652 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes);
654 this.indexArtifact(bbart);
655 bbartifacts.add(bbart);
661 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
662 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
663 BlackboardArtifact.ARTIFACT_TYPE.TSK_SERVICE_ACCOUNT, bbartifacts));
671 private void getAutofill() {
673 FileManager fileManager = currentCase.getServices().getFileManager();
674 List<AbstractFile> webDataFiles;
676 webDataFiles = fileManager.findFiles(dataSource,
"Web Data",
"Chrome");
677 }
catch (TskCoreException ex) {
678 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getAutofills.errMsg.errGettingFiles");
679 logger.log(Level.SEVERE, msg, ex);
680 this.addErrorMessage(this.getName() +
": " + msg);
684 if (webDataFiles.isEmpty()) {
685 logger.log(Level.INFO,
"Didn't find any Chrome Web Data files.");
690 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
692 while (j < webDataFiles.size()) {
693 AbstractFile webDataFile = webDataFiles.get(j++);
694 if (webDataFile.getSize() == 0) {
697 String tempFilePath = RAImageIngestModule.getRATempPath(currentCase,
"chrome") + File.separator + webDataFile.getName() + j +
".db";
699 ContentUtils.writeToFile(webDataFile,
new File(tempFilePath), context::dataSourceIngestIsCancelled);
700 }
catch (ReadContentInputStreamException ex) {
701 logger.log(Level.WARNING, String.format(
"Error reading Chrome Autofill artifacts file '%s' (id=%d).",
702 webDataFile.getName(), webDataFile.getId()), ex);
703 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getAutofill.errMsg.errAnalyzingFiles",
704 this.getName(), webDataFile.getName()));
706 }
catch (IOException ex) {
707 logger.log(Level.SEVERE, String.format(
"Error writing temp sqlite db file '%s' for Chrome Web data file '%s' (id=%d).",
708 tempFilePath, webDataFile.getName(), webDataFile.getId()), ex);
709 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles",
710 this.getName(), webDataFile.getName()));
713 File dbFile =
new File(tempFilePath);
714 if (context.dataSourceIngestIsCancelled()) {
720 boolean isSchemaV8X = Util.checkColumn(
"date_created",
"autofill", tempFilePath);
723 bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X));
725 bbartifacts.addAll(getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X));
729 IngestServices.getInstance().fireModuleDataEvent(
new ModuleDataEvent(
730 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
731 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, bbartifacts));
744 private Collection<BlackboardArtifact> getFormAutofillArtifacts (AbstractFile webDataFile, String dbFilePath ,
boolean isSchemaV8X ) {
746 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
749 String autoFillquery = (isSchemaV8X) ? AUTOFILL_QUERY_V8X
752 List<HashMap<String, Object>> autofills = this.dbConnect(dbFilePath, autoFillquery);
753 logger.log(Level.INFO,
"{0}- Now getting Autofill information from {1} with {2}artifacts identified.",
new Object[]{moduleName, dbFilePath, autofills.size()});
754 for (HashMap<String, Object> result : autofills) {
755 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
758 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
759 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
760 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
762 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
763 RecentActivityExtracterModuleFactory.getModuleName(),
764 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
766 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
767 RecentActivityExtracterModuleFactory.getModuleName(),
768 (Integer.valueOf(result.get(
"count").toString()))));
770 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
771 RecentActivityExtracterModuleFactory.getModuleName(),
772 Long.valueOf(result.get(
"date_created").toString())));
776 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
777 RecentActivityExtracterModuleFactory.getModuleName(),
778 Long.valueOf(result.get(
"date_last_used").toString())));
782 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, webDataFile, bbattributes);
784 this.indexArtifact(bbart);
785 bbartifacts.add(bbart);
802 private Collection<BlackboardArtifact> getFormAddressArtifacts (AbstractFile webDataFile, String dbFilePath ,
boolean isSchemaV8X ) {
803 Collection<BlackboardArtifact> bbartifacts =
new ArrayList<>();
805 String webformAddressQuery = (isSchemaV8X) ? WEBFORM_ADDRESS_QUERY_V8X
806 : WEBFORM_ADDRESS_QUERY;
809 List<HashMap<String, Object>> addresses = this.dbConnect(dbFilePath, webformAddressQuery);
810 logger.log(Level.INFO,
"{0}- Now getting Web form addresses from {1} with {2}artifacts identified.",
new Object[]{moduleName, dbFilePath, addresses.size()});
811 for (HashMap<String, Object> result : addresses) {
812 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
815 String first_name = result.get(
"first_name").toString() != null ? result.get(
"first_name").toString() :
"";
816 String middle_name = result.get(
"middle_name").toString() != null ? result.get(
"middle_name").toString() :
"";
817 String last_name = result.get(
"last_name").toString() != null ? result.get(
"last_name").toString() :
"";
820 String email_Addr = result.get(
"email").toString() != null ? result.get(
"email").toString() :
"";
821 String phone_number = result.get(
"number").toString() != null ? result.get(
"number").toString() :
"";
824 String city = result.get(
"city").toString() != null ? result.get(
"city").toString() :
"";
825 String state = result.get(
"state").toString() != null ? result.get(
"state").toString() :
"";
826 String zipcode = result.get(
"zipcode").toString() != null ? result.get(
"zipcode").toString() :
"";
827 String country_code = result.get(
"country_code").toString() != null ? result.get(
"country_code").toString() :
"";
830 String full_name =
"";
831 String street_address =
"";
832 long date_modified = 0;
837 full_name = result.get(
"full_name").toString() != null ? result.get(
"full_name").toString() :
"";
838 street_address = result.get(
"street_address").toString() != null ? result.get(
"street_address").toString() :
"";
839 date_modified = result.get(
"date_modified").toString() != null ? Long.valueOf(result.get(
"date_modified").toString()) : 0;
840 use_count = result.get(
"use_count").toString() != null ? Integer.valueOf(result.get(
"use_count").toString()) : 0;
841 use_date = result.get(
"use_date").toString() != null ? Long.valueOf(result.get(
"use_date").toString()) : 0;
843 String address_line_1 = result.get(
"address_line_1").toString() != null ? result.get(
"street_address").toString() :
"";
844 String address_line_2 = result.get(
"address_line_2").toString() != null ? result.get(
"address_line_2").toString() :
"";
845 street_address = String.join(
" ", address_line_1, address_line_2);
849 if (email_Addr != null && !email_Addr.isEmpty()) {
851 Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.EMAIL, email_Addr, NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), webDataFile);
852 }
catch (NoCurrentCaseException | TskCoreException ex) {
853 logger.log(Level.SEVERE, String.format(
"Error creating email account instance for '%s' from Chrome WebData file '%s' .",
854 email_Addr, webDataFile.getName()), ex);
858 if (phone_number != null && !phone_number.isEmpty()) {
860 Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, phone_number, NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), webDataFile);
861 }
catch (NoCurrentCaseException | TskCoreException ex) {
862 logger.log(Level.SEVERE, String.format(
"Error creating phone account instance for '%s' from Chrome WebData file '%s' .",
863 phone_number, webDataFile.getName()), ex);
868 if (full_name == null || full_name.isEmpty()) {
869 full_name = String.join(
" ", first_name, middle_name, last_name);
871 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME_PERSON,
872 RecentActivityExtracterModuleFactory.getModuleName(),
875 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
876 RecentActivityExtracterModuleFactory.getModuleName(),
879 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER,
880 RecentActivityExtracterModuleFactory.getModuleName(),
883 String locationAddress = String.join(
", ", street_address, city, state, zipcode, country_code);
884 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCATION,
885 RecentActivityExtracterModuleFactory.getModuleName(),
888 if (date_modified > 0) {
889 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED,
890 RecentActivityExtracterModuleFactory.getModuleName(),
895 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
896 RecentActivityExtracterModuleFactory.getModuleName(),
901 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
902 RecentActivityExtracterModuleFactory.getModuleName(),
907 BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS, webDataFile, bbattributes);
909 this.indexArtifact(bbart);
910 bbartifacts.add(bbart);
918 private boolean isChromePreVersion30(String temps) {
919 String query =
"PRAGMA table_info(downloads)";
920 List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
921 for (HashMap<String, Object> col : columns) {
922 if (col.get(
"name").equals(
"url")) {