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 [--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 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 printgpt [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--loader=filename] [--debugmode] [--skipresponse] [--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]
edl r <partitionname> <filename> [--memory=memtype] [--sectorsize==bytes] [--lun=lun] [--loader=filename] [--skipresponse] [--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]
edl rf <filename> [--memory=memtype] [--lun=lun] [--sectorsize==bytes] [--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]
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] [--devicemodel=value]
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] [--devicemodel=value]
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] [--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 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]
@ -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 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 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 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]
@ -43,17 +43,17 @@ Usage:
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 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 setbootablestoragedrive <lun> [--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]
edl send <command> [--loader=filename] [--debugmode] [--skipresponse] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
edl xml <xmlfile> [--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] [--devicemodel=value] [--skipstorageinit] [--portname=portname] [--serial]
edl reset [--resetmode=mode] [--loader=filename] [--debugmode] [--vid=vid] [--pid=pid] [--portname=portname] [--serial]
edl nop [--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] [--devicemodel=value]
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] [--devicemodel=value]
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] [--skipstorageinit] [--portname=portname] [--serial] [--devicemodel=value]
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] [--devicemodel=value]
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 provision <xmlfile> [--loader=filename] [--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]
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] [--devicemodel=value]
Description:
server # Run tcp/ip server
@ -147,7 +147,7 @@ from binascii import hexlify
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):
@ -232,26 +232,6 @@ class main(metaclass=LogBase):
self.cdc.close()
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):
if is_windows():
proper_driver = console_cmd(r'reg query HKLM\HARDWARE\DEVICEMAP\SERIALCOMM')
@ -308,6 +288,10 @@ class main(metaclass=LogBase):
self.cdc.timeout = 1500
conninfo = self.doconnect(loop)
mode = conninfo["mode"]
if not "data" in conninfo:
version = 2
else:
version = conninfo["data"].version
if mode == "sahara":
cmd = conninfo["cmd"]
if cmd == cmd_t.SAHARA_HELLO_REQ:
@ -318,9 +302,9 @@ class main(metaclass=LogBase):
time.sleep(0.5)
print("Device is in memory dump mode, dumping memory")
if args["--partitions"]:
self.sahara.debug_mode(args["--partitions"].split(","))
self.sahara.debug_mode(args["--partitions"].split(","),version=version)
else:
self.sahara.debug_mode()
self.sahara.debug_mode(version=version)
self.exit()
else:
print("Device is in streaming mode, uploading loader")
@ -333,7 +317,7 @@ class main(metaclass=LogBase):
else:
mode, resp = sahara_connect
if mode == "sahara":
mode = self.sahara.upload_loader()
mode = self.sahara.upload_loader(version=version)
if "enprg" in self.sahara.programmer.lower():
mode = "load_enandprg"
elif "nprg" in self.sahara.programmer.lower():
@ -346,14 +330,14 @@ class main(metaclass=LogBase):
print("Error, couldn't find suitable enprg/nprg loader :(")
self.exit()
else:
sahara_info = self.sahara.cmd_info()
sahara_info = self.sahara.cmd_info(version=version)
if sahara_info is not None:
resp = self.sahara.connect()
mode = resp["mode"]
if "data" in resp:
data = resp["data"]
if mode == "sahara":
mode = self.sahara.upload_loader()
mode = self.sahara.upload_loader(version=version)
else:
print("Error on sahara handshake, resetting.")
self.sahara.cmd_reset()

View file

