diff --git a/mtkclient/Library/Filesystem/bin/winfsp-x64.dll b/mtkclient/Library/Filesystem/bin/winfsp-x64.dll new file mode 100644 index 0000000..34cc377 Binary files /dev/null and b/mtkclient/Library/Filesystem/bin/winfsp-x64.dll differ diff --git a/mtkclient/Library/Filesystem/bin/winfsp-x86.dll b/mtkclient/Library/Filesystem/bin/winfsp-x86.dll new file mode 100644 index 0000000..0dacb65 Binary files /dev/null and b/mtkclient/Library/Filesystem/bin/winfsp-x86.dll differ diff --git a/mtkclient/Library/Filesystem/mtkdafs.py b/mtkclient/Library/Filesystem/mtkdafs.py index 5307021..40a38be 100644 --- a/mtkclient/Library/Filesystem/mtkdafs.py +++ b/mtkclient/Library/Filesystem/mtkdafs.py @@ -1,38 +1,34 @@ -from fuse import FuseOSError, Operations, LoggingMixIn -from pathlib import Path -import logging -import os -from stat import S_IFDIR, S_IFLNK, S_IFREG -from time import time -import mmap -import errno +from stat import S_IFDIR, S_IFREG from tempfile import NamedTemporaryFile +from time import time +import sys +import os +if not os.environ.get('FUSE_LIBRARY_PATH') and os.name == 'nt': + os.environ.setdefault('FUSE_LIBRARY_PATH', os.path.join(os.path.dirname(__file__), r"bin\winfsp-%s.dll" % ("x64" if sys.maxsize > 0xffffffff else "x86"))) +from fuse import Operations, LoggingMixIn + class MtkDaFS(LoggingMixIn, Operations): def __init__(self, da_handler, rw=False): self.da_handler = da_handler self.rw = rw - self.files = {} - - self.files['/'] = dict( + self.files = {'/': dict( st_mode=(S_IFDIR | 0o555), st_ctime=time(), st_mtime=time(), st_atime=time(), - st_nlink=2) - self.files['/emmc_user.bin'] = dict( + st_nlink=2), '/emmc_user.bin': dict( st_mode=(S_IFREG | 0o777) if self.rw else (S_IFREG | 0o555), st_ctime=time(), st_mtime=time(), st_atime=time(), st_nlink=2, - st_size = self.da_handler.mtk.daloader.daconfig.flashsize) - self.files['/partitions'] = dict( + st_size=self.da_handler.mtk.daloader.daconfig.flashsize), '/partitions': dict( st_mode=(S_IFDIR | 0o555), st_ctime=time(), st_mtime=time(), st_atime=time(), - st_nlink=2) + st_nlink=2)} for part in self.da_handler.mtk.daloader.get_partition_data(): self.files[f'/partitions/{part.name}'] = dict( @@ -41,35 +37,36 @@ class MtkDaFS(LoggingMixIn, Operations): st_mtime=time(), st_atime=time(), st_nlink=2, - st_size = part.sectors*self.da_handler.mtk.daloader.daconfig.pagesize, - offset=part.sector*self.da_handler.mtk.daloader.daconfig.pagesize) + st_size=part.sectors * self.da_handler.mtk.daloader.daconfig.pagesize, + offset=part.sector * self.da_handler.mtk.daloader.daconfig.pagesize) def readdir(self, path, fh): - return ['.', '..'] + [ x.removeprefix(path).removeprefix('/') for x in self.files if x.startswith(path) and x != path] + return ['.', '..'] + [x.removeprefix(path).removeprefix('/') for x in self.files if + x.startswith(path) and x != path] def read(self, path, size, offset, fh): - if size+offset > self.files[path]['st_size']: + if size + offset > self.files[path]['st_size']: return b'' file_offset = 0 if 'offset' in self.files[path]: file_offset = self.files[path]['offset'] - data = self.da_handler.da_ro(start=file_offset+offset, length=size, filename='', parttype=None) + data = self.da_handler.da_ro(start=file_offset + offset, length=size, filename='', parttype=None) return bytes(data) def write(self, path, data, offset, fh): if not self.rw: return 0 - - if offset+len(data) > self.files[path]['st_size']: + + if offset + len(data) > self.files[path]['st_size']: return b'' - + file_offset = 0 if 'offset' in self.files[path]: file_offset = self.files[path]['offset'] - + with NamedTemporaryFile('rb+', buffering=0) as f_write: f_write.write(data) - self.da_handler.da_wo(start=file_offset+offset, length=len(data), filename=f_write.name, parttype=None) + self.da_handler.da_wo(start=file_offset + offset, length=len(data), filename=f_write.name, parttype=None) return len(data) def getattr(self, path, fh=None): diff --git a/stage2 b/stage2 index 57c9c1a..c911653 100755 --- a/stage2 +++ b/stage2 @@ -17,6 +17,7 @@ from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto from mtkclient.config.mtk_config import Mtk_Config from mtkclient.config.usb_ids import default_ids + class Stage2(metaclass=LogBase): def __init__(self, args, loglevel=logging.INFO): self.__logger = self.__logger @@ -40,8 +41,8 @@ class Stage2(metaclass=LogBase): self.__logger.setLevel(logging.INFO) self.cdc = usb_class(portconfig=default_ids, loglevel=loglevel, devclass=10) - self.usbread=self.cdc.usbread - self.usbwrite=self.cdc.usbwrite + self.usbread = self.cdc.usbread + self.usbwrite = self.cdc.usbwrite def preinit(self): try: @@ -160,7 +161,7 @@ class Stage2(metaclass=LogBase): self.usbwrite(pack(">I", sectors)) if display: - pg.show_progress(prefix="Progress:",pos=0,total=sectors) + pg.show_progress(prefix="Progress:", pos=0, total=sectors) for sector in range(sectors): tmp = self.usbread(0x200) @@ -183,7 +184,7 @@ class Stage2(metaclass=LogBase): else: return buffer[start % 0x200:(start % 0x200) + length] - def userdata(self, start=0, length=32*0x200, filename="data.bin"): + def userdata(self, start=0, length=32 * 0x200, filename="data.bin"): sectors = 0 if length != 0: sectors = (length // 0x200) + (1 if length % 0x200 else 0) @@ -191,7 +192,6 @@ class Stage2(metaclass=LogBase): if self.cdc.connected: self.readflash(type=0, start=start, length=length, display=True, filename=filename) - def preloader(self, start, length, filename): sectors = 0 if start != 0: @@ -318,8 +318,8 @@ class Stage2(metaclass=LogBase): start = 0 else: start = (start // 0x100) - if start>0xFFFF: - start=0xFFFF + if start > 0xFFFF: + start = 0xFFFF if length == 0: sectors = 16 * 1024 * 1024 // 0x100 else: @@ -339,8 +339,8 @@ class Stage2(metaclass=LogBase): bytestoread = sectors * 0x100 count = sectors pg = progress(pagesize=0x200) - if sectors>0xFFFF: - count=0xFFFF + if sectors > 0xFFFF: + count = 0xFFFF with open(filename, "wb") as wf: self.usbwrite(pack(">I", 0xf00dd00d)) self.usbwrite(pack(">I", 0x2000)) @@ -353,28 +353,28 @@ class Stage2(metaclass=LogBase): if len(tmp) != 0x100: self.error("Error on getting data") return - pg.show_progress(prefix="Progress:",pos=sector,total=sectors) + pg.show_progress(prefix="Progress:", pos=sector, total=sectors) bytesread += 0x100 size = min(bytestoread, len(tmp)) wf.write(tmp[:size]) bytestoread -= size - while bytestoread>0: + while bytestoread > 0: self.usbwrite(pack(">I", 0xf00dd00d)) self.usbwrite(pack(">I", 0x2000)) - self.usbwrite(pack(">H", sector+1)) + self.usbwrite(pack(">H", sector + 1)) self.usbwrite(pack(">H", 1)) tmp = self.usbread(0x100) size = min(bytestoread, len(tmp)) wf.write(tmp[:size]) bytestoread -= size pg.show_progress(prefix="Progress:", pos=sector, total=sectors) - sector+=1 + sector += 1 pg.show_progress(prefix="Progress:", pos=sectors, total=sectors) print("Done") def keys(self, data=b"", otp=None, mode="dxcc"): # self.hwcrypto.disable_range_blacklist("cqdma",self.cmd_C8) - keyinfo="" + keyinfo = "" retval = {} meid = self.config.get_meid() socid = self.config.get_socid() @@ -401,31 +401,32 @@ class Stage2(metaclass=LogBase): retval["socid"] = hexlify(socid).decode('utf-8') except Exception as err: pass - if self.setup.dxcc_base is not None and mode not in ["sej_aes_decrypt","sej_aes_encrypt","sej_sst_decrypt","sej_sst_encrypt","dxcc_sha256"]: - rpmbkey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="rpmb") + if self.setup.dxcc_base is not None and mode not in ["sej_aes_decrypt", "sej_aes_encrypt", "sej_sst_decrypt", + "sej_sst_encrypt", "dxcc_sha256"]: + rpmbkey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="rpmb") rpmb2key = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="rpmb2") - fdekey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="fde") - ikey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="itrustee") - platkey, provkey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="prov") - keyinfo+="\nKeys :\n-----------------------------------------\n" - keyinfo+="RPMB: " + hexlify(rpmbkey).decode('utf-8')+"\n" - keyinfo+="RPMB2: " + hexlify(rpmb2key).decode('utf-8') + "\n" - keyinfo+="FDE : " + hexlify(fdekey).decode('utf-8')+"\n" - keyinfo+="iTrustee: " + hexlify(ikey).decode('utf-8')+"\n" - keyinfo+="Platform: " + hexlify(platkey).decode('utf-8')+"\n" - keyinfo+="Provisioning: " + hexlify(provkey).decode('utf-8')+"\n" - keyinfo+="\n" + fdekey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="fde") + ikey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="itrustee") + platkey, provkey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="prov") + keyinfo += "\nKeys :\n-----------------------------------------\n" + keyinfo += "RPMB: " + hexlify(rpmbkey).decode('utf-8') + "\n" + keyinfo += "RPMB2: " + hexlify(rpmb2key).decode('utf-8') + "\n" + keyinfo += "FDE : " + hexlify(fdekey).decode('utf-8') + "\n" + keyinfo += "iTrustee: " + hexlify(ikey).decode('utf-8') + "\n" + keyinfo += "Platform: " + hexlify(platkey).decode('utf-8') + "\n" + keyinfo += "Provisioning: " + hexlify(provkey).decode('utf-8') + "\n" + keyinfo += "\n" if rpmbkey is not None: self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) - self.config.hwparam.writesetting("rpmbkey",hexlify(rpmbkey).decode('utf-8')) + self.config.hwparam.writesetting("rpmbkey", hexlify(rpmbkey).decode('utf-8')) retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8') if rpmb2key is not None: self.info("RPMB2 : " + hexlify(rpmb2key).decode('utf-8')) - self.config.hwparam.writesetting("rpmb2key",hexlify(rpmb2key).decode('utf-8')) + self.config.hwparam.writesetting("rpmb2key", hexlify(rpmb2key).decode('utf-8')) retval["rpmb2key"] = hexlify(rpmb2key).decode('utf-8') if fdekey is not None: self.info("FDE : " + hexlify(fdekey).decode('utf-8')) - self.config.hwparam.writesetting("fdekey",hexlify(fdekey).decode('utf-8')) + self.config.hwparam.writesetting("fdekey", hexlify(fdekey).decode('utf-8')) retval["fdekey"] = hexlify(fdekey).decode('utf-8') if ikey is not None: self.info("iTrustee : " + hexlify(ikey).decode('utf-8')) @@ -437,8 +438,9 @@ class Stage2(metaclass=LogBase): self.config.hwparam.writesetting("provkey", hexlify(provkey).decode('utf-8')) retval["provkey"] = hexlify(provkey).decode('utf-8') return retval, keyinfo - elif self.setup.sej_base is not None and mode not in ["sej_aes_decrypt","sej_aes_encrypt","sej_sst_decrypt","sej_sst_encrypt","dxcc_sha256"]: - retval={} + elif self.setup.sej_base is not None and mode not in ["sej_aes_decrypt", "sej_aes_encrypt", "sej_sst_decrypt", + "sej_sst_encrypt", "dxcc_sha256"]: + retval = {} rpmbkey = self.hwcrypto.aes_hwcrypt(mode="rpmb", data=meid, otp=otp, btype="sej") if rpmbkey: self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) @@ -456,30 +458,30 @@ class Stage2(metaclass=LogBase): self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8')) retval["mtee3"] = hexlify(mtee3).decode('utf-8') - keyinfo+="\nKeys :\n-----------------------------------------\n" - keyinfo+="RPMB: " + hexlify(rpmbkey).decode('utf-8') - keyinfo+="\n" + keyinfo += "\nKeys :\n-----------------------------------------\n" + keyinfo += "RPMB: " + hexlify(rpmbkey).decode('utf-8') + keyinfo += "\n" keyinfo += "MTEE: " + hexlify(mtee).decode('utf-8') keyinfo += "\n" retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8') return retval, keyinfo if mode == "sej_aes_decrypt": dec_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=False, otp=otp) - keyinfo+="\n" - keyinfo+="Data: " + hexlify(dec_data).decode('utf-8') - keyinfo+="\n" + keyinfo += "\n" + keyinfo += "Data: " + hexlify(dec_data).decode('utf-8') + keyinfo += "\n" return dec_data, keyinfo elif mode == "sej_aes_encrypt": enc_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=True, otp=otp) - keyinfo+="\n" - keyinfo+="Data: " + hexlify(enc_data).decode('utf-8') - keyinfo+="\n" + keyinfo += "\n" + keyinfo += "Data: " + hexlify(enc_data).decode('utf-8') + keyinfo += "\n" return enc_data, keyinfo elif mode == "sej_sst_decrypt": dec_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=False, otp=otp) - keyinfo+="\n" - keyinfo+="Data: " + hexlify(dec_data).decode('utf-8') - keyinfo+="\n" + keyinfo += "\n" + keyinfo += "Data: " + hexlify(dec_data).decode('utf-8') + keyinfo += "\n" return dec_data, keyinfo elif mode == "sej_sst_encrypt": enc_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=True, otp=otp) @@ -489,9 +491,9 @@ class Stage2(metaclass=LogBase): return enc_data, keyinfo elif mode == "dxcc_sha256": sha256val = self.hwcrypto.aes_hwcrypt(mode="sha256", data=data, btype="dxcc") - keyinfo+="\n" - keyinfo+="SHA256: " + hexlify(sha256val).decode('utf-8') - keyinfo+="\n" + keyinfo += "\n" + keyinfo += "SHA256: " + hexlify(sha256val).decode('utf-8') + keyinfo += "\n" return sha256val, keyinfo return None, "" @@ -501,7 +503,6 @@ class Stage2(metaclass=LogBase): self.usbwrite(pack(">I", 0x3000)) - def getint(valuestr): if valuestr == '': return None @@ -544,71 +545,72 @@ def showcommands(): def main(): parser = argparse.ArgumentParser(description=info) - subparsers = parser.add_subparsers(dest="cmd", help='Valid commands are: rpmb, preloader, data, boot2, memread, memwrite, keys') + subparsers = parser.add_subparsers(dest="cmd", + help='Valid commands are: rpmb, preloader, data, boot2, memread, memwrite, keys') parser_rpmb = subparsers.add_parser("rpmb", help="Dump the rpmb") parser_rpmb.add_argument('--start', dest='start', type=str, - help='Start offset to dump') + help='Start offset to dump') parser_rpmb.add_argument('--length', dest='length', type=str, - help='Max length to dump') + help='Max length to dump') parser_rpmb.add_argument('--reverse', dest='reverse', action="store_true", - help='Reverse byte order (example: rpmb command)') + help='Reverse byte order (example: rpmb command)') parser_rpmb.add_argument('--filename', dest='filename', type=str, - help='Read from / save to filename') + help='Read from / save to filename') parser_preloader = subparsers.add_parser("preloader", help="Dump the preloader") parser_preloader.add_argument('--start', dest='start', type=str, - help='Start offset to dump') + help='Start offset to dump') parser_preloader.add_argument('--length', dest='length', type=str, - help='Max length to dump') + help='Max length to dump') parser_preloader.add_argument('--filename', dest='filename', type=str, - help='Read from / save to filename') + help='Read from / save to filename') parser_data = subparsers.add_parser("data", help="Read the mmc") parser_data.add_argument('--start', dest='start', type=str, - help='Start offset to dump') + help='Start offset to dump') parser_data.add_argument('--length', dest='length', type=str, - help='Max length to dump') + help='Max length to dump') parser_data.add_argument('--filename', dest='filename', type=str, - help='Read from / save to filename') + help='Read from / save to filename') parser_boot2 = subparsers.add_parser("boot2", help="Dump boot2") parser_boot2.add_argument('--start', dest='start', type=str, - help='Start offset to dump') + help='Start offset to dump') parser_boot2.add_argument('--length', dest='length', type=str, - help='Max length to dump') + help='Max length to dump') parser_boot2.add_argument('--filename', dest='filename', type=str, - help='Read from / save to filename') + help='Read from / save to filename') parser_memread = subparsers.add_parser("memread", help="Read memory") parser_memread.add_argument(dest='start', type=str, - help='Start offset to dump') + help='Start offset to dump') parser_memread.add_argument(dest='length', type=str, - help='Max length to dump') + help='Max length to dump') parser_memread.add_argument('--filename', dest='filename', type=str, - help='Save to filename') + help='Save to filename') parser_memwrite = subparsers.add_parser("memwrite", help="Write memory") parser_memwrite.add_argument(dest='start', type=str, - help='Start offset to dump') + help='Start offset to dump') parser_memwrite.add_argument('data', type=str, - help='Data to write [hexstring, dword or filename]') + help='Data to write [hexstring, dword or filename]') parser_reboot = subparsers.add_parser("reboot", help="Reboot device") parser_seccfg = subparsers.add_parser("seccfg", help="Generate seccfg") parser_seccfg.add_argument('flag', type=str, - help='Option for generating: unlock or lock') + help='Option for generating: unlock or lock') parser_seccfg.add_argument('--sw', dest='sw', action="store_true", - help='Option for generating: sw or hw') + help='Option for generating: sw or hw') parser_keys = subparsers.add_parser("keys", help="Write memory") parser_keys.add_argument('--otp', dest='otp', type=str, - help='OTP for keys (dxcc,sej,gcpu)') + help='OTP for keys (dxcc,sej,gcpu)') parser_keys.add_argument('--mode', dest='mode', default=None, type=str, - help='keymode (dxcc,sej,gcpu,sej_aes_decrypt,sej_aes_decrypt,sej_sst_decrypt,sej_sst_encrypt') + help='keymode (dxcc,sej,gcpu,sej_aes_decrypt,sej_aes_decrypt,sej_sst_decrypt,sej_sst_encrypt') parser_keys.add_argument('--data', dest='data', default=None, type=str, - help='data') + help='data') args = parser.parse_args() cmd = args.cmd if cmd not in cmds: @@ -673,35 +675,35 @@ def main(): exit(0) start = getint(args.start) if os.path.exists(args.data): - filename=args.data - data=None + filename = args.data + data = None else: if "0x" in args.data: - data=getint(args.data) + data = getint(args.data) else: - data=args.data - filename=None + data = args.data + filename = None if st2.memwrite(start, data, filename): print(f"Successfully wrote data to {hex(start)}.") else: print(f"Failed to write data to {hex(start)}.") elif cmd == "keys": - keyinfo="" - data=b"" - if args.mode in ["sej_aes_decrypt","sej_aes_encrypt","sej_sst_decrypt","sej_sst_encrypt"]: + keyinfo = "" + data = b"" + if args.mode in ["sej_aes_decrypt", "sej_aes_encrypt", "sej_sst_decrypt", "sej_sst_encrypt"]: if not args.data: print("Option --data is needed") exit(0) data = bytes.fromhex(args.data) # otp_hisense=bytes.fromhex("486973656E736500000000000000000000000000000000000000000000000000") # st2.jump(0x223449) - keys, keyinfo=st2.keys(data=data, mode=args.mode, otp=args.otp) + keys, keyinfo = st2.keys(data=data, mode=args.mode, otp=args.otp) print(keyinfo) print("Wrote keys to logs/hwparam.json") elif cmd == "reboot": st2.reboot() elif cmd == "seccfg": - if args.flag not in ["unlock","lock"]: + if args.flag not in ["unlock", "lock"]: print("Valid flags are: unlock, lock") sys.exit(1) """ @@ -720,15 +722,15 @@ def main(): SBOOT_RUNTIME_OFF = 0 SBOOT_RUNTIME_ON = 1 """ - if args.flag=="unlock": + if args.flag == "unlock": lock_state = 3 critical_lock_state = 1 - elif args.flag=="lock": + elif args.flag == "lock": lock_state = 1 critical_lock_state = 0 with open("seccfg.bin", "wb") as wf: seccfg_ver = 4 - seccfg_size = 0x3C + seccfg_size = 0x3C sboot_runtime = 0 seccfg_data = pack("