Add support for Nothing Phones, add support for qc sahara v3

This commit is contained in:
Bjoern Kerler 2023-10-05 09:05:46 +02:00
parent 356ab5e3a2
commit a411f608ff
10 changed files with 332 additions and 180 deletions

72
edl
View file

@ -14,14 +14,14 @@ Usage:
edl [--debugmode] [--portname=portname] [--serial] edl [--debugmode] [--portname=portname] [--serial]
edl [--gpt-num-part-entries=number] [--gpt-part-entry-size=number] [--gpt-part-entry-start-lba=number] [--portname=portname] [--serial] edl [--gpt-num-part-entries=number] [--gpt-part-entry-size=number] [--gpt-part-entry-start-lba=number] [--portname=portname] [--serial]
edl [--memory=memtype] [--skipstorageinit] [--maxpayload=bytes] [--sectorsize==bytes] [--portname=portname] [--serial] edl [--memory=memtype] [--skipstorageinit] [--maxpayload=bytes] [--sectorsize==bytes] [--portname=portname] [--serial]
edl server [--tcpport=portnumber] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl server [--tcpport=portnumber] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl memorydump [--partitions=partnames] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--serial_number=serial_number] edl memorydump [--partitions=partnames] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--serial_number=serial_number]
edl printgpt [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl printgpt [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl gpt <directory> [--memory=memtype] [--lun=lun] [--genxml] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl gpt <directory> [--memory=memtype] [--lun=lun] [--genxml] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl r <partitionname> <filename> [--memory=memtype] [--sectorsize==bytes] [--lun=lun] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl r <partitionname> <filename> [--memory=memtype] [--sectorsize==bytes] [--lun=lun] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl rl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--genxml] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl rl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--genxml] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl rf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl rf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl rs <start_sector> <sectors> <filename> [--lun=lun] [--sectorsize==bytes] [--memory=memtype] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl rs <start_sector> <sectors> <filename> [--lun=lun] [--sectorsize==bytes] [--memory=memtype] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl w <partitionname> <filename> [--partitionfilename=filename] [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skipwrite] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl w <partitionname> <filename> [--partitionfilename=filename] [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skipwrite] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
edl wl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl wl <directory> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skip=partnames] [--skipresponse] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
edl wf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl wf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
@ -29,7 +29,7 @@ Usage:
edl e <partitionname> [--memory=memtype] [--skipwrite] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl e <partitionname> [--memory=memtype] [--skipwrite] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
edl es <start_sector> <sectors> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skipwrite] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl es <start_sector> <sectors> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--skipwrite] [--loader=filename] [--skipresponse] [--debugmode] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
edl ep <partitionname> <sectors> [--memory=memtype] [--skipwrite] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl ep <partitionname> <sectors> [--memory=memtype] [--skipwrite] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
edl footer <filename> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl footer <filename> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl peek <offset> <length> <filename> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl peek <offset> <length> <filename> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
edl peekhex <offset> <length> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl peekhex <offset> <length> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
edl peekdword <offset> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl peekdword <offset> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
@ -43,17 +43,17 @@ Usage:
edl secureboot [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl secureboot [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
edl pbl <filename> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl pbl <filename> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
edl qfp <filename> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl qfp <filename> [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial]
edl getstorageinfo [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl getstorageinfo [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl setbootablestoragedrive <lun> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl setbootablestoragedrive <lun> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
edl setactiveslot <slot> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl setactiveslot <slot> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
edl send <command> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl send <command> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
edl xml <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl xml <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl rawxml <xmlstring> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial] edl rawxml <xmlstring> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl reset [--resetmode=mode] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl reset [--resetmode=mode] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
edl nop [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] edl nop [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
edl modules <command> <options> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--portname=portname] [--serial] edl modules <command> <options> [--memory=memtype] [--lun=lun] [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--devicemodel=value] [--portname=portname] [--serial]
edl provision <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl provision <xmlfile> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
edl qfil <rawprogram> <patch> <imagedir> [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] edl qfil <rawprogram> <patch> <imagedir> [--loader=filename] [--memory=memtype] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial] [--devicemodel=value]
Description: Description:
server # Run tcp/ip server server # Run tcp/ip server
@ -147,7 +147,7 @@ from binascii import hexlify
args = docopt(__doc__, version='3') args = docopt(__doc__, version='3')
print("Qualcomm Sahara / Firehose Client V3.61 (c) B.Kerler 2018-2023.") print("Qualcomm Sahara / Firehose Client V3.62 (c) B.Kerler 2018-2023.")
def parse_cmd(rargs): def parse_cmd(rargs):
@ -232,26 +232,6 @@ class main(metaclass=LogBase):
self.cdc.close() self.cdc.close()
sys.exit() sys.exit()
def handle_streaming(self, mode):
self.cdc.timeout = None
sahara_info = self.sahara.streaminginfo()
if sahara_info:
mode, resp = self.sahara.connect()
if mode == "sahara":
mode = self.sahara.upload_loader()
if "enprg" in self.sahara.programmer.lower():
mode = "load_enandprg"
elif "nprg" in self.sahara.programmer.lower():
mode = "load_nandprg"
elif mode != "":
mode = "load_" + mode
if "load_" in mode:
time.sleep(0.3)
else:
print("Error, couldn't find suitable enprg/nprg loader :(")
self.exit()
return mode
def run(self): def run(self):
if is_windows(): if is_windows():
proper_driver = console_cmd(r'reg query HKLM\HARDWARE\DEVICEMAP\SERIALCOMM') proper_driver = console_cmd(r'reg query HKLM\HARDWARE\DEVICEMAP\SERIALCOMM')
@ -308,6 +288,10 @@ class main(metaclass=LogBase):
self.cdc.timeout = 1500 self.cdc.timeout = 1500
conninfo = self.doconnect(loop) conninfo = self.doconnect(loop)
mode = conninfo["mode"] mode = conninfo["mode"]
if not "data" in conninfo:
version = 2
else:
version = conninfo["data"].version
if mode == "sahara": if mode == "sahara":
cmd = conninfo["cmd"] cmd = conninfo["cmd"]
if cmd == cmd_t.SAHARA_HELLO_REQ: if cmd == cmd_t.SAHARA_HELLO_REQ:
@ -318,9 +302,9 @@ class main(metaclass=LogBase):
time.sleep(0.5) time.sleep(0.5)
print("Device is in memory dump mode, dumping memory") print("Device is in memory dump mode, dumping memory")
if args["--partitions"]: if args["--partitions"]:
self.sahara.debug_mode(args["--partitions"].split(",")) self.sahara.debug_mode(args["--partitions"].split(","),version=version)
else: else:
self.sahara.debug_mode() self.sahara.debug_mode(version=version)
self.exit() self.exit()
else: else:
print("Device is in streaming mode, uploading loader") print("Device is in streaming mode, uploading loader")
@ -333,7 +317,7 @@ class main(metaclass=LogBase):
else: else:
mode, resp = sahara_connect mode, resp = sahara_connect
if mode == "sahara": if mode == "sahara":
mode = self.sahara.upload_loader() mode = self.sahara.upload_loader(version=version)
if "enprg" in self.sahara.programmer.lower(): if "enprg" in self.sahara.programmer.lower():
mode = "load_enandprg" mode = "load_enandprg"
elif "nprg" in self.sahara.programmer.lower(): elif "nprg" in self.sahara.programmer.lower():
@ -346,14 +330,14 @@ class main(metaclass=LogBase):
print("Error, couldn't find suitable enprg/nprg loader :(") print("Error, couldn't find suitable enprg/nprg loader :(")
self.exit() self.exit()
else: else:
sahara_info = self.sahara.cmd_info() sahara_info = self.sahara.cmd_info(version=version)
if sahara_info is not None: if sahara_info is not None:
resp = self.sahara.connect() resp = self.sahara.connect()
mode = resp["mode"] mode = resp["mode"]
if "data" in resp: if "data" in resp:
data = resp["data"] data = resp["data"]
if mode == "sahara": if mode == "sahara":
mode = self.sahara.upload_loader() mode = self.sahara.upload_loader(version=version)
else: else:
print("Error on sahara handshake, resetting.") print("Error on sahara handshake, resetting.")
self.sahara.cmd_reset() self.sahara.cmd_reset()

View file

@ -12,24 +12,32 @@ from edlclient.Library.utils import LogBase
try: try:
from edlclient.Library.Modules.generic import generic from edlclient.Library.Modules.generic import generic
except ImportError as e: except ImportError as e:
print(e)
generic = None generic = None
pass pass
try: try:
from edlclient.Library.Modules.oneplus import oneplus from edlclient.Library.Modules.oneplus import oneplus
except ImportError as e: except ImportError as e:
print(e)
oneplus = None oneplus = None
pass pass
try: try:
from edlclient.Library.Modules.xiaomi import xiaomi from edlclient.Library.Modules.xiaomi import xiaomi
except ImportError as e: except ImportError as e:
print(e)
xiaomi = None xiaomi = None
pass pass
try:
from edlclient.Library.Modules.nothing import nothing
except ImportError as e:
nothing = None
pass
class modules(metaclass=LogBase): class modules(metaclass=LogBase):
def __init__(self, fh, serial, supported_functions, loglevel, devicemodel, args): def __init__(self, fh, serial:int, supported_functions, loglevel, devicemodel:str, args):
self.fh = fh self.fh = fh
self.args = args self.args = args
self.serial = serial self.serial = serial
@ -47,17 +55,20 @@ class modules(metaclass=LogBase):
try: try:
self.generic = generic(fh=self.fh, serial=self.serial, args=self.args, loglevel=loglevel) self.generic = generic(fh=self.fh, serial=self.serial, args=self.args, loglevel=loglevel)
except Exception as e: except Exception as e:
self.error(e)
pass pass
self.ops = None self.ops = None
try: try:
self.ops = oneplus(fh=self.fh, projid=self.devicemodel, serial=self.serial, self.ops = oneplus(fh=self.fh, projid=self.devicemodel, serial=self.serial,
supported_functions=self.supported_functions, args=self.args, loglevel=loglevel) supported_functions=self.supported_functions, args=self.args, loglevel=loglevel)
except Exception as e: except Exception as e:
self.error(e)
pass pass
self.xiaomi = None self.xiaomi = None
try: try:
self.xiaomi = xiaomi(fh=self.fh) self.xiaomi = xiaomi(fh=self.fh)
except Exception as e: except Exception as e:
self.error(e)
pass pass
def addpatch(self): def addpatch(self):

View file

@ -0,0 +1,65 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 under GPLv3 license
# If you use my code, make sure you refer to my name
#
# !!!!! If you use this code in commercial products, your product is automatically
# GPLv3 and has to be open sourced under GPLv3 as well. !!!!!
import hashlib
import logging
import random
from edlclient.Library.utils import LogBase
class nothing(metaclass=LogBase):
def __init__(self, fh, projid="22111", serial=123456, ATOBuild=0, Flash_Mode=0, cf=0, supported_functions=None,
loglevel=logging.INFO):
self.fh = fh
self.projid = projid
#self.projid == "22111":
self.hashverify = "16386b4035411a770b12507b2e30297c0c5471230b213e6a1e1e701c6a425150"
self.serial = serial
self.supported_functions = supported_functions
self.__logger.setLevel(loglevel)
if loglevel == logging.DEBUG:
logfilename = "log.txt"
fh = logging.FileHandler(logfilename)
self.__logger.addHandler(fh)
def generatetoken(self, token1: str = None):
if token1 is None:
token1 = random.randbytes(32).hex()
authresp = token1 + self.projid + ("%x" % self.serial) + self.hashverify
token2 = hashlib.sha256(bytes(authresp,'utf-8')).hexdigest()[:64]
token3 = self.hashverify
return bytes(f"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>\n <ntprojectverify token1=\"{token1}\" token2=\"{token2}\" token3=\"{token3}\"/>\n</data>\n",'utf-8')
def ntprojectverify(self):
"""
Nothing Phone 2
"""
authcmd = b"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>\n <checkntfeature />\n</data>\n"
rsp = self.fh.xmlsend(authcmd)
if rsp.resp:
authresp = self.generatetoken()
rsp = self.fh.xmlsend(authresp)
if rsp.resp:
if b"ACK" in rsp.data:
return True
if "value" in rsp.resp:
if rsp.resp["value"] == "ACK":
if 'authenticated' in rsp.log[0].lower() and 'true' in rsp.log[0].lower():
return True
return False
if __name__ == "__main__":
nt = nothing(fh=None, projid="22111", serial=1729931115)
res=nt.generatetoken(token1="512034500a07154561661e0f371f4a712a0b76074605724c640e301d632b3671")
org=b"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><data>\n <ntprojectverify token1=\"512034500a07154561661e0f371f4a712a0b76074605724c640e301d632b3671\" token2=\"1ecd222465436eb8acc0cfc41e90d1e677165c184ea7d9631615014dac88c669\" token3=\"16386b4035411a770b12507b2e30297c0c5471230b213e6a1e1e701c6a425150\"/>\n</data>\n"
if res!=org:
print("Error !")
print(res)
print(nt.generatetoken())

View file

@ -24,7 +24,7 @@ import random
from struct import pack from struct import pack
import logging import logging
from edlclient.Library.utils import LogBase from edlclient.Library.utils import LogBase
from edlclient.Library.Modules.oneplus_param import paramtools
try: try:
from edlclient.Library.cryptutils import cryptutils from edlclient.Library.cryptutils import cryptutils
except Exception as e: except Exception as e:
@ -128,7 +128,7 @@ deviceconfig = {
class oneplus(metaclass=LogBase): class oneplus(metaclass=LogBase):
def __init__(self, fh, projid="18825", serial=123456, ATOBuild=0, Flash_Mode=0, cf=0, supported_functions=None, def __init__(self, fh, projid:str="18825", serial=123456, ATOBuild=0, Flash_Mode=0, cf=0, supported_functions=None,
args=None, loglevel=logging.INFO): args=None, loglevel=logging.INFO):
self.fh = fh self.fh = fh
self.__logger = self.__logger self.__logger = self.__logger
@ -160,7 +160,6 @@ class oneplus(metaclass=LogBase):
filehandler = logging.FileHandler(logfilename) filehandler = logging.FileHandler(logfilename)
self.__logger.addHandler(filehandler) self.__logger.addHandler(filehandler)
try: try:
from edlclient.Library.Modules.oneplus_param import paramtools
if projid in deviceconfig: if projid in deviceconfig:
mode = deviceconfig[projid]["param_mode"] mode = deviceconfig[projid]["param_mode"]
self.ops_parm = paramtools(mode=mode, serial=serial) self.ops_parm = paramtools(mode=mode, serial=serial)
@ -200,10 +199,11 @@ class oneplus(metaclass=LogBase):
exit(0) exit(0)
elif version == 3: elif version == 3:
if cm is not None: if cm is not None:
oneplus2(fh, cm, serial, pk, prodkey, self.ATOBuild, self.Flash_Mode, self.cf) return oneplus2(fh, cm, serial, pk, prodkey, self.ATOBuild, self.Flash_Mode, self.cf)
else: else:
assert "Device is not supported" assert "Device is not supported"
exit(0) exit(0)
assert "Unknown projid:"+str(projid)
return None return None
def run(self): def run(self):
@ -225,16 +225,16 @@ class oneplus(metaclass=LogBase):
if self.ops.setprojmodel_verify: if self.ops.setprojmodel_verify:
return self.ops.setprojmodel_verify(pk, token) return self.ops.setprojmodel_verify(pk, token)
def setswprojmodel_verify(self, pk, token, device_timestamp): def setswprojmodel_verify(self, pk, token):
if self.ops.setswprojmodel_verify: if self.ops.setswprojmodel_verify:
return self.ops.setswprojmodel_verify(pk, token, device_timestamp) return self.ops.setswprojmodel_verify(pk, token)
def program_verify(self, pk, token, tokendata): def program_verify(self, pk, token, tokendata):
if self.ops.program_verify: if self.ops.program_verify:
return self.ops.program_verify(pk, token, tokendata) return self.ops.program_verify(pk, token, tokendata)
def generatetoken(self, program=False, device_timestamp="123456789"): def generatetoken(self, program=False):
return self.ops.generatetoken(program=program, device_timestamp=device_timestamp) return self.ops.generatetoken(program=program)
def demacia(self): def demacia(self):
if self.ops.demacia(): if self.ops.demacia():
@ -310,7 +310,7 @@ class oneplus1:
data = "<?xml version=\"1.0\" ?>\n<data>\n<demacia token=\"" + token + "\" pk=\"" + pk + "\" />\n</data>" data = "<?xml version=\"1.0\" ?>\n<data>\n<demacia token=\"" + token + "\" pk=\"" + pk + "\" />\n</data>"
return data return data
def generatetoken(self, program=False, device_timestamp=None): def generatetoken(self, program=False):
timestamp = str(int(time.time())) timestamp = str(int(time.time()))
ha = cryptutils().hash() ha = cryptutils().hash()
h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix
@ -429,6 +429,7 @@ class oneplus1:
class oneplus2(metaclass=LogBase): class oneplus2(metaclass=LogBase):
def __init__(self, fh, ModelVerifyPrjName="20889", serial=123456, pk="", prodkey="", ATOBuild=0, Flash_Mode=0, def __init__(self, fh, ModelVerifyPrjName="20889", serial=123456, pk="", prodkey="", ATOBuild=0, Flash_Mode=0,
cf=0, loglevel=logging.INFO): cf=0, loglevel=logging.INFO):
self.device_timestamp = None
self.ModelVerifyPrjName = ModelVerifyPrjName self.ModelVerifyPrjName = ModelVerifyPrjName
self.pk = pk self.pk = pk
self.fh = fh self.fh = fh
@ -445,10 +446,10 @@ class oneplus2(metaclass=LogBase):
fh = logging.FileHandler(logfilename) fh = logging.FileHandler(logfilename)
self.__logger.addHandler(fh) self.__logger.addHandler(fh)
def crypt_token(self, data, pk, device_timestamp, decrypt=False): def crypt_token(self, data, pk, device_timestamp:int, decrypt=False):
aes = cryptutils().aes() aes = cryptutils().aes()
aeskey = b"\x46\xA5\x97\x30\xBB\x0D\x41\xE8" + bytes(pk, 'utf-8') + \ aeskey = b"\x46\xA5\x97\x30\xBB\x0D\x41\xE8" + bytes(pk, 'utf-8') + \
pack("<Q", int(device_timestamp, 10)) # we get this using setprocstart pack("<Q", device_timestamp) # we get this using setprocstart
aesiv = b"\xDC\x91\x0D\x88\xE3\xC6\xEE\x65\xF0\xC7\x44\xB4\x02\x30\xCE\x40" aesiv = b"\xDC\x91\x0D\x88\xE3\xC6\xEE\x65\xF0\xC7\x44\xB4\x02\x30\xCE\x40"
if decrypt: if decrypt:
cdata = unhexlify(data) cdata = unhexlify(data)
@ -463,7 +464,7 @@ class oneplus2(metaclass=LogBase):
rdata = hexlify(result) rdata = hexlify(result)
return rdata.upper().decode('utf-8') return rdata.upper().decode('utf-8')
def generatetoken(self, program=False, device_timestamp=None): # setswprojmodel def generatetoken(self, program=False): # setswprojmodel
timestamp = str(int(time.time())) timestamp = str(int(time.time()))
ha = cryptutils().hash() ha = cryptutils().hash()
h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix
@ -482,7 +483,7 @@ class oneplus2(metaclass=LogBase):
for item in items: for item in items:
data += item + "," data += item + ","
data = data[:-1] data = data[:-1]
token = self.crypt_token(data, self.pk, device_timestamp) token = self.crypt_token(data, self.pk, self.device_timestamp)
return self.pk, token return self.pk, token
def run(self, flag): def run(self, flag):
@ -493,7 +494,9 @@ class oneplus2(metaclass=LogBase):
return False return False
data = res.decode('utf-8') data = res.decode('utf-8')
device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1] device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1]
pk, token = self.generatetoken(False, device_timestamp) self.device_timestamp = int(device_timestamp)
print(self.device_timestamp)
pk, token = self.generatetoken(False)
res = self.fh.cmd_send(f"setswprojmodel token=\"{token}\" pk=\"{pk}\"") res = self.fh.cmd_send(f"setswprojmodel token=\"{token}\" pk=\"{pk}\"")
if not b"model_check=\"0\"" in res or not b"auth_token_verify=\"0\"" in res: if not b"model_check=\"0\"" in res or not b"auth_token_verify=\"0\"" in res:
print("Setswprojmodel failed.") print("Setswprojmodel failed.")
@ -501,10 +504,10 @@ class oneplus2(metaclass=LogBase):
return False return False
return True return True
def setswprojmodel_verify(self, pk, token, device_timestamp): def setswprojmodel_verify(self, pk, token):
self.pk = pk self.pk = pk
ha = cryptutils().hash() ha = cryptutils().hash()
items = self.crypt_token(token, pk, device_timestamp, True) items = self.crypt_token(token, pk, self.device_timestamp, True)
info = ["ModelVerifyPrjName", "random_postfix", "ModelVerifyHashToken", "ato_build_state", "flash_mode", info = ["ModelVerifyPrjName", "random_postfix", "ModelVerifyHashToken", "ato_build_state", "flash_mode",
"Version", "soc_sn", "cf", "timestamp", "secret"] "Version", "soc_sn", "cf", "timestamp", "secret"]
i = 0 i = 0
@ -568,10 +571,11 @@ def main():
serial = args["--serial"] serial = args["--serial"]
device_timestamp = args["--ts"] device_timestamp = args["--ts"]
op2 = oneplus(None, projid="20889", serial=serial, ATOBuild=0, Flash_Mode=0, cf=0) op2 = oneplus(None, projid="20889", serial=serial, ATOBuild=0, Flash_Mode=0, cf=0)
op2.ops.device_timestamp = int(device_timestamp)
# 20889 OP N10 5G Europe # 20889 OP N10 5G Europe
print(f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setprocstart /></data>\"") print(f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setprocstart /></data>\"")
# Response should be : <?xml version="1.0" ?><data><response value=1 device_timestamp="%llu" /></data> # Response should be : <?xml version="1.0" ?><data><response value=1 device_timestamp="%llu" /></data>
pk, token = op2.generatetoken(False, device_timestamp) pk, token = op2.generatetoken(False)
print( print(
f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setswprojmodel " + f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setswprojmodel " +
f"token=\\\"{token}\\\" pk=\\\"{pk}\\\" /></data>\" --debugmode") f"token=\\\"{token}\\\" pk=\\\"{pk}\\\" /></data>\" --debugmode")
@ -605,9 +609,10 @@ def main():
projid = args["--projid"][0] projid = args["--projid"][0]
device_timestamp = args["--ts"] device_timestamp = args["--ts"]
op = oneplus(None, projid=projid, serial=123456) op = oneplus(None, projid=projid, serial=123456)
op.ops.device_timestamp = int(device_timestamp)
token = args["<token>"] token = args["<token>"]
pk = args["<pk>"] pk = args["<pk>"]
op.setswprojmodel_verify(pk, token, device_timestamp) op.setswprojmodel_verify(pk, token)
def test_setswprojmodel_verify(): def test_setswprojmodel_verify():
@ -617,8 +622,9 @@ def test_setswprojmodel_verify():
op = oneplus(None, projid=projid, serial=123456) op = oneplus(None, projid=projid, serial=123456)
data = deviceresp.decode('utf-8') data = deviceresp.decode('utf-8')
device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1] device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1]
pk, token = op.generatetoken(False, device_timestamp) op.ops.device_timestamp = int(device_timestamp)
if not op.setswprojmodel_verify(pk, token, device_timestamp): pk, token = op.generatetoken(False)
if not op.setswprojmodel_verify(pk, token):
assert "Setswprojmodel error" assert "Setswprojmodel error"

