mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
5566: Add more comments to modules.
This commit is contained in:
parent
fee109775c
commit
8580b9b6b9
@ -50,12 +50,52 @@ import json
|
||||
import traceback
|
||||
import general
|
||||
|
||||
"""
|
||||
Finds the SQLite DB for Facebook messenger, parses the DB for contacts & messages,
|
||||
and adds artifacts to the case.
|
||||
"""
|
||||
|
||||
class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
|
||||
|
||||
|
||||
"""
|
||||
Facebook Messenger is a messaging application for Facebook users.
|
||||
It can be used to have one-to-one as well as group message conversations -
|
||||
text, send photos videos and other media file. It can also be used to make
|
||||
phone calls - audio as well as video.
|
||||
|
||||
This module finds the SQLite DB for FB messenger, parses the DB for contacts,
|
||||
messages, and call logs and creates artifacts.
|
||||
|
||||
FB messenger requires Facebook accounts. Although Facebook and Facebook Messenger are
|
||||
two different applications with separate packages, their database structure is very similar
|
||||
and FB messenger seems to share the FB database if FB is inatalled.
|
||||
|
||||
FB assigns each user a unique FB id, fbid - a long numeric id.
|
||||
Each user also has a display name.
|
||||
|
||||
FB uses a notion of user key, which is of the form FACEBOOK:<fbid>
|
||||
|
||||
FB messenger version 239.0.0.41 has the following database structure:
|
||||
- contacts_db2
|
||||
-- A contacts table that stores the contacts/friends.
|
||||
|
||||
- threads_db2
|
||||
-- A messages table to store the messages
|
||||
--- A sender column - this is a JSON structure which has a the FB user key of sender.
|
||||
--- A attachments column - a JSON structure that has details of the attachments,
|
||||
--- A msg_type column: message type - indicates whether its a text/mms message or a audio/video call
|
||||
--- A thread_key column - identifies the message thread
|
||||
--- A timestamp_ms column - date/time message was sent
|
||||
--- A text column - message text, if applicable
|
||||
|
||||
-- A thread_participants table to identify participants in a particular thread
|
||||
--- A thread_key column - identifies a message thread
|
||||
--- A user_key column to identify a particpant in the thread
|
||||
|
||||
|
||||
-- A thread_users to identify the user details, primarliy name, of a user that has been a particiapnt in any thread
|
||||
--- A user_key column - identifies a unique user
|
||||
--- A name column - user display name
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._logger = Logger.getLogger(self.__class__.__name__)
|
||||
|
||||
@ -70,13 +110,15 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
|
||||
|
||||
## Analyze contacts
|
||||
def analyzeContacts(self, dataSource, fileManager, context):
|
||||
|
||||
## FB messenger and FB have same database structure for contacts.
|
||||
## In our example the FB Messenger database was empty.
|
||||
## In our dataset, the FB Messenger database was empty.
|
||||
## But the FB database had the data.
|
||||
|
||||
contactsDbs = AppSQLiteDB.findAppDatabases(dataSource, "contacts_db2", True, self._FACEBOOK_PACKAGE_NAME)
|
||||
for contactsDb in contactsDbs:
|
||||
try:
|
||||
## The device owner's FB account details can be found in the contacts table in a row with added_time_ms of 0.
|
||||
selfAccountResultSet = contactsDb.runQuery("SELECT fbid, display_name FROM contacts WHERE added_time_ms = 0")
|
||||
if selfAccountResultSet:
|
||||
if not self.selfAccountAddress:
|
||||
@ -90,7 +132,8 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
|
||||
contactsDBHelper = CommunicationArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self._MODULE_NAME, contactsDb.getDBFile(),
|
||||
Account.Type.FACEBOOK)
|
||||
|
||||
|
||||
## get the other contacts/friends
|
||||
contactsResultSet = contactsDb.runQuery("SELECT fbid, display_name, added_time_ms FROM contacts WHERE added_time_ms <> 0")
|
||||
if contactsResultSet is not None:
|
||||
while contactsResultSet.next():
|
||||
@ -147,14 +190,20 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
|
||||
self._MODULE_NAME, threadsDb.getDBFile(),
|
||||
Account.Type.FACEBOOK)
|
||||
|
||||
## Messages are found in the messages table. The participant ids can be found in the thread_participants table.
|
||||
## Messages are found in the messages table.
|
||||
## The participant ids can be found in the thread_participants table.
|
||||
## Participant names are found in thread_users table.
|
||||
## Joining these tables produces multiple rows per message, one row for each recipient
|
||||
sqlString = "SELECT msg_id, text, sender, timestamp_ms, messages.thread_key as thread_key,"\
|
||||
" snippet, thread_participants.user_key as user_key, thread_users.name as name FROM messages"\
|
||||
" JOIN thread_participants ON messages.thread_key = thread_participants.thread_key"\
|
||||
" JOIN thread_users ON thread_participants.user_key = thread_users.user_key"\
|
||||
" ORDER BY msg_id"
|
||||
## Joining these tables produces multiple rows per message, one row for each recipient.
|
||||
## The result set is processed to collect the multiple recipients for a given message.
|
||||
|
||||
sqlString = """
|
||||
SELECT msg_id, text, sender, timestamp_ms, messages.thread_key as thread_key,
|
||||
snippet, thread_participants.user_key as user_key, thread_users.name as name
|
||||
FROM messages
|
||||
JOIN thread_participants ON messages.thread_key = thread_participants.thread_key
|
||||
JOIN thread_users ON thread_participants.user_key = thread_users.user_key
|
||||
ORDER BY msg_id
|
||||
"""
|
||||
|
||||
messagesResultSet = threadsDb.runQuery(sqlString)
|
||||
if messagesResultSet is not None:
|
||||
@ -212,7 +261,7 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
|
||||
|
||||
# Get msg text
|
||||
# Sometimes there may not be an explict msg text,
|
||||
# but a app genrated snippet instead
|
||||
# but an app generated snippet instead
|
||||
msgText = messagesResultSet.getString("text")
|
||||
if not msgText:
|
||||
msgText = messagesResultSet.getString("snippet")
|
||||
|
@ -46,13 +46,21 @@ from org.sleuthkit.datamodel.blackboardutils import ArtifactsHelper
|
||||
import traceback
|
||||
import general
|
||||
|
||||
"""
|
||||
Finds the SQLite DB for Android installed applications, parses the DB,
|
||||
and adds artifacts to the case.
|
||||
"""
|
||||
|
||||
class InstalledApplicationsAnalyzer(general.AndroidComponentAnalyzer):
|
||||
|
||||
moduleName = "Android Installed Applications Analyzer"
|
||||
|
||||
"""
|
||||
Android has a database to track the applications that are
|
||||
purchased and installed on the phone.
|
||||
|
||||
This module finds the SQLite DB for insalled application, and creates artifacts.
|
||||
|
||||
|
||||
Android 5.1.1 has the following database structure istalled applications:
|
||||
- library.db
|
||||
-- A ownership table that stores pplications purchased, with purchase date
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._logger = Logger.getLogger(self.__class__.__name__)
|
||||
@ -67,7 +75,7 @@ class InstalledApplicationsAnalyzer(general.AndroidComponentAnalyzer):
|
||||
try:
|
||||
current_case = Case.getCurrentCaseThrows()
|
||||
libraryDbHelper = ArtifactsHelper(current_case.getSleuthkitCase(),
|
||||
self.moduleName, libraryDb.getDBFile())
|
||||
self._MODULE_NAME, libraryDb.getDBFile())
|
||||
queryString = "SELECT doc_id, purchase_time FROM ownership"
|
||||
ownershipResultSet = libraryDb.runQuery(queryString)
|
||||
if ownershipResultSet is not None:
|
||||
|
@ -52,6 +52,30 @@ and adds artifacts to the case.
|
||||
"""
|
||||
class OperaAnalyzer(general.AndroidComponentAnalyzer):
|
||||
|
||||
"""
|
||||
Opera is a web browser on Android phones.
|
||||
|
||||
This module finds the SQLite DB for Opera, parses the DB for bookmarks,
|
||||
downloads, web history, cookies, autofill and creates artifacts.
|
||||
|
||||
|
||||
Opera version 53.1.2569 has the following database structure:
|
||||
|
||||
- cookies
|
||||
-- A cookies table to store cookies
|
||||
- history
|
||||
-- A urls table to store history of visted urls
|
||||
-- A downloads table to store downloads
|
||||
- Web Data
|
||||
-- A autofill table to store discrete autofill name/value pairs
|
||||
-- A autofill_profile_names to store name fields (first name, middle name, last name)
|
||||
-- A autofill_profiles to store the physical snailmail address (street address, city, state, country, zip)
|
||||
-- A autofill_profile_phones to store phone numbers
|
||||
-- A autofill_profile_emails to store email addresses
|
||||
|
||||
|
||||
"""
|
||||
|
||||
moduleName = "Opera Parser"
|
||||
progName = "Opera"
|
||||
|
||||
@ -68,7 +92,7 @@ class OperaAnalyzer(general.AndroidComponentAnalyzer):
|
||||
for cookiesDb in cookiesDbs:
|
||||
try:
|
||||
cookiesDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self.moduleName, cookiesDb.getDBFile())
|
||||
self._MODULE_NAME, cookiesDb.getDBFile())
|
||||
cookiesResultSet = cookiesDb.runQuery("SELECT host_key, name, value, creation_utc FROM cookies")
|
||||
if cookiesResultSet is not None:
|
||||
while cookiesResultSet.next():
|
||||
@ -98,7 +122,7 @@ class OperaAnalyzer(general.AndroidComponentAnalyzer):
|
||||
for historyDb in historyDbs:
|
||||
try:
|
||||
historyDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self.moduleName, historyDb.getDBFile())
|
||||
self._MODULE_NAME, historyDb.getDBFile())
|
||||
historyResultSet = historyDb.runQuery("SELECT url, title, last_visit_time FROM urls")
|
||||
if historyResultSet is not None:
|
||||
while historyResultSet.next():
|
||||
@ -127,7 +151,7 @@ class OperaAnalyzer(general.AndroidComponentAnalyzer):
|
||||
for downloadsDb in downloadsDbs:
|
||||
try:
|
||||
downloadsDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self.moduleName, downloadsDb.getDBFile())
|
||||
self._MODULE_NAME, downloadsDb.getDBFile())
|
||||
queryString = "SELECT target_path, start_time, url FROM downloads"\
|
||||
" INNER JOIN downloads_url_chains ON downloads.id = downloads_url_chains.id"
|
||||
downloadsResultSet = downloadsDb.runQuery(queryString)
|
||||
@ -156,7 +180,7 @@ class OperaAnalyzer(general.AndroidComponentAnalyzer):
|
||||
for autofillDb in autofillDbs:
|
||||
try:
|
||||
autofillDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self.moduleName, autofillDb.getDBFile())
|
||||
self._MODULE_NAME, autofillDb.getDBFile())
|
||||
autofillsResultSet = autofillDb.runQuery("SELECT name, value, count, date_created FROM autofill")
|
||||
if autofillsResultSet is not None:
|
||||
while autofillsResultSet.next():
|
||||
@ -184,14 +208,15 @@ class OperaAnalyzer(general.AndroidComponentAnalyzer):
|
||||
for webFormAddressDb in webFormAddressDbs:
|
||||
try:
|
||||
webFormAddressDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self.moduleName, webFormAddressDb.getDBFile())
|
||||
queryString = "SELECT street_address, city, state, zipcode, country_code, date_modified, first_name, last_name, number, email FROM autofill_profiles "\
|
||||
" INNER JOIN autofill_profile_names"\
|
||||
" ON autofill_profiles.guid = autofill_profile_names.guid"\
|
||||
" INNER JOIN autofill_profile_phones"\
|
||||
" ON autofill_profiles.guid = autofill_profile_phones.guid"\
|
||||
" INNER JOIN autofill_profile_emails"\
|
||||
" ON autofill_profiles.guid = autofill_profile_emails.guid"
|
||||
self._MODULE_NAME, webFormAddressDb.getDBFile())
|
||||
queryString = """
|
||||
SELECT street_address, city, state, zipcode, country_code,
|
||||
date_modified, first_name, last_name, number, email
|
||||
FROM autofill_profiles
|
||||
INNER JOIN autofill_profile_names ON autofill_profiles.guid = autofill_profile_names.guid
|
||||
INNER JOIN autofill_profile_phones ON autofill_profiles.guid = autofill_profile_phones.guid
|
||||
INNER JOIN autofill_profile_emails ON autofill_profiles.guid = autofill_profile_emails.guid
|
||||
"""
|
||||
webFormAddressResultSet = webFormAddressDb.runQuery(queryString)
|
||||
if webFormAddressResultSet is not None:
|
||||
while webFormAddressResultSet.next():
|
||||
|
@ -46,12 +46,34 @@ from org.sleuthkit.datamodel.blackboardutils import WebBrowserArtifactsHelper
|
||||
import traceback
|
||||
import general
|
||||
|
||||
"""
|
||||
Finds the SQLite DB for S-Browser, parses the DB for Bookmarks, Cookies, Web History
|
||||
and adds artifacts to the case.
|
||||
"""
|
||||
|
||||
class SBrowserAnalyzer(general.AndroidComponentAnalyzer):
|
||||
|
||||
"""
|
||||
SBrowser is the default/native browser on Android phones.
|
||||
|
||||
This module finds the SQLite DB for SBrowser, parses the DB for bookmarks,
|
||||
downloads, web history, cookies, autofill and creates artifacts.
|
||||
|
||||
|
||||
SBrowser has the following database structure:
|
||||
- sbrowser.db
|
||||
-- A bookmarks table that store bookmarks
|
||||
- cookies
|
||||
-- A cookies table to store cookies
|
||||
- history
|
||||
-- A urls table to store history of visted urls
|
||||
-- A downloads table to store downloads
|
||||
- Web Data
|
||||
-- A autofill table to store discrete autofill name/value pairs
|
||||
-- A autofill_profile_names to store name fields (first name, middle name, last name)
|
||||
-- A autofill_profiles to store the physical snailmail address (street address, city, state, country, zip)
|
||||
-- A autofill_profile_phones to store phone numbers
|
||||
-- A autofill_profile_emails to store email addresses
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._logger = Logger.getLogger(self.__class__.__name__)
|
||||
self._PACKAGE_NAME = "com.sec.android.app.sbrowser"
|
||||
@ -182,7 +204,12 @@ class SBrowserAnalyzer(general.AndroidComponentAnalyzer):
|
||||
try:
|
||||
autofillDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self._MODULE_NAME, autofillDb.getDBFile())
|
||||
autofillsResultSet = autofillDb.runQuery("SELECT name, value, count, date_created FROM autofill INNER JOIN autofill_dates ON autofill.pair_id = autofill_dates.pair_id")
|
||||
queryString = """
|
||||
SELECT name, value, count, date_created
|
||||
FROM autofill
|
||||
INNER JOIN autofill_dates ON autofill.pair_id = autofill_dates.pair_id
|
||||
"""
|
||||
autofillsResultSet = autofillDb.runQuery(queryString)
|
||||
if autofillsResultSet is not None:
|
||||
while autofillsResultSet.next():
|
||||
creationTime = autofillsResultSet.getLong("date_created") / 1000000 - 11644473600 # Webkit time
|
||||
@ -210,13 +237,16 @@ class SBrowserAnalyzer(general.AndroidComponentAnalyzer):
|
||||
try:
|
||||
webFormAddressDbHelper = WebBrowserArtifactsHelper(self.current_case.getSleuthkitCase(),
|
||||
self._MODULE_NAME, webFormAddressDb.getDBFile())
|
||||
queryString = "SELECT street_address, city, state, zipcode, country_code, date_modified, first_name, last_name, number, email FROM autofill_profiles "\
|
||||
" INNER JOIN autofill_profile_names"\
|
||||
" ON autofill_profiles.guid = autofill_profile_names.guid"\
|
||||
" INNER JOIN autofill_profile_phones"\
|
||||
" ON autofill_profiles.guid = autofill_profile_phones.guid"\
|
||||
" INNER JOIN autofill_profile_emails"\
|
||||
" ON autofill_profiles.guid = autofill_profile_emails.guid"
|
||||
"""
|
||||
Autofill form data is split across multiple tables. The quqery below joins the various tables.
|
||||
"""
|
||||
queryString = """
|
||||
SELECT street_address, city, state, zipcode, country_code, date_modified, first_name, last_name, number, email
|
||||
FROM autofill_profiles
|
||||
INNER JOIN autofill_profile_names ON autofill_profiles.guid = autofill_profile_names.guid
|
||||
INNER JOIN autofill_profile_phones ON autofill_profiles.guid = autofill_profile_phones.guid
|
||||
INNER JOIN autofill_profile_emails ON autofill_profiles.guid = autofill_profile_emails.guid
|
||||
"""
|
||||
webFormAddressResultSet = webFormAddressDb.runQuery(queryString)
|
||||
if webFormAddressResultSet is not None:
|
||||
while webFormAddressResultSet.next():
|
||||
|
Loading…
x
Reference in New Issue
Block a user