-
Notifications
You must be signed in to change notification settings - Fork 20
/
extractor.py
executable file
·158 lines (147 loc) · 7.25 KB
/
extractor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env python
import os, re, shutil, sys, pdb, apsw, io, time
import extractor.mms_sms.extract, extractor.call_log.extract, extractor.contacts.extract, extractor.accounts.extract, extractor.aosp_email.extract, extractor.google_calendar.extract, extractor.facebook.extract, extractor.facebook_messenger.extract, extractor.gmail.extract, extractor.google_maps.extract, extractor.skype.extract, extractor.system.extract, extractor.whatsapp.extract, extractor.tinder.extract
import report.makereports
import mounter.mount
def main(case):
os.system('cls' if os.name == 'nt' else 'clear')
reportoption = selectreport() #Ask to make HTML reports
if sys.platform in ('linux', 'linux2'):
mountcheck = os.path.join(case, "mount", "mountstatus")
mstatusfile = open (mountcheck, 'r')
mstatusread = mstatusfile.read()
mstatusread = int(mstatusread)
mstatbool = False
if mstatusread == 1: #If the program doesn't believe the disk is mounted, mount the image. If it does, continue.
mstatbool = True
mstatusfile.close()
if mstatbool == False:
print('Image does not appear to be mounted. Mounting image (forensically safe)...')
mounter.mount.mountfs(case)
userdatadir = getuserdatapath(case)
extractdir = os.path.join(case, "extracted data")
timeline = False
if reportoption == 1:
timeline = askfortimeline(case)
try:
if os.path.exists(extractdir): #refreshes the extract directory
shutil.rmtree(extractdir)
os.makedirs(extractdir)
if os.path.exists(os.path.join(userdatadir, "system", "users")):#These are the extraction scripts for each service
extractor.accounts.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.android.email")):
extractor.aosp_email.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.android.providers.contacts")):
extractor.call_log.extract.extract(case, userdatadir)
extractor.contacts.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.facebook.katana")):
extractor.facebook.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.facebook.orca")):
extractor.facebook_messenger.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.google.android.gm")):
extractor.gmail.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.android.providers.calendar")):
extractor.google_calendar.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.google.android.apps.maps")):
extractor.google_maps.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.android.providers.telephony")):
extractor.mms_sms.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.skype.raider")):
extractor.skype.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "misc")):
extractor.system.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.whatsapp")):
extractor.whatsapp.extract.extract(case, userdatadir)
if os.path.exists(os.path.join(userdatadir, "data", "com.tinder")):
extractor.tinder.extract.extract(case, userdatadir)
input("Debug! go copy the 'tinder' folder")
if sys.platform in ('linux', 'linux2'):
print("--> [Linux] Fixing permissions for easy, non-root access")
os.system('chown -R $USER "' + extractdir + '"')
os.system('chmod -R 777 "' + extractdir + '"')
if reportoption == 1:
report.makereports.makeindex(case, timeline)
report.makereports.makereports(case, timeline)
except PermissionError:
if os.name == 'nt':
print("Error! This needs to be run with Administrator privileges. Press Enter to return to the menu.")
else:
print("Error! This needs to be run under 'sudo' or as root. Press Enter to return to the menu.")
input()
except KeyboardInterrupt:
print("CTRL-C (cancel command) registered. Performing cleanup")
shutil.rmtree(extractdir)
shutil.rmtree(os.path.join(case, "reports"))
os.makedirs(extractdir)
os.makedirs(os.path.join(case, "reports"))
time.sleep(5)
def getuserdatapath(case):
filepath = os.path.join(case, "image", "userdata-name.txt")
try:
fileopen = open(filepath, "r")
except FileNotFoundError:
writeuserdata(filepath, case)
fileopen = open(filepath, "r")
userdata = fileopen.read()
if userdata == '':
fileopen.close()
writeuserdata(filepath, case)
return(userdata)
def writeuserdata(filepath, case):
if sys.platform in ('linux', 'linux2'):
print ("The userdata partition number is unknown. Please type in the partition number (you can find the selectable numbers in " + case + "mount, assuming you mounted the partitions before making a report)")
path = ''
while not os.path.isdir(path):
partnumber = input("Partition number [0-99]")
path = os.path.join(case, "mount", "Partition " + partnumber)
path = path + os.sep
if not os.path.isdir(path):
print("Error! chould not find partition " + partnumber)
else:
print ("The path for the mounted userdata partition was not found. Please type in (or drag-and-drop) the full path to the root of the mounted userdata partition\n\n")
path = ''
while not os.path.isdir(path):
path = input("[userdata partition path]")
path = path.replace("'","")
path = re.sub(" $", "", path)
path = path + os.sep
if not os.path.isdir(path):
print("Error! " + path +" is not a valid directory")
fileopen = open(filepath, "w")
fileopen.write(path)
fileopen.close
def selectreport(): #Gives the user the option to make HTML reports on extracted data
reportoption = 2
while reportoption == 2:
os.system('cls' if os.name == 'nt' else 'clear')
print("AFFT can make automated HTML reports based on the findings. This will analyse and present the data in a user-friendly format, but will make the extraction process significantly longer.")
print("\nMake automated reports?")
option = input("[Y/N]")
option = option.lower()
if option == 'y' or option == 'yes':
reportoption = 1
elif option == 'n' or option == 'no':
reportoption = 0
return reportoption
def askfortimeline(case): #If the user opts into reports, ask if they want to make a timeline too
print("Create a timeline of all supported events? (Takes significantly longer)")
answer = input('[Y/N]')
answer = answer.upper()
if answer == 'Y':
if not os.path.exists(os.path.join(case, "reports")):
os.makedirs(os.path.join(case, "reports"))
if not os.path.exists(os.path.join(case, "reports", "timeline")):
os.makedirs(os.path.join(case, "reports", "timeline"))
tldb = os.path.join(case, "reports", "timeline.db")
if os.path.isfile(tldb):
os.remove(tldb)
tloutopen = io.StringIO()
tlconnection = apsw.Connection(tldb)
dbshell = apsw.Shell(stdout=tloutopen, db=tlconnection)
dbshell.process_sql("CREATE TABLE timeline(_id INTEGER PRIMARY KEY NOT NULL, service, message, timestamp)")
return(True)
elif answer == 'N':
return(False)
else:
print("Unrecognised answer. Defaulting to 'N'")
return(False)