View file

@ -12,12 +12,10 @@ Usage:
oneplus_param.py gencode <imei> oneplus_param.py gencode <imei>
oneplus_param.py setparam <filename> <sid> <offset> <value> [--mode=mode] [--serial=serial] oneplus_param.py setparam <filename> <sid> <offset> <value> [--mode=mode] [--serial=serial]
""" """
from enum import Enum
from struct import calcsize, pack, unpack
import hashlib import hashlib
import zlib import zlib
import qrcode from enum import Enum
from struct import calcsize, pack, unpack
try: try:
from edlclient.Library.cryptutils import cryptutils from edlclient.Library.cryptutils import cryptutils
@ -31,10 +29,6 @@ except ImportError as e:
from cryptutils import cryptutils from cryptutils import cryptutils
except ImportError as e: except ImportError as e:
print(str(e)) print(str(e))
try:
from edlclient.Library.Modules.oneplus_param import *
except ImportError:
pass
from binascii import unhexlify, hexlify from binascii import unhexlify, hexlify
@ -984,6 +978,7 @@ def main():
print("oneplus Factory qr code generator (c) B. Kerler 2019\nGPLv3 License\n----------------------") print("oneplus Factory qr code generator (c) B. Kerler 2019\nGPLv3 License\n----------------------")
print("Code : *#*#5646#*#* , *#808#, *#36446337# = com.android.engineeringmode.manualtest.DecryptActivity") print("Code : *#*#5646#*#* , *#808#, *#36446337# = com.android.engineeringmode.manualtest.DecryptActivity")
results = param.gencode([imei, "YOU_CAN_PASS_NOW"]) results = param.gencode([imei, "YOU_CAN_PASS_NOW"])
import qrcode
img = qrcode.make("op_eng://" + results[0]) img = qrcode.make("op_eng://" + results[0])
print("Code : " + results[0]) print("Code : " + results[0])
img.save(imei + ".png") img.save(imei + ".png")