@ -12,24 +12,32 @@ from edlclient.Library.utils import LogBase
try:
from edlclient.Library.Modules.generic import generic
except ImportError as e:
print(e)
generic = None
pass
try:
from edlclient.Library.Modules.oneplus import oneplus
except ImportError as e:
print(e)
oneplus = None
pass
try:
from edlclient.Library.Modules.xiaomi import xiaomi
except ImportError as e:
print(e)
xiaomi = None
pass
try:
from edlclient.Library.Modules.nothing import nothing
except ImportError as e:
nothing = None
pass
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.args = args
self.serial = serial
@ -47,17 +55,20 @@ class modules(metaclass=LogBase):
try:
self.generic = generic(fh=self.fh, serial=self.serial, args=self.args, loglevel=loglevel)
except Exception as e:
self.error(e)
pass
self.ops = None
try:
self.ops = oneplus(fh=self.fh, projid=self.devicemodel, serial=self.serial,
supported_functions=self.supported_functions, args=self.args, loglevel=loglevel)
except Exception as e:
self.error(e)
pass
self.xiaomi = None
try:
self.xiaomi = xiaomi(fh=self.fh)
except Exception as e:
self.error(e)
pass
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
import logging
from edlclient.Library.utils import LogBase
from edlclient.Library.Modules.oneplus_param import paramtools
try:
from edlclient.Library.cryptutils import cryptutils
except Exception as e:
@ -128,7 +128,7 @@ deviceconfig = {
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):
self.fh = fh
self.__logger = self.__logger
@ -160,7 +160,6 @@ class oneplus(metaclass=LogBase):
filehandler = logging.FileHandler(logfilename)
self.__logger.addHandler(filehandler)
try:
from edlclient.Library.Modules.oneplus_param import paramtools
if projid in deviceconfig:
mode = deviceconfig[projid]["param_mode"]
self.ops_parm = paramtools(mode=mode, serial=serial)
@ -200,10 +199,11 @@ class oneplus(metaclass=LogBase):
exit(0)
elif version == 3:
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:
assert "Device is not supported"
exit(0)
assert "Unknown projid:"+str(projid)
return None
def run(self):
@ -225,16 +225,16 @@ class oneplus(metaclass=LogBase):
if self.ops.setprojmodel_verify:
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:
return self.ops.setswprojmodel_verify(pk, token, device_timestamp)
return self.ops.setswprojmodel_verify(pk, token)
def program_verify(self, pk, token, tokendata):
if self.ops.program_verify:
return self.ops.program_verify(pk, token, tokendata)
def generatetoken(self, program=False, device_timestamp="123456789"):
return self.ops.generatetoken(program=program, device_timestamp=device_timestamp)
def generatetoken(self, program=False):
return self.ops.generatetoken(program=program)
def demacia(self):
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>"
return data
def generatetoken(self, program=False, device_timestamp=None):
def generatetoken(self, program=False):
timestamp = str(int(time.time()))
ha = cryptutils().hash()
h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix
@ -429,6 +429,7 @@ class oneplus1:
class oneplus2(metaclass=LogBase):
def __init__(self, fh, ModelVerifyPrjName="20889", serial=123456, pk="", prodkey="", ATOBuild=0, Flash_Mode=0,
cf=0, loglevel=logging.INFO):
self.device_timestamp = None
self.ModelVerifyPrjName = ModelVerifyPrjName
self.pk = pk
self.fh = fh
@ -445,10 +446,10 @@ class oneplus2(metaclass=LogBase):
fh = logging.FileHandler(logfilename)
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()
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"
if decrypt:
cdata = unhexlify(data)
@ -463,7 +464,7 @@ class oneplus2(metaclass=LogBase):
rdata = hexlify(result)
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()))
ha = cryptutils().hash()
h1 = self.prodkey + self.ModelVerifyPrjName + self.random_postfix
@ -482,7 +483,7 @@ class oneplus2(metaclass=LogBase):
for item in items:
data += item + ","
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
def run(self, flag):
@ -493,7 +494,9 @@ class oneplus2(metaclass=LogBase):
return False
data = res.decode('utf-8')
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}\"")
if not b"model_check=\"0\"" in res or not b"auth_token_verify=\"0\"" in res:
print("Setswprojmodel failed.")
@ -501,10 +504,10 @@ class oneplus2(metaclass=LogBase):
return False
return True
def setswprojmodel_verify(self, pk, token, device_timestamp):
def setswprojmodel_verify(self, pk, token):
self.pk = pk
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",
"Version", "soc_sn", "cf", "timestamp", "secret"]
i = 0
@ -568,10 +571,11 @@ def main():
serial = args["--serial"]
device_timestamp = args["--ts"]
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
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>
pk, token = op2.generatetoken(False, device_timestamp)
pk, token = op2.generatetoken(False)
print(
f"./edl.py rawxml \"<?xml version=\\\"1.0\\\" ?><data><setswprojmodel " +
f"token=\\\"{token}\\\" pk=\\\"{pk}\\\" /></data>\" --debugmode")
@ -605,9 +609,10 @@ def main():
projid = args["--projid"][0]
device_timestamp = args["--ts"]
op = oneplus(None, projid=projid, serial=123456)
op.ops.device_timestamp = int(device_timestamp)
token = args["<token>"]
pk = args["<pk>"]
op.setswprojmodel_verify(pk, token, device_timestamp)
op.setswprojmodel_verify(pk, token)
def test_setswprojmodel_verify():
@ -617,8 +622,9 @@ def test_setswprojmodel_verify():
op = oneplus(None, projid=projid, serial=123456)
data = deviceresp.decode('utf-8')
device_timestamp = data[data.rfind("device_timestamp"):].split("\"")[1]
pk, token = op.generatetoken(False, device_timestamp)
if not op.setswprojmodel_verify(pk, token, device_timestamp):
op.ops.device_timestamp = int(device_timestamp)
pk, token = op.generatetoken(False)
if not op.setswprojmodel_verify(pk, token):
assert "Setswprojmodel error"

