├── README.md
├── printGetPostVariables.py
└── parseMapMyRide.py
/README.md:
--------------------------------------------------------------------------------
1 | # mobileForensics
2 |
3 | The objective of this repository is to provide tools to help in mobile forensics investigations.
4 |
5 | parseMapMyRide
6 | Extracts Geo location data from parseMapMyRide workout application database workout.db as well as user related information extracted from mmkd_user file. These files are located in /apps/com.mapmyride.android2/db.
7 |
8 | Sample usage:
9 |
10 | python parseMapMyRide.py
11 | Workout(s) extracted: 3
12 | Entries with GPS location extracted: 1407 Import the file workoutGPS.txt into excel using ; as delimiter.
13 | Extracted user data into userMapMyRide.csv
14 |
--------------------------------------------------------------------------------
/printGetPostVariables.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # Author David Bernal
3 | '''
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 | This program is distributed in the hope that it will be useful,
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 | You should have received a copy of the GNU General Public License
13 | along with this program. If not, see .
14 | '''
15 |
16 | #This program is useful to debug web applicatons, it sets up a web server and prints all the POST parameters sent as well as all the headers.
17 |
18 | from urlparse import urlparse, parse_qs
19 | import BaseHTTPServer
20 | import time
21 |
22 | HOST_NAME = '0.0.0.0'
23 | PORT_NUMBER = 80
24 |
25 | class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
26 |
27 | def do_HEAD(s):
28 | s.send_response(404)
29 | s.send_header("Content-type", "text/html")
30 | s.end_headers()
31 |
32 | def do_GET(s):
33 | """Respond to a GET request."""
34 | print "GET request"
35 | s.send_response(200)
36 | s.send_header("Content-type", "text/html")
37 | s.end_headers()
38 |
39 | query_components = parse_qs(urlparse(s.path).query)
40 |
41 | print s.headers
42 | #print query_components
43 | print urlparse(s.path).query
44 | for component in query_components.keys():
45 | print "component: " + component + " value: " + str(query_components[component])
46 | print "-------"
47 |
48 | s.wfile.write("
Response
")
49 | return
50 |
51 | def do_POST(s):
52 | """Respond to a POST request."""
53 | print "POST request"
54 | s.send_response(200)
55 | s.send_header("Content-type", "text/html")
56 | s.end_headers()
57 |
58 | length = int(s.headers.getheader('content-length'))
59 | field_data = s.rfile.read(length)
60 | query_components = parse_qs(field_data)
61 |
62 | s.wfile.write(" Response
")
63 | print s.headers
64 |
65 | for component in query_components.keys():
66 | value = query_components[component][0]
67 |
68 | print "component: " + component + " -- value: " + str(value)
69 |
70 | if __name__ == '__main__':
71 | server_class = BaseHTTPServer.HTTPServer
72 | httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler)
73 | print time.asctime(), "Inicio - %s:%s" % (HOST_NAME, PORT_NUMBER)
74 | try:
75 | httpd.serve_forever()
76 | except KeyboardInterrupt:
77 | pass
78 |
--------------------------------------------------------------------------------
/parseMapMyRide.py:
--------------------------------------------------------------------------------
1 | # Author David Bernal
2 | '''
3 | This program is free software: you can redistribute it and/or modify
4 | it under the terms of the GNU General Public License as published by
5 | the Free Software Foundation, either version 3 of the License, or
6 | (at your option) any later version.
7 |
8 | This program is distributed in the hope that it will be useful,
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 |
13 | You should have received a copy of the GNU General Public License
14 | along with this program. If not, see .
15 | '''
16 |
17 | # Parser for mapMyRide appliations, extracts user, workout and GPS data for every workout.
18 | import sqlite3
19 | import os
20 | import sys
21 | import time
22 |
23 | def epocToUTC(epoc):
24 | return time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(float(epoc)))
25 |
26 | mapMyRideWorkoutDB = "workout.db"
27 |
28 | if not os.path.isfile(mapMyRideWorkoutDB):
29 | print "Please place the file " + mapMyRideWorkoutDB + " on the same folder than " + sys.argv[0] + " and try again."
30 | sys.exit(1)
31 |
32 | f = open("workoutSummary.csv", "w")
33 | db = sqlite3.connect(mapMyRideWorkoutDB)
34 | res = db.execute("select localid, name, starttime, endtime, notes from workouts")
35 | col_name_list = [tuple[0] for tuple in res.description]
36 | f.write(";".join(col_name_list))
37 |
38 | workoutCount = 0
39 | for row in res:
40 | workoutCount += 1
41 | f.write("\n" + str(row[0]) + ";" + row[1] + ";" + epocToUTC(row[2][:10]) + ";" + epocToUTC(row[3][:10]) + ";" + str(row[4]) )
42 | f.close()
43 | print "Workout(s) extracted: " + str(workoutCount)
44 |
45 | f = open("workoutGPS.txt", "w")
46 | res = db.execute("select localid, timestamp, longitude, latitude, altitude from timeseries")
47 | col_name_list = [tuple[0] for tuple in res.description]
48 | f.write(";".join(col_name_list) + ";Google maps URL (Generated by the script)")
49 |
50 | timeSeriesCount = 0
51 | for row in res:
52 | timeSeriesCount += 1
53 | f.write("\n" + row[0] + ";" + epocToUTC(str(row[1])[:10]) + ";" + str(row[2]) + ";" + str(row[3]) + ";" + str(row[4]) + ";http://maps.google.com/?q=" + str(row[3]) +","+str(row[2]))
54 | f.close()
55 |
56 | print "Entries with GPS location extracted: " + str(timeSeriesCount) + " Import the file workoutGPS.txt into excel using ; as delimiter."
57 |
58 | mapMyRideUserDB = "mmdk_user"
59 |
60 | if not os.path.isfile(mapMyRideUserDB):
61 | print "To extract user data please place the file " + mapMyRideUserDB + " on the same folder than " + sys.argv[0] + " and try again."
62 | sys.exit(1)
63 |
64 | f = open("userMapMyRide.csv", "w")
65 | db = sqlite3.connect(mapMyRideUserDB)
66 | res = db.execute("select username, email, first_name, last_name, birthdate, height, weight, gender, date_joined, location_country, profile_image_medium from user_entity")
67 | col_name_list = [tuple[0] for tuple in res.description]
68 | f.write(",".join(col_name_list))
69 |
70 | for row in res:
71 | f.write("\n" + row[0] + "," + row[1] + "," + row[2] + "," + row[3] + "," + str(row[4]) + "," + str(row[5])+ "," + str(row[6]) + "," + row[7] + "," + epocToUTC(str(row[8])[:10]) + "," + row[9] + "," + row[10])
72 | f.close()
73 | print "Extracted user data into userMapMyRide.csv"
--------------------------------------------------------------------------------