View file

@ -8,6 +8,7 @@
import binascii import binascii
import io import io
import os.path
import platform import platform
import time import time
import json import json
@ -15,6 +16,8 @@ from struct import unpack
from binascii import hexlify from binascii import hexlify
from queue import Queue from queue import Queue
from threading import Thread from threading import Thread
from edlclient.Library.Modules.nothing import nothing
from edlclient.Library.utils import * from edlclient.Library.utils import *
from edlclient.Library.gpt import gpt from edlclient.Library.gpt import gpt
from edlclient.Library.sparse import QCSparse from edlclient.Library.sparse import QCSparse
@ -1031,6 +1034,15 @@ class firehose(metaclass=LogBase):
self.cfg.SECTOR_SIZE_IN_BYTES = 4096 self.cfg.SECTOR_SIZE_IN_BYTES = 4096
return self.configure(0) return self.configure(0)
self.parse_storage() self.parse_storage()
for function in self.supported_functions:
if function == "checkntfeature":
if type(self.devicemodel)==list:
self.devicemodel=self.devicemodel[0]
self.nothing = nothing(fh=self, projid=self.devicemodel, serial=self.serial,
supported_functions=self.supported_functions,
loglevel=self.loglevel)
if self.nothing is not None:
self.nothing.ntprojectverify()
self.luns = self.getluns(self.args) self.luns = self.getluns(self.args)
return True return True
@ -1127,6 +1139,8 @@ class firehose(metaclass=LogBase):
if "chip serial num" in line.lower(): if "chip serial num" in line.lower():
try: try:
serial = line.split("0x")[1][:-1] serial = line.split("0x")[1][:-1]
if ")" in serial:
serial=serial[:serial.rfind(")")]
self.serial = int(serial, 16) self.serial = int(serial, 16)
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
self.debug(str(err)) self.debug(str(err))
@ -1150,7 +1164,8 @@ class firehose(metaclass=LogBase):
try: try:
if os.path.exists(self.cfg.programmer): if os.path.exists(self.cfg.programmer):
data = open(self.cfg.programmer, "rb").read() data = open(self.cfg.programmer, "rb").read()
for cmd in [b"demacia", b"setprojmodel", b"setswprojmodel", b"setprocstart", b"SetNetType"]: for cmd in [b"demacia", b"setprojmodel", b"setswprojmodel", b"setprocstart", b"SetNetType",
b"checkntfeature"]:
if cmd in data: if cmd in data:
self.supported_functions.append(cmd.decode('utf-8')) self.supported_functions.append(cmd.decode('utf-8'))
state = { state = {
@ -1158,7 +1173,19 @@ class firehose(metaclass=LogBase):
"programmer": self.cfg.programmer, "programmer": self.cfg.programmer,
"serial": self.serial "serial": self.serial
} }
open("edl_config.json", "w").write(json.dumps(state)) if os.path.exists("edl_config.json"):
data = json.loads(open("edl_config.json","rb").read().decode('utf-8'))
if "serial" in data and data["serial"]!=state["serial"]:
open("edl_config.json", "w").write(json.dumps(state))
else:
self.supported_functions = data["supported_functions"]
self.cfg.programmer = data["programmer"]
else:
open("edl_config.json", "w").write(json.dumps(state))
if "001920e101cf0000_fa2836525c2aad8a_fhprg.bin" in self.cfg.programmer:
self.devicemodel = '20111'
elif "000b80e100020000_467f3020c4cc788d_fhprg.bin" in self.cfg.programmer:
self.devicemodel = '22111'
except: except:
pass pass