View file

@ -12,12 +12,10 @@ Usage:
oneplus_param.py gencode <imei>
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 zlib
import qrcode
from enum import Enum
from struct import calcsize, pack, unpack
try:
from edlclient.Library.cryptutils import cryptutils
@ -31,10 +29,6 @@ except ImportError as e:
from cryptutils import cryptutils
except ImportError as e:
print(str(e))
try:
from edlclient.Library.Modules.oneplus_param import *
except ImportError:
pass
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("Code : *#*#5646#*#* , *#808#, *#36446337# = com.android.engineeringmode.manualtest.DecryptActivity")
results = param.gencode([imei, "YOU_CAN_PASS_NOW"])
import qrcode
img = qrcode.make("op_eng://" + results[0])
print("Code : " + results[0])
img.save(imei + ".png")

View file

@ -8,6 +8,7 @@
import binascii
import io
import os.path
import platform
import time
import json
@ -15,6 +16,8 @@ from struct import unpack
from binascii import hexlify
from queue import Queue
from threading import Thread
from edlclient.Library.Modules.nothing import nothing
from edlclient.Library.utils import *
from edlclient.Library.gpt import gpt
from edlclient.Library.sparse import QCSparse
@ -1031,6 +1034,15 @@ class firehose(metaclass=LogBase):
self.cfg.SECTOR_SIZE_IN_BYTES = 4096
return self.configure(0)
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)
return True
@ -1127,6 +1139,8 @@ class firehose(metaclass=LogBase):
if "chip serial num" in line.lower():
try:
serial = line.split("0x")[1][:-1]
if ")" in serial:
serial=serial[:serial.rfind(")")]
self.serial = int(serial, 16)
except Exception as err: # pylint: disable=broad-except
self.debug(str(err))
@ -1150,7 +1164,8 @@ class firehose(metaclass=LogBase):
try:
if os.path.exists(self.cfg.programmer):
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:
self.supported_functions.append(cmd.decode('utf-8'))
state = {
@ -1158,7 +1173,19 @@ class firehose(metaclass=LogBase):
"programmer": self.cfg.programmer,
"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:
pass

View file

@ -390,7 +390,7 @@ class gpt(metaclass=LogBase):
if pa.type == "EFI_UNUSED":
continue
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
def print(self):

View file

@ -98,11 +98,11 @@ class sahara(metaclass=LogBase):
self.error(str(e))
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
length = 0x30
version = SAHARA_VERSION
responsedata = pack("<IIIIIIIIIIII", cmd, length, version, version_min, max_cmd_len, mode, 0, 0, 0, 0, 0, 0)
#version = SAHARA_VERSION
responsedata = pack("<IIIIIIIIIIII", cmd, length, version, version_min, max_cmd_len, mode, 1, 2, 3, 4, 5, 6)
try:
self.cdc.write(responsedata)
return True
@ -155,8 +155,8 @@ class sahara(metaclass=LogBase):
self.error(str(e))
return {"mode": "error"}
def enter_command_mode(self):
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_COMMAND):
def enter_command_mode(self, version=2):
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_COMMAND, version=version):
return False
res = self.get_rsp()
if "cmd" in res:
@ -179,11 +179,9 @@ class sahara(metaclass=LogBase):
def cmdexec_get_msm_hwid(self):
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')
except Exception as e: # pylint: disable=broad-except
self.debug(str(e))
return None
return None
def cmdexec_get_pkhash(self):
try:
@ -212,104 +210,111 @@ class sahara(metaclass=LogBase):
res = self.cmd_exec(exec_cmd_t.SAHARA_EXEC_CMD_READ_DEBUG_DATA)
return res
def cmd_info(self):
if self.enter_command_mode():
def cmd_info(self, version):
if self.enter_command_mode(version=version):
self.serial = self.cmdexec_get_serial_num()
self.serials = "{:08x}".format(self.serial)
self.hwid = self.cmdexec_get_msm_hwid()
self.pkhash = self.cmdexec_get_pkhash()
# if self.version>=2.4:
# self.sblversion = "{:08x}".format(self.cmdexec_get_sbl_version())
if self.hwid is not None:
self.hwidstr = "{:016x}".format(self.hwid)
self.msm_id = int(self.hwidstr[2:8], 16)
self.oem_id = int(self.hwidstr[-8:-4], 16)
self.model_id = int(self.hwidstr[-4:], 16)
self.oem_str = "{:04x}".format(self.oem_id)
self.model_id = "{:04x}".format(self.model_id)
self.msm_str = "{:08x}".format(self.msm_id)
if self.msm_id in msmids:
cpustr = f"CPU detected: \"{msmids[self.msm_id]}\"\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" +
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
f"OEM_ID:0x{self.oem_str}," +
f"MODEL_ID:0x{self.model_id})\n" +
f"PK_HASH: 0x{self.pkhash}\n" +
f"Serial: 0x{self.serials}\n" +
f"SBL Version: 0x{self.sblversion}\n")
else:
"""
self.info(f"\n------------------------\n" +
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
f"OEM_ID:0x{self.oem_str}," +
f"MODEL_ID:0x{self.model_id})\n" +
cpustr +
f"PK_HASH: 0x{self.pkhash}\n" +
f"Serial: 0x{self.serials}\n")
if self.programmer == "":
if self.hwidstr in self.loaderdb:
mt = self.loaderdb[self.hwidstr]
unfused = False
for rootcert in root_cert_hash:
if self.pkhash[0:16] in root_cert_hash[rootcert]:
unfused = True
break
if unfused:
self.info("Possibly unfused device detected, so any loader should be fine...")
if self.pkhash[0:16] in mt:
self.programmer = mt[self.pkhash[0:16]]
self.info(f"Trying loader: {self.programmer}")
if version < 3:
self.hwid = self.cmdexec_get_msm_hwid()
self.pkhash = self.cmdexec_get_pkhash()
# if self.version>=2.4:
# self.sblversion = "{:08x}".format(self.cmdexec_get_sbl_version())
if self.hwid is not None:
self.hwidstr = "{:016x}".format(self.hwid)
self.msm_id = int(self.hwidstr[2:8], 16)
self.oem_id = int(self.hwidstr[-8:-4], 16)
self.model_id = int(self.hwidstr[-4:], 16)
self.oem_str = "{:04x}".format(self.oem_id)
self.model_id = "{:04x}".format(self.model_id)
self.msm_str = "{:08x}".format(self.msm_id)
if self.msm_id in msmids:
cpustr = f"CPU detected: \"{msmids[self.msm_id]}\"\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"\nVersion {hex(version)}\n------------------------\n" +
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
f"OEM_ID:0x{self.oem_str}," +
f"MODEL_ID:0x{self.model_id})\n" +
f"PK_HASH: 0x{self.pkhash}\n" +
f"Serial: 0x{self.serials}\n" +
f"SBL Version: 0x{self.sblversion}\n")
else:
"""
self.info(f"\nVersion {hex(version)}\n------------------------\n" +
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
f"OEM_ID:0x{self.oem_str}," +
f"MODEL_ID:0x{self.model_id})\n" +
cpustr +
f"PK_HASH: 0x{self.pkhash}\n" +
f"Serial: 0x{self.serials}\n")
if self.programmer == "":
if self.hwidstr in self.loaderdb:
mt = self.loaderdb[self.hwidstr]
unfused = False
for rootcert in root_cert_hash:
if self.pkhash[0:16] in root_cert_hash[rootcert]:
unfused = True
break
if unfused:
self.info("Possibly unfused device detected, so any loader should be fine...")
if self.pkhash[0:16] in mt:
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:
for loader in mt:
self.programmer = mt[loader]
self.info(f"Possible loader available: {self.programmer}")
for loader in mt:
self.programmer = mt[loader]
for loader in self.loaderdb[self.hwidstr]:
self.programmer = self.loaderdb[self.hwidstr][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:
for loader in self.loaderdb[self.hwidstr]:
self.programmer = self.loaderdb[self.hwidstr][loader]
self.info(f"Trying loader: {self.programmer}")
break
# print("Couldn't find a loader for given hwid and pkhash :(")
# exit(0)
elif self.hwidstr is not None and self.pkhash is not None:
msmid = self.hwidstr[:8]
found = False
for hwidstr in self.loaderdb:
if msmid == hwidstr[:8]:
if self.pkhash[0:16] in self.loaderdb[hwidstr]:
self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]]
self.info(f"Found loader: {self.programmer}")
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True
# print("Couldn't find a loader for given hwid and pkhash :(")
# exit(0)
elif self.hwidstr is not None and self.pkhash is not None:
msmid = self.hwidstr[:8]
found = False
for hwidstr in self.loaderdb:
if msmid == hwidstr[:8]:
if self.pkhash[0:16] in self.loaderdb[hwidstr]:
self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]]
self.info(f"Found loader: {self.programmer}")
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True
else:
if self.pkhash[0:16] in self.loaderdb[hwidstr]:
self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]]
self.info(f"Found possible loader: {self.programmer}")
found = True
if found:
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True
else:
if self.pkhash[0:16] in self.loaderdb[hwidstr]:
self.programmer = self.loaderdb[hwidstr][self.pkhash[0:16]]
self.info(f"Found possible loader: {self.programmer}")
found = True
if found:
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True
self.error(
f"Couldn't find a loader for given hwid and pkhash ({self.hwidstr}_{self.pkhash[0:16]}" +
"_[FHPRG/ENPRG].bin) :(")
return False
else:
self.error(
f"Couldn't find a loader for given hwid and pkhash ({self.hwidstr}_{self.pkhash[0:16]}" +
"_[FHPRG/ENPRG].bin) :(")
self.error(f"Couldn't find a suitable loader :(")
return False
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
else:
self.error(f"Couldn't find a suitable loader :(")
return False
self.cmd_modeswitch(sahara_mode_t.SAHARA_MODE_COMMAND)
return True
return False
def streaminginfo(self):
@ -432,8 +437,8 @@ class sahara(metaclass=LogBase):
self.cmd_reset()
return True
def debug_mode(self, dump_partitions=None):
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_MEMORY_DEBUG):
def debug_mode(self, dump_partitions=None, version=2):
if not self.cmd_hello(sahara_mode_t.SAHARA_MODE_MEMORY_DEBUG, version=version):
return False
if os.path.exists("memory"):
rmrf("memory")
@ -501,7 +506,7 @@ class sahara(metaclass=LogBase):
return False
return False
def upload_loader(self):
def upload_loader(self, version):
if self.programmer == "":
return ""
try:
@ -512,7 +517,7 @@ class sahara(metaclass=LogBase):
self.error(str(e))
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 ""
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
rootsignature3offset = casignature2offset + len2
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:
return None
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"]
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()
return sign_info
def init_loader_db():
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:
file_name = os.path.join(dirpath, filename)
found = False
@ -315,6 +373,7 @@ def main(argv):
print("%s has no signature." % filename)
copyfile(filename,
os.path.join(outputdir, "Unknown", filename[filename.rfind("/") + 1:].lower()))
elfpos += 0x30
continue
if version < 6: # MSM,MDM
signatureoffset = memsection.file_start_addr + 0x28 + code_size + signature_size

View file

@ -4,7 +4,7 @@ import os
setup(
name='edlclient',
version='3.60',
version='3.62',
packages=find_packages(),
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'],