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;
46 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
48 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
56 class Chrome
extends Extract {
58 private static final String historyQuery =
"SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, "
59 +
"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";
60 private static final String cookieQuery =
"SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies";
61 private static final String downloadQuery =
"SELECT full_path, url, start_time, received_bytes FROM downloads";
62 private static final String downloadQueryVersion30 =
"SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id";
63 private static final String loginQuery =
"SELECT origin_url, username_value, signon_realm from logins";
65 private Content dataSource;
69 moduleName = NbBundle.getMessage(Chrome.class,
"Chrome.moduleName");
74 this.dataSource = dataSource;
75 this.context = context;
87 private void getHistory() {
88 FileManager fileManager = currentCase.getServices().getFileManager();
89 List<AbstractFile> historyFiles;
91 historyFiles = fileManager.
findFiles(dataSource,
"History",
"Chrome");
92 }
catch (TskCoreException ex) {
93 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.errGettingFiles");
94 logger.log(Level.SEVERE, msg, ex);
95 this.addErrorMessage(this.getName() +
": " + msg);
100 List<AbstractFile> allocatedHistoryFiles =
new ArrayList<>();
101 for (AbstractFile historyFile : historyFiles) {
102 if (historyFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
103 allocatedHistoryFiles.add(historyFile);
108 if (allocatedHistoryFiles.isEmpty()) {
109 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getHistory.errMsg.couldntFindAnyFiles");
110 logger.log(Level.INFO, msg);
116 while (j < historyFiles.size()) {
118 final AbstractFile historyFile = historyFiles.get(j++);
119 if (historyFile.getSize() == 0) {
124 }
catch (IOException ex) {
125 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome web history artifacts.{0}", ex);
126 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getHistory.errMsg.errAnalyzingFile",
127 this.getName(), historyFile.getName()));
130 File dbFile =
new File(temps);
135 List<HashMap<String, Object>> tempList;
136 tempList = this.dbConnect(temps, historyQuery);
137 logger.log(Level.INFO,
"{0}- Now getting history from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
138 for (HashMap<String, Object> result : tempList) {
139 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
140 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
141 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
142 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
143 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
144 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
145 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
146 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
147 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
148 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
149 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
150 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
151 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
152 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
153 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
154 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
155 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
156 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
157 (Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
""))));
158 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
164 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY));
170 private void getBookmark() {
171 FileManager fileManager = currentCase.getServices().getFileManager();
172 List<AbstractFile> bookmarkFiles = null;
174 bookmarkFiles = fileManager.
findFiles(dataSource,
"Bookmarks",
"Chrome");
175 }
catch (TskCoreException ex) {
176 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getBookmark.errMsg.errGettingFiles");
177 logger.log(Level.SEVERE, msg, ex);
178 this.addErrorMessage(this.getName() +
": " + msg);
182 if (bookmarkFiles.isEmpty()) {
183 logger.log(Level.INFO,
"Didn't find any Chrome bookmark files.");
190 while (j < bookmarkFiles.size()) {
191 AbstractFile bookmarkFile = bookmarkFiles.get(j++);
192 if (bookmarkFile.getSize() == 0) {
198 }
catch (IOException ex) {
199 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome bookmark artifacts.{0}", ex);
200 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile",
201 this.getName(), bookmarkFile.getName()));
205 logger.log(Level.INFO,
"{0}- Now getting Bookmarks from {1}",
new Object[]{moduleName, temps});
206 File dbFile =
new File(temps);
212 FileReader tempReader;
214 tempReader =
new FileReader(temps);
215 }
catch (FileNotFoundException ex) {
216 logger.log(Level.SEVERE,
"Error while trying to read into the Bookmarks for Chrome.", ex);
217 this.addErrorMessage(
218 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzeFile", this.getName(),
219 bookmarkFile.getName()));
223 final JsonParser parser =
new JsonParser();
224 JsonElement jsonElement;
225 JsonObject jElement, jRoot, jBookmark;
226 JsonArray jBookmarkArray;
229 jsonElement = parser.parse(tempReader);
230 jElement = jsonElement.getAsJsonObject();
231 jRoot = jElement.get(
"roots").getAsJsonObject();
232 jBookmark = jRoot.get(
"bookmark_bar").getAsJsonObject();
233 jBookmarkArray = jBookmark.getAsJsonArray(
"children");
234 }
catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
235 logger.log(Level.WARNING,
"Error parsing Json from Chrome Bookmark.", ex);
236 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile3",
237 this.getName(), bookmarkFile.getName()));
241 for (JsonElement result : jBookmarkArray) {
242 JsonObject address = result.getAsJsonObject();
243 if (address == null) {
246 JsonElement urlEl = address.get(
"url");
249 url = urlEl.getAsString();
254 JsonElement nameEl = address.get(
"name");
255 if (nameEl != null) {
256 name = nameEl.getAsString();
261 JsonElement dateEl = address.get(
"date_added");
262 if (dateEl != null) {
263 date = dateEl.getAsLong();
265 date = Long.valueOf(0);
267 String domain = Util.extractDomain(url);
269 BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
270 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
272 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
273 NbBundle.getMessage(
this.getClass(),
274 "Chrome.parentModuleName"), url));
275 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
276 NbBundle.getMessage(
this.getClass(),
277 "Chrome.parentModuleName"), name));
278 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
279 NbBundle.getMessage(
this.getClass(),
280 "Chrome.parentModuleName"), (date / 1000000) - Long.valueOf(
"11644473600")));
281 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
282 NbBundle.getMessage(
this.getClass(),
283 "Chrome.parentModuleName"),
284 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
285 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
286 NbBundle.getMessage(
this.getClass(),
287 "Chrome.parentModuleName"), domain));
288 bbart.addAttributes(bbattributes);
291 this.indexArtifact(bbart);
292 }
catch (TskCoreException ex) {
293 logger.log(Level.SEVERE,
"Error while trying to insert Chrome bookmark artifact{0}", ex);
294 this.addErrorMessage(
295 NbBundle.getMessage(
this.getClass(),
"Chrome.getBookmark.errMsg.errAnalyzingFile4",
296 this.getName(), bookmarkFile.getName()));
308 private void getCookie() {
310 FileManager fileManager = currentCase.getServices().getFileManager();
311 List<AbstractFile> cookiesFiles;
313 cookiesFiles = fileManager.
findFiles(dataSource,
"Cookies",
"Chrome");
314 }
catch (TskCoreException ex) {
315 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getCookie.errMsg.errGettingFiles");
316 logger.log(Level.SEVERE, msg, ex);
317 this.addErrorMessage(this.getName() +
": " + msg);
321 if (cookiesFiles.isEmpty()) {
322 logger.log(Level.INFO,
"Didn't find any Chrome cookies files.");
328 while (j < cookiesFiles.size()) {
329 AbstractFile cookiesFile = cookiesFiles.get(j++);
330 if (cookiesFile.getSize() == 0) {
336 }
catch (IOException ex) {
337 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome cookie artifacts.{0}", ex);
338 this.addErrorMessage(
339 NbBundle.getMessage(
this.getClass(),
"Chrome.getCookie.errMsg.errAnalyzeFile", this.getName(),
340 cookiesFile.getName()));
343 File dbFile =
new File(temps);
349 List<HashMap<String, Object>> tempList = this.dbConnect(temps, cookieQuery);
350 logger.log(Level.INFO,
"{0}- Now getting cookies from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
351 for (HashMap<String, Object> result : tempList) {
352 Collection<BlackboardAttribute> bbattributes =
new ArrayList<BlackboardAttribute>();
353 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
354 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
355 ((result.get(
"host_key").toString() != null) ? result.get(
"host_key").toString() :
"")));
356 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
357 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
358 (Long.valueOf(result.get(
"last_access_utc").toString()) / 1000000) - Long.valueOf(
"11644473600")));
360 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
361 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
362 ((result.get(
"name").toString() != null) ? result.get(
"name").toString() :
"")));
363 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
364 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
365 ((result.get(
"value").toString() != null) ? result.get(
"value").toString() :
"")));
366 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
367 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
368 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
369 String domain = result.get(
"host_key").toString();
370 domain = domain.replaceFirst(
"^\\.+(?!$)",
"");
371 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
372 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), domain));
373 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
385 private void getDownload() {
386 FileManager fileManager = currentCase.getServices().getFileManager();
387 List<AbstractFile> downloadFiles = null;
389 downloadFiles = fileManager.
findFiles(dataSource,
"History",
"Chrome");
390 }
catch (TskCoreException ex) {
391 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getDownload.errMsg.errGettingFiles");
392 logger.log(Level.SEVERE, msg, ex);
393 this.addErrorMessage(this.getName() +
": " + msg);
397 if (downloadFiles.isEmpty()) {
398 logger.log(Level.INFO,
"Didn't find any Chrome download files.");
404 while (j < downloadFiles.size()) {
405 AbstractFile downloadFile = downloadFiles.get(j++);
406 if (downloadFile.getSize() == 0) {
412 }
catch (IOException ex) {
413 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome download artifacts.{0}", ex);
414 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"Chrome.getDownload.errMsg.errAnalyzeFiles1",
415 this.getName(), downloadFile.getName()));
418 File dbFile =
new File(temps);
424 List<HashMap<String, Object>> tempList;
426 if (isChromePreVersion30(temps)) {
427 tempList = this.dbConnect(temps, downloadQuery);
429 tempList = this.dbConnect(temps, downloadQueryVersion30);
432 logger.log(Level.INFO,
"{0}- Now getting downloads 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<BlackboardAttribute>();
435 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
436 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), (result.get(
"full_path").toString())));
437 long pathID = Util.findID(dataSource, (result.get(
"full_path").toString()));
439 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
440 NbBundle.getMessage(
this.getClass(),
441 "Chrome.parentModuleName"), pathID));
443 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
444 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
445 ((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"")));
447 Long time = (Long.valueOf(result.get(
"start_time").toString()) / 1000000) - Long.valueOf(
"11644473600");
451 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
452 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), time));
453 String domain = Util.extractDomain((result.get(
"url").toString() != null) ? result.get(
"url").toString() :
"");
454 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
455 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"), domain));
456 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
457 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
458 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
459 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
466 BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD));
472 private void getLogin() {
473 FileManager fileManager = currentCase.getServices().getFileManager();
474 List<AbstractFile> signonFiles;
476 signonFiles = fileManager.
findFiles(dataSource,
"signons.sqlite",
"Chrome");
477 }
catch (TskCoreException ex) {
478 String msg = NbBundle.getMessage(this.getClass(),
"Chrome.getLogin.errMsg.errGettingFiles");
479 logger.log(Level.SEVERE, msg, ex);
480 this.addErrorMessage(this.getName() +
": " + msg);
484 if (signonFiles.isEmpty()) {
485 logger.log(Level.INFO,
"Didn't find any Chrome signon files.");
491 while (j < signonFiles.size()) {
492 AbstractFile signonFile = signonFiles.get(j++);
493 if (signonFile.getSize() == 0) {
499 }
catch (IOException ex) {
500 logger.log(Level.SEVERE,
"Error writing temp sqlite db for Chrome login artifacts.{0}", ex);
501 this.addErrorMessage(
502 NbBundle.getMessage(
this.getClass(),
"Chrome.getLogin.errMsg.errAnalyzingFiles", this.getName(),
503 signonFile.getName()));
506 File dbFile =
new File(temps);
511 List<HashMap<String, Object>> tempList = this.dbConnect(temps, loginQuery);
512 logger.log(Level.INFO,
"{0}- Now getting login information from {1} with {2}artifacts identified.",
new Object[]{moduleName, temps, tempList.size()});
513 for (HashMap<String, Object> result : tempList) {
514 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
515 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
516 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
517 ((result.get(
"origin_url").toString() != null) ? result.get(
"origin_url").toString() :
"")));
521 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
522 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
523 (Long.valueOf(result.get(
"last_visit_time").toString()) / 1000000) - Long.valueOf(
"11644473600")));
524 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
525 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
526 ((result.get(
"from_visit").toString() != null) ? result.get(
"from_visit").toString() :
"")));
527 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
528 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
529 ((result.get(
"title").toString() != null) ? result.get(
"title").toString() :
"")));
530 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
531 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
532 NbBundle.getMessage(
this.getClass(),
"Chrome.moduleName")));
533 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
534 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
535 (Util.extractDomain((result.get(
"origin_url").toString() != null) ? result.get(
"url").toString() :
""))));
536 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
537 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
538 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
539 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
540 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
541 result.get(
"signon_realm").toString()));
542 this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes);
544 Collection<BlackboardAttribute> osAcctAttributes =
new ArrayList<>();
545 osAcctAttributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
546 NbBundle.getMessage(
this.getClass(),
"Chrome.parentModuleName"),
547 ((result.get(
"username_value").toString() != null) ? result.get(
"username_value").toString().replaceAll(
"'",
"''") :
"")));
548 this.addArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT, signonFile, osAcctAttributes);
557 private boolean isChromePreVersion30(String temps) {
558 String query =
"PRAGMA table_info(downloads)";
559 List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
560 for (HashMap<String, Object> col : columns) {
561 if (col.get(
"name").equals(
"url")) {
static String getRATempPath(Case a_case, String mod)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
boolean dataSourceIngestIsCancelled()
synchronized List< AbstractFile > findFiles(String fileName)
synchronized static Logger getLogger(String name)
static synchronized IngestServices getInstance()