View file

@ -390,7 +390,7 @@ class gpt(metaclass=LogBase):
if pa.type == "EFI_UNUSED": if pa.type == "EFI_UNUSED":
continue continue
self.partentries[pa.name]=pa self.partentries[pa.name]=pa
self.totalsectors = self.header.last_usable_lba + 34 self.totalsectors = self.header.first_usable_lba + self.header.last_usable_lba
return True return True
def print(self): def print(self):

View file

@ -98,11 +98,11 @@ class sahara(metaclass=LogBase):
self.error(str(e)) self.error(str(e))
return {} return {}
def cmd_hello(self, mode, version_min=1, max_cmd_len=0): # CMD 0x1, RSP 0x2 def cmd_hello(self, mode, version_min=1, max_cmd_len=0, version=2): # CMD 0x1, RSP 0x2
cmd = cmd_t.SAHARA_HELLO_RSP cmd = cmd_t.SAHARA_HELLO_RSP
length = 0x30 length = 0x30
version = SAHARA_VERSION #version = SAHARA_VERSION
responsedata = pack("<IIIIIIIIIIII", cmd, length, version, version_min, max_cmd_len, mode, 0, 0, 0, 0, 0, 0) responsedata = pack("<IIIIIIIIIIII", cmd, length, version, version_min, max_cmd_len, mode, 1, 2, 3, 4, 5, 6)
try: try:
self.cdc.write(responsedata) self.cdc.write(responsedata)
return True return True
@ -155,8 +155,8 @@ class sahara(metaclass=LogBase):
self.error(str(e)) self.error(str(e))
return {"mode": "error"} return {"mode": "error"}
def enter_command_mode(self): def enter_command_mode(self, version=2):
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_COMMAND): if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_COMMAND, version=version):
return False return False
res = self.get_rsp() res = self.get_rsp()
if "cmd" in res: if "cmd" in res:
@ -179,11 +179,9 @@ class sahara(metaclass=LogBase):
def cmdexec_get_msm_hwid(self): def cmdexec_get_msm_hwid(self):
res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_MSM_HW_ID_READ) res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_MSM_HW_ID_READ)
try: if res is not None:
return int.from_bytes(res[:8],'little') return int.from_bytes(res[:8],'little')
except Exception as e: # pylint: disable=broad-except return None
self.debug(str(e))
return None
def cmdexec_get_pkhash(self): def cmdexec_get_pkhash(self):
try: try:
@ -212,104 +210,111 @@ class sahara(metaclass=LogBase):
res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_READ_DEBUG_DATA) res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_READ_DEBUG_DATA)
return res return res
def cmd_info(self): def cmd_info(self, version):
if self.enter_command_mode(): if self.enter_command_mode(version=version):
self.serial = self.cmdexec_get_serial_num() self.serial = self.cmdexec_get_serial_num()
self.serials = "{:08x}".format(self.serial) self.serials = "{:08x}".format(self.serial)
self.hwid = self.cmdexec_get_msm_hwid() if version < 3:
self.pkhash = self.cmdexec_get_pkhash() self.hwid = self.cmdexec_get_msm_hwid()
# if self.version>=2.4: self.pkhash = self.cmdexec_get_pkhash()
# self.sblversion = "{:08x}".format(self.cmdexec_get_sbl_version()) # if self.version>=2.4:
if self.hwid is not None: # self.sblversion = "{:08x}".format(self.cmdexec_get_sbl_version())
self.hwidstr = "{:016x}".format(self.hwid) if self.hwid is not None:
self.msm_id = int(self.hwidstr[2:8], 16) self.hwidstr = "{:016x}".format(self.hwid)
self.oem_id = int(self.hwidstr[-8:-4], 16) self.msm_id = int(self.hwidstr[2:8], 16)
self.model_id = int(self.hwidstr[-4:], 16) self.oem_id = int(self.hwidstr[-8:-4], 16)
self.oem_str = "{:04x}".format(self.oem_id) self.model_id = int(self.hwidstr[-4:], 16)
self.model_id = "{:04x}".format(self.model_id) self.oem_str = "{:04x}".format(self.oem_id)
self.msm_str = "{:08x}".format(self.msm_id) self.model_id = "{:04x}".format(self.model_id)
if self.msm_id in msmids: self.msm_str = "{:08x}".format(self.msm_id)
cpustr = f"CPU detected: \"{msmids[self.msm_id]}\"\n" if self.msm_id in msmids:
else: cpustr = f"CPU detected: \"{msmids[self.msm_id]}\"\n"
cpustr = "Unknown CPU, please send log as issue to https://github.com/bkerler/edl\n" else:
""" cpustr = "Unknown CPU, please send log as issue to https://github.com/bkerler/edl\n"
if self.version >= 2.4: """
self.info(f"\n------------------------\n" + if self.version >= 2.4:
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," + self.info(f"\nVersion {hex(version)}\n------------------------\n" +
f"OEM_ID:0x{self.oem_str}," + f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
f"MODEL_ID:0x{self.model_id})\n" + f"OEM_ID:0x{self.oem_str}," +
f"PK_HASH: 0x{self.pkhash}\n" + f"MODEL_ID:0x{self.model_id})\n" +
f"Serial: 0x{self.serials}\n" + f"PK_HASH: 0x{self.pkhash}\n" +
f"SBL Version: 0x{self.sblversion}\n") f"Serial: 0x{self.serials}\n" +
else: f"SBL Version: 0x{self.sblversion}\n")
""" else:
self.info(f"\n------------------------\n" + """
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," + self.info(f"\nVersion {hex(version)}\n------------------------\n" +
f"OEM_ID:0x{self.oem_str}," + f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
f"MODEL_ID:0x{self.model_id})\n" + f"OEM_ID:0x{self.oem_str}," +
cpustr + f"MODEL_ID:0x{self.model_id})\n" +
f"PK_HASH: 0x{self.pkhash}\n" + cpustr +
f"Serial: 0x{self.serials}\n") f"PK_HASH: 0x{self.pkhash}\n" +
if self.programmer == "": f"Serial: 0x{self.serials}\n")
if self.hwidstr in self.loaderdb: if self.programmer == "":
mt = self.loaderdb[self.hwidstr] if self.hwidstr in self.loaderdb:
unfused = False mt = self.loaderdb[self.hwidstr]
for rootcert in root_cert_hash: unfused = False
if self.pkhash[0:16] in root_cert_hash[rootcert]: for rootcert in root_cert_hash:
unfused = True if self.pkhash[0:16] in root_cert_hash[rootcert]:
break unfused = True
if unfused: break
self.info("Possibly unfused device detected, so any loader should be fine...") if unfused:
if self.pkhash[0:16] in mt: self.info("Possibly unfused device detected, so any loader should be fine...")
self.programmer = mt[self.pkhash[0:16]] if self.pkhash[0:16] in mt:
self.info(f"Trying loader: {self.programmer}") self.programmer = mt[self.pkhash[0:16]]
self.info(f"Trying loader: {self.programmer}")
else:
for loader in mt:
self.programmer = mt[loader]
self.info(f"Possible loader available: {self.programmer}")
for loader in mt:
self.programmer = mt[loader]
self.info(f"Trying loader: {self.programmer}")
break
elif self.pkhash[0:16] in mt:
self.programmer = self.loaderdb[self.hwidstr][self.pkhash[0:16]]
self.info(f"Detected loader: {self.programmer}")
else: else:
for loader in mt: for loader in self.loaderdb[self.hwidstr]:
self.programmer = mt[loader] self.programmer = self.loaderdb[self.hwidstr][loader]
self.info(f"Possible loader available: {self.programmer}")
for loader in mt:
self.programmer = mt[loader]
self.info(f"Trying loader: {self.programmer}") self.info(f"Trying loader: {self.programmer}")
break break
elif self.pkhash[0:16] in mt: # print("Couldn't find a loader for given hwid and pkhash :(")
self.programmer = self.loaderdb[self.hwidstr][self.pkhash[0:16]] # exit(0)
self.info(f"Detected loader: {self.programmer}") elif self.hwidstr is not None and self.pkhash is not None:
else: msmid = self.hwidstr[:8]
for loader in self.loaderdb[self.hwidstr]: found = False
self.programmer = self.loaderdb[self.hwidstr][loader] for hwidstr in self.loaderdb:
self.info(f"Trying loader: {self.programmer}") if msmid == hwidstr[:8]:
break if self.pkhash[0:16] in self.loaderdb[hwidstr]:
# print("Couldn't find a loader for given hwid and pkhash :(") self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]]
# exit(0) self.info(f"Found loader: {self.programmer}")
elif self.hwidstr is not None and self.pkhash is not None: self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
msmid = self.hwidstr[:8] return True
found = False else:
for hwidstr in self.loaderdb: if self.pkhash[0:16] in self.loaderdb[hwidstr]:
if msmid == hwidstr[:8]: self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]]
if self.pkhash[0:16] in self.loaderdb[hwidstr]: self.info(f"Found possible loader: {self.programmer}")
self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]] found = True
self.info(f"Found loader: {self.programmer}") if found:
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND) self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True return True
else: else:
if self.pkhash[0:16] in self.loaderdb[hwidstr]: self.error(
self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]] f"Couldn't find a loader for given hwid and pkhash ({self.hwidstr}_{self.pkhash[0:16]}" +
self.info(f"Found possible loader: {self.programmer}") "_[FHPRG/ENPRG].bin) :(")
found = True return False
if found:
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True
else: else:
self.error( self.error(f"Couldn't find a suitable loader :(")
f"Couldn't find a loader for given hwid and pkhash ({self.hwidstr}_{self.pkhash[0:16]}" + return False
"_[FHPRG/ENPRG].bin) :(") else:
self.info(f"\nVersion {hex(version)}\n------------------------\n" +
f"Serial: 0x{self.serials}\n")
if self.programmer=="":
self.error("No autodetection of loader possible with sahara version 3 and above :( Aborting.")
return False return False
else:
self.error(f"Couldn't find a suitable loader :(")
return False
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND) self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True return True
return False return False
def streaminginfo(self): def streaminginfo(self):
@ -432,8 +437,8 @@ class sahara(metaclass=LogBase):
self.cmd_reset() self.cmd_reset()
return True return True
def debug_mode(self, dump_partitions=None): def debug_mode(self, dump_partitions=None, version=2):
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_MEMORY_DEBUG): if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_MEMORY_DEBUG, version=version):
return False return False
if os.path.exists("memory"): if os.path.exists("memory"):
rmrf("memory") rmrf("memory")
@ -501,7 +506,7 @@ class sahara(metaclass=LogBase):
return False return False
return False return False
def upload_loader(self): def upload_loader(self, version):
if self.programmer == "": if self.programmer == "":
return "" return ""
try: try:
@ -512,7 +517,7 @@ class sahara(metaclass=LogBase):
self.error(str(e)) self.error(str(e))
sys.exit() sys.exit()
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_IMAGE_TX_PENDING): if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_IMAGE_TX_PENDING, version=version):
return "" return ""
try: try:

