Skip to content

Instantly share code, notes, and snippets.

@thurask
Last active July 26, 2018 17:40
Show Gist options
  • Save thurask/f3af7377ec784bfa867e191cd53dff4c to your computer and use it in GitHub Desktop.
Save thurask/f3af7377ec784bfa867e191cd53dff4c to your computer and use it in GitHub Desktop.
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