├── log-monkey.png
├── sysdiagnose-sys.py
├── sysdiagnose-uuid2path.py
├── sysdiagnose-networkprefs.py
├── sysdiagnose-net-ext-cache.py
├── sysdiagnose-networkinterfaces.py
├── sysdiagnose-mobilecontainermanager.py
├── sysdiagnose-appupdates.py
├── sysdiagnose-mobilebackup.py
├── sysdiagnose-wifi-icloud.py
├── sysdiagnose-mobileactivation.py
├── sysdiagnose-wifi-plist.py
├── README.md
├── sysdiagnose-appconduit.py
├── sysdiagnose-wifi-net.py
└── sysdiagnose-wifi-kml.py
/log-monkey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cheeky4n6monkey/iOS_sysdiagnose_forensic_scripts/HEAD/log-monkey.png
--------------------------------------------------------------------------------
/sysdiagnose-sys.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from /logs/SystemVersion/SystemVersion.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | version_string = "sysdiagnose-sys.py v2019-05-10 Version 1.0"
12 |
13 | if sys.version_info[0] < 3:
14 | print("Must be using Python 3! Exiting ...")
15 | exit(-1)
16 |
17 | print("Running " + version_string + "\n")
18 |
19 | usage = "\n%prog -i inputfile\n"
20 |
21 | parser = OptionParser(usage=usage)
22 | parser.add_option("-i", dest="inputfile",
23 | action="store", type="string",
24 | help="/logs/SystemVersion/SystemVersion.plist To Be Searched")
25 | (options, args) = parser.parse_args()
26 |
27 | with open(options.inputfile, 'rb') as fp:
28 | pl = plistlib.load(fp)
29 | print("ProductName = " + pl["ProductName"])
30 | print("ProductVersion = " + pl["ProductVersion"])
31 | print("ProductBuildVersion = " + pl["ProductBuildVersion"])
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/sysdiagnose-uuid2path.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from logs/tailspindb/UUIDToBinaryLocations (XML plist)
5 | # Uses Python3's plistlib
6 | # Author: cheeky4n6monkey@gmail.com
7 |
8 | import sys
9 | from optparse import OptionParser
10 | import plistlib
11 | import pprint
12 |
13 | version_string = "sysdiagnose-uuid2path.py v2019-05-10 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 | usage = "\n%prog -i inputfile\n"
20 |
21 | parser = OptionParser(usage=usage)
22 | parser.add_option("-i", dest="inputfile",
23 | action="store", type="string",
24 | help="logs/tailspindb/UUIDToBinaryLocations plist To Be Printed")
25 | (options, args) = parser.parse_args()
26 |
27 | #no arguments given by user, print help and exit
28 | if len(sys.argv) == 1:
29 | parser.print_help()
30 | exit(-1)
31 |
32 | print("Running " + version_string + "\n")
33 |
34 | with open(options.inputfile, 'rb') as fp:
35 | pl = plistlib.load(fp)
36 | for key, val in pl.items():
37 | print(str(key) + ", " + str(val))
38 |
39 | print("\n" + str(len(pl.keys())) + " GUIDs found\n")
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/sysdiagnose-networkprefs.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from /logs/Networking/preferences.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | version_string = "sysdiagnose-networkprefs.py v2019-05-10 Version 1.0"
12 |
13 | if sys.version_info[0] < 3:
14 | print("Must be using Python 3! Exiting ...")
15 | exit(-1)
16 |
17 | print("Running " + version_string + "\n")
18 |
19 | usage = "\n%prog -i inputfile\n"
20 |
21 | parser = OptionParser(usage=usage)
22 | parser.add_option("-i", dest="inputfile",
23 | action="store", type="string",
24 | help="/logs/Networking/preferences.plist To Be Searched")
25 | (options, args) = parser.parse_args()
26 |
27 | with open(options.inputfile, 'rb') as fp:
28 | pl = plistlib.load(fp)
29 | #print(pl.keys()) # dict_keys(['CurrentSet', 'System', 'Sets', 'NetworkServices'])
30 |
31 | if 'System' in pl.keys():
32 | #print(pl["System"])
33 | #print(type(pl["System"])) = dict
34 | if 'System' in pl["System"].keys():
35 | for key, val in pl["System"].items():
36 | if key == 'System':
37 | print("System ComputerName = " + val["ComputerName"]) # System/System/ComputerName
38 | print("System HostName = " + val["HostName"]) # System/System/HostName
39 | if key == 'Network':
40 | for key2, val2 in val["HostNames"].items():
41 | print("Network LocalHostName = " + val2) # for each System/Network/HostNames/LocalHostName
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/sysdiagnose-net-ext-cache.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from logs/Networking/com.apple.networkextension.cache.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | #import pprint
12 |
13 | version_string = "sysdiagnose-net-ext-cache.py v2019-05-10 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 |
20 | usage = "\n%prog -i inputfile\n"
21 |
22 | parser = OptionParser(usage=usage)
23 | parser.add_option("-i", dest="inputfile",
24 | action="store", type="string",
25 | help="logs/Networking/com.apple.networkextension.cache.plist To Be Searched")
26 | parser.add_option("-v", dest="verbose",
27 | action="store_true", default=False,
28 | help="Print GUIDs as well as app names")
29 | (options, args) = parser.parse_args()
30 |
31 | #no arguments given by user, print help and exit
32 | if len(sys.argv) == 1:
33 | parser.print_help()
34 | exit(-1)
35 |
36 | print("Running " + version_string + "\n")
37 |
38 | count = 0
39 | with open(options.inputfile, 'rb') as fp:
40 | pl = plistlib.load(fp)
41 | #pprint.pprint(pl)
42 | #print(pl.keys())
43 |
44 | if 'app-rules' in pl.keys():
45 | for key, list1 in pl["app-rules"].items():
46 | count += 1
47 | if (options.verbose):
48 | print(str(key) + " = " + ', '.join(list1)) # verbose with GUIDs
49 | else:
50 | print(str(key)) # just app names
51 |
52 | print("\n" + str(count) + " cache entries retrieved\n")
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/sysdiagnose-networkinterfaces.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from logs/Networking/NetworkInterfaces.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | version_string = "sysdiagnose-networkinterfaces.py v2019-11-08 Version 1.0"
12 |
13 | if sys.version_info[0] < 3:
14 | print("Must be using Python 3! Exiting ...")
15 | exit(-1)
16 |
17 | print("Running " + version_string + "\n")
18 |
19 | usage = "\n%prog -i inputfile\n"
20 |
21 | parser = OptionParser(usage=usage)
22 | parser.add_option("-i", dest="inputfile",
23 | action="store", type="string",
24 | help="logs/Networking/NetworkInterfaces.plist To Be Searched")
25 | (options, args) = parser.parse_args()
26 |
27 | with open(options.inputfile, 'rb') as fp:
28 | pl = plistlib.load(fp)
29 | if 'Interfaces' in pl.keys():
30 | #print(pl["Interfaces"])
31 | #print(type(pl["Interfaces"])) = dict
32 |
33 | for dictn in pl['Interfaces']:
34 | print("==================================")
35 | print("BSD Name = " + dictn['BSD Name'])
36 | if 'Active' in dictn.keys():
37 | print("Active = " + str(dictn['Active']))
38 | if 'IOMACAddress' in dictn.keys():
39 | #print("IOMACAddress = " + str(dictn['IOMACAddress'])) # dictn['IOMACAddress'] = bytes type
40 | print("IOMACAddress = " + dictn['IOMACAddress'].hex()) # string type
41 | if 'IOPathMatch' in dictn.keys():
42 | print("IOPathMatch = " + dictn['IOPathMatch'])
43 |
44 | for key, val in dictn['SCNetworkInterfaceInfo'].items():
45 | if key == 'UserDefinedName':
46 | print("UserDefinedName = " + val)
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/sysdiagnose-mobilecontainermanager.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print uninstall infor from logs/MobileContainerManager/containermanagerd.log.0
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 |
10 | version_string = "sysdiagnose-mobilecontainermanager.py v2019-05-10 Version 1.0"
11 |
12 | if sys.version_info[0] < 3:
13 | print("Must be using Python 3! Exiting ...")
14 | exit(-1)
15 |
16 | print("Running " + version_string + "\n")
17 |
18 | usage = "\n%prog -i inputfile\n"
19 |
20 | parser = OptionParser(usage=usage)
21 | parser.add_option("-i", dest="inputfile",
22 | action="store", type="string",
23 | help="logs/MobileContainerManager/containermanagerd.log.0 To Be Searched")
24 | (options, args) = parser.parse_args()
25 |
26 | #no arguments given by user, print help and exit
27 | if len(sys.argv) == 1:
28 | parser.print_help()
29 | exit(-1)
30 |
31 | linecount = 0
32 | hitcount = 0
33 | with open(options.inputfile, 'r') as fp:
34 | data = fp.readlines()
35 |
36 | for line in data:
37 | linecount += 1
38 |
39 | if '[MCMGroupManager _removeGroupContainersIfNeededforUser:groupContainerClass:identifiers:referenceCounts:]: Last reference to group container' in line:
40 | hitcount += 1
41 | #print("\n" + line)
42 | txts = line.split()
43 | #print(txts, linecount)
44 | #print(len(txts))
45 | dayofweek = txts[0]
46 | month = txts[1]
47 | day = txts[2]
48 | time = txts[3]
49 | year = txts[4]
50 | group = txts[15]
51 | print(day + " " + month + " " + year + " " + time + " Removed " + group + " [line " + str(linecount) + "]")
52 |
53 | print("\nFound " + str(hitcount) + " group removal entries\n")
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/sysdiagnose-appupdates.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print connection info from logs/appinstallation/AppUpdates.sqlite.db
5 | # Author: david@autopsit.org
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import time
10 | import datetime
11 | import sqlite3
12 |
13 | version_string = "sysdiagnose-appupdates.py v2019-10-02 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 | print("Running " + version_string + "\n")
20 |
21 | usage = "\n%prog -i inputfile\n"
22 |
23 | parser = OptionParser(usage=usage)
24 | parser.add_option("-i", dest="inputfile",
25 | action="store", type="string",
26 | help="logs/appinstallation/AppUpdates.sqlite.db to be parsed")
27 | (options, args) = parser.parse_args()
28 |
29 | #no arguments given by user, print help and exit
30 | if len(sys.argv) == 1:
31 | parser.print_help()
32 | exit(-1)
33 |
34 | try:
35 | appinstalldb = sqlite3.connect(options.inputfile)
36 | cursor = appinstalldb.cursor()
37 | print("pid\tbundle_id\tinstall_date(UTC)\ttimestamp(UTC)")
38 | for row in cursor.execute("SELECT pid, bundle_id, install_date, timestamp FROM app_updates"):
39 | [pid, bundle_id, install_date, timestamp] = row
40 | if (install_date is not None):
41 | # convert "install_date" from Cocoa EPOCH -> UTC
42 | epoch = install_date + 978307200 # difference between COCOA and UNIX epoch is 978307200 seconds
43 | utctime = datetime.datetime.utcfromtimestamp(epoch)
44 | else:
45 | utctime = "NULL"
46 | if (timestamp is not None):
47 | # convert "timestamp" from Unix EPOCH -> UTC
48 | utctimestamp = datetime.datetime.utcfromtimestamp(timestamp)
49 | else:
50 | utctimestamp = "NULL"
51 |
52 | print("%s\t%s\t%s\t%s" % (pid, bundle_id, utctime, utctimestamp))
53 | except:
54 | print("AN UNHANDLED ERROR OCCURRED AND THE DB WAS NOT PARSED")
55 |
56 |
57 |
58 | # That's all folks ;)
59 |
60 |
--------------------------------------------------------------------------------
/sysdiagnose-mobilebackup.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from logs/MobileBackup/com.apple.MobileBackup.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | #import pprint
12 |
13 | version_string = "sysdiagnose-mobilebackup.py v2019-05-10 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 |
20 | usage = "\n%prog -i inputfile\n"
21 |
22 | parser = OptionParser(usage=usage)
23 | parser.add_option("-i", dest="inputfile",
24 | action="store", type="string",
25 | help="logs/MobileBackup/com.apple.MobileBackup.plist To Be Searched")
26 | (options, args) = parser.parse_args()
27 |
28 | #no arguments given by user, print help and exit
29 | if len(sys.argv) == 1:
30 | parser.print_help()
31 | exit(-1)
32 |
33 | print("Running " + version_string + "\n")
34 |
35 | with open(options.inputfile, 'rb') as fp:
36 | pl = plistlib.load(fp)
37 | #pprint.pprint(pl)
38 | #print(pl.keys())
39 |
40 | if 'BackupStateInfo' in pl.keys():
41 | for key, val in pl["BackupStateInfo"].items():
42 | #print("key = " + str(key) + ", val = " + str(val))
43 | if key == 'date':
44 | print("BackupStateInfo Date = " + str(val))
45 | if key == 'isCloud':
46 | print("BackupStateInfo isCloud = " + str(val))
47 |
48 | if 'RestoreInfo' in pl.keys():
49 | for key, val in pl["RestoreInfo"].items():
50 | if key == 'RestoreDate':
51 | print("RestoreInfo Date = " + str(val))
52 | if key == 'BackupBuildVersion':
53 | print("RestoreInfo BackupBuildVersion = " + str(val))
54 | if key == 'DeviceBuildVersion':
55 | print("RestoreInfo DeviceBuildVersion = " + str(val))
56 | if key == 'WasCloudRestore':
57 | print("RestoreInfo WasCloudRestore = " + str(val))
58 |
59 |
60 |
--------------------------------------------------------------------------------
/sysdiagnose-wifi-icloud.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from WiFi/ICLOUD_com.apple.wifid.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | version_string = "sysdiagnose-wifi-icloud.py v2019-05-10 Version 1.0"
12 |
13 | if sys.version_info[0] < 3:
14 | print("Must be using Python 3! Exiting ...")
15 | exit(-1)
16 |
17 | print("Running " + version_string + "\n")
18 |
19 | usage = "\n%prog -i inputfile\n"
20 |
21 | parser = OptionParser(usage=usage)
22 | parser.add_option("-i", dest="inputfile",
23 | action="store", type="string",
24 | help="WiFi/ICLOUD_com.apple.wifid.plist To Be Searched")
25 | parser.add_option("-t", dest="outputtsv",
26 | action="store_true", default=False,
27 | help="Write TSV output file called sysdiagnose-wifi-icloud-output.TSV")
28 | (options, args) = parser.parse_args()
29 |
30 | netlist = []
31 |
32 | with open(options.inputfile, 'rb') as fp:
33 | pl = plistlib.load(fp)
34 | if 'values' in pl.keys():
35 | name = ""
36 | timestamp =""
37 | bssid = ""
38 | ssid = ""
39 | addedat = ""
40 | addedby = ""
41 | enabled = ""
42 | for key, val in pl['values'].items(): # values contains an entry for each wifi net
43 | print("==================================")
44 | print("Name = " + key)
45 | name = key
46 |
47 | if type(val) == dict:
48 | for key2, val2 in val.items():
49 | if key2 == 'timestamp':
50 | print("timestamp = " + str(val2))
51 | timestamp = str(val2)
52 |
53 | if key2 == 'value':
54 | if type(val2) == dict:
55 | for key3, val3 in val2.items():
56 | if key3 == 'BSSID':
57 | print("BSSID = " + str(val3))
58 | bssid = str(val3)
59 | if key3 == 'SSID_STR':
60 | print("SSID_STR = " + str(val3))
61 | ssid = str(val3)
62 | if key3 == 'added_at':
63 | print("added_at = " + str(val3))
64 | addedat = str(val3)
65 | if key3 == 'added_by':
66 | print("added_by = " + str(val3))
67 | addedby = str(val3)
68 | if key3 == 'enabled':
69 | print("enabled = " + str(val3))
70 | enabled = str(val3)
71 |
72 | netlist.append((name, timestamp, bssid, ssid, addedat, addedby, enabled))
73 |
74 | print("\nRetrieved " + str(len(pl['values'].keys())) + " wifi entries\n")
75 |
76 |
77 | if (options.outputtsv):
78 | with open("sysdiagnose-wifi-icloud-output.TSV", 'w') as wp:
79 | wp.write("NAME\tTIMESTAMP\tBSSID\tSSID\tADDEDAT\tADDEDBY\tENABLED\n") # header
80 | for name, timestamp, bssid, ssid, addedat, addedby, enabled in netlist:
81 | wp.write(name+"\t"+timestamp+"\t"+bssid+"\t"+ssid+"\t"+addedat+"\t"+addedby+"\t"+enabled+"\n")
82 |
83 | print("Also outputted to sysdiagnose-wifi-icloud-output.TSV\n")
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/sysdiagnose-mobileactivation.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print Mobile Activation Startup and Upgrade info from logs/MobileActivation/mobileactivationd.log.*
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 |
10 | version_string = "sysdiagnose-mobileactivation.py v2019-05-10 Version 1.0"
11 |
12 | if sys.version_info[0] < 3:
13 | print("Must be using Python 3! Exiting ...")
14 | exit(-1)
15 |
16 | print("Running " + version_string + "\n")
17 |
18 | usage = "\n%prog -i inputfile\n"
19 |
20 | parser = OptionParser(usage=usage)
21 | parser.add_option("-i", dest="inputfile",
22 | action="store", type="string",
23 | help="logs/MobileActivation/mobileactivationd.log.* To Be Searched")
24 | (options, args) = parser.parse_args()
25 |
26 | #no arguments given by user, print help and exit
27 | if len(sys.argv) == 1:
28 | parser.print_help()
29 | exit(-1)
30 |
31 | linecount = 0
32 | hitcount = 0
33 | activationcount = 0
34 | with open(options.inputfile, 'r') as fp:
35 | data = fp.readlines()
36 |
37 | for line in data:
38 | linecount += 1
39 |
40 | if 'perform_data_migration' in line:
41 | hitcount += 1
42 | #print("\n" + line)
43 | txts = line.split()
44 | #print(txts, linecount)
45 | #print(len(txts))
46 | dayofweek = txts[0]
47 | month = txts[1]
48 | day = txts[2]
49 | time = txts[3]
50 | year = txts[4]
51 | frombuild = txts[12]
52 | tobuild = txts[14]
53 | print("\n" + day + " " + month + " " + year + " " + time + " Upgraded from " + frombuild + " to " + tobuild + " [line " + str(linecount) + "]")
54 |
55 |
56 | if 'MA: main: ____________________ Mobile Activation Startup _____________________' in line:
57 | activationcount += 1
58 | #print("\n" + line)
59 | txts = line.split()
60 | #print(txts, linecount)
61 | #print(len(txts))
62 | dayofweek = txts[0]
63 | month = txts[1]
64 | day = txts[2]
65 | time = txts[3]
66 | year = txts[4]
67 | print("\n" + day + " " + month + " " + year + " " + time + " Mobile Activation Startup " + " [line " + str(linecount) + "]")
68 |
69 | if 'MA: main: build_version:' in line:
70 | #print("\n" + line)
71 | txts = line.split()
72 | #print(txts, linecount)
73 | #print(len(txts))
74 | dayofweek = txts[0]
75 | month = txts[1]
76 | day = txts[2]
77 | time = txts[3]
78 | year = txts[4]
79 | buildver = txts[11]
80 | print(day + " " + month + " " + year + " " + time + " Mobile Activation Build Version = " + buildver)
81 |
82 | if 'MA: main: hardware_model:' in line:
83 | #print("\n" + line)
84 | txts = line.split()
85 | #print(txts, linecount)
86 | #print(len(txts))
87 | dayofweek = txts[0]
88 | month = txts[1]
89 | day = txts[2]
90 | time = txts[3]
91 | year = txts[4]
92 | hwmodel = txts[11]
93 | print(day + " " + month + " " + year + " " + time + " Mobile Activation Hardware Model = " + hwmodel)
94 |
95 | if 'MA: main: product_type:' in line:
96 | #print("\n" + line)
97 | txts = line.split()
98 | #print(txts, linecount)
99 | #print(len(txts))
100 | dayofweek = txts[0]
101 | month = txts[1]
102 | day = txts[2]
103 | time = txts[3]
104 | year = txts[4]
105 | prod = txts[11]
106 | print(day + " " + month + " " + year + " " + time + " Mobile Activation Product Type = " + prod)
107 |
108 | if 'MA: main: device_class:' in line:
109 | #print("\n" + line)
110 | txts = line.split()
111 | #print(txts, linecount)
112 | #print(len(txts))
113 | dayofweek = txts[0]
114 | month = txts[1]
115 | day = txts[2]
116 | time = txts[3]
117 | year = txts[4]
118 | devclass = txts[11]
119 | print(day + " " + month + " " + year + " " + time + " Mobile Activation Device Class = " + devclass)
120 |
121 | print("\nFound " + str(hitcount) + " Upgrade entries")
122 |
123 | print("Found " + str(activationcount) + " Mobile Activation Startup entries\n")
124 |
125 |
--------------------------------------------------------------------------------
/sysdiagnose-wifi-plist.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the values from WiFi/com.apple.wifi.plist or WiFi/preferences.plist
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import plistlib
10 |
11 | #import pprint
12 |
13 | version_string = "sysdiagnose-wifi-plist.py v2019-10-24 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 |
20 | usage = "\n%prog -i inputfile\n"
21 |
22 | parser = OptionParser(usage=usage)
23 | parser.add_option("-i", dest="inputfile",
24 | action="store", type="string",
25 | help="WiFi/com.apple.wifi.plist or WiFi/preferences.plist To Be Searched")
26 | parser.add_option("-t", dest="outputtsv",
27 | action="store_true", default=False,
28 | help="Write TSV output file called sysdiagnose-wifi-plist-output.TSV")
29 | (options, args) = parser.parse_args()
30 |
31 | #no arguments given by user, print help and exit
32 | if len(sys.argv) == 1:
33 | parser.print_help()
34 | exit(-1)
35 |
36 | print("Running " + version_string + "\n")
37 |
38 | outputlist = []
39 | with open(options.inputfile, 'rb', ) as fp:
40 | pl = plistlib.load(fp)
41 | #pprint.pprint(pl)
42 | #print(pl.keys())
43 |
44 | if 'List of known networks' in pl.keys():
45 | for dic in pl['List of known networks']: # list of dicts
46 | #print(item)
47 | print("=============================")
48 | print("SSID_STR = " + dic['SSID_STR'])
49 | ssid = dic['SSID_STR']
50 | bssid = ""
51 | if 'BSSID' in dic.keys():
52 | print("BSSID = " + dic['BSSID'])
53 | bssid = dic['BSSID']
54 |
55 | netusage = ""
56 | if 'networkUsage' in dic.keys():
57 | print("networkUsage = " + str(dic['networkUsage']))
58 | netusage = str(dic['networkUsage'])
59 |
60 | countrycode = ""
61 | if '80211D_IE' in dic.keys():
62 | #print(type(dic['80211D_IE'])) # dict
63 | for key2, val2 in dic['80211D_IE'].items():
64 | if key2 == 'IE_KEY_80211D_COUNTRY_CODE':
65 | print("IE_KEY_80211D_COUNTRY_CODE = " + val2)
66 | countrycode = val2
67 |
68 | devname = ""
69 | mfr = ""
70 | serialnum = ""
71 | modelname = ""
72 | if 'WPS_PROB_RESP_IE' in dic.keys():
73 | for key3, val3 in dic['WPS_PROB_RESP_IE'].items():
74 |
75 | if key3 == 'IE_KEY_WPS_DEV_NAME':
76 | print("IE_KEY_WPS_DEV_NAME = " + val3)
77 | devname = val3
78 | if key3 == 'IE_KEY_WPS_MANUFACTURER':
79 | print("IE_KEY_WPS_MANUFACTURER = " + val3)
80 | mfr = val3
81 | if key3 == 'IE_KEY_WPS_SERIAL_NUM':
82 | print("IE_KEY_WPS_SERIAL_NUM = " + val3)
83 | serialnum = val3
84 | #serialnum = "testserial"
85 | if key3 == 'IE_KEY_WPS_MODEL_NAME':
86 | print("IE_KEY_WPS_MODEL_NAME = " + val3)
87 | modelname = val3
88 | #modelname = "testmodel"
89 |
90 | lastjoined = ""
91 | if 'lastJoined' in dic.keys():
92 | print("lastJoined = " + str(dic['lastJoined']))
93 | lastjoined = str(dic['lastJoined'])
94 | lastautojoined = ""
95 | if 'lastAutoJoined' in dic.keys():
96 | print("lastAutoJoined = " + str(dic['lastAutoJoined']))
97 | lastautojoined = str(dic['lastAutoJoined'])
98 | enabled = ""
99 | if 'enabled' in dic.keys():
100 | enabled = str(dic['enabled'])
101 | print("enabled = " + str(dic['enabled']))
102 | print("=============================\n")
103 |
104 | outputlist.append((ssid, bssid, netusage, countrycode, devname, mfr, serialnum, modelname, lastjoined, lastautojoined, enabled))
105 |
106 |
107 | if (options.outputtsv):
108 | with open("sysdiagnose-wifi-plist-output.TSV", 'w') as wp:
109 | wp.write("SSID\tBSSID\tNETUSAGE\tCOUNTRYCODE\tDEVICENAME\tMANUFACTURER\tSERIALNUM\tMODELNAME\tLASTJOINED\tLASTAUTOJOINED\tENABLED\n") # header
110 | for ssid, bssid, netusage, countrycode, devname, mfr, serialnum, modelname, lastjoined, lastautojoined, enabled in outputlist:
111 | wp.write(ssid+"\t"+bssid+"\t"+netusage+"\t"+countrycode+"\t"+devname+"\t"+mfr+"\t"+serialnum+"\t"+modelname+"\t"+lastjoined+"\t"+lastautojoined+"\t"+enabled+"\n")
112 |
113 | print("Also outputted to sysdiagnose-wifi-plist-output.TSV\n")
114 |
115 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # iOS_sysdiagnose_forensic_scripts
2 |
3 |
4 |
5 |
7 |
8 |
9 | iOS devices have the ability to create numerous logs containing forensically useful information.
10 | These logs may contain volatile information which should be collected ASAP during forensic processing.
11 |
12 | Mattia Epifani (Github: mattiaepi , [Twitter: @mattiaep](https://twitter.com/mattiaep)) , Heather Mahalik (Github: hmahalik , [Twitter: @HeatherMahalik](https://twitter.com/HeatherMahalik)) and [@Cheeky4n6monkey](https://twitter.com/cheeky4n6monkey) have written a document describing their initial research into these logs. This document is freely available from:
13 |
https://www.for585.com/sysdiagnose
14 |
15 | Big Thankyous to Peter Maaswinkel and Pranav Anand for their additional testing and document review.
16 |
Thanks also to David Durvaux (ddurvaux) for sharing his script - sysdiagnose-appupdates.py
17 |
Thanks to Silvia Spallarossa for her testing of the scripts and bug fixes for sysdiagnose-networkinterfaces.py.
18 |
19 | It is strongly suggested that interested forensic monkeys first read the document BEFORE attempting to use these scripts.
20 | The document details the various iOS logs available, methods of generating and collecting those logs and how to use these scripts to extract forensically interesting information from them.
21 |
22 | These scripts were written for Python3 (tested under Ubuntu 16.04 and macOS X Mojave) using test data from various iOS12 devices. They do not require any third party Python libaries.
23 |
24 |
25 | Here is a usage summary of the available scripts:
26 |
27 | | Name | Description | Output | Usage Example |
28 | | sysdiagnose-sys.py | Extracts OS info from logs/SystemVersion/SystemVersion.plist | Command line | python3 sysdiagnose-sys.py -i SystemVersion.plist |
29 |
30 | | sysdiagnose-networkprefs.py | Extracts hostnames from logs/Networking/preferences.plist | Command line | python3 sysdiagnose-networkprefs.py -i preferences.plist |
31 |
32 | | sysdiagnose-networkinterfaces.py | Extracts network config info from logs/Networking/NetworkInterfaces.plist | Command line | python3 sysdiagnose-networkinterfaces.py -i NetworkInterfaces.plist |
33 |
34 | | sysdiagnose-mobilecontainermanager.py | Extracts uninstall info from logs/MobileContainerManager/containermanagerd.log.0 | Command line | python3 sysdiagnose-mobilecontainermanager.py -i containermanagerd.log.0 |
35 |
36 | | sysdiagnose-mobilebackup.py | Extracts backup info from logs/MobileBackup/com.apple.MobileBackup.plist | Command line | python3 sysdiagnose-mobilebackup.py -i com.apple.MobileBackup.plist |
37 |
38 | | sysdiagnose-mobileactivation.py | Mobile Activation Startup and Upgrade info from logs/MobileActivation/mobileactivationd.log.* | Command line | python3 sysdiagnose-mobileactivation.py -i mobileactivation.log |
39 |
40 | | sysdiagnose-wifi-plist.py | Extracts Wi-Fi network values from WiFi/com.apple.wifi.plist Use -t option for TSV output file
41 | | Command line and TSV | python3 sysdiagnose-wifi-plist.py -i com.apple.wifi.plist -t |
42 |
43 | | sysdiagnose-wifi-icloud.py | Extracts Wi-Fi network values from WiFi/ICLOUD.apple.wifid.plist Use -t option for TSV output file | Command line and TSV | python3 sysdiagnose-wifi-icloud.py -i ICLOUD.apple.wifid.plist -t |
44 |
45 | | sysdiagnose-wifi-net.py | Extracts Wi-Fi network names to categorized TSV files from WiFi/wifi *.log | TSV files | python3 sysdiagnose-wifi-net.py -i wifi-buf.log |
46 |
47 | | sysdiagnose-wifi-kml.py | Extracts Wi-Fi geolocation values and creates a KML from wifi*.log | KML | python3 sysdiagnose-wifi-kml.py -i wifi-buf.log |
48 |
49 | | sysdiagnose-uuid2path.py | Extracts GUID and path info from logs/tailspindb/UUIDToBinaryLocations | Command line (comma separated) | python3 sysdiagnose-uuid2path.py -i UUIDToBinaryLocations |
50 |
51 | | sysdiagnose-net-ext-cache.py | Extracts app name & GUID info from logs/Networking/com.apple.networkextension.cache.plist Use -v option to print GUID info | Command line | python3 sysdiagnose-net-ext-cache.py -i com.apple.networkextension.cache.plist -v |
52 |
53 | | sysdiagnose-appconduit.py | Extracts connection info from logs/AppConduit/AppConduit.log.* | Command line | python3 sysdiagnose-appconduit.py -i AppConduit.log |
54 |
55 | | sysdiagnose-appupdates.py | Extracts update info from logs/appinstallation/AppUpdates.sqlite.db.* | Command line | python3 sysdiagnose-appupdates.py -i AppUpdates.sqlitedb |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/sysdiagnose-appconduit.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print connection info from logs/AppConduit/AppConduit.log.*
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 |
10 | version_string = "sysdiagnose-appconduit.py v2019-05-10 Version 1.0"
11 |
12 | if sys.version_info[0] < 3:
13 | print("Must be using Python 3! Exiting ...")
14 | exit(-1)
15 |
16 | print("Running " + version_string + "\n")
17 |
18 | usage = "\n%prog -i inputfile\n"
19 |
20 | parser = OptionParser(usage=usage)
21 | parser.add_option("-i", dest="inputfile",
22 | action="store", type="string",
23 | help="logs/AppConduit/AppConduit.log.* To Be Searched")
24 | (options, args) = parser.parse_args()
25 |
26 | #no arguments given by user, print help and exit
27 | if len(sys.argv) == 1:
28 | parser.print_help()
29 | exit(-1)
30 |
31 | linecount = 0
32 | connectedcount = 0
33 | resumecount = 0
34 | reunioncount = 0
35 | disconnectedcount = 0
36 | suspendcount = 0
37 |
38 | with open(options.inputfile, 'r') as fp:
39 | data = fp.readlines()
40 |
41 | for line in data:
42 | linecount += 1
43 |
44 | if '[ACXCompanionSyncConnectionManager devicesAreNowConnected:]: Device' in line:
45 | connectedcount += 1
46 | #print("\n" + line)
47 | txts = line.split()
48 | #print(txts, linecount)
49 | #print(len(txts))
50 | if(len(txts) > 10):
51 | dayofweek = txts[0]
52 | month = txts[1]
53 | day = txts[2]
54 | time = txts[3]
55 | year = txts[4]
56 | device = txts[11]
57 | print(day + " " + month + " " + year + " " + time + " - " + device + " Now Connected [line " + str(linecount) + "]")
58 | else:
59 | #malformed message ... ignore
60 | print("\nMalformed devicesAreNowConnected entry at line "+str(linecount)+"\n")
61 |
62 |
63 | if '[ACXInstallQueue reachabilityChangedForDevice:]_block_invoke: Resuming because' in line:
64 | resumecount += 1
65 | #print("\n" + line)
66 | txts = line.split()
67 | #print(txts, linecount)
68 | #print(len(txts))
69 | if(len(txts) > 11):
70 | dayofweek = txts[0]
71 | month = txts[1]
72 | day = txts[2]
73 | time = txts[3]
74 | year = txts[4]
75 | device = txts[12]
76 | print(day + " " + month + " " + year + " " + time + " - " + device + " Resuming [line " + str(linecount) + "]")
77 | else:
78 | #malformed message ... ignore
79 | print("\nMalformed Resuming entry at line "+str(linecount)+"\n")
80 |
81 |
82 | if '[ACXCompanionSyncConnection performReunionSyncWithReason:]_block_invoke: Starting reunion sync because ' in line:
83 | reunioncount += 1
84 | #print("\n" + line)
85 | txts = line.split()
86 | #print(txts, linecount)
87 | #print(len(txts))
88 | if(len(txts) > 14):
89 | dayofweek = txts[0]
90 | month = txts[1]
91 | day = txts[2]
92 | time = txts[3]
93 | year = txts[4]
94 | device = txts[15]
95 | print(day + " " + month + " " + year + " " + time + " - " + device + " Starting Reunion Sync [line " + str(linecount) + "]")
96 | else:
97 | #malformed message ... ignore
98 | print("\nMalformed Sync entry at line "+str(linecount)+"\n")
99 |
100 |
101 | if '[ACXCompanionSyncConnectionManager devicesAreNoLongerConnected:]: Device' in line:
102 | disconnectedcount += 1
103 | #print("\n" + line)
104 | txts = line.split()
105 | #print(txts, linecount)
106 | #print(len(txts))
107 | if(len(txts) > 10):
108 | dayofweek = txts[0]
109 | month = txts[1]
110 | day = txts[2]
111 | time = txts[3]
112 | year = txts[4]
113 | device = txts[11]
114 | print(day + " " + month + " " + year + " " + time + " - " + device + " Disconnected [line " + str(linecount) + "]")
115 | else:
116 | #malformed message ... ignore
117 | print("\nMalformed devicesAreNoLongerConnected entry at line "+str(linecount)+"\n")
118 |
119 | if '[ACXInstallQueue reachabilityChangedForDevice:]_block_invoke: Suspending because' in line:
120 | suspendcount += 1
121 | #print("\n" + line)
122 | txts = line.split()
123 | #print(txts, linecount)
124 | #print(len(txts))
125 | if(len(txts) > 11):
126 | dayofweek = txts[0]
127 | month = txts[1]
128 | day = txts[2]
129 | time = txts[3]
130 | year = txts[4]
131 | device = txts[12]
132 | print(day + " " + month + " " + year + " " + time + " - " + device + " Suspending [line " + str(linecount) + "]")
133 | else:
134 | #malformed message ... ignore
135 | print("\nMalformed Suspending entry at line "+str(linecount)+"\n")
136 |
137 |
138 | print("\nFound " + str(connectedcount) + " Now Connected entries")
139 | print("Found " + str(resumecount) + " Resuming entries")
140 | print("Found " + str(reunioncount) + " Starting Reunion Sync entries")
141 | print("Found " + str(disconnectedcount) + " Disconnected entries")
142 | print("Found " + str(suspendcount) + " Suspending entries\n")
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/sysdiagnose-wifi-net.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the Network names (and log to TSV) from WiFi/wifi*.log
5 | # Author: cheeky4n6monkey@gmail.com
6 |
7 | import sys
8 | from optparse import OptionParser
9 | import tarfile
10 | import re
11 | import shlex
12 |
13 | version_string = "sysdiagnose-wifi-net.py v2019-05-10 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 | #no arguments given by user, print help and exit
20 | if len(sys.argv) == 1:
21 | parser.print_help()
22 | exit(-1)
23 |
24 | print("Running " + version_string + "\n")
25 |
26 | usage = "\n%prog -i inputfile\n"
27 |
28 | parser = OptionParser(usage=usage)
29 | parser.add_option("-i", dest="inputfile",
30 | action="store", type="string",
31 | help="WiFi/wifi*.log To Be Searched")
32 | (options, args) = parser.parse_args()
33 |
34 | linecount = 0
35 | ignorecount = 0
36 | filterednetworkscount = 0
37 | channelsfoundcount = 0
38 | backgroundscancount = 0
39 | MRUnetworkscount = 0
40 | ppmattachedcount = 0
41 | alreadyattachedcount = 0
42 |
43 | filterednetworks = []
44 | channelsfound = []
45 | backgroundscan = []
46 | MRUnetworks = []
47 | ppmattached = []
48 | alreadyattached = []
49 |
50 | #print(options.inputfile[0:-4]) # = wifi-buf-04-26-2019__16:00:52.768.log
51 |
52 | if options.inputfile.endswith('.tgz'): # eg wifi-buf-04-26-2019__16:00:52.768.log.tgz
53 | # untar file first to current directory
54 | # tarfile.open Throws InvalidHeader error!
55 | with tarfile.open(options.inputfile, 'r:gz') as t:
56 | t.extractall('./')
57 | # does not get here due to exception ... todo
58 |
59 | # readfile = ass-ume extracted name is same as input name minus the .tgz
60 | with open(options.inputfile[0:-4], 'r') as fp:
61 | data = fp.readlines()
62 | # TODO: Implement processing when given zip file
63 |
64 | else: # ass-ume input file has been untarred already and is plaintext
65 | with open(options.inputfile, 'r') as fp:
66 | data = fp.readlines()
67 |
68 | for line in data:
69 | linecount += 1
70 |
71 | if 'AJScan: Filtered networks -' in line:
72 | #print("\n" + line)
73 | txts = line.split()
74 | #print(txts, str(linecount))
75 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
76 | if len(txts) > 7: # 7th field is first network name (after "AJScan: Filtered networks -")
77 | filterednetworkscount += 1
78 | date = txts[0]
79 | time = txts[1]
80 | networks = txts[7:-1] # skip last item "..."
81 | #print("$$$ Filtered Networks found = " + ' '.join(networks) + ", line = " + str(linecount))
82 | for net in networks: # each network gets own entry
83 | filterednetworks.append((date, time, net, linecount))
84 | else:
85 | #wrong number of fields (eg missing date) ... skip hit completely
86 | print("\nERROR - Filtered Networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
87 | ignorecount += 1
88 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
89 | if len(txts) > 6: # 7th field is first network name (after "AJScan: Filtered networks -")
90 | filterednetworkscount += 1
91 | date = txts[0]
92 | time = txts[1]
93 | networks = txts[6:-1] # skip last item "..."
94 | #print("$$$ Filtered Networks found = " + ' '.join(networks) + ", line = " + str(linecount))
95 | for net in networks: # each network gets own entry
96 | filterednetworks.append((date, time, net, linecount))
97 | else:
98 | #wrong number of fields (eg missing date) ... skip hit completely
99 | print("\nERROR - Filtered Networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
100 | ignorecount += 1
101 |
102 | if 'Scanning 2Ghz Channels found:' in line:
103 | #print("\n" + line)
104 | txts = line.split()
105 | #print(txts, str(linecount))
106 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
107 | # Can be empty ...
108 | if len(txts) > 7: # there is something after the "Scanning 2Ghz Channels found:"
109 | channelsfoundcount += 1
110 | date = txts[0]
111 | time = txts[1]
112 | networks = ' '.join(txts[7:])
113 | networks2 = networks.split(', ') # parse comma seperated string list
114 | #print("@@@ Scanning Channels found: " + ' '.join(networks2) + ", line = " + str(linecount))
115 | for net in networks2: # each network gets own entry
116 | channelsfound.append((date, time, net, linecount))
117 | else:
118 | #wrong number of fields (eg missing date) ... skip hit completely
119 | print("\nERROR - Scanning Channels = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
120 | ignorecount += 1
121 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
122 | # Can be empty ...
123 | if len(txts) > 6: # there is something after the "Scanning 2Ghz Channels found:"
124 | channelsfoundcount += 1
125 | date = txts[0]
126 | time = txts[1]
127 | networks = ' '.join(txts[6:])
128 | networks2 = networks.split(', ') # parse comma seperated string list
129 | #print("@@@ Scanning Channels found: " + ' '.join(networks2) + ", line = " + str(linecount))
130 | for net in networks2: # each network gets own entry
131 | channelsfound.append((date, time, net, linecount))
132 | else:
133 | #wrong number of fields (eg missing date) ... skip hit completely
134 | print("\nERROR - Scanning Channels = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
135 | ignorecount += 1
136 |
137 | if 'Preparing background scan request for ' in line:
138 | #print("\n" + line)
139 | txts = line.split()
140 | #print(txts, str(linecount))
141 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
142 | if len(txts) > 7: # 7th field should contain network name
143 | backgroundscancount += 1
144 | date = txts[0]
145 | time = txts[1]
146 |
147 | result = re.search('Preparing background scan request for (.*) on channels:', line)
148 | #print(result)
149 | if (result is None): # search for 2nd variant
150 | result = re.search('Preparing background scan request for (.*) Background Scan Caching is Enabled', line)
151 | if (result is not None):
152 | networks = result.group(1) # group all network names together via regex
153 | networks2 = shlex.split(networks) # split which is "" friendly. It won't break up quoted phrases that have spaces
154 |
155 | #print("!!! Background Scan networks found " + ' '.join(networks2) + ", line = " + str(linecount))
156 | for net in networks2: # each network gets own entry
157 | backgroundscan.append((date, time, net, linecount))
158 | else:
159 | #wrong number of fields (eg missing date) ... skip hit completely
160 | print("\nERROR - background scan request = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
161 | ignorecount += 1
162 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
163 | if len(txts) > 6: # 7th field should contain network name
164 | backgroundscancount += 1
165 | date = txts[0]
166 | time = txts[1]
167 |
168 | result = re.search('Preparing background scan request for (.*) on channels:', line)
169 | #print(result)
170 | if (result is None): # search for 2nd variant
171 | result = re.search('Preparing background scan request for (.*) Background Scan Caching is Enabled', line)
172 | if (result is not None):
173 | networks = result.group(1) # group all network names together via regex
174 | networks2 = shlex.split(networks) # split which is "" friendly. It won't break up quoted phrases that have spaces
175 |
176 | #print("!!! Background Scan networks found " + ' '.join(networks2) + ", line = " + str(linecount))
177 | for net in networks2: # each network gets own entry
178 | backgroundscan.append((date, time, net, linecount))
179 | else:
180 | #wrong number of fields (eg missing date) ... skip hit completely
181 | print("\nERROR - background scan request = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
182 | ignorecount += 1
183 |
184 | if 'Scanning for MRU Networks:' in line:
185 | #print("\n" + line)
186 | txts = line.split()
187 | #print(txts, str(linecount))
188 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
189 | if len(txts) > 7: # 7th field should contain network name
190 | MRUnetworkscount += 1
191 | date = txts[0]
192 | time = txts[1]
193 | # time can be 3/18/2019 6:40:17.341 Scanning for MRU Networks:
194 | # or 1/07/2019 19:12:36.354 Scanning for MRU Networks:
195 | tlength = len(time) # should be 11 or 12
196 | mru = line.split(' ')# double spaces between networks eg "BLAH" on channels: 1 "BLAH2" on channels: 2
197 | #print(mru)
198 | #print("mru len = " + str(len(mru)))
199 |
200 | if (tlength == 11):
201 | # mru = [' 1/19/2019', '8:46:40.818 Scanning for MRU Networks:', '"Marriott_GUEST" on channels: 136 48 \n']
202 | if len(mru) > 2: # has to be something after "Scanning for MRU Networks:"
203 | #print("### MRU networks found: " + ', '.join(mru[2:]) + ", line = " + str(linecount))
204 | for m in mru[2:]:
205 | MRUnetworks.append((date, time, m.rstrip(), linecount))
206 |
207 | if (tlength == 12):
208 | # mru = [' 1/07/2019 19:11:57.026 Scanning for MRU Networks:', '"AndroidAP" on channels: 1', '"Vodafone" on channels: 36', '"*WIFI-AIRPORT" on channels: 60 40 \n']
209 | if len(mru) > 1: # has to be something after "Scanning for MRU Networks:"
210 | #print("### MRU networks found: " + ', '.join(mru[1:]) + ", line = " + str(linecount))
211 | for m in mru[1:]:
212 | MRUnetworks.append((date, time, m.rstrip(), linecount))
213 | else:
214 | #wrong number of fields (eg missing date) ... skip hit completely
215 | print("\nERROR - MRU networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
216 | ignorecount += 1
217 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
218 | if len(txts) > 6: # 7th field should contain network name
219 | MRUnetworkscount += 1
220 | date = txts[0]
221 | time = txts[1]
222 | # time can be 3/18/2019 6:40:17.341 Scanning for MRU Networks:
223 | # or 1/07/2019 19:12:36.354 Scanning for MRU Networks:
224 | tlength = len(time) # should be 11 or 12
225 | mru = line.split(' ')# double spaces between networks eg "BLAH" on channels: 1 "BLAH2" on channels: 2
226 | #print(mru)
227 | #print("mru len = " + str(len(mru)))
228 |
229 | if (tlength == 11):
230 | # mru = [' 1/19/2019', '8:46:40.818 Scanning for MRU Networks:', '"Marriott_GUEST" on channels: 136 48 \n']
231 | if len(mru) > 2: # has to be something after "Scanning for MRU Networks:"
232 | #print("### MRU networks found: " + ', '.join(mru[2:]) + ", line = " + str(linecount))
233 | for m in mru[2:]:
234 | MRUnetworks.append((date, time, m.rstrip(), linecount))
235 |
236 | if (tlength == 12):
237 | # mru = [' 1/07/2019 19:11:57.026 Scanning for MRU Networks:', '"AndroidAP" on channels: 1', '"Vodafone" on channels: 36', '"*WIFI-AIRPORT" on channels: 60 40 \n']
238 | if len(mru) > 1: # has to be something after "Scanning for MRU Networks:"
239 | #print("### MRU networks found: " + ', '.join(mru[1:]) + ", line = " + str(linecount))
240 | for m in mru[1:]:
241 | MRUnetworks.append((date, time, m.rstrip(), linecount))
242 | else:
243 | #wrong number of fields (eg missing date) ... skip hit completely
244 | print("\nERROR - MRU networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
245 | ignorecount += 1
246 |
247 | if '__WiFiDeviceManagerReleasePpmResource: PPM attached - still connected to ' in line:
248 | #print("\n" + line)
249 | txts = line.split()
250 | #print(txts, str(linecount))
251 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
252 | if len(txts) > 10:
253 | ppmattachedcount += 1
254 | date = txts[0]
255 | time = txts[1]
256 | net = txts[10:] # Assuming only one entry
257 | #print("$$$ PPM attached networks found = " + ' '.join(net).rstrip('.') + ", line = " + str(linecount))
258 | ppmattached.append((date, time, ' '.join(net).rstrip('.'), linecount)) # net has . at end
259 | else:
260 | #wrong number of fields (eg missing date) ... skip hit completely
261 | print("\nERROR - PPM attached networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
262 | ignorecount += 1
263 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
264 | if len(txts) > 9:
265 | ppmattachedcount += 1
266 | date = txts[0]
267 | time = txts[1]
268 | net = txts[9:] # Assuming only one entry
269 | #print("$$$ PPM attached networks found = " + ' '.join(net).rstrip('.') + ", line = " + str(linecount))
270 | ppmattached.append((date, time, ' '.join(net).rstrip('.'), linecount)) # net has . at end
271 | else:
272 | #wrong number of fields (eg missing date) ... skip hit completely
273 | print("\nERROR - PPM attached networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
274 | ignorecount += 1
275 |
276 | if '__WiFiDeviceManagerAutoAssociate: Already connected to ' in line:
277 | #print("\n" + line)
278 | txts = line.split()
279 | #print(txts, str(linecount))
280 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
281 | if len(txts) > 7:
282 | alreadyattachedcount += 1
283 | date = txts[0]
284 | time = txts[1]
285 | net = txts[7:] # Assuming only one entry
286 | #print("$$$ Already attached networks found = " + ' '.join(net).rstrip('.') + ", line = " + str(linecount))
287 | alreadyattached.append((date, time, ' '.join(net).rstrip('.'), linecount)) # net has . at end
288 | else:
289 | #wrong number of fields (eg missing date) ... skip hit completely
290 | print("\nERROR - Already attached networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
291 | ignorecount += 1
292 |
293 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
294 | if len(txts) > 6:
295 | alreadyattachedcount += 1
296 | date = txts[0]
297 | time = txts[1]
298 | net = txts[6:] # Assuming only one entry
299 | #print("$$$ Already attached networks found = " + ' '.join(net).rstrip('.') + ", line = " + str(linecount))
300 | alreadyattached.append((date, time, ' '.join(net).rstrip('.'), linecount)) # net has . at end
301 | else:
302 | #wrong number of fields (eg missing date) ... skip hit completely
303 | print("\nERROR - Already attached networks = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
304 | ignorecount += 1
305 |
306 | print("\n\n=====================================================")
307 |
308 | print("\nFound " + str(filterednetworkscount) + " filtered network messages in " + options.inputfile)
309 | print("\nFound " + str(channelsfoundcount) + " found channel messages in " + options.inputfile)
310 | print("\nFound " + str(backgroundscancount) + " background scan channel messages in " + options.inputfile)
311 | print("\nFound " + str(MRUnetworkscount) + " MRU network messages in " + options.inputfile)
312 | print("\nFound " + str(ppmattachedcount) + " PPM attached still connected messages in " + options.inputfile)
313 | print("\nFound " + str(alreadyattachedcount) + " already attached still connected messages in " + options.inputfile)
314 | print("\n=====================================================\n")
315 |
316 | if filterednetworkscount > 0:
317 | f_filtered = open("wifi-buf-net_filtered.TSV", "w")
318 | f_filtered.write("DATE\tTIME\tTYPE\tNETWORK\tLINE\tLOGFILE\n")
319 |
320 | for date, time, net, linecount in filterednetworks:
321 | f_filtered.write(date + "\t" + time + "\tFilteredNetworks\t" + net +"\t" + str(linecount) + "\t" + options.inputfile + "\n")
322 | f_filtered.close()
323 | print("Logged "+ str(len(filterednetworks)) + " FilteredNetworks to wifi-buf-net_filtered.TSV output file\n")
324 |
325 | if channelsfoundcount > 0:
326 | f_channel = open("wifi-buf-net_channels.TSV", "w")
327 | f_channel.write("DATE\tTIME\tTYPE\tNETWORK\tLINE\tLOGFILE\n")
328 |
329 | for date, time, net, linecount in channelsfound:
330 | f_channel.write(date + "\t" + time + "\tFoundChannels\t" + net +"\t" + str(linecount) + "\t" + options.inputfile + "\n")
331 | f_channel.close()
332 | print("Logged "+ str(len(channelsfound)) + " FoundChannels to wifi-buf-net_channels.TSV output file\n")
333 |
334 | if backgroundscancount > 0:
335 | f_bgscan = open("wifi-buf-net_bgscan.TSV", "w")
336 | f_bgscan.write("DATE\tTIME\tTYPE\tNETWORK\tLINE\tLOGFILE\n")
337 |
338 | for date, time, net, linecount in backgroundscan:
339 | f_bgscan.write(date + "\t" + time + "\tBGScans\t" + net +"\t" + str(linecount) + "\t" + options.inputfile + "\n")
340 | f_bgscan.close()
341 | print("Logged "+ str(len(backgroundscan)) + " BGScans to wifi-buf-net_bgscan.TSV output file\n")
342 |
343 | if MRUnetworkscount > 0:
344 | f_mru = open("wifi-buf-net_mru.TSV", "w")
345 | f_mru.write("DATE\tTIME\tTYPE\tNETWORK\tLINE\tLOGFILE\n")
346 |
347 | for date, time, m, linecount in MRUnetworks:
348 | f_mru.write(date + "\t" + time + "\tMRUs\t" + m +"\t" + str(linecount) + "\t" + options.inputfile + "\n")
349 |
350 | f_mru.close()
351 | print("Logged "+ str(len(MRUnetworks)) + " MRUs to wifi-buf-net_mru.TSV output file\n")
352 |
353 | if ppmattachedcount > 0:
354 | f_mru = open("wifi-buf-net_ppmattached.TSV", "w")
355 | f_mru.write("DATE\tTIME\tTYPE\tNETWORK\tLINE\tLOGFILE\n")
356 |
357 | for date, time, m, linecount in ppmattached:
358 | f_mru.write(date + "\t" + time + "\tPPMAttached\t" + m +"\t" + str(linecount) + "\t" + options.inputfile + "\n")
359 |
360 | f_mru.close()
361 | print("Logged "+ str(len(ppmattached)) + " PPMAttached to wifi-buf-net_ppmattached.TSV output file\n")
362 |
363 | if alreadyattachedcount > 0:
364 | f_mru = open("wifi-buf-net_alreadyattached.TSV", "w")
365 | f_mru.write("DATE\tTIME\tTYPE\tNETWORK\tLINE\tLOGFILE\n")
366 |
367 | for date, time, m, linecount in alreadyattached:
368 | f_mru.write(date + "\t" + time + "\tAlreadyAttached\t" + m +"\t" + str(linecount) + "\t" + options.inputfile + "\n")
369 |
370 | f_mru.close()
371 | print("Logged "+ str(len(alreadyattached)) + " AlreadyAttached to wifi-buf-net_alreadyattached.TSV output file\n")
372 |
373 | print("=====================================================\n")
374 | print("Ignored " + str(ignorecount) + " malformed entries")
375 | print("Exiting ...\n")
376 |
377 |
378 |
379 |
--------------------------------------------------------------------------------
/sysdiagnose-wifi-kml.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 |
3 | # For Python3
4 | # Script to print the geolocation values from WiFi/wifi*.log
5 | # and log locations to output KML
6 | # Author: cheeky4n6monkey@gmail.com
7 |
8 | #import os
9 | import sys
10 | from optparse import OptionParser
11 | import tarfile
12 |
13 | version_string = "sysdiagnose-wifi-kml.py v2019-05-10 Version 1.0"
14 |
15 | if sys.version_info[0] < 3:
16 | print("Must be using Python 3! Exiting ...")
17 | exit(-1)
18 |
19 | print("Running " + version_string + "\n")
20 |
21 | usage = "\n%prog -i inputfile\n"
22 |
23 | parser = OptionParser(usage=usage)
24 | parser.add_option("-i", dest="inputfile",
25 | action="store", type="string",
26 | help="WiFi/wifi*.log To Be Searched")
27 | (options, args) = parser.parse_args()
28 |
29 | #no arguments given by user, print help and exit
30 | if len(sys.argv) == 1:
31 | parser.print_help()
32 | exit(-1)
33 |
34 | linecount = 0
35 | ignorecount = 0
36 | updatecount = 0
37 | geotagcount = 0
38 | callbackcount = 0
39 | localecallbackcount = 0
40 | checklocalecount = 0
41 | networktranscount = 0
42 | wifimanagercount = 0
43 | wificurrentlocation = 0
44 |
45 | locations = []
46 | scanlocations = []
47 | geolocations = []
48 | callbacklocations = []
49 | localecallbacklocations = []
50 | checklocalelocations = []
51 | networktranslocations = []
52 | copylocations = []
53 |
54 | #print(options.inputfile[0:-4]) # = wifi-buf-04-26-2019__16:00:52.768.log
55 |
56 | if options.inputfile.endswith('.tgz'): # eg wifi-buf-04-26-2019__16:00:52.768.log.tgz
57 | # untar file first to current directory
58 | # tarfile.open currently Throws InvalidHeader error!
59 | with tarfile.open(options.inputfile, 'r:gz') as t:
60 | t.extractall('./')
61 |
62 | # does not get here due to exception ... todo
63 |
64 | # readfile = ass-ume extracted name is same as input name minus the .tgz
65 | with open(options.inputfile[0:-4], 'r') as fp:
66 | data = fp.readlines()
67 | # TODO: Implement processing when given zip file
68 | '''
69 | for line in data:
70 | if 'didUpdateLocations:' in line:
71 | count += 1
72 | print(line)
73 | '''
74 | else: # ass-ume input file has been untarred already and is plaintext
75 | with open(options.inputfile, 'r') as fp:
76 | data = fp.readlines()
77 |
78 | for line in data:
79 | linecount += 1
80 |
81 | if 'didUpdateLocations: latitude' in line:
82 | #print("\n" + line)
83 | txts = line.split()
84 | #print(txts, linecount)
85 | #print(len(txts))
86 |
87 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
88 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
89 | updatecount += 1
90 | date = txts[0]
91 | time = txts[1]
92 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
93 | llg = txts[5][10:] # strip leading "longitude="
94 | acc = txts[6][9:] # strip leading "Accuracy="
95 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
96 | src = txts[8][7:] # strip leading "source="
97 | #print("didUpdateLocations dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
98 | locations.append(("didUpdateLocations", linecount, updatecount, date, time, llat, llg, acc, tinterval, src))
99 | else:
100 | #wrong number of fields (eg missing date) ... skip hit completely
101 | print("\nERROR - didUpdateLocations = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
102 | ignorecount += 1
103 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
104 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
105 | updatecount += 1
106 | date = txts[0]
107 | time = txts[1]
108 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
109 | llg = txts[4][10:] # strip leading "longitude="
110 | acc = txts[5][9:] # strip leading "Accuracy="
111 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
112 | src = txts[7][7:] # strip leading "source="
113 | # print("didUpdateLocations dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
114 | locations.append(("didUpdateLocations", linecount, updatecount, date, time, llat, llg, acc, tinterval, src))
115 | else:
116 | #wrong number of fields (eg missing date) ... skip hit completely
117 | print("\nERROR - didUpdateLocations = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
118 | ignorecount += 1
119 |
120 | elif '__WiFiManagerGeoTagNetwork: latitude' in line:
121 | #print("\n" + line)
122 | txts = line.split()
123 | #print(txts, linecount)
124 | #print(len(txts))
125 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
126 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
127 | geotagcount += 1
128 | date = txts[0]
129 | time = txts[1]
130 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
131 | llg = txts[5][10:] # strip leading "longitude="
132 | acc = txts[6][9:] # strip leading "Accuracy="
133 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
134 | src = txts[8][7:] # strip leading "source="
135 | #print("__WiFiManagerGeoTagNetwork dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
136 | geolocations.append(("__WiFiManagerGeoTagNetwork", linecount, geotagcount, date, time, llat, llg, acc, tinterval, src))
137 | else:
138 | #wrong number of fields (eg missing date) ... skip hit completely
139 | print("\nERROR - __WiFiManagerGeoTagNetwork = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
140 | ignorecount += 1
141 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
142 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
143 | geotagcount += 1
144 | date = txts[0]
145 | time = txts[1]
146 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
147 | llg = txts[4][10:] # strip leading "longitude="
148 | acc = txts[5][9:] # strip leading "Accuracy="
149 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
150 | src = txts[7][7:] # strip leading "source="
151 | # print("__WiFiManagerGeoTagNetwork dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
152 | geolocations.append(("__WiFiManagerGeoTagNetwork", linecount, geotagcount, date, time, llat, llg, acc, tinterval, src))
153 | else:
154 | #wrong number of fields (eg missing date) ... skip hit completely
155 | print("\nERROR - __WiFiManagerGeoTagNetwork = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
156 | ignorecount += 1
157 |
158 | elif '__WiFiManagerLocationManagerCallback: latitude' in line:
159 | #print("\n" + line)
160 | txts = line.split()
161 | #print(txts, linecount)
162 | #print(len(txts))
163 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
164 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
165 | callbackcount += 1
166 | date = txts[0]
167 | time = txts[1]
168 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
169 | llg = txts[5][10:] # strip leading "longitude="
170 | acc = txts[6][9:] # strip leading "Accuracy="
171 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
172 | src = txts[8][7:] # strip leading "source="
173 | #print("__WiFiManagerLocationManagerCallback dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
174 | callbacklocations.append(("__WiFiManagerLocationManagerCallback", linecount, callbackcount, date, time, llat, llg, acc, tinterval, src))
175 | else:
176 | #wrong number of fields (eg missing date) ... skip hit completely
177 | print("\nERROR - __WiFiManagerLocationManagerCallback = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
178 | ignorecount += 1
179 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
180 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
181 | callbackcount += 1
182 | date = txts[0]
183 | time = txts[1]
184 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
185 | llg = txts[4][10:] # strip leading "longitude="
186 | acc = txts[5][9:] # strip leading "Accuracy="
187 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
188 | src = txts[7][7:] # strip leading "source="
189 | # print("__WiFiManagerLocationManagerCallback dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
190 | callbacklocations.append(("__WiFiManagerLocationManagerCallback", linecount, callbackcount, date, time, llat, llg, acc, tinterval, src))
191 | else:
192 | #wrong number of fields (eg missing date) ... skip hit completely
193 | print("\nERROR - __WiFiManagerLocationManagerCallback = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
194 | ignorecount += 1
195 |
196 | elif '__WiFiLocaleManagerLocationManagerCallback: latitude' in line:
197 | #print("\n" + line)
198 | txts = line.split()
199 | #print(txts, linecount)
200 | #print(len(txts))
201 |
202 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
203 | # Note: current logs may not contain an location for this
204 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
205 | localecallbackcount += 1
206 | date = txts[0]
207 | time = txts[1]
208 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
209 | llg = txts[5][10:] # strip leading "longitude="
210 | acc = txts[6][9:] # strip leading "Accuracy="
211 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
212 | src = txts[8][7:] # strip leading "source="
213 | #print("__WiFiLocaleManagerLocationManagerCallback dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
214 | localecallbacklocations.append(("__WiFiLocaleManagerLocationManagerCallback", linecount, localecallbackcount, date, time, llat, llg, acc, tinterval, src))
215 | else:
216 | #wrong number of fields (eg missing date) ... skip hit completely
217 | print("\nERROR - __WiFiLocaleManagerLocationManagerCallback = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
218 | ignorecount += 1
219 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
220 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
221 | localecallbackcount += 1
222 | date = txts[0]
223 | time = txts[1]
224 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
225 | llg = txts[4][10:] # strip leading "longitude="
226 | acc = txts[5][9:] # strip leading "Accuracy="
227 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
228 | src = txts[7][7:] # strip leading "source="
229 | # print("__WiFiLocaleManagerLocationManagerCallback dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
230 | localecallbacklocations.append(("__WiFiLocaleManagerLocationManagerCallback", linecount, localecallbackcount, date, time, llat, llg, acc, tinterval, src))
231 | else:
232 | #wrong number of fields (eg missing date) ... skip hit completely
233 | print("\nERROR - __WiFiLocaleManagerLocationManagerCallback = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
234 | ignorecount += 1
235 |
236 | elif 'WiFiLocaleManagerCheckLocale: latitude' in line:
237 | #print("\n" + line)
238 | txts = line.split()
239 | #print(txts, linecount)
240 | #print(len(txts))
241 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
242 | # Note: current logs may not contain an entry for this
243 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
244 | checklocalecount += 1
245 | date = txts[0]
246 | time = txts[1]
247 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
248 | llg = txts[5][10:] # strip leading "longitude="
249 | acc = txts[6][9:] # strip leading "Accuracy="
250 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
251 | src = txts[8][7:] # strip leading "source="
252 | #print("WiFiLocaleManagerCheckLocale dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
253 | checklocalelocations.append(("WiFiLocaleManagerCheckLocale", linecount, checklocalecount, date, time, llat, llg, acc, tinterval, src))
254 | else:
255 | #wrong number of fields (eg missing date) ... skip hit completely
256 | print("\nERROR - WiFiLocaleManagerCheckLocale = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
257 | ignorecount += 1
258 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
259 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
260 | checklocalecount += 1
261 | date = txts[0]
262 | time = txts[1]
263 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
264 | llg = txts[4][10:] # strip leading "longitude="
265 | acc = txts[5][9:] # strip leading "Accuracy="
266 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
267 | src = txts[7][7:] # strip leading "source="
268 | # print("WiFiLocaleManagerCheckLocale dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
269 | checklocalelocations.append(("WiFiLocaleManagerCheckLocale", linecount, checklocalecount, date, time, llat, llg, acc, tinterval, src))
270 | else:
271 | #wrong number of fields (eg missing date) ... skip hit completely
272 | print("\nERROR - WiFiLocaleManagerCheckLocale = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
273 | ignorecount += 1
274 |
275 | elif '__WiFiDeviceManagerAttemptNetworkTransition: latitude' in line:
276 | #print("\n" + line)
277 | txts = line.split()
278 | #print(txts, linecount)
279 | #print(len(txts))
280 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
281 | # Note: current logs may not contain an entry for this
282 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
283 | networktranscount += 1
284 | date = txts[0]
285 | time = txts[1]
286 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
287 | llg = txts[5][10:] # strip leading "longitude="
288 | acc = txts[6][9:] # strip leading "Accuracy="
289 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
290 | src = txts[8][7:] # strip leading "source="
291 | #print("__WiFiDeviceManagerAttemptNetworkTransition dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
292 | networktranslocations.append(("__WiFiDeviceManagerAttemptNetworkTransition", linecount, networktranscount, date, time, llat, llg, acc, tinterval, src))
293 | else:
294 | #wrong number of fields (eg missing date) ... skip hit completely
295 | print("\nERROR - __WiFiDeviceManagerAttemptNetworkTransition = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
296 | ignorecount += 1
297 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
298 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
299 | networktranscount += 1
300 | date = txts[0]
301 | time = txts[1]
302 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
303 | llg = txts[4][10:] # strip leading "longitude="
304 | acc = txts[5][9:] # strip leading "Accuracy="
305 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
306 | src = txts[7][7:] # strip leading "source="
307 | # print("__WiFiDeviceManagerAttemptNetworkTransition dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + ", line = " + str(linecount))
308 | networktranslocations.append(("__WiFiDeviceManagerAttemptNetworkTransition", linecount, networktranscount, date, time, llat, llg, acc, tinterval, src))
309 | else:
310 | #wrong number of fields (eg missing date) ... skip hit completely
311 | print("\nERROR - __WiFiDeviceManagerAttemptNetworkTransition = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
312 | ignorecount += 1
313 |
314 | elif '__WiFiDeviceManagerScanPreviousNetworkChannel: latitude' in line:
315 | #print("\n" + line)
316 | txts = line.split()
317 | #print(txts, str(linecount))
318 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
319 | if len(txts) > 8: # latitude is the 4th field but check we have all fields before parsing
320 | wifimanagercount += 1
321 | date = txts[0]
322 | time = txts[1]
323 | llat = txts[4][9:-1] # strip trailing "," and leading "latitude="
324 | llg = txts[5][10:] # strip leading "longitude="
325 | acc = txts[6][9:] # strip leading "Accuracy="
326 | tinterval = txts[7][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
327 | src = txts[8][7:] # strip leading "source="
328 | #print("__WiFiDeviceManagerScanPreviousNetworkChannel dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + " line = " + str(linecount))
329 | scanlocations.append(("__WiFiDeviceManagerScanPreviousNetworkChannel", linecount, wifimanagercount, date, time, llat, llg, acc, tinterval, src))
330 | else:
331 | #wrong number of fields (eg missing date) ... skip hit completely
332 | print("\nERROR - __WiFiDeviceManagerScanPreviousNetworkChannel = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
333 | ignorecount += 1
334 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
335 | if len(txts) > 7: # latitude is the 4th field but check we have all fields before parsing
336 | wifimanagercount += 1
337 | date = txts[0]
338 | time = txts[1]
339 | llat = txts[3][9:-1] # strip trailing "," and leading "latitude="
340 | llg = txts[4][10:] # strip leading "longitude="
341 | acc = txts[5][9:] # strip leading "Accuracy="
342 | tinterval = txts[6][21:-4] # strip leading "timeIntervalSinceNow=" and trailing "secs"
343 | src = txts[7][7:] # strip leading "source="
344 | # print("__WiFiDeviceManagerScanPreviousNetworkChannel dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + " int = " + tinterval + " src = " + src + " line = " + str(linecount))
345 | scanlocations.append(("__WiFiDeviceManagerScanPreviousNetworkChannel", linecount, wifimanagercount, date, time, llat, llg, acc, tinterval, src))
346 | else:
347 | #wrong number of fields (eg missing date) ... skip hit completely
348 | print("\nERROR - __WiFiDeviceManagerScanPreviousNetworkChannel = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
349 | ignorecount += 1
350 |
351 | elif 'WiFiManagerCopyCurrentLocation: currentLocation' in line:
352 | #print("\n" + line)
353 | txts = line.split()
354 | #print(txts, str(linecount))
355 | #print(len(txts))
356 | if ':' in line: # current log format has extra : text after date/time eg "wifi-mm-dd-yyyy__hh[separator]mm[separator]ss.sss.log"
357 | # Note: current logs may not contain an entry for this
358 | if len(txts) > 16: # currentLocation pair is the 4th field but check we have all fields before parsing
359 | wificurrentlocation += 1
360 | date = txts[0]
361 | time = txts[1]
362 | llat, llg = txts[4][17:-1].split(',') # currentLocation:<+44.38199906,+9.06126224> => +44.38199906,+9.06126224
363 | acc = txts[5] + txts[5][:-1] # combine into +/-1433.02
364 | speed = txts[8] # speed m/s
365 | course = txts[12][:-1] # course
366 | atdate = txts[14] # @date
367 | attime = txts[15] + " " + txts[16] # @time AM/PM
368 | tz = ' '.join(txts[17:]) # ass-ume remainder is timezone. each word is an item in a list so need to join
369 | #print(tz)
370 | #print("WiFiManagerCopyCurrentLocation dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + \
371 | #" spd = " + speed + " course = " + course + " atdate = " + atdate + " attime = " + attime +\
372 | #" " + tz + " line = " + str(linecount))
373 | # use a separate locations list because of the additional stored values (speed, course etc)
374 | copylocations.append(("WiFiManagerCopyCurrentLocation", linecount, wificurrentlocation, date, time, llat, llg, acc, speed, course, atdate, attime, tz, src))
375 | else:
376 | #wrong number of fields (eg missing date) ... skip hit completely
377 | print("\nERROR - WiFiManagerCopyCurrentLocation = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
378 | ignorecount += 1
379 | else: #archived log format eg WiFiManager/wifi-buf-mm-dd-yyyy__hh-mm-ss.sss.log
380 | if len(txts) > 15: # currentLocation pair is the 4th field but check we have all fields before parsing
381 | wificurrentlocation += 1
382 | date = txts[0]
383 | time = txts[1]
384 | llat, llg = txts[3][17:-1].split(',') # currentLocation:<+44.38199906,+9.06126224> => +44.38199906,+9.06126224
385 | acc = txts[4] + txts[5][:-1] # combine into +/-1433.02
386 | speed = txts[7] # speed m/s
387 | course = txts[11][:-1] # course
388 | atdate = txts[13] # @date
389 | attime = txts[14] + " " + txts[15] # @time AM/PM
390 | tz = ' '.join(txts[16:]) # ass-ume remainder is timezone. each word is an item in a list so need to join
391 | #print(tz)
392 | # print("WiFiManagerCopyCurrentLocation dt = " + date + " " + time + " llat = " + llat + " llg = " + llg + " acc = " + acc + \
393 | # " spd = " + speed + " course = " + course + " atdate = " + atdate + " attime = " + attime +\
394 | # " " + tz + " line = " + str(linecount))
395 | # use a separate locations list because of the additional stored values (speed, course etc)
396 | copylocations.append(("WiFiManagerCopyCurrentLocation", linecount, wificurrentlocation, date, time, llat, llg, acc, speed, course, atdate, attime, tz, src))
397 | else:
398 | #wrong number of fields (eg missing date) ... skip hit completely
399 | print("\nERROR - WiFiManagerCopyCurrentLocation = Wrong Number of fields in file (line = " + str(linecount) + ") - Ignoring ...\n")
400 | ignorecount += 1
401 | elif 'latitude' in line: # we get here, something is wrong
402 | ignorecount += 1
403 | print("\n\n**** WARNING: Unexpected format for log entry - Ignoring ... ****")
404 | print(line + " from line = " + str(linecount) + "\n") # malfomed line is ...
405 |
406 |
407 | print("\n\n=====================================================")
408 | print("\nFound " + str(updatecount) + " valid didUpdateLocation instances in " + options.inputfile)
409 | print("\nFound " + str(geotagcount) + " valid __WiFiManagerGeoTagNetwork instances in " + options.inputfile)
410 | print("\nFound " + str(callbackcount) + " valid __WiFiManagerLocationManagerCallback instances in " + options.inputfile)
411 | print("\nFound " + str(localecallbackcount) + " valid __WiFiLocaleManagerLocationManagerCallback instances in " + options.inputfile)
412 | print("\nFound " + str(checklocalecount) + " valid WiFiLocaleManagerCheckLocale instances in " + options.inputfile)
413 | print("\nFound " + str(networktranscount) + " valid __WiFiDeviceManagerAttemptNetworkTransition instances in " + options.inputfile)
414 | print("\nFound " + str(wifimanagercount) + " valid __WiFiDeviceManagerScanPreviousNetworkChannel instances in " + options.inputfile)
415 | print("\nFound " + str(wificurrentlocation) + " valid WiFiManagerCopyCurrentLocation instances in " + options.inputfile)
416 | print("\n=====================================================")
417 |
418 | if (len(locations)+len(copylocations)+len(scanlocations)+len(geolocations)+len(callbacklocations)+len(localecallbacklocations)+\
419 | len(checklocalelocations) + len(networktranslocations) > 0):
420 | f = open("wifi-buf-locations.kml", "w")
421 | f.write("\n")
422 | f.write("\n")
423 | f.write("")
424 | f.write("\n" + options.inputfile + "1\n")
425 | f.write("didUpdateLocation0\n")
426 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in locations: # yellow dot
427 | f.write("\n\n")
428 | f.write("\n")
429 | f.write("" + name + str(groupcount) + "\n")
430 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
431 | f.write("" + llg + ", " + llat + "\n")
432 | f.write("")
433 | f.write("\n")
434 | f.write("__WiFiManagerGeoTagNetwork0\n")
435 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in geolocations: # blue pushpin
436 | f.write("\n\n")
437 | f.write("" + name + str(groupcount) + "\n")
438 | f.write("\n")
439 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
440 | f.write("" + llg + ", " + llat + "\n")
441 | f.write("")
442 | f.write("\n")
443 | f.write("__WiFiManagerLocationManagerCallback0\n")
444 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in callbacklocations: # pink pushpin
445 | f.write("\n\n")
446 | f.write("" + name + str(groupcount) + "\n")
447 | f.write("\n")
448 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
449 | f.write("" + llg + ", " + llat + "\n")
450 | f.write("")
451 | f.write("\n")
452 | f.write("__WiFiLocaleManagerLocationManagerCallback0\n")
453 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in localecallbacklocations: # purple pushpin
454 | f.write("\n\n")
455 | f.write("" + name + str(groupcount) + "\n")
456 | f.write("\n")
457 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
458 | f.write("" + llg + ", " + llat + "\n")
459 | f.write("")
460 | f.write("\n")
461 | f.write("WiFiLocaleManagerCheckLocale0\n")
462 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in checklocalelocations: # light blue pushpin
463 | f.write("\n\n")
464 | f.write("" + name + str(groupcount) + "\n")
465 | f.write("\n")
466 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
467 | f.write("" + llg + ", " + llat + "\n")
468 | f.write("")
469 | f.write("\n")
470 | f.write("__WiFiDeviceManagerAttemptNetworkTransition0\n")
471 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in networktranslocations: # white pushpin
472 | f.write("\n\n")
473 | f.write("" + name + str(groupcount) + "\n")
474 | f.write("\n")
475 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
476 | f.write("" + llg + ", " + llat + "\n")
477 | f.write("")
478 | f.write("\n")
479 | f.write("__WiFiDeviceManagerScanPreviousNetworkChannel0\n")
480 | for name, linecount, groupcount, date, time, llat, llg, acc, tinterval, src in scanlocations: # green pushpin
481 | f.write("\n\n")
482 | f.write("" + name + str(groupcount) + "\n")
483 | f.write("\n")
484 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
485 | f.write("" + llg + ", " + llat + "\n")
486 | f.write("")
487 | f.write("\n")
488 | f.write("WiFiManagerCopyCurrentLocation0\n")
489 | for name, linecount, groupcount, date, time, llat, llg, acc, speed, course, atdate, attime, tz, src in copylocations: # red tinted white pushpin
490 | f.write("\n\n")
491 | f.write("" + name + str(groupcount) + "\n")
492 | f.write("\n")
493 | f.write(" " + name + " " + str(groupcount) + "\nlat = " + llat + ", long = " + llg + "\n" + date + " " + time + "\naccuracy = " + acc + \
494 | "\nspeed = " + speed + "\ncourse = " + course + "\nat " + atdate + " " + attime + " " + tz + "\nsource = " + src + "\n\nfile = " + options.inputfile + "\nline = " + str(linecount) + "\n")
495 | f.write("" + llg + ", " + llat + "\n")
496 | f.write("")
497 | f.write("\n")
498 | f.write("\n\n")
499 | f.write("\n")
500 | f.close()
501 |
502 | print("\nLogged "+ str(len(locations) + len(geolocations) + len(callbacklocations) +\
503 | len(localecallbacklocations) + len(checklocalelocations) + len(networktranslocations) + \
504 | len(scanlocations) + len(copylocations)) + " locations to wifi-buf-locations.kml output file\n")
505 | print("Ignored " + str(ignorecount) + " malformed log entries\n")
506 |
507 |
508 |
509 |
--------------------------------------------------------------------------------