View file

@ -108,7 +108,53 @@ def extract_hdr(memsection, version, sign_info, mem_section, code_size, signatur
len2 = unpack(">H", mem_section[casignature2offset + 2:casignature2offset + 4])[0] + 4 len2 = unpack(">H", mem_section[casignature2offset + 2:casignature2offset + 4])[0] + 4
rootsignature3offset = casignature2offset + len2 rootsignature3offset = casignature2offset + len2
len3 = unpack(">H", mem_section[rootsignature3offset + 2:rootsignature3offset + 4])[0] + 4 len3 = unpack(">H", mem_section[rootsignature3offset + 2:rootsignature3offset + 4])[0] + 4
sign_info.pk_hash = hashlib.sha384(mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
idx = signatureoffset
signature = {}
while idx != -1:
if idx >= len(mem_section):
break
idx = mem_section.find('\x04\x0B'.encode(), idx)
if idx == -1:
break
length = mem_section[idx + 3]
if length > 60:
idx += 1
continue
try:
text = mem_section[idx + 4:idx + 4 + length].decode().split(' ')
signature[text[2]] = text[1]
except:
text = ""
idx += 1
idx = mem_section.find('QC_IMAGE_VERSION_STRING='.encode(), 0)
if idx != -1:
sign_info.qc_version = grabtext(mem_section[idx + len("QC_IMAGE_VERSION_STRING="):])
idx = mem_section.find('OEM_IMAGE_VERSION_STRING='.encode(), 0)
if idx != -1:
sign_info.oem_version = grabtext(mem_section[idx + len("OEM_IMAGE_VERSION_STRING="):])
idx = mem_section.find('IMAGE_VARIANT_STRING='.encode(), 0)
if idx != -1:
sign_info.image_variant = grabtext(mem_section[idx + len("IMAGE_VARIANT_STRING="):])
if "MODEL_ID" in signature:
sign_info.model_id = signature["MODEL_ID"]
if "OEM_ID" in signature:
sign_info.oem_id = signature["OEM_ID"]
if "HW_ID" in signature:
sign_info.hw_id = signature["HW_ID"]
if "SW_ID" in signature:
sign_info.sw_id = signature["SW_ID"]
if "SW_SIZE" in signature:
sign_info.sw_size = signature["SW_SIZE"]
if "SHA256" in signature:
sign_info.pk_hash = hashlib.sha256(mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
elif "SHA384" in signature:
sign_info.pk_hash = hashlib.sha384(
mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
else:
sign_info.pk_hash = hashlib.sha384(
mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
except: except:
return None return None
return sign_info return sign_info
@ -166,12 +212,24 @@ def extract_old_hdr(signatureoffset, sign_info, mem_section, code_size, signatur
sign_info.sw_id = signature["SW_ID"] sign_info.sw_id = signature["SW_ID"]
if "SW_SIZE" in signature: if "SW_SIZE" in signature:
sign_info.sw_size = signature["SW_SIZE"] sign_info.sw_size = signature["SW_SIZE"]
if "SHA256" in signature:
sign_info.pk_hash = hashlib.sha256(mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
elif "SHA384" in signature:
sign_info.pk_hash = hashlib.sha384(
mem_section[rootsignature3offset:rootsignature3offset + len3]).hexdigest()
return sign_info return sign_info
def init_loader_db(): def init_loader_db():
loaderdb = {} loaderdb = {}
for (dirpath, dirnames, filenames) in os.walk(os.path.join(current_dir,"..","..","Loaders")): loaders=os.path.join(current_dir,"..","..","Loaders")
if not os.path.exists(loaders):
loaders = os.path.join(current_dir, "Loaders")
if not os.path.exists(loaders):
print("Couldn't find Loaders directory")
return loaderdb
for (dirpath, dirnames, filenames) in os.walk(loaders):
for filename in filenames: for filename in filenames:
file_name = os.path.join(dirpath, filename) file_name = os.path.join(dirpath, filename)
found = False found = False
@ -315,6 +373,7 @@ def main(argv):
print("%s has no signature." % filename) print("%s has no signature." % filename)
copyfile(filename, copyfile(filename,
os.path.join(outputdir, "Unknown", filename[filename.rfind("/") + 1:].lower())) os.path.join(outputdir, "Unknown", filename[filename.rfind("/") + 1:].lower()))
elfpos += 0x30
continue continue
if version < 6: # MSM,MDM if version < 6: # MSM,MDM
signatureoffset = memsection.file_start_addr + 0x28 + code_size + signature_size signatureoffset = memsection.file_start_addr + 0x28 + code_size + signature_size

View file

@ -4,7 +4,7 @@ import os
setup( setup(
name='edlclient', name='edlclient',
version='3.60', version='3.62',
packages=find_packages(), packages=find_packages(),
long_description=open("README.md").read(), long_description=open("README.md").read(),
scripts=['edl','edlclient/Tools/qc_diag.py','edlclient/Tools/sierrakeygen.py','edlclient/Tools/boottodwnload','edlclient/Tools/enableadb','edlclient/Tools/fhloaderparse','edlclient/Tools/beagle_to_loader'], scripts=['edl','edlclient/Tools/qc_diag.py','edlclient/Tools/sierrakeygen.py','edlclient/Tools/boottodwnload','edlclient/Tools/enableadb','edlclient/Tools/fhloaderparse','edlclient/Tools/beagle_to_loader'],