Last active
July 26, 2018 17:40
-
-
Save thurask/f3af7377ec784bfa867e191cd53dff4c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collections | |
import json | |
import xml.etree.ElementTree | |
import requests | |
# Edit this to filter only certain model numbers | |
VALIDHWIDS = ["SQC100-1", "SQC100-2", "SQC100-3", "SQC100-4", "SQC100-5", "SQW100-1", "SQW100-3", "SQW100-4", "STK100-1", "STK100-2", "SQK100-1", "SQK100-2", "STR100-1", "STR100-2", "STJ100-1", "STJ100-2", "STA100-2", "STA100-3", "STA100-5", "STA100-6", "SQR100-1", "SQR100-2", "SQR100-3", "SQN100-1", "SQN100-2", "SQN100-3", "SQN100-4", "SQN100-5", "STL100-1", "STL100-2", "STL100-3", "STL100-4"] | |
# Edit this to filter only certain countries, set to an empty list to scan all networks | |
MCCFILTER = [302] | |
# Edit this to scan only certain networks, set to an empty list to scan all networks | |
MNCFILTER = [220, 490, 610, 720] | |
# Edit this to scan for prior OS versions, set to False to just scan for the latest | |
BUNDLES = False | |
def jsonget(remoteurl): | |
remotelist = requests.get(remoteurl) | |
masterlist = json.loads(remotelist.text) | |
return masterlist | |
def get_json(): | |
netlist = jsonget("https://raw.githubusercontent.com/pbakondy/mcc-mnc-list/master/mcc-mnc-list.json") | |
devlist = jsonget("https://raw.githubusercontent.com/thurask/bbarchivist/master/bbarchivist/json/devices.json") | |
return netlist, devlist["devices"] | |
def certchecker_prep(table, device): | |
for key in table: | |
if 'secret' not in key and key['name'] == device: | |
model = key['device'] | |
family = key['family'] | |
hwid = key['hwid'] | |
break | |
return model, family, hwid | |
def clean_devlist(devlist): | |
cleanlist = collections.defaultdict(list) | |
for hwid in VALIDHWIDS: | |
model, family, hwix = certchecker_prep(devlist, hwid) | |
cleanlist[model].append((hwix, hwid)) | |
return cleanlist | |
def smart_int_convert(integer): | |
stoppers = ("?", "-") | |
if integer is None: | |
return 0 | |
elif any(stopper in integer for stopper in stoppers): | |
return 0 | |
else: | |
return int(integer) | |
def pick_n_place(listitem): | |
mcc = smart_int_convert(listitem.get("mcc", 0)) | |
mnc = smart_int_convert(listitem.get("mnc", 0)) | |
active = True if listitem.get("status") == "Operational" else False | |
ccode = listitem.get("countryCode") | |
brand = listitem.get("brand") | |
if brand is None: | |
brand = listitem.get("operator") | |
title = "{0}: {1}".format(ccode, brand) | |
return title, mcc, mnc, active | |
def clean_masterlist(netlist): | |
cleanlist = collections.defaultdict(list) | |
for listitem in netlist: | |
title, mcc, mnc, active = pick_n_place(listitem) | |
if active: | |
cleanlist[mcc].append((mnc, title)) | |
return cleanlist | |
def return_npc(mcc, mnc): | |
return "{0}{1}30".format(str(mcc).zfill(3), str(mnc).zfill(3)) | |
def carrier_query(npc, device, session): | |
url = "https://cs.sl.blackberry.com/cse/updateDetails/2.2/" | |
query = prep_carrier_query(npc, device) | |
header = {"Content-Type": "text/xml;charset=UTF-8"} | |
req = session.post(url, headers=header, data=query) | |
pcx = parse_carrier_xml(req.text) | |
return pcx | |
def prep_available_bundle(device, npc): | |
query = '<?xml version="1.0" encoding="UTF-8"?><availableBundlesRequest version="1.0.0" authEchoTS="1366644680359"><deviceId><pin>0x2FFFFFB3</pin></deviceId><clientProperties><hardware><id>0x{0}</id><isBootROMSecure>true</isBootROMSecure></hardware><network><vendorId>0x0</vendorId><homeNPC>0x{1}</homeNPC><currentNPC>0x{1}</currentNPC></network><software><currentLocale>en_US</currentLocale><legalLocale>en_US</legalLocale><osVersion>10.0.0.0</osVersion><radioVersion>10.0.0.0</radioVersion></software></clientProperties><updateDirectives><bundleVersionFilter></bundleVersionFilter></updateDirectives></availableBundlesRequest>'.format(device, npc) | |
return query | |
def parse_available_bundle(roottext): | |
root = xml.etree.ElementTree.fromstring(roottext) | |
package = root.find('./data/content') | |
bundlelist = [child.attrib["version"] for child in package] | |
return bundlelist | |
def available_bundle_lookup(npc, device, session): | |
server = "https://cs.sl.blackberry.com/cse/availableBundles/1.0.0/" | |
query = prep_available_bundle(device, npc) | |
header = {"Content-Type": "text/xml;charset=UTF-8"} | |
req = session.post(server, headers=header, data=query) | |
bundlelist = parse_available_bundle(req.text) | |
return bundlelist | |
def prep_carrier_query(npc, device): | |
query = '<?xml version="1.0" encoding="UTF-8"?><updateDetailRequest version="2.2.1" authEchoTS="1366644680359"><clientProperties><hardware><pin>0x2FFFFFB3</pin><bsn>1128121361</bsn><imei>004401139269240</imei><id>0x{0}</id></hardware><network><homeNPC>0x{1}</homeNPC><iccid>89014104255505565333</iccid></network><software><currentLocale>en_US</currentLocale><legalLocale>en_US</legalLocale></software></clientProperties><updateDirectives><allowPatching type="REDBEND">true</allowPatching><upgradeMode>{2}</upgradeMode><provideDescriptions>false</provideDescriptions><provideFiles>true</provideFiles><queryType>NOTIFICATION_CHECK</queryType></updateDirectives><pollType>manual</pollType><resultPackageSetCriteria><softwareRelease softwareReleaseVersion="{3}" /><releaseIndependent><packageType operation="include">application</packageType></releaseIndependent></resultPackageSetCriteria></updateDetailRequest>'.format(device, npc, "repair", "latest") | |
return query | |
def carrier_swver_get(root): | |
for child in root.iter("softwareReleaseMetadata"): | |
swver = child.get("softwareReleaseVersion") | |
return swver | |
def parse_carrier_xml(data): | |
root = xml.etree.ElementTree.fromstring(data) | |
sw_exists = root.find('./data/content/softwareReleaseMetadata') | |
swver = "N/A" if sw_exists is None else "" | |
if sw_exists is not None: | |
swver = carrier_swver_get(root) | |
files = [] | |
package_exists = root.find('./data/content/fileSets/fileSet') | |
osver = radver = "" | |
if package_exists is not None: | |
baseurl = "{0}/".format(package_exists.get("url")) | |
osver, radver, files = carrier_child_finder(root, files, baseurl) | |
return swver, osver, radver, files | |
def carrier_child_finder(root, files, baseurl): | |
osver = radver = "" | |
for child in root.iter("package"): | |
files.append(baseurl + child.get("path")) | |
if child.get("type") == "system:radio": | |
radver = child.get("version") | |
elif child.get("type") == "system:desktop": | |
osver = child.get("version") | |
elif child.get("type") == "system:os": | |
osver = child.get("version") | |
return osver, radver, files | |
def prep_scan(): | |
sess = requests.Session() | |
netlist, devlist = get_json() | |
netlist = clean_masterlist(netlist) | |
devlist = clean_devlist(devlist) | |
validmodels = devlist.keys() | |
if not MCCFILTER: | |
mcclist = netlist.keys() | |
else: | |
mcclist = MCCFILTER | |
return sess, netlist, devlist, validmodels, mcclist | |
def scan_output_bundles(family, modelno, npc, hwid, sess): | |
bundlelist = available_bundle_lookup(npc, hwid, sess) | |
if bundlelist: | |
print("\t{0} {1}:".format(family, modelno)) | |
for bund in bundlelist: | |
print("\t\tOS {0}".format(bund)) | |
def scan_output_latest(family, modelno, npc, hwid, sess): | |
swv, osv, radv, files = carrier_query(npc, hwid, sess) | |
if swv != "N/A": | |
print("\t{0} {1}: OS {2} / SW {3}".format(family, modelno, osv, swv)) | |
def scan_output(sess, devlist, validmodels, mcc, mnc, carrier): | |
print("MCC {0}, MNC {1}, {2}".format(mcc, mnc, carrier)) | |
for family in validmodels: | |
devpairs = devlist[family] | |
for devpair in devpairs: | |
hwid, modelno = devpair | |
npc = return_npc(mcc, mnc) | |
if BUNDLES: | |
scan_output_bundles(family, modelno, npc, hwid, sess) | |
else: | |
scan_output_latest(family, modelno, npc, hwid, sess) | |
def main(): | |
sess, netlist, devlist, validmodels, mcclist = prep_scan() | |
for mcc in mcclist: | |
if not MNCFILTER: | |
mnclist = netlist[mcc] | |
else: | |
mnclist = [x for x in netlist[mcc] if x[0] in MNCFILTER] | |
for netpair in mnclist: | |
mnc, carrier = netpair | |
scan_output(sess, devlist, validmodels, mcc, mnc, carrier) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment