Merge pull request #993 from ColdWindScholar/main

Fix "OSError: Unable to find libfuse" on Windows and Optimized the code and fixed other bugs
This commit is contained in:
Bjoern Kerler 2024-05-12 11:26:46 +02:00 committed by GitHub
commit 491f930424
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
46 changed files with 582 additions and 687 deletions

18
mtk
View file

@ -40,16 +40,6 @@ cmds = {
"script": "Run multiple commands using text script" "script": "Run multiple commands using text script"
} }
def showcommands():
print(info)
print("-----------------------------------\n")
print("Available commands are:\n")
for cmd in cmds:
print("%20s" % (cmd) + ":\t" + cmds[cmd])
print()
if __name__ == '__main__': if __name__ == '__main__':
print(info) print(info)
print("") print("")
@ -620,12 +610,12 @@ if __name__ == '__main__':
parser_ess.add_argument('--da_addr', help='Set a specific da payload addr') parser_ess.add_argument('--da_addr', help='Set a specific da payload addr')
parser_ess.add_argument('--brom_addr', help='Set a specific brom payload addr') parser_ess.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_ess.add_argument('--ptype', parser_ess.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)') help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
parser_ess.add_argument('--preloader', help='Set the preloader filename for dram config') parser_ess.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_ess.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly') parser_ess.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_ess.add_argument('--parttype', help='Partition type\n' + parser_ess.add_argument('--parttype', help='Partition type\n' +
'\t\tEMMC: [user, boot1, boot2, gp1, gp2, gp3, gp4, rpmb]' + '\t\tEMMC: [user, boot1, boot2, gp1, gp2, gp3, gp4, rpmb]' +
'\t\tUFS: [lu0, lu1, lu2, lu0_lu1]') '\t\tUFS: [lu0, lu1, lu2, lu0_lu1]')
parser_ess.add_argument('--filename', help='Optional filename') parser_ess.add_argument('--filename', help='Optional filename')
parser_ess.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode') parser_ess.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
parser_ess.add_argument('--socid', help='Read Soc ID') parser_ess.add_argument('--socid', help='Read Soc ID')
@ -947,7 +937,7 @@ if __name__ == '__main__':
args = parser.parse_args() args = parser.parse_args()
cmd = args.cmd cmd = args.cmd
if cmd not in cmds: if cmd not in cmds:
showcommands() parser.print_help()
exit(0) exit(0)
mtk = Main(args).run(parser) mtk = Main(args).run(parser)

View file

@ -8,7 +8,7 @@ block_cipher = None
a = Analysis(['mtk'], a = Analysis(['mtk'],
pathex=[], pathex=[],
binaries=[], binaries=[],
datas=[('mtkclient/Windows/*', '.'), ('mtkclient/payloads', 'mtkclient/payloads'), ('mtkclient/Loader', 'mtkclient/Loader')], datas=[('mtkclient/Windows/*', '.'), ('mtkclient/payloads', 'mtkclient/payloads'), ('mtkclient/Loader', 'mtkclient/Loader'), ('mtkclient/Library/Filesystem/bin', 'mtkclient/Library/Filesystem/bin')],
hiddenimports=[], hiddenimports=[],
hookspath=[], hookspath=[],
hooksconfig={}, hooksconfig={},

111
mtk_gui
View file

@ -105,7 +105,7 @@ def load_translations(application):
locale = QLocale.system() locale = QLocale.system()
translator = QTranslator(application) translator = QTranslator(application)
directory = os.path.dirname(__file__) directory = os.path.dirname(__file__)
lang = 'mtkclient/gui/i18n/' + locale.name() lang = f'mtkclient/gui/i18n/{locale.name()}'
if locale.name() == "en_NL": if locale.name() == "en_NL":
lang = lang.replace("en_NL", "nl_NL") lang = lang.replace("en_NL", "nl_NL")
# lang = 'mtkclient/gui/i18n/fr_FR' # lang = 'mtkclient/gui/i18n/fr_FR'
@ -154,10 +154,7 @@ class MainWindow(QMainWindow):
global lock global lock
lock.acquire() lock.acquire()
doneBytes = 0 doneBytes = 0
if "currentPartitionSizeDone" in self.Status: curpartBytes = self.Status[f"currentPartitionSize{'Done' if 'currentPartitionSizeDone' in self.Status else ''}"]
curpartBytes = self.Status["currentPartitionSizeDone"]
else:
curpartBytes = self.Status["currentPartitionSize"]
if "allPartitions" in self.Status: if "allPartitions" in self.Status:
for partition in self.Status["allPartitions"]: for partition in self.Status["allPartitions"]:
@ -168,11 +165,7 @@ class MainWindow(QMainWindow):
fullPercentageDone = int((doneBytes / totalBytes) * 100) fullPercentageDone = int((doneBytes / totalBytes) * 100)
self.ui.fullProgress.setValue(fullPercentageDone) self.ui.fullProgress.setValue(fullPercentageDone)
timeinfototal = self.timeEstTotal.update(fullPercentageDone, 100) timeinfototal = self.timeEstTotal.update(fullPercentageDone, 100)
self.ui.fullProgressText.setText("<table width='100%'><tr><td><b>Total:</b> " + self.ui.fullProgressText.setText(f"<table width='100%'><tr><td><b>Total:</b> {convert_size(doneBytes)} / {convert_size(totalBytes)}</td><td align='right'>{timeinfototal}{QCoreApplication.translate('main', ' left')}</td></tr></table>")
convert_size(doneBytes) + " / " + convert_size(totalBytes) +
"</td><td align='right'>" + timeinfototal +
QCoreApplication.translate("main", " left") +
"</td></tr></table>")
else: else:
partBytes = self.Status["currentPartitionSize"] partBytes = self.Status["currentPartitionSize"]
doneBytes = self.Status["currentPartitionSizeDone"] doneBytes = self.Status["currentPartitionSizeDone"]
@ -244,21 +237,21 @@ class MainWindow(QMainWindow):
self.readflash.disableButtonsSignal.connect(self.disablebuttons) self.readflash.disableButtonsSignal.connect(self.disablebuttons)
self.ui.readpartitionsbtn.clicked.connect(self.readflash.dumpPartition) self.ui.readpartitionsbtn.clicked.connect(self.readflash.dumpPartition)
self.ui.readselectallcheckbox.clicked.connect(self.readflash.selectAll) self.ui.readselectallcheckbox.clicked.connect(self.readflash.selectAll)
self.ui.readpreloaderbtn.clicked.connect(self.on_readpreloader) self.ui.readpreloaderbtn.clicked.connect(lambda: self.readflash.dumpFlash("boot1"))
self.ui.readflashbtn.clicked.connect(self.on_readfullflash) self.ui.readflashbtn.clicked.connect(lambda: self.readflash.dumpFlash("user"))
self.ui.readrpmbbtn.clicked.connect(self.on_readrpmb) self.ui.readrpmbbtn.clicked.connect(lambda: self.readflash.dumpFlash("rpmb"))
self.ui.readboot2btn.clicked.connect(self.on_readboot2) self.ui.readboot2btn.clicked.connect(lambda: self.readflash.dumpFlash("boot2"))
def initkeys(self): def initkeys(self):
self.genkeys = generateKeysMenu(self.ui, self, self.devhandler.da_handler, self.sendToLog) self.genkeys = generateKeysMenu(self.ui, self, self.devhandler.da_handler, self.sendToLog)
self.ui.generatekeybtn.clicked.connect(self.on_generatekeys) self.ui.generatekeybtn.clicked.connect(self.genkeys.generateKeys)
self.genkeys.enableButtonsSignal.connect(self.enablebuttons) self.genkeys.enableButtonsSignal.connect(self.enablebuttons)
self.genkeys.disableButtonsSignal.connect(self.disablebuttons) self.genkeys.disableButtonsSignal.connect(self.disablebuttons)
def initunlock(self): def initunlock(self):
self.unlock = UnlockMenu(self.ui, self, self.devhandler.da_handler, self.sendToLog) self.unlock = UnlockMenu(self.ui, self, self.devhandler.da_handler, self.sendToLog)
self.ui.unlockbutton.clicked.connect(self.on_unlock) self.ui.unlockbutton.clicked.connect(lambda: self.unlock.unlock("unlock"))
self.ui.lockbutton.clicked.connect(self.on_lock) self.ui.lockbutton.clicked.connect(lambda: self.unlock.unlock("lock"))
self.unlock.enableButtonsSignal.connect(self.enablebuttons) self.unlock.enableButtonsSignal.connect(self.enablebuttons)
self.unlock.disableButtonsSignal.connect(self.disablebuttons) self.unlock.disableButtonsSignal.connect(self.disablebuttons)
@ -267,21 +260,21 @@ class MainWindow(QMainWindow):
self.eraseflash.enableButtonsSignal.connect(self.enablebuttons) self.eraseflash.enableButtonsSignal.connect(self.enablebuttons)
self.eraseflash.disableButtonsSignal.connect(self.disablebuttons) self.eraseflash.disableButtonsSignal.connect(self.disablebuttons)
self.ui.eraseselectallpartitionscheckbox.clicked.connect(self.eraseflash.selectAll) self.ui.eraseselectallpartitionscheckbox.clicked.connect(self.eraseflash.selectAll)
self.ui.erasepartitionsbtn.clicked.connect(self.on_erasepartflash) self.ui.erasepartitionsbtn.clicked.connect(self.eraseflash.erasePartition)
self.ui.eraserpmbbtn.clicked.connect(self.on_eraserpmb) self.ui.eraserpmbbtn.clicked.connect(lambda: self.eraseflash.eraseFlash("rpmb"))
self.ui.erasepreloaderbtn.clicked.connect(self.on_erasepreloader) self.ui.erasepreloaderbtn.clicked.connect(lambda: self.eraseflash.eraseFlash("boot1"))
self.ui.eraseboot2btn.clicked.connect(self.on_eraseboot2) self.ui.eraseboot2btn.clicked.connect(lambda: self.eraseflash.eraseFlash("boot2"))
def initwrite(self): def initwrite(self):
self.writeflash = WriteFlashWindow(self.ui, self, self.devhandler.da_handler, self.sendToLog) self.writeflash = WriteFlashWindow(self.ui, self, self.devhandler.da_handler, self.sendToLog)
self.writeflash.enableButtonsSignal.connect(self.enablebuttons) self.writeflash.enableButtonsSignal.connect(self.enablebuttons)
self.writeflash.disableButtonsSignal.connect(self.disablebuttons) self.writeflash.disableButtonsSignal.connect(self.disablebuttons)
self.ui.writeselectfromdir.clicked.connect(self.writeflash.selectFiles) self.ui.writeselectfromdir.clicked.connect(self.writeflash.selectFiles)
self.ui.writeflashbtn.clicked.connect(self.on_writefullflash) self.ui.writeflashbtn.clicked.connect(lambda: self.writeflash.writeFlash("user"))
self.ui.writepartbtn.clicked.connect(self.on_writepartflash) self.ui.writepartbtn.clicked.connect(self.writeflash.writePartition)
self.ui.writeboot2btn.clicked.connect(self.on_writeboot2) self.ui.writeboot2btn.clicked.connect(lambda: self.writeflash.writeFlash("boot2"))
self.ui.writepreloaderbtn.clicked.connect(self.on_writepreloader) self.ui.writepreloaderbtn.clicked.connect(lambda: self.writeflash.writeFlash("boot1"))
self.ui.writerpmbbtn.clicked.connect(self.on_writerpmb) self.ui.writerpmbbtn.clicked.connect(lambda: self.writeflash.writeFlash("rpmb"))
@Slot(str) @Slot(str)
def update_status_text(self, text): def update_status_text(self, text):
@ -338,12 +331,7 @@ class MainWindow(QMainWindow):
def getpartitions(self): def getpartitions(self):
data, guid_gpt = self.devhandler.da_handler.mtk.daloader.get_gpt() data, guid_gpt = self.devhandler.da_handler.mtk.daloader.get_gpt()
if guid_gpt is None: self.ui.readtitle.setText(QCoreApplication.translate("main", "Error reading gpt" if guid_gpt is None else "Select partitions to dump"))
print("Error reading gpt")
self.ui.readtitle.setText(QCoreApplication.translate("main", "Error reading gpt"))
else:
self.ui.readtitle.setText(QCoreApplication.translate("main", "Select partitions to dump"))
readpartitionListWidgetVBox = QVBoxLayout() readpartitionListWidgetVBox = QVBoxLayout()
readpartitionListWidget = QWidget(self) readpartitionListWidget = QWidget(self)
readpartitionListWidget.setLayout(readpartitionListWidgetVBox) readpartitionListWidget.setLayout(readpartitionListWidgetVBox)
@ -421,65 +409,8 @@ class MainWindow(QMainWindow):
lineedit.setDisabled(False) lineedit.setDisabled(False)
return fname return fname
def on_writefullflash(self):
self.writeflash.writeFlash("user")
return
def on_writepreloader(self):
self.writeflash.writeFlash("boot1")
return
def on_writeboot2(self):
self.writeflash.writeFlash("boot2")
return
def on_writerpmb(self):
self.writeflash.writeFlash("rpmb")
return
def on_writepartflash(self):
self.writeflash.writePartition()
return
def on_erasepartflash(self):
self.eraseflash.erasePartition()
return
def on_eraseboot2(self):
self.eraseflash.eraseBoot2()
def on_erasepreloader(self):
self.eraseflash.erasePreloader()
def on_eraserpmb(self):
self.eraseflash.eraseRpmb()
def on_generatekeys(self):
self.genkeys.generateKeys()
def on_unlock(self):
self.unlock.unlock("unlock")
def on_lock(self):
self.unlock.unlock("lock")
def on_readpreloader(self):
self.readflash.dumpFlash("boot1")
def on_readboot2(self):
self.readflash.dumpFlash("boot2")
return
def on_readfullflash(self):
self.readflash.dumpFlash("user")
def on_readrpmb(self):
self.readflash.dumpFlash("rpmb")
return
def sendToLog(self, info): def sendToLog(self, info):
t = time.localtime() self.ui.logBox.appendPlainText(time.strftime("[%H:%M:%S", time.localtime()) + "]: " + info)
self.ui.logBox.appendPlainText(time.strftime("[%H:%M:%S", t) + "]: " + info)
self.ui.logBox.verticalScrollBar().setValue(self.ui.logBox.verticalScrollBar().maximum()) self.ui.logBox.verticalScrollBar().setValue(self.ui.logBox.verticalScrollBar().maximum())
def sendToProgress(self, progress): def sendToProgress(self, progress):

View file

@ -8,7 +8,7 @@ block_cipher = None
a = Analysis(['mtk_gui'], a = Analysis(['mtk_gui'],
pathex=[], pathex=[],
binaries=[], binaries=[],
datas=[('mtkclient/gui/images', 'mtkclient/gui/images'), ('mtkclient/Windows/*', '.'), ('mtkclient/payloads', 'mtkclient/payloads'), ('mtkclient/Loader', 'mtkclient/Loader')], datas=[('mtkclient/gui/images', 'mtkclient/gui/images'), ('mtkclient/Windows/*', '.'), ('mtkclient/payloads', 'mtkclient/payloads'), ('mtkclient/Loader', 'mtkclient/Loader'), ('mtkclient/Library/Filesystem/bin', 'mtkclient/Library/Filesystem/bin')],
hiddenimports=[], hiddenimports=[],
hookspath=[], hookspath=[],
hooksconfig={}, hooksconfig={},

View file

@ -88,7 +88,7 @@ class serial_class(DeviceClass):
for usbid in self.portconfig: for usbid in self.portconfig:
if port.pid == usbid[1] and port.vid == usbid[0]: if port.pid == usbid[1] and port.vid == usbid[0]:
# portid = port.location[-1:] # portid = port.location[-1:]
print(f"Detected {hex(port.vid)}:{hex(port.pid)} device at: " + port.device) print(f"Detected {hex(port.vid)}:{hex(port.pid)} device at: {port.device}")
ids.append(port.device) ids.append(port.device)
return sorted(ids) return sorted(ids)

View file

@ -95,7 +95,8 @@ class CDC_CMDS:
class usb_class(DeviceClass): class usb_class(DeviceClass):
def load_windows_dll(self): @staticmethod
def load_windows_dll():
if os.name == 'nt': if os.name == 'nt':
windows_dir = None windows_dir = None
try: try:
@ -142,10 +143,7 @@ class usb_class(DeviceClass):
self.backend = None self.backend = None
def set_fast_mode(self, enabled): def set_fast_mode(self, enabled):
if enabled: self.fast = bool(enabled)
self.fast = True
else:
self.fast = False
def verify_data(self, data, pre="RX:"): def verify_data(self, data, pre="RX:"):
if self.__logger.level == logging.DEBUG: if self.__logger.level == logging.DEBUG:
@ -207,7 +205,7 @@ class usb_class(DeviceClass):
if stopbits is not None: if stopbits is not None:
if stopbits not in sbits.keys(): if stopbits not in sbits.keys():
valid = ", ".join(str(k) for k in sorted(sbits.keys())) valid = ", ".join(str(k) for k in sorted(sbits.keys()))
raise ValueError("Valid stopbits are " + valid) raise ValueError(f"Valid stopbits are {valid}")
self.stopbits = stopbits self.stopbits = stopbits
else: else:
self.stopbits = 0 self.stopbits = 0
@ -215,7 +213,7 @@ class usb_class(DeviceClass):
if databits is not None: if databits is not None:
if databits not in dbits: if databits not in dbits:
valid = ", ".join(str(d) for d in sorted(dbits)) valid = ", ".join(str(d) for d in sorted(dbits))
raise ValueError("Valid databits are " + valid) raise ValueError(f"Valid databits are {valid}")
self.databits = databits self.databits = databits
else: else:
self.databits = 0 self.databits = 0
@ -223,7 +221,7 @@ class usb_class(DeviceClass):
if parity is not None: if parity is not None:
if parity not in pmodes: if parity not in pmodes:
valid = ", ".join(str(pm) for pm in sorted(pmodes)) valid = ", ".join(str(pm) for pm in sorted(pmodes))
raise ValueError("Valid parity modes are " + valid) raise ValueError(f"Valid parity modes are {valid}")
self.parity = parity self.parity = parity
else: else:
self.parity = 0 self.parity = 0
@ -234,7 +232,7 @@ class usb_class(DeviceClass):
dif = [abs(br - baudrate) for br in brs] dif = [abs(br - baudrate) for br in brs]
best = brs[dif.index(min(dif))] best = brs[dif.index(min(dif))]
raise ValueError( raise ValueError(
"Invalid baudrates, nearest valid is {}".format(best)) f"Invalid baudrates, nearest valid is {best}")
self.baudrate = baudrate self.baudrate = baudrate
linecode = [ linecode = [
@ -254,7 +252,7 @@ class usb_class(DeviceClass):
wlen = self.device.ctrl_transfer( wlen = self.device.ctrl_transfer(
req_type, CDC_CMDS.SET_LINE_CODING, req_type, CDC_CMDS.SET_LINE_CODING,
data_or_wLength=data, wIndex=1) data_or_wLength=data, wIndex=1)
self.debug("Linecoding set, {}b sent".format(wlen)) self.debug(f"Linecoding set, {wlen}b sent")
def setbreak(self): def setbreak(self):
txdir = 0 # 0:OUT, 1:IN txdir = 0 # 0:OUT, 1:IN
@ -264,7 +262,7 @@ class usb_class(DeviceClass):
wlen = self.device.ctrl_transfer( wlen = self.device.ctrl_transfer(
bmRequestType=req_type, bRequest=CDC_CMDS.SEND_BREAK, bmRequestType=req_type, bRequest=CDC_CMDS.SEND_BREAK,
wValue=0, data_or_wLength=0, wIndex=1) wValue=0, data_or_wLength=0, wIndex=1)
self.debug("Break set, {}b sent".format(wlen)) self.debug(f"Break set, {wlen}b sent")
def setcontrollinestate(self, RTS=None, DTR=None, isFTDI=False): def setcontrollinestate(self, RTS=None, DTR=None, isFTDI=False):
cmds = CDC_CMDS() cmds = CDC_CMDS()
@ -284,7 +282,7 @@ class usb_class(DeviceClass):
wValue=ctrlstate, wValue=ctrlstate,
wIndex=1, wIndex=1,
data_or_wLength=0) data_or_wLength=0)
self.debug("Linecoding set, {}b sent".format(wlen)) self.debug(f"Linecoding set, {wlen}b sent")
def flush(self): def flush(self):
return return
@ -348,7 +346,7 @@ class usb_class(DeviceClass):
self.debug("Detaching kernel driver") self.debug("Detaching kernel driver")
self.device.detach_kernel_driver(0) self.device.detach_kernel_driver(0)
except Exception as err: except Exception as err:
self.debug("No kernel driver supported: " + str(err)) self.debug(f"No kernel driver supported: {str(err)}")
try: try:
usb.util.claim_interface(self.device, 0) usb.util.claim_interface(self.device, 0)
except Exception: except Exception:
@ -360,7 +358,7 @@ class usb_class(DeviceClass):
self.debug("Detaching kernel driver") self.debug("Detaching kernel driver")
self.device.detach_kernel_driver(self.interface) self.device.detach_kernel_driver(self.interface)
except Exception as err: except Exception as err:
self.debug("No kernel driver supported: " + str(err)) self.debug(f"No kernel driver supported: {str(err)}")
try: try:
if self.interface != 0: if self.interface != 0:
usb.util.claim_interface(self.device, self.interface) usb.util.claim_interface(self.device, self.interface)
@ -720,7 +718,7 @@ class Scsi:
ret_tag += self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, datasize) ret_tag += self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, datasize)
if datasize > 0: if datasize > 0:
data = self.usb.read(datasize, timeout) data = self.usb.read(datasize, timeout)
print("DATA: " + hexlify(data).decode('utf-8')) print(f"DATA: {hexlify(data).decode('utf-8')}")
print("Sent HTC adb enable command") print("Sent HTC adb enable command")
def send_htc_ums_adbenable(self): # HTC10 def send_htc_ums_adbenable(self): # HTC10
@ -758,7 +756,7 @@ class Scsi:
ret_tag += self.send_mass_storage_command(lun, common_cmnd2, USB_DIR_IN, datasize) ret_tag += self.send_mass_storage_command(lun, common_cmnd2, USB_DIR_IN, datasize)
if datasize > 0: if datasize > 0:
data = self.usb.read(datasize, timeout) data = self.usb.read(datasize, timeout)
print("DATA: " + hexlify(data).decode('utf-8')) print(f"DATA: {hexlify(data).decode('utf-8')}")
print("Send HTC adb enable command") print("Send HTC adb enable command")
def send_fih_adbenable(self): # motorola xt560, nokia 3.1, #f_mass_storage.c def send_fih_adbenable(self): # motorola xt560, nokia 3.1, #f_mass_storage.c
@ -780,7 +778,7 @@ class Scsi:
# ret_tag+=self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, 0x600) # ret_tag+=self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, 0x600)
if datasize > 0: if datasize > 0:
data = self.usb.read(datasize, timeout) data = self.usb.read(datasize, timeout)
print("DATA: " + hexlify(data).decode('utf-8')) print(f"DATA: {hexlify(data).decode('utf-8')}")
print("Sent FIH adb enable command") print("Sent FIH adb enable command")
self.usb.close() self.usb.close()
@ -795,7 +793,7 @@ class Scsi:
self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, 0x600) self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, 0x600)
if datasize > 0: if datasize > 0:
data = self.usb.read(datasize, timeout) data = self.usb.read(datasize, timeout)
print("DATA: " + hexlify(data).decode('utf-8')) print(f"DATA: {hexlify(data).decode('utf-8')}")
print("Sent alcatel adb enable command") print("Sent alcatel adb enable command")
self.usb.close() self.usb.close()
@ -814,7 +812,7 @@ class Scsi:
ret_tag += self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, 0x600) ret_tag += self.send_mass_storage_command(lun, common_cmnd, USB_DIR_IN, 0x600)
if datasize > 0: if datasize > 0:
data = self.usb.read(datasize, timeout) data = self.usb.read(datasize, timeout)
print("DATA: " + hexlify(data).decode('utf-8')) print(f"DATA: {hexlify(data).decode('utf-8')}")
print("Sent FIH root command") print("Sent FIH root command")
self.usb.close() self.usb.close()

View file

@ -8,7 +8,7 @@ from mtkclient.Library.Connection.usblib import Scsi
def main(): def main():
info = 'MassStorageBackdoor (c) B.Kerler 2019.' info = 'MassStorageBackdoor (c) B.Kerler 2019.'
parser = argparse.ArgumentParser(description=info) parser = argparse.ArgumentParser(description=info)
print("\n" + info + "\n\n") print(f"\n{info}\n\n")
parser.add_argument('-vid', metavar="<vid>", help='[Option] Specify vid, default=0x2e04)', default="0x2e04") parser.add_argument('-vid', metavar="<vid>", help='[Option] Specify vid, default=0x2e04)', default="0x2e04")
parser.add_argument('-pid', metavar="<pid>", help='[Option] Specify pid, default=0xc025)', default="0xc025") parser.add_argument('-pid', metavar="<pid>", help='[Option] Specify pid, default=0xc025)', default="0xc025")
parser.add_argument('-interface', metavar="<pid>", help='[Option] Specify interface number)', default="") parser.add_argument('-interface', metavar="<pid>", help='[Option] Specify interface number)', default="")

View file

@ -160,9 +160,9 @@ class DAconfig(metaclass=LogBase):
self.parse_da_loader(loader, self.dasetup) self.parse_da_loader(loader, self.dasetup)
else: else:
if not os.path.exists(loader): if not os.path.exists(loader):
self.warning("Couldn't open " + loader) self.warning(f"Couldn't open {loader}")
else: else:
self.info("Using custom loader: " + loader) self.info(f"Using custom loader: {loader}")
self.parse_da_loader(loader, self.dasetup) self.parse_da_loader(loader, self.dasetup)
def m_extract_emi(self, data): def m_extract_emi(self, data):
@ -203,7 +203,7 @@ class DAconfig(metaclass=LogBase):
with open(preloader, "rb") as rf: with open(preloader, "rb") as rf:
data = rf.read() data = rf.read()
else: else:
self.error("Preloader : " + preloader + " doesn't exist. Aborting.") self.error(f"Preloader : {preloader} doesn't exist. Aborting.")
exit(1) exit(1)
try: try:
self.emiver, self.emi = self.m_extract_emi(data) self.emiver, self.emi = self.m_extract_emi(data)
@ -211,17 +211,14 @@ class DAconfig(metaclass=LogBase):
self.emiver = 0 self.emiver = 0
self.emi = None self.emi = None
def parse_da_loader(self, loader:str, dasetup:dict): def parse_da_loader(self, loader: str, dasetup: dict):
try: try:
with open(loader, 'rb') as bootldr: with open(loader, 'rb') as bootldr:
# data = bootldr.read() # data = bootldr.read()
# self.debug(hexlify(data).decode('utf-8')) # self.debug(hexlify(data).decode('utf-8'))
hdr = bootldr.read(0x68) hdr = bootldr.read(0x68)
count_da = unpack("<I", bootldr.read(4))[0] count_da = unpack("<I", bootldr.read(4))[0]
if b"MTK_DA_v6" in hdr: v6 = b"MTK_DA_v6" in hdr
v6 = True
else:
v6 = False
for i in range(0, count_da): for i in range(0, count_da):
bootldr.seek(0x6C + (i * 0xDC)) bootldr.seek(0x6C + (i * 0xDC))
da = DA(bootldr.read(0xDC)) da = DA(bootldr.read(0xDC))
@ -245,7 +242,7 @@ class DAconfig(metaclass=LogBase):
dasetup[da.hw_code].append(da) dasetup[da.hw_code].append(da)
return True return True
except Exception as e: except Exception as e:
self.error("Couldn't open loader: " + loader + ". Reason: " + str(e)) self.error(f"Couldn't open loader: {loader}. Reason: {str(e)}")
return False return False
def setup(self): def setup(self):

View file

@ -303,7 +303,7 @@ class DALegacy(metaclass=LogBase):
pdram[0] = draminfo[:9] pdram[0] = draminfo[:9]
draminfo = draminfo[:4][::-1] + draminfo[4:8][::-1] + draminfo[8:12][::-1] + draminfo[12:16][::-1] draminfo = draminfo[:4][::-1] + draminfo[4:8][::-1] + draminfo[8:12][::-1] + draminfo[12:16][::-1]
pdram[1] = draminfo[:9] pdram[1] = draminfo[:9]
self.info("DRAM config needed for : " + hexlify(draminfo).decode('utf-8')) self.info(f"DRAM config needed for : {hexlify(draminfo).decode('utf-8')}")
if self.daconfig.emi is None: if self.daconfig.emi is None:
found = False found = False
for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_loader_path(), 'Preloader')): for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_loader_path(), 'Preloader')):
@ -312,7 +312,7 @@ class DALegacy(metaclass=LogBase):
data = rf.read() data = rf.read()
if pdram[0] in data or pdram[1] in data: if pdram[0] in data or pdram[1] in data:
preloader = os.path.join(root, file) preloader = os.path.join(root, file)
print("Detected preloader: " + preloader) print(f"Detected preloader: {preloader}")
self.daconfig.extract_emi(preloader) self.daconfig.extract_emi(preloader)
found = True found = True
break break
@ -347,25 +347,25 @@ class DALegacy(metaclass=LogBase):
dramlength = len(self.daconfig.emi) dramlength = len(self.daconfig.emi)
if self.daconfig.emiver in [0xF, 0x10, 0x11, 0x14, 0x15]: if self.daconfig.emiver in [0xF, 0x10, 0x11, 0x14, 0x15]:
dramlength = unpack(">I", self.usbread(0x4))[0] # 0x000000BC dramlength = unpack(">I", self.usbread(0x4))[0] # 0x000000BC
self.info("RAM-Length: " + hex(dramlength)) self.info(f"RAM-Length: {hex(dramlength)}")
self.usbwrite(self.Rsp.ACK) self.usbwrite(self.Rsp.ACK)
lendram = len(self.daconfig.emi) lendram = len(self.daconfig.emi)
if hwcode != 0x8127: if hwcode != 0x8127:
self.usbwrite(pack(">I", lendram)) self.usbwrite(pack(">I", lendram))
elif self.daconfig.emiver in [0x0B]: elif self.daconfig.emiver in [0x0B]:
info = self.usbread(0x10) # 0x000000BC info = self.usbread(0x10) # 0x000000BC
self.info("RAM-Info: " + hexlify(info).decode('utf-8')) self.info(f"RAM-Info: {hexlify(info).decode('utf-8')}")
dramlength = unpack(">I", self.usbread(0x4))[0] dramlength = unpack(">I", self.usbread(0x4))[0]
self.usbwrite(self.Rsp.ACK) self.usbwrite(self.Rsp.ACK)
elif self.daconfig.emiver in [0x0C, 0x0D]: elif self.daconfig.emiver in [0x0C, 0x0D]:
dramlength = unpack(">I", self.usbread(0x4))[0] dramlength = unpack(">I", self.usbread(0x4))[0]
self.info("RAM-Length: " + hex(dramlength)) self.info(f"RAM-Length: {hex(dramlength)}")
self.usbwrite(self.Rsp.ACK) self.usbwrite(self.Rsp.ACK)
self.daconfig.emi = self.daconfig.emi[:dramlength] self.daconfig.emi = self.daconfig.emi[:dramlength]
self.daconfig.emi = pack(">I", 0x100) + self.daconfig.emi[0x4:dramlength] self.daconfig.emi = pack(">I", 0x100) + self.daconfig.emi[0x4:dramlength]
elif self.daconfig.emiver in [0x00]: elif self.daconfig.emiver in [0x00]:
dramlength = unpack(">I", self.usbread(0x4))[0] # 0x000000B0 dramlength = unpack(">I", self.usbread(0x4))[0] # 0x000000B0
self.info("RAM-Length: " + hex(dramlength)) self.info(f"RAM-Length: {hex(dramlength)}")
self.usbwrite(self.Rsp.ACK) self.usbwrite(self.Rsp.ACK)
lendram = len(self.daconfig.emi) lendram = len(self.daconfig.emi)
self.daconfig.emi = self.daconfig.emi[:dramlength] self.daconfig.emi = self.daconfig.emi[:dramlength]
@ -582,7 +582,7 @@ class DALegacy(metaclass=LogBase):
self.info("Reading nand info") self.info("Reading nand info")
nandinfo = unpack(">I", self.usbread(4))[0] nandinfo = unpack(">I", self.usbread(4))[0]
self.debug("NAND_INFO: " + hex(nandinfo)) self.debug(f"NAND_INFO: {hex(nandinfo)}")
ids = unpack(">H", self.usbread(2))[0] ids = unpack(">H", self.usbread(2))[0]
nandids = [] nandids = []
for i in range(0, ids): for i in range(0, ids):
@ -590,7 +590,7 @@ class DALegacy(metaclass=LogBase):
nandids.append(tmp) nandids.append(tmp)
self.info("Reading emmc info") self.info("Reading emmc info")
emmcinfolegacy = unpack(">I", self.usbread(4))[0] emmcinfolegacy = unpack(">I", self.usbread(4))[0]
self.debug("EMMC_INFO: " + hex(emmcinfolegacy)) self.debug(f"EMMC_INFO: {hex(emmcinfolegacy)}")
emmcids = [] emmcids = []
for i in range(0, 4): for i in range(0, 4):
tmp = unpack(">I", self.usbread(4))[0] tmp = unpack(">I", self.usbread(4))[0]
@ -607,7 +607,7 @@ class DALegacy(metaclass=LogBase):
ackval = self.usbread(1) ackval = self.usbread(1)
ackval += self.usbread(1) ackval += self.usbread(1)
ackval += self.usbread(1) ackval += self.usbread(1)
self.info("ACK: " + hexlify(ackval).decode('utf-8')) self.info(f"ACK: {hexlify(ackval).decode('utf-8')}")
self.info("Setting stage 2 config ...") self.info("Setting stage 2 config ...")
if self.set_stage2_config(self.config.hwcode): if self.set_stage2_config(self.config.hwcode):
self.info("Uploading stage 2...") self.info("Uploading stage 2...")
@ -791,7 +791,7 @@ class DALegacy(metaclass=LogBase):
buffer = self.usbread(1) buffer = self.usbread(1)
if buffer != self.Rsp.ACK: if buffer != self.Rsp.ACK:
self.error( self.error(
f"Error on sending brom stage {stage} addr {hex(address+pos)}: " + hexlify(buffer).decode('utf-8')) f"Error on sending brom stage {stage} addr {hex(address+pos)}: {hexlify(buffer).decode('utf-8')}")
self.config.set_gui_status(self.config.tr("Error on sending brom stage")) self.config.set_gui_status(self.config.tr("Error on sending brom stage"))
break break
time.sleep(0.5) time.sleep(0.5)
@ -802,7 +802,7 @@ class DALegacy(metaclass=LogBase):
self.config.set_gui_status(self.config.tr(f"Successfully uploaded stage {stage}")) self.config.set_gui_status(self.config.tr(f"Successfully uploaded stage {stage}"))
return True return True
else: else:
self.error(f"Error on sending brom stage {stage} : " + hexlify(buffer).decode('utf-8')) self.error(f"Error on sending brom stage {stage} : {hexlify(buffer).decode('utf-8')}")
self.config.set_gui_status(self.config.tr("Error on sending brom stage")) self.config.set_gui_status(self.config.tr("Error on sending brom stage"))
return False return False

View file

@ -80,7 +80,8 @@ class legacyext(metaclass=LogBase):
self.warning("Legacy DA2 CMD F0 not patched.") self.warning("Legacy DA2 CMD F0 not patched.")
return da2patched return da2patched
def fix_hash(self, da1, da2, da2sig_len, hashpos, hashmode): @staticmethod
def fix_hash(da1, da2, da2sig_len, hashpos, hashmode):
da1 = bytearray(da1) da1 = bytearray(da1)
dahash = None dahash = None
if hashmode == 1: if hashmode == 1:
@ -245,26 +246,25 @@ class legacyext(metaclass=LogBase):
except Exception: except Exception:
return return
hwc = self.cryptosetup() hwc = self.cryptosetup()
retval = {} retval = {"hwcode": hex(self.config.hwcode)}
retval["hwcode"] = hex(self.config.hwcode)
meid = self.config.get_meid() meid = self.config.get_meid()
socid = self.config.get_socid() socid = self.config.get_socid()
hwcode = self.config.get_hwcode() hwcode = self.config.get_hwcode()
pubk = self.read_pubk() pubk = self.read_pubk()
if pubk is not None: if pubk is not None:
retval["pubkey"] = pubk.hex() retval["pubkey"] = pubk.hex()
self.info("PUBK : " + pubk.hex()) self.info(f"PUBK : {pubk.hex()}")
self.config.hwparam.writesetting("pubkey", pubk.hex()) self.config.hwparam.writesetting("pubkey", pubk.hex())
if meid is not None: if meid is not None:
self.info("MEID : " + hexlify(meid).decode('utf-8')) self.info(f"MEID : {hexlify(meid).decode('utf-8')}")
retval["meid"] = hexlify(meid).decode('utf-8') retval["meid"] = hexlify(meid).decode('utf-8')
self.config.hwparam.writesetting("meid", hexlify(meid).decode('utf-8')) self.config.hwparam.writesetting("meid", hexlify(meid).decode('utf-8'))
if socid is not None: if socid is not None:
self.info("SOCID : " + hexlify(socid).decode('utf-8')) self.info(f"SOCID : {hexlify(socid).decode('utf-8')}")
retval["socid"] = hexlify(socid).decode('utf-8') retval["socid"] = hexlify(socid).decode('utf-8')
self.config.hwparam.writesetting("socid", hexlify(socid).decode('utf-8')) self.config.hwparam.writesetting("socid", hexlify(socid).decode('utf-8'))
if hwcode is not None: if hwcode is not None:
self.info("HWCODE : " + hex(hwcode)) self.info(f"HWCODE : {hex(hwcode)}")
retval["hwcode"] = hex(hwcode) retval["hwcode"] = hex(hwcode)
self.config.hwparam.writesetting("hwcode", hex(hwcode)) self.config.hwparam.writesetting("hwcode", hex(hwcode))
if self.config.chipconfig.dxcc_base is not None: if self.config.chipconfig.dxcc_base is not None:
@ -281,24 +281,24 @@ class legacyext(metaclass=LogBase):
# self.info("Provkey : " + hexlify(provkey).decode('utf-8')) # self.info("Provkey : " + hexlify(provkey).decode('utf-8'))
# self.info("Platkey : " + hexlify(platkey).decode('utf-8')) # self.info("Platkey : " + hexlify(platkey).decode('utf-8'))
if rpmbkey is not None: if rpmbkey is not None:
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) self.info(f"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') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
if rpmb2key is not None: if rpmb2key is not None:
self.info("RPMB2 : " + hexlify(rpmb2key).decode('utf-8')) self.info(f"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') retval["rpmb2key"] = hexlify(rpmb2key).decode('utf-8')
if fdekey is not None: if fdekey is not None:
self.info("FDE : " + hexlify(fdekey).decode('utf-8')) self.info(f"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') retval["fdekey"] = hexlify(fdekey).decode('utf-8')
if ikey is not None: if ikey is not None:
self.info("iTrustee : " + hexlify(ikey).decode('utf-8')) self.info(f"iTrustee : {hexlify(ikey).decode('utf-8')}")
self.config.hwparam.writesetting("kmkey", hexlify(ikey).decode('utf-8')) self.config.hwparam.writesetting("kmkey", hexlify(ikey).decode('utf-8'))
retval["kmkey"] = hexlify(ikey).decode('utf-8') retval["kmkey"] = hexlify(ikey).decode('utf-8')
if self.config.chipconfig.prov_addr: if self.config.chipconfig.prov_addr:
provkey = self.custom_read(self.config.chipconfig.prov_addr, 16) provkey = self.custom_read(self.config.chipconfig.prov_addr, 16)
self.info("PROV : " + hexlify(provkey).decode('utf-8')) self.info(f"PROV : {hexlify(provkey).decode('utf-8')}")
self.config.hwparam.writesetting("provkey", hexlify(provkey).decode('utf-8')) self.config.hwparam.writesetting("provkey", hexlify(provkey).decode('utf-8'))
retval["provkey"] = hexlify(provkey).decode('utf-8') retval["provkey"] = hexlify(provkey).decode('utf-8')
""" """
@ -311,7 +311,7 @@ class legacyext(metaclass=LogBase):
otp = self.config.get_otp() otp = self.config.get_otp()
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp) mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
if mtee3: if mtee3:
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8')) self.info(f"MTEE3 : {hexlify(mtee3).decode('utf-8')}")
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8')) self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
retval["mtee3"] = hexlify(mtee3).decode('utf-8') retval["mtee3"] = hexlify(mtee3).decode('utf-8')
return retval return retval
@ -331,19 +331,19 @@ class legacyext(metaclass=LogBase):
self.setotp(hwc) self.setotp(hwc)
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp) rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
if rpmbkey: if rpmbkey:
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) self.info(f"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') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
self.info("Generating sej mtee...") self.info("Generating sej mtee...")
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp) mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp)
if mtee: if mtee:
self.info("MTEE : " + hexlify(mtee).decode('utf-8')) self.info(f"MTEE : {hexlify(mtee).decode('utf-8')}")
self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8')) self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8'))
retval["mtee"] = hexlify(mtee).decode('utf-8') retval["mtee"] = hexlify(mtee).decode('utf-8')
self.info("Generating sej mtee3...") self.info("Generating sej mtee3...")
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp) mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
if mtee3: if mtee3:
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8')) self.info(f"MTEE3 : {hexlify(mtee3).decode('utf-8')}")
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8')) self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
retval["mtee3"] = hexlify(mtee3).decode('utf-8') retval["mtee3"] = hexlify(mtee3).decode('utf-8')
else: else:
@ -353,7 +353,7 @@ class legacyext(metaclass=LogBase):
self.info("Generating gcpu mtee2 key...") self.info("Generating gcpu mtee2 key...")
mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee") mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee")
if mtee2 is not None: if mtee2 is not None:
self.info("MTEE2 : " + hexlify(mtee2).decode('utf-8')) self.info(f"MTEE2 : {hexlify(mtee2).decode('utf-8')}")
self.config.hwparam.writesetting("mtee2", hexlify(mtee2).decode('utf-8')) self.config.hwparam.writesetting("mtee2", hexlify(mtee2).decode('utf-8'))
retval["mtee2"] = hexlify(mtee2).decode('utf-8') retval["mtee2"] = hexlify(mtee2).decode('utf-8')
self.config.hwparam.writesetting("hwcode", retval["hwcode"]) self.config.hwparam.writesetting("hwcode", retval["hwcode"])

View file

@ -30,7 +30,8 @@ class DA_handler(metaclass=LogBase):
self.eh = ErrorHandler() self.eh = ErrorHandler()
self.mtk = mtk self.mtk = mtk
def close(self): @staticmethod
def close():
sys.exit(0) sys.exit(0)
def dump_preloader_ram(self): def dump_preloader_ram(self):
@ -91,7 +92,7 @@ class DA_handler(metaclass=LogBase):
if mtk.config.target_config["sbc"] and not mtk.config.is_brom and mtk.config.loader is None: if mtk.config.target_config["sbc"] and not mtk.config.is_brom and mtk.config.loader is None:
mtk = mtk.bypass_security() mtk = mtk.bypass_security()
self.mtk = mtk self.mtk = mtk
if self.mtk.daloader.patch : if self.mtk.daloader.patch:
self.info("Device was protected. Successfully bypassed security.") self.info("Device was protected. Successfully bypassed security.")
else: else:
self.info("Device is still protected, trying to boot to brom") self.info("Device is still protected, trying to boot to brom")
@ -197,7 +198,7 @@ class DA_handler(metaclass=LogBase):
rpartition = gptentry rpartition = gptentry
break break
if rpartition is not None: if rpartition is not None:
self.info(f"Dumping partition \"{rpartition.name}\"") self.info(f'Dumping partition "{rpartition.name}"')
if self.mtk.daloader.readflash(addr=rpartition.sector * self.config.pagesize, if self.mtk.daloader.readflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize, length=rpartition.sectors * self.config.pagesize,
filename=partfilename, parttype=parttype): filename=partfilename, parttype=parttype):
@ -645,7 +646,7 @@ class DA_handler(metaclass=LogBase):
elif cmd == "printgpt": elif cmd == "printgpt":
data, guid_gpt = mtk.daloader.get_gpt() data, guid_gpt = mtk.daloader.get_gpt()
if not guid_gpt: if not guid_gpt:
self.error("Error reading gpt, please read whole flash using \"mtk rf flash.bin\".") self.error('Error reading gpt, please read whole flash using "mtk rf flash.bin".')
else: else:
guid_gpt.print() guid_gpt.print()
elif cmd == "r": elif cmd == "r":
@ -685,7 +686,8 @@ class DA_handler(metaclass=LogBase):
print(f"Failed to dump offset {hex(start)} with length {hex(length)} as {filename}.") print(f"Failed to dump offset {hex(start)} with length {hex(length)} as {filename}.")
elif cmd == "fs": elif cmd == "fs":
print(f'Mounting FUSE fs at: {args.mountpoint}...') print(f'Mounting FUSE fs at: {args.mountpoint}...')
fs = FUSE(MtkDaFS(self, rw=args.rw), mountpoint=args.mountpoint, foreground=True, allow_other=True, nothreads=True) fs = FUSE(MtkDaFS(self, rw=args.rw), mountpoint=args.mountpoint, foreground=True, allow_other=True,
nothreads=True)
elif cmd == "footer": elif cmd == "footer":
filename = args.filename filename = args.filename
self.da_footer(filename=filename) self.da_footer(filename=filename)

View file

@ -89,7 +89,8 @@ class DAloader(metaclass=LogBase):
return idx, hashmode, hashlen return idx, hashmode, hashlen
return idx, hashmode, hashlen return idx, hashmode, hashlen
def find_da_hash_V6(self, da1, siglen): @staticmethod
def find_da_hash_V6(da1, siglen):
pos = len(da1) - siglen - 0x30 pos = len(da1) - siglen - 0x30
hash = da1[pos:pos + 0x30] hash = da1[pos:pos + 0x30]
if hash[-4:] == b"\x00\x00\x00\x00": if hash[-4:] == b"\x00\x00\x00\x00":
@ -110,7 +111,8 @@ class DAloader(metaclass=LogBase):
self.debug("Error: No hash found") self.debug("Error: No hash found")
return -1, -1 return -1, -1
def calc_da_hash(self, da1, da2): @staticmethod
def calc_da_hash(da1, da2):
hashdigest = hashlib.sha1(da2).digest() hashdigest = hashlib.sha1(da2).digest()
hashdigest256 = hashlib.sha256(da2).digest() hashdigest256 = hashlib.sha256(da2).digest()
idx = da1.find(hashdigest) idx = da1.find(hashdigest)
@ -120,7 +122,8 @@ class DAloader(metaclass=LogBase):
hashmode = 2 hashmode = 2
return hashmode, idx return hashmode, idx
def fix_hash(self, da1, da2, hashpos, hashmode, hashlen): @staticmethod
def fix_hash(da1, da2, hashpos, hashmode, hashlen):
da1 = bytearray(da1) da1 = bytearray(da1)
dahash = None dahash = None
if hashmode == 1: if hashmode == 1:
@ -226,7 +229,7 @@ class DAloader(metaclass=LogBase):
if self.mtk.config.chipconfig.damode == damodes.XFLASH: if self.mtk.config.chipconfig.damode == damodes.XFLASH:
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel) self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
if porttype not in ["off", "usb", "uart"]: if porttype not in ["off", "usb", "uart"]:
self.error("Only \"off\",\"usb\" or \"uart\" are allowed.") self.error('Only "off","usb" or "uart" are allowed.')
if self.da.set_meta(porttype): if self.da.set_meta(porttype):
self.info(f"Successfully set meta mode to {porttype}") self.info(f"Successfully set meta mode to {porttype}")
return True return True

View file

@ -323,7 +323,7 @@ class xflashext(metaclass=LogBase):
return False return False
data = unpack("<I", val)[0] data = unpack("<I", val)[0]
if dwords == 1: if dwords == 1:
self.debug(f"RX: {hex(addr + (pos * 4))} -> " + hex(data)) self.debug(f"RX: {hex(addr + (pos * 4))} -> {hex(data)}")
return data return data
res.append(data) res.append(data)
else: else:
@ -460,7 +460,7 @@ class xflashext(metaclass=LogBase):
self.error("Couldn't read rpmb.") self.error("Couldn't read rpmb.")
return False return False
wf.write(data) wf.write(data)
self.info("Done reading rpmb to " + filename) self.info(f"Done reading rpmb to {filename}")
return True return True
return False return False
@ -658,22 +658,22 @@ class xflashext(metaclass=LogBase):
pubk = self.read_pubk() pubk = self.read_pubk()
if pubk is not None: if pubk is not None:
retval["pubkey"] = pubk.hex() retval["pubkey"] = pubk.hex()
self.info("PUBK : " + pubk.hex()) self.info(f"PUBK : {pubk.hex()}")
self.config.hwparam.writesetting("pubkey", pubk.hex()) self.config.hwparam.writesetting("pubkey", pubk.hex())
if meid is not None: if meid is not None:
self.info("MEID : " + meid.hex()) self.info(f"MEID : {meid.hex()}")
retval["meid"] = meid.hex() retval["meid"] = meid.hex()
self.config.hwparam.writesetting("meid", meid.hex()) self.config.hwparam.writesetting("meid", meid.hex())
if socid is not None: if socid is not None:
self.info("SOCID : " + socid.hex()) self.info(f"SOCID : {socid.hex()}")
retval["socid"] = socid.hex() retval["socid"] = socid.hex()
self.config.hwparam.writesetting("socid", socid.hex()) self.config.hwparam.writesetting("socid", socid.hex())
if hwcode is not None: if hwcode is not None:
self.info("HWCODE : " + hex(hwcode)) self.info(f"HWCODE : {hex(hwcode)}")
retval["hwcode"] = hex(hwcode) retval["hwcode"] = hex(hwcode)
self.config.hwparam.writesetting("hwcode", hex(hwcode)) self.config.hwparam.writesetting("hwcode", hex(hwcode))
if cid is not None: if cid is not None:
self.info("CID : " + cid) self.info(f"CID : {cid}")
retval["cid"] = cid retval["cid"] = cid
if self.config.chipconfig.dxcc_base is not None: if self.config.chipconfig.dxcc_base is not None:
self.info("Generating dxcc rpmbkey...") self.info("Generating dxcc rpmbkey...")
@ -691,34 +691,34 @@ class xflashext(metaclass=LogBase):
# self.info("Provkey : " + provkey.hex()) # self.info("Provkey : " + provkey.hex())
# self.info("Platkey : " + platkey.hex()) # self.info("Platkey : " + platkey.hex())
if mirpmbkey is not None: if mirpmbkey is not None:
self.info("MIRPMB : " + mirpmbkey.hex()) self.info(f"MIRPMB : {mirpmbkey.hex()}")
self.config.hwparam.writesetting("mirpmbkey", mirpmbkey.hex()) self.config.hwparam.writesetting("mirpmbkey", mirpmbkey.hex())
retval["mirpmbkey"] = mirpmbkey.hex() retval["mirpmbkey"] = mirpmbkey.hex()
if rpmbkey is not None: if rpmbkey is not None:
self.info("RPMB : " + rpmbkey.hex()) self.info(f"RPMB : {rpmbkey.hex()}")
self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex()) self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex())
retval["rpmbkey"] = rpmbkey.hex() retval["rpmbkey"] = rpmbkey.hex()
if rpmb2key is not None: if rpmb2key is not None:
self.info("RPMB2 : " + rpmb2key.hex()) self.info(f"RPMB2 : {rpmb2key.hex()}")
self.config.hwparam.writesetting("rpmb2key", rpmb2key.hex()) self.config.hwparam.writesetting("rpmb2key", rpmb2key.hex())
retval["rpmb2key"] = rpmb2key.hex() retval["rpmb2key"] = rpmb2key.hex()
if fdekey is not None: if fdekey is not None:
self.info("FDE : " + fdekey.hex()) self.info(f"FDE : {fdekey.hex()}")
self.config.hwparam.writesetting("fdekey", fdekey.hex()) self.config.hwparam.writesetting("fdekey", fdekey.hex())
retval["fdekey"] = fdekey.hex() retval["fdekey"] = fdekey.hex()
if ikey is not None: if ikey is not None:
self.info("iTrustee : " + ikey.hex()) self.info(f"iTrustee : {ikey.hex()}")
self.config.hwparam.writesetting("kmkey", ikey.hex()) self.config.hwparam.writesetting("kmkey", ikey.hex())
retval["kmkey"] = ikey.hex() retval["kmkey"] = ikey.hex()
if self.config.chipconfig.prov_addr: if self.config.chipconfig.prov_addr:
provkey = self.custom_read(self.config.chipconfig.prov_addr, 16) provkey = self.custom_read(self.config.chipconfig.prov_addr, 16)
self.info("PROV : " + provkey.hex()) self.info(f"PROV : {provkey.hex()}")
self.config.hwparam.writesetting("provkey", provkey.hex()) self.config.hwparam.writesetting("provkey", provkey.hex())
retval["provkey"] = provkey.hex() retval["provkey"] = provkey.hex()
hrid = self.xflash.get_hrid() hrid = self.xflash.get_hrid()
rid = self.xflash.get_random_id() rid = self.xflash.get_random_id()
if hrid is not None: if hrid is not None:
self.info("HRID : " + hrid.hex()) self.info(f"HRID : {hrid.hex()}")
self.config.hwparam.writesetting("hrid", hrid.hex()) self.config.hwparam.writesetting("hrid", hrid.hex())
retval["hrid"] = hrid.hex() retval["hrid"] = hrid.hex()
else: else:
@ -727,19 +727,19 @@ class xflashext(metaclass=LogBase):
val += self.read_fuse(0xD) val += self.read_fuse(0xD)
val += self.read_fuse(0xE) val += self.read_fuse(0xE)
val += self.read_fuse(0xF) val += self.read_fuse(0xF)
self.info("HRID : " + val.hex()) self.info(f"HRID : {val.hex()}")
self.config.hwparam.writesetting("hrid", val.hex()) self.config.hwparam.writesetting("hrid", val.hex())
retval["hrid"] = val.hex() retval["hrid"] = val.hex()
if rid is not None: if rid is not None:
self.info("RID : " + rid.hex()) self.info(f"RID : {rid.hex()}")
self.config.hwparam.writesetting("rid", rid.hex()) self.config.hwparam.writesetting("rid", rid.hex())
retval["rid"] = rid.hex() retval["rid"] = rid.hex()
if hwcode == 0x699 and self.config.chipconfig.sej_base is not None: if hwcode == 0x699 and self.config.chipconfig.sej_base is not None:
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej") mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej")
if mtee3: if mtee3:
self.config.hwparam.writesetting("mtee3", mtee3.hex()) self.config.hwparam.writesetting("mtee3", mtee3.hex())
self.info("MTEE3 : " + mtee3.hex()) self.info(f"MTEE3 : {mtee3.hex()}")
retval["mtee3"] = mtee3.hex() retval["mtee3"] = mtee3.hex()
return retval return retval
elif self.config.chipconfig.sej_base is not None: elif self.config.chipconfig.sej_base is not None:
@ -754,19 +754,19 @@ class xflashext(metaclass=LogBase):
self.setotp(hwc) self.setotp(hwc)
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp) rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
if rpmbkey: if rpmbkey:
self.info("RPMB : " + rpmbkey.hex()) self.info(f"RPMB : {rpmbkey.hex()}")
self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex()) self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex())
retval["rpmbkey"] = rpmbkey.hex() retval["rpmbkey"] = rpmbkey.hex()
self.info("Generating sej mtee...") self.info("Generating sej mtee...")
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp) mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp)
if mtee: if mtee:
self.config.hwparam.writesetting("mtee", mtee.hex()) self.config.hwparam.writesetting("mtee", mtee.hex())
self.info("MTEE : " + mtee.hex()) self.info(f"MTEE : {mtee.hex()}")
retval["mtee"] = mtee.hex() retval["mtee"] = mtee.hex()
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp) mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
if mtee3: if mtee3:
self.config.hwparam.writesetting("mtee3", mtee3.hex()) self.config.hwparam.writesetting("mtee3", mtee3.hex())
self.info("MTEE3 : " + mtee3.hex()) self.info(f"MTEE3 : {mtee3.hex()}")
retval["mtee3"] = mtee3.hex() retval["mtee3"] = mtee3.hex()
else: else:
self.info("SEJ Mode: No meid found. Are you in brom mode ?") self.info("SEJ Mode: No meid found. Are you in brom mode ?")
@ -775,7 +775,7 @@ class xflashext(metaclass=LogBase):
self.info("Generating gcpu mtee2 key...") self.info("Generating gcpu mtee2 key...")
mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee") mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee")
if mtee2 is not None: if mtee2 is not None:
self.info("MTEE2 : " + mtee2.hex()) self.info(f"MTEE2 : {mtee2.hex()}")
self.config.hwparam.writesetting("mtee2", mtee2.hex()) self.config.hwparam.writesetting("mtee2", mtee2.hex())
retval["mtee2"] = mtee2.hex() retval["mtee2"] = mtee2.hex()
return retval return retval

View file

@ -72,7 +72,8 @@ class DAXFlash(metaclass=LogBase):
except Exception: except Exception:
self.carbonara = None self.carbonara = None
def usleep(self, usec): @staticmethod
def usleep(usec):
time.sleep(usec / 100000) time.sleep(usec / 100000)
def ack(self, rstatus=True): def ack(self, rstatus=True):
@ -108,7 +109,7 @@ class DAXFlash(metaclass=LogBase):
hdr = self.usbread(4 + 4 + 4) hdr = self.usbread(4 + 4 + 4)
magic, datatype, length = unpack("<III", hdr) magic, datatype, length = unpack("<III", hdr)
except Exception as err: except Exception as err:
self.error("xread error: " + str(err)) self.error(f"xread error: {str(err)}")
return -1 return -1
if magic != 0xFEEEEEEF: if magic != 0xFEEEEEEF:
self.error("xread error: Wrong magic") self.error("xread error: Wrong magic")
@ -353,8 +354,7 @@ class DAXFlash(metaclass=LogBase):
if self.daconfig.flashtype == "emmc": if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.rpmb_size) length = min(length, self.emmc.rpmb_size)
else: else:
self.error("Unknown parttype. Known parttypes are \"boot1\",\"boot2\",\"gp1\"," + self.error('Unknown parttype. Known parttypes are "boot1","boot2","gp1","gp2","gp3","gp4","rpmb"')
"\"gp2\",\"gp3\",\"gp4\",\"rpmb\"")
return [] return []
elif storage == DaStorage.MTK_DA_STORAGE_UFS: elif storage == DaStorage.MTK_DA_STORAGE_UFS:
if parttype is None or parttype == "lu3" or parttype == "user": # USER if parttype is None or parttype == "lu3" or parttype == "user": # USER
@ -370,7 +370,7 @@ class DAXFlash(metaclass=LogBase):
parttype = UFS_PartitionType.UFS_LU4 parttype = UFS_PartitionType.UFS_LU4
length = min(length, self.ufs.lu2_size) length = min(length, self.ufs.lu2_size)
else: else:
self.error("Unknown parttype. Known parttypes are \"lu1\",\"lu2\",\"lu3\",\"lu4\"") self.error('Unknown parttype. Known parttypes are "lu1","lu2","lu3","lu4"')
return [] return []
elif storage in [DaStorage.MTK_DA_STORAGE_NAND, DaStorage.MTK_DA_STORAGE_NAND_MLC, elif storage in [DaStorage.MTK_DA_STORAGE_NAND, DaStorage.MTK_DA_STORAGE_NAND_MLC,
DaStorage.MTK_DA_STORAGE_NAND_SLC, DaStorage.MTK_DA_STORAGE_NAND_TLC, DaStorage.MTK_DA_STORAGE_NAND_SLC, DaStorage.MTK_DA_STORAGE_NAND_TLC,
@ -1119,11 +1119,11 @@ class DAXFlash(metaclass=LogBase):
if self.daconfig.emi is None: if self.daconfig.emi is None:
emmc_info = self.get_emmc_info(False) emmc_info = self.get_emmc_info(False)
if emmc_info is not None and emmc_info.user_size != 0: if emmc_info is not None and emmc_info.user_size != 0:
self.info("DRAM config needed for : " + hexlify(emmc_info.cid[:8]).decode('utf-8')) self.info(f"DRAM config needed for : {hexlify(emmc_info.cid[:8]).decode('utf-8')}")
else: else:
ufs_info = self.get_ufs_info() ufs_info = self.get_ufs_info()
if ufs_info is not None and ufs_info.block_size != 0: if ufs_info is not None and ufs_info.block_size != 0:
self.info("DRAM config needed for : " + hexlify(ufs_info.cid).decode('utf-8')) self.info(f"DRAM config needed for : {hexlify(ufs_info.cid).decode('utf-8')}")
self.info("No preloader given. Searching for preloader") self.info("No preloader given. Searching for preloader")
found = False found = False
for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_loader_path(), 'Preloader')): for root, dirs, files in os.walk(os.path.join(self.pathconfig.get_loader_path(), 'Preloader')):
@ -1188,7 +1188,7 @@ class DAXFlash(metaclass=LogBase):
self.error("Error on booting to da (xflash)") self.error("Error on booting to da (xflash)")
return False return False
else: else:
self.error("Didn't get brom connection, got instead: " + hexlify(connagent).decode('utf-8')) self.error(f"Didn't get brom connection, got instead: {hexlify(connagent).decode('utf-8')}")
return False return False

View file

@ -377,7 +377,7 @@ class xmlflashext(metaclass=LogBase):
self.error("Couldn't read rpmb.") self.error("Couldn't read rpmb.")
return False return False
wf.write(data) wf.write(data)
self.info("Done reading rpmb to " + filename) self.info(f"Done reading rpmb to {filename}")
return True return True
return False return False
@ -686,22 +686,22 @@ class xmlflashext(metaclass=LogBase):
pubk = self.read_pubk() pubk = self.read_pubk()
if pubk is not None: if pubk is not None:
retval["pubkey"] = pubk.hex() retval["pubkey"] = pubk.hex()
self.info("PUBK : " + pubk.hex()) self.info(f"PUBK : {pubk.hex()}")
self.config.hwparam.writesetting("pubkey", pubk.hex()) self.config.hwparam.writesetting("pubkey", pubk.hex())
if meid is not None: if meid is not None:
self.info("MEID : " + meid.hex()) self.info(f"MEID : {meid.hex}")
retval["meid"] = meid.hex() retval["meid"] = meid.hex()
self.config.hwparam.writesetting("meid", meid.hex()) self.config.hwparam.writesetting("meid", meid.hex())
if socid is not None: if socid is not None:
self.info("SOCID : " + socid.hex()) self.info(f"SOCID : {socid.hex()}")
retval["socid"] = socid.hex() retval["socid"] = socid.hex()
self.config.hwparam.writesetting("socid", socid.hex()) self.config.hwparam.writesetting("socid", socid.hex())
if hwcode is not None: if hwcode is not None:
self.info("HWCODE : " + hex(hwcode)) self.info(f"HWCODE : {hex(hwcode)}")
retval["hwcode"] = hex(hwcode) retval["hwcode"] = hex(hwcode)
self.config.hwparam.writesetting("hwcode", hex(hwcode)) self.config.hwparam.writesetting("hwcode", hex(hwcode))
if cid is not None: if cid is not None:
self.info("CID : " + cid) self.info(f"CID : {cid}")
retval["cid"] = cid retval["cid"] = cid
if self.config.chipconfig.dxcc_base is not None: if self.config.chipconfig.dxcc_base is not None:
self.info("Generating dxcc rpmbkey...") self.info("Generating dxcc rpmbkey...")
@ -719,28 +719,28 @@ class xmlflashext(metaclass=LogBase):
# self.info("Provkey : " + provkey.hex()) # self.info("Provkey : " + provkey.hex())
# self.info("Platkey : " + platkey.hex()) # self.info("Platkey : " + platkey.hex())
if mirpmbkey is not None: if mirpmbkey is not None:
self.info("MIRPMB : " + mirpmbkey.hex()) self.info(f"MIRPMB : {mirpmbkey.hex()}")
self.config.hwparam.writesetting("mirpmbkey", mirpmbkey.hex()) self.config.hwparam.writesetting("mirpmbkey", mirpmbkey.hex())
retval["mirpmbkey"] = mirpmbkey.hex() retval["mirpmbkey"] = mirpmbkey.hex()
if rpmbkey is not None: if rpmbkey is not None:
self.info("RPMB : " + rpmbkey.hex()) self.info(f"RPMB : {rpmbkey.hex()}")
self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex()) self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex())
retval["rpmbkey"] = rpmbkey.hex() retval["rpmbkey"] = rpmbkey.hex()
if rpmb2key is not None: if rpmb2key is not None:
self.info("RPMB2 : " + rpmb2key.hex()) self.info(f"RPMB2 : {rpmb2key.hex()}")
self.config.hwparam.writesetting("rpmb2key", rpmb2key.hex()) self.config.hwparam.writesetting("rpmb2key", rpmb2key.hex())
retval["rpmb2key"] = rpmb2key.hex() retval["rpmb2key"] = rpmb2key.hex()
if fdekey is not None: if fdekey is not None:
self.info("FDE : " + fdekey.hex()) self.info(f"FDE : {fdekey.hex()}")
self.config.hwparam.writesetting("fdekey", fdekey.hex()) self.config.hwparam.writesetting("fdekey", fdekey.hex())
retval["fdekey"] = fdekey.hex() retval["fdekey"] = fdekey.hex()
if ikey is not None: if ikey is not None:
self.info("iTrustee : " + ikey.hex()) self.info(f"iTrustee : {ikey.hex()}")
self.config.hwparam.writesetting("kmkey", ikey.hex()) self.config.hwparam.writesetting("kmkey", ikey.hex())
retval["kmkey"] = ikey.hex() retval["kmkey"] = ikey.hex()
if self.config.chipconfig.prov_addr: if self.config.chipconfig.prov_addr:
provkey = self.custom_read(self.config.chipconfig.prov_addr, 16) provkey = self.custom_read(self.config.chipconfig.prov_addr, 16)
self.info("PROV : " + provkey.hex()) self.info(f"PROV : {provkey.hex()}")
self.config.hwparam.writesetting("provkey", provkey.hex()) self.config.hwparam.writesetting("provkey", provkey.hex())
retval["provkey"] = provkey.hex() retval["provkey"] = provkey.hex()
@ -749,7 +749,7 @@ class xmlflashext(metaclass=LogBase):
val += self.read_fuse(0xD) val += self.read_fuse(0xD)
val += self.read_fuse(0xE) val += self.read_fuse(0xE)
val += self.read_fuse(0xF) val += self.read_fuse(0xF)
self.info("HRID : " + val.hex()) self.info(f"HRID : {val.hex()}")
self.config.hwparam.writesetting("hrid", val.hex()) self.config.hwparam.writesetting("hrid", val.hex())
retval["hrid"] = val.hex() retval["hrid"] = val.hex()
@ -757,7 +757,7 @@ class xmlflashext(metaclass=LogBase):
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej") mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej")
if mtee3: if mtee3:
self.config.hwparam.writesetting("mtee3", mtee3.hex()) self.config.hwparam.writesetting("mtee3", mtee3.hex())
self.info("MTEE3 : " + mtee3.hex()) self.info(f"MTEE3 : {mtee3.hex()}")
retval["mtee3"] = mtee3.hex() retval["mtee3"] = mtee3.hex()
return retval return retval
elif self.config.chipconfig.sej_base is not None: elif self.config.chipconfig.sej_base is not None:
@ -772,19 +772,19 @@ class xmlflashext(metaclass=LogBase):
self.setotp(hwc) self.setotp(hwc)
rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp) rpmbkey = hwc.aes_hwcrypt(mode="rpmb", data=meid, btype="sej", otp=otp)
if rpmbkey: if rpmbkey:
self.info("RPMB : " + rpmbkey.hex()) self.info(f"RPMB : {rpmbkey.hex()}")
self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex()) self.config.hwparam.writesetting("rpmbkey", rpmbkey.hex())
retval["rpmbkey"] = rpmbkey.hex() retval["rpmbkey"] = rpmbkey.hex()
self.info("Generating sej mtee...") self.info("Generating sej mtee...")
mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp) mtee = hwc.aes_hwcrypt(mode="mtee", btype="sej", otp=otp)
if mtee: if mtee:
self.config.hwparam.writesetting("mtee", mtee.hex()) self.config.hwparam.writesetting("mtee", mtee.hex())
self.info("MTEE : " + mtee.hex()) self.info(f"MTEE : {mtee.hex()}")
retval["mtee"] = mtee.hex() retval["mtee"] = mtee.hex()
mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp) mtee3 = hwc.aes_hwcrypt(mode="mtee3", btype="sej", otp=otp)
if mtee3: if mtee3:
self.config.hwparam.writesetting("mtee3", mtee3.hex()) self.config.hwparam.writesetting("mtee3", mtee3.hex())
self.info("MTEE3 : " + mtee3.hex()) self.info(f"MTEE3 : {mtee3.hex()}")
retval["mtee3"] = mtee3.hex() retval["mtee3"] = mtee3.hex()
else: else:
self.info("SEJ Mode: No meid found. Are you in brom mode ?") self.info("SEJ Mode: No meid found. Are you in brom mode ?")
@ -793,7 +793,7 @@ class xmlflashext(metaclass=LogBase):
self.info("Generating gcpu mtee2 key...") self.info("Generating gcpu mtee2 key...")
mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee") mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee")
if mtee2 is not None: if mtee2 is not None:
self.info("MTEE2 : " + mtee2.hex()) self.info(f"MTEE2 : {mtee2.hex()}")
self.config.hwparam.writesetting("mtee2", mtee2.hex()) self.config.hwparam.writesetting("mtee2", mtee2.hex())
retval["mtee2"] = mtee2.hex() retval["mtee2"] = mtee2.hex()
return retval return retval

View file

@ -14,7 +14,8 @@ class XMLCmd(metaclass=LogBase):
self.mtk = mtk self.mtk = mtk
self.MAGIC = 0xFEEEEEEF self.MAGIC = 0xFEEEEEEF
def create_cmd(self, cmd: str, content: dict = None, version="1.0"): @staticmethod
def create_cmd(cmd: str, content: dict = None, version="1.0"):
cmd = f"<?xml version=\"1.0\" encoding=\"utf-8\"?><da><version>{version}</version><command>CMD:{cmd}</command>" cmd = f"<?xml version=\"1.0\" encoding=\"utf-8\"?><da><version>{version}</version><command>CMD:{cmd}</command>"
if content is not None: if content is not None:
for item in content: for item in content:
@ -323,11 +324,13 @@ class XMLCmd(metaclass=LogBase):
cmd = self.create_cmd("WRITE-REGISTER", content) cmd = self.create_cmd("WRITE-REGISTER", content)
return cmd return cmd
def cmd_read_partition_name(self): @staticmethod
def cmd_read_partition_name():
cmd = "" cmd = ""
return cmd return cmd
def cmd_debug_ufs(self): @staticmethod
def cmd_debug_ufs():
cmd = "" cmd = ""
return cmd return cmd

View file

@ -708,7 +708,7 @@ class DAXML(metaclass=LogBase):
self.error("Couldn't find item key") self.error("Couldn't find item key")
return data return data
def get_sys_property(self, key: int = "DA.SLA", length: int = 0x200000): def get_sys_property(self, key: str = "DA.SLA", length: int = 0x200000):
self.send_command(self.Cmd.cmd_get_sys_property(key=key, length=length), noack=True) self.send_command(self.Cmd.cmd_get_sys_property(key=key, length=length), noack=True)
cmd, result = self.get_command_result() cmd, result = self.get_command_result()
if type(result) is not upfile: if type(result) is not upfile:
@ -783,8 +783,7 @@ class DAXML(metaclass=LogBase):
if self.daconfig.flashtype == "emmc": if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.gp1_size) length = min(length, self.emmc.gp1_size)
else: else:
self.error("Unknown parttype. Known parttypes are \"boot1\",\"boot2\",\"gp1\"," + self.error('Unknown parttype. Known parttypes are "boot1","boot2","gp1","gp2","gp3","gp4","rpmb"')
"\"gp2\",\"gp3\",\"gp4\",\"rpmb\"")
return [] return []
elif storage == DaStorage.MTK_DA_STORAGE_UFS: elif storage == DaStorage.MTK_DA_STORAGE_UFS:
if parttype is None or parttype == "lu3" or parttype == "user": # USER if parttype is None or parttype == "lu3" or parttype == "user": # USER

View file

@ -53,10 +53,7 @@ class Hashimoto(Exploitation, metaclass=LogBase):
if addr is None: if addr is None:
addr = self.chipconfig.da_payload_addr addr = self.chipconfig.da_payload_addr
if self.payload(payload, addr): if self.payload(payload, addr):
if dontack: if dontack or self.usbread(4) == pack(">I", ack):
return ack
result = self.usbread(4)
if result == pack(">I", ack):
return ack return ack
return None return None
@ -71,10 +68,7 @@ class Hashimoto(Exploitation, metaclass=LogBase):
if filename is None: if filename is None:
data = bytearray() data = bytearray()
for addr in range(0x200000, 0x240000, 16): for addr in range(0x200000, 0x240000, 16):
if not self.chipconfig.blacklist: data.extend(self.hwcrypto.cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
data.extend(self.hwcrypto.cqdma.mem_read(addr, 16, True))
else:
data.extend(self.hwcrypto.cqdma.mem_read(addr, 16, False))
return data, filename return data, filename
else: else:
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
@ -86,10 +80,7 @@ class Hashimoto(Exploitation, metaclass=LogBase):
print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr, print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr,
bar_length=50) bar_length=50)
old = round(prog, 1) old = round(prog, 1)
if not self.chipconfig.blacklist: wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, True))
else:
wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, False))
print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50)
return True return True
@ -110,9 +101,6 @@ class Hashimoto(Exploitation, metaclass=LogBase):
print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr, print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr,
bar_length=50) bar_length=50)
old = round(prog, 1) old = round(prog, 1)
if not self.chipconfig.blacklist: wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, True))
else:
wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, False))
print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50) print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50)
return True return True

View file

@ -82,7 +82,7 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
self.mtk.preloader.display = False self.mtk.preloader.display = False
if self.mtk.preloader.init(display=False): if self.mtk.preloader.init(display=False):
self.mtk = self.mtk.crasher(display=False) self.mtk = self.mtk.crasher(display=False)
self.info("Bruteforce, testing " + hex(startaddr) + "...") self.info(f"Bruteforce, testing {hex(startaddr)}...")
if self.linecode is None: if self.linecode is None:
self.linecode = self.mtk.port.cdc.device.ctrl_transfer(0xA1, 0x21, 0, 0, 7) + array.array('B', [0]) self.linecode = self.mtk.port.cdc.device.ctrl_transfer(0xA1, 0x21, 0, 0, 7) + array.array('B', [0])
found, startaddr = self.newbrute(startaddr) found, startaddr = self.newbrute(startaddr)
@ -92,8 +92,8 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
cpu = "" cpu = ""
if self.mtk.config.cpu != "": if self.mtk.config.cpu != "":
cpu = "_" + self.mtk.config.cpu cpu = "_" + self.mtk.config.cpu
filename = "brom" + cpu + "_" + hex(self.mtk.config.hwcode)[2:] + ".bin" filename = f"brom{cpu}_{hex(self.mtk.config.hwcode)[2:]}.bin"
self.info("Found " + hex(startaddr) + f", dumping bootrom to {filename}") self.info(f"Found {hex(startaddr)}, dumping bootrom to {filename}")
self.dump_brom(filename, dump_ptr=startaddr) self.dump_brom(filename, dump_ptr=startaddr)
break break
else: else:
@ -110,7 +110,7 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
# noinspection PyProtectedMember # noinspection PyProtectedMember
udev._ctx.managed_claim_interface = lambda *args, **kwargs: None udev._ctx.managed_claim_interface = lambda *args, **kwargs: None
except AttributeError as e: except AttributeError as e:
raise RuntimeError("libusb is not installed for port {}".format(udev.dev.port)) from e raise RuntimeError(f"libusb is not installed for port {udev.dev.port}") from e
if dump: if dump:
try: try:
@ -135,7 +135,7 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
for address in range(dump_ptr, 0xffff, 4): for address in range(dump_ptr, 0xffff, 4):
if address % 0x100 == 0: if address % 0x100 == 0:
self.info("Bruteforce, testing " + hex(address) + "...") self.info(f"Bruteforce, testing {hex(address)}...")
for i in range(3): for i in range(3):
self.kamakiri2(address - 5 + (3 - i)) self.kamakiri2(address - 5 + (3 - i))
try: try:
@ -143,7 +143,7 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
return True, address return True, address
except RuntimeError: except RuntimeError:
try: try:
self.info("Bruteforce, testing " + hex(address) + "...") self.info(f"Bruteforce, testing {hex(address)}...")
self.mtk.preloader.read32(addr) self.mtk.preloader.read32(addr)
except Exception: except Exception:
return False, address + 4 return False, address + 4
@ -212,7 +212,7 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
if result == pack(">I", ack): if result == pack(">I", ack):
return ack return ack
else: else:
self.info("Error, payload answered instead: " + hexlify(result).decode('utf-8')) self.info(f"Error, payload answered instead: {hexlify(result).decode('utf-8')}")
return None return None
def patchda1_and_da2(self): def patchda1_and_da2(self):

Binary file not shown.

Binary file not shown.

View file

@ -1,38 +1,34 @@
from fuse import FuseOSError, Operations, LoggingMixIn from stat import S_IFDIR, S_IFREG
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 tempfile import NamedTemporaryFile 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): class MtkDaFS(LoggingMixIn, Operations):
def __init__(self, da_handler, rw=False): def __init__(self, da_handler, rw=False):
self.da_handler = da_handler self.da_handler = da_handler
self.rw = rw self.rw = rw
self.files = {} self.files = {'/': dict(
self.files['/'] = dict(
st_mode=(S_IFDIR | 0o555), st_mode=(S_IFDIR | 0o555),
st_ctime=time(), st_ctime=time(),
st_mtime=time(), st_mtime=time(),
st_atime=time(), st_atime=time(),
st_nlink=2) st_nlink=2), '/emmc_user.bin': dict(
self.files['/emmc_user.bin'] = dict(
st_mode=(S_IFREG | 0o777) if self.rw else (S_IFREG | 0o555), st_mode=(S_IFREG | 0o777) if self.rw else (S_IFREG | 0o555),
st_ctime=time(), st_ctime=time(),
st_mtime=time(), st_mtime=time(),
st_atime=time(), st_atime=time(),
st_nlink=2, st_nlink=2,
st_size = self.da_handler.mtk.daloader.daconfig.flashsize) st_size=self.da_handler.mtk.daloader.daconfig.flashsize), '/partitions': dict(
self.files['/partitions'] = dict(
st_mode=(S_IFDIR | 0o555), st_mode=(S_IFDIR | 0o555),
st_ctime=time(), st_ctime=time(),
st_mtime=time(), st_mtime=time(),
st_atime=time(), st_atime=time(),
st_nlink=2) st_nlink=2)}
for part in self.da_handler.mtk.daloader.get_partition_data(): for part in self.da_handler.mtk.daloader.get_partition_data():
self.files[f'/partitions/{part.name}'] = dict( self.files[f'/partitions/{part.name}'] = dict(
@ -41,35 +37,36 @@ class MtkDaFS(LoggingMixIn, Operations):
st_mtime=time(), st_mtime=time(),
st_atime=time(), st_atime=time(),
st_nlink=2, st_nlink=2,
st_size = part.sectors*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) offset=part.sector * self.da_handler.mtk.daloader.daconfig.pagesize)
def readdir(self, path, fh): 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): 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'' return b''
file_offset = 0 file_offset = 0
if 'offset' in self.files[path]: if 'offset' in self.files[path]:
file_offset = self.files[path]['offset'] 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) return bytes(data)
def write(self, path, data, offset, fh): def write(self, path, data, offset, fh):
if not self.rw: if not self.rw:
return 0 return 0
if offset+len(data) > self.files[path]['st_size']: if offset + len(data) > self.files[path]['st_size']:
return b'' return b''
file_offset = 0 file_offset = 0
if 'offset' in self.files[path]: if 'offset' in self.files[path]:
file_offset = self.files[path]['offset'] file_offset = self.files[path]['offset']
with NamedTemporaryFile('rb+', buffering=0) as f_write: with NamedTemporaryFile('rb+', buffering=0) as f_write:
f_write.write(data) 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) return len(data)
def getattr(self, path, fh=None): def getattr(self, path, fh=None):

View file

@ -108,7 +108,7 @@ class hwcrypto(metaclass=LogBase):
elif mode == "sha256": elif mode == "sha256":
return self.dxcc.generate_sha256(data=data) return self.dxcc.generate_sha256(data=data)
else: else:
self.error("Unknown aes_hwcrypt type: " + btype) self.error(f"Unknown aes_hwcrypt type: {btype}")
self.error("aes_hwcrypt supported types are: sej") self.error("aes_hwcrypt supported types are: sej")
return bytearray() return bytearray()

View file

@ -1050,7 +1050,8 @@ class dxcc(metaclass=LogBase):
def sasi_paldmaunmap(self, value1): def sasi_paldmaunmap(self, value1):
return return
def sasi_paldmamap(self, value1): @staticmethod
def sasi_paldmamap(value1):
# value2=value1 # value2=value1
return value1 return value1
@ -1305,12 +1306,14 @@ class dxcc(metaclass=LogBase):
self.sasi_sb_adddescsequence(xdesc) self.sasi_sb_adddescsequence(xdesc)
return self.SB_HalWaitDescCompletion() == 0 return self.SB_HalWaitDescCompletion() == 0
def mtee_decrypt(self, data): @staticmethod
def mtee_decrypt(data):
key = bytes.fromhex("B936C14D95A99585073E5607784A51F7444B60D6BFD6110F76D004CCB7E1950E") key = bytes.fromhex("B936C14D95A99585073E5607784A51F7444B60D6BFD6110F76D004CCB7E1950E")
skey = hashlib.sha256(key).digest() skey = hashlib.sha256(key).digest()
return AES.new(key=skey[:16], iv=skey[16:], mode=AES.MODE_CBC).decrypt(data) return AES.new(key=skey[:16], iv=skey[16:], mode=AES.MODE_CBC).decrypt(data)
def descramble(self, data): @staticmethod
def descramble(data):
key = bytes.fromhex("5C0E349A27DC46034C7B6744A378BD17") key = bytes.fromhex("5C0E349A27DC46034C7B6744A378BD17")
iv = bytes.fromhex("A0B0924686447109F2D51DCDDC93458A") iv = bytes.fromhex("A0B0924686447109F2D51DCDDC93458A")
ctr = Counter.new(128, initial_value=bytes_to_long(iv)) ctr = Counter.new(128, initial_value=bytes_to_long(iv))

View file

@ -642,7 +642,7 @@ class GCpu(metaclass=LogBase):
self.aes_setup_cbc(addr, data) self.aes_setup_cbc(addr, data)
def mtk_crypto_hmac_sha256_by_devkey_using_seed(self, seed, data): def mtk_crypto_hmac_sha256_by_devkey_using_seed(self, seed, data):
dev_key = bytearray("\x00" * 16) dev_key = bytearray(16)
self.init() self.init()
if not self.load_hw_key(0x30): if not self.load_hw_key(0x30):
self.memptr_set(0x12, seed) self.memptr_set(0x12, seed)
@ -667,7 +667,7 @@ class GCpu(metaclass=LogBase):
def mtk_crypto_hmac_sha256_by_devkey(self, data: bytearray, seed: bytearray): def mtk_crypto_hmac_sha256_by_devkey(self, data: bytearray, seed: bytearray):
if seed is None: if seed is None:
seed = bytearray("\x00" * 16) seed = bytearray(16)
dev_val = self.get_devinfo_with_index(12) dev_val = self.get_devinfo_with_index(12)
seed = xor_data(seed, dev_val, 4) seed = xor_data(seed, dev_val, 4)
dev_val = self.get_devinfo_with_index(13) dev_val = self.get_devinfo_with_index(13)
@ -675,7 +675,8 @@ class GCpu(metaclass=LogBase):
self.info("seed: " + hexlify(seed[:16]).decode('utf-8')) self.info("seed: " + hexlify(seed[:16]).decode('utf-8'))
return self.mtk_crypto_hmac_sha256_by_devkey_using_seed(seed, data) return self.mtk_crypto_hmac_sha256_by_devkey_using_seed(seed, data)
def byteswap(self, data): @staticmethod
def byteswap(data):
data = bytearray(data) data = bytearray(data)
for i in range(0, len(data) // 2): for i in range(0, len(data) // 2):
j = len(data) - i - 1 j = len(data) - i - 1

View file

@ -184,7 +184,8 @@ class sej(metaclass=LogBase):
else: else:
self.__logger.setLevel(logging.INFO) self.__logger.setLevel(logging.INFO)
def uffs(self, x): @staticmethod
def uffs(x):
v1 = x v1 = x
if x & 0xFFFF: if x & 0xFFFF:
result = 1 result = 1
@ -669,7 +670,8 @@ class sej(metaclass=LogBase):
hw_key = self.sej_do_aes(True, iv, swkey, 32) hw_key = self.sej_do_aes(True, iv, swkey, 32)
self.sej_set_key(AES_HW_WRAP_KEY, AES_KEY_256, hw_key) self.sej_set_key(AES_HW_WRAP_KEY, AES_KEY_256, hw_key)
def sej_sec_cfg_sw(self, data, encrypt=True): @staticmethod
def sej_sec_cfg_sw(data, encrypt=True):
""" """
Left for reference - hw implementation Left for reference - hw implementation
-------------------------------------- --------------------------------------

View file

@ -116,7 +116,7 @@ class Port(metaclass=LogBase):
sys.stdout.flush() sys.stdout.flush()
except Exception as serr: except Exception as serr:
print("Handshake: " + str(serr)) print(f"Handshake: {str(serr)}")
if "access denied" in str(serr): if "access denied" in str(serr):
self.warning(str(serr)) self.warning(str(serr))
self.debug(str(serr)) self.debug(str(serr))
@ -194,13 +194,13 @@ class Port(metaclass=LogBase):
else: else:
cmdrsp = self.usbread(dlen) cmdrsp = self.usbread(dlen)
if cmdrsp[0] is not value[0]: if cmdrsp[0] is not value[0]:
self.error("Cmd error :" + hexlify(cmdrsp).decode('utf-8')) self.error(f"Cmd error :{hexlify(cmdrsp).decode('utf-8')}")
return -1 return -1
if bytestoread > 0: if bytestoread > 0:
resp = self.usbread(bytestoread) resp = self.usbread(bytestoread)
return resp return resp
else: else:
self.warning("Couldn't send :" + hexlify(value).decode('utf-8')) self.warning(f"Couldn't send :{hexlify(value).decode('utf-8')}")
return resp return resp
def echo(self, data): def echo(self, data):

View file

@ -7,7 +7,8 @@ from capstone import (Cs, CS_MODE_BIG_ENDIAN, CS_MODE_LITTLE_ENDIAN,
CS_MODE_ARM, CS_MODE_THUMB, CS_MODE_V8, CS_MODE_V9, CS_MODE_ARM, CS_MODE_THUMB, CS_MODE_V8, CS_MODE_V9,
CS_MODE_MCLASS, CS_MODE_MICRO, CS_MODE_MIPS32, CS_MODE_MIPS64, CS_MODE_MCLASS, CS_MODE_MICRO, CS_MODE_MIPS32, CS_MODE_MIPS64,
CS_MODE_MIPS32R6, CS_MODE_16, CS_MODE_32, CS_MODE_64) CS_MODE_MIPS32R6, CS_MODE_16, CS_MODE_32, CS_MODE_64)
from keystone import (Ks, KS_MODE_BIG_ENDIAN, KS_MODE_LITTLE_ENDIAN, KS_ARCH_ARM, KS_MODE_THUMB, KS_MODE_ARM, KS_MODE_V8, from keystone import (Ks, KS_MODE_BIG_ENDIAN, KS_MODE_LITTLE_ENDIAN, KS_ARCH_ARM, KS_MODE_THUMB, KS_MODE_ARM,
KS_MODE_V8,
KS_ARCH_ARM64, KS_ARCH_MIPS, KS_MODE_MICRO, KS_MODE_MIPS3, KS_MODE_MIPS32R6, KS_ARCH_ARM64, KS_ARCH_MIPS, KS_MODE_MICRO, KS_MODE_MIPS3, KS_MODE_MIPS32R6,
KS_MODE_MIPS32, KS_MODE_MIPS64, KS_MODE_16, KS_MODE_32, KS_MODE_64, KS_ARCH_X86, KS_MODE_MIPS32, KS_MODE_MIPS64, KS_MODE_16, KS_MODE_32, KS_MODE_64, KS_ARCH_X86,
KS_ARCH_PPC, KS_MODE_PPC32, KS_MODE_PPC64, KS_MODE_QPX, KS_ARCH_PPC, KS_MODE_PPC32, KS_MODE_PPC64, KS_MODE_QPX,
@ -21,7 +22,7 @@ def asm(code, cpu, mode, bigendian):
little = KS_MODE_BIG_ENDIAN # big-endian mode little = KS_MODE_BIG_ENDIAN # big-endian mode
else: else:
little = KS_MODE_LITTLE_ENDIAN # little-endian mode (default mode) little = KS_MODE_LITTLE_ENDIAN # little-endian mode (default mode)
print("CPU: %s, MODE: %s" % (cpu, mode)) print(f"CPU: {cpu}, MODE: {mode}")
ks = None ks = None
if cpu == "arm": if cpu == "arm":
# ARM architecture (including Thumb, Thumb-2) # ARM architecture (including Thumb, Thumb-2)
@ -142,10 +143,8 @@ def disasm(code, cpu, mode, bigendian, size):
print("CPU and/or mode not supported!") print("CPU and/or mode not supported!")
exit(0) exit(0)
instr = [] instr = [f"{i.mnemonic}\t{i.op_str}" for i in cs.disasm(code, size)]
for i in cs.disasm(code, size): # print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
# print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
instr.append("%s\t%s" % (i.mnemonic, i.op_str))
return instr return instr
@ -193,7 +192,7 @@ def main():
print("[asmtools] Usage: -asm cpu,mode or -disasm cpu,mode") print("[asmtools] Usage: -asm cpu,mode or -disasm cpu,mode")
exit(0) exit(0)
if (args.infile == '' and args.inp == ''): if not args.infile == '' and args.inp == '':
print("[asmtools] I must have an infile to work on (-in) or a string input (--inp") print("[asmtools] I must have an infile to work on (-in) or a string input (--inp")
exit(0) exit(0)
@ -251,4 +250,5 @@ def main():
''' '''
main() if __name__ == '__main__':
main()

View file

@ -76,7 +76,8 @@ class cryptutils:
class aes: class aes:
# GF(2^128) defined by 1 + a + a^2 + a^7 + a^128 # GF(2^128) defined by 1 + a + a^2 + a^7 + a^128
# Please note the MSB is x0 and LSB is x127 # Please note the MSB is x0 and LSB is x127
def gf_2_128_mul(self, x, y): @staticmethod
def gf_2_128_mul(x, y):
assert x < (1 << 128) assert x < (1 << 128)
assert y < (1 << 128) assert y < (1 << 128)
res = 0 res = 0
@ -88,7 +89,7 @@ class cryptutils:
class AES_GCM: class AES_GCM:
# Galois/Counter Mode with AES-128 and 96-bit IV # Galois/Counter Mode with AES-128 and 96-bit IV
''' """
Example: Example:
master_key = 0x0ADAABC70895E008147A48C27791F654 #54F69177C2487A1408E09508C7ABDA0A master_key = 0x0ADAABC70895E008147A48C27791F654 #54F69177C2487A1408E09508C7ABDA0A
init_value = 0x2883B4173F9A838437C1CD86CCFAA5ED #EDA5FACC86CDC13784839A3F17B48328 init_value = 0x2883B4173F9A838437C1CD86CCFAA5ED #EDA5FACC86CDC13784839A3F17B48328
@ -122,7 +123,7 @@ class cryptutils:
b"\xA0\x62\x9E\xF9\xF4\xE7\xE8\x65" b"\xA0\x62\x9E\xF9\xF4\xE7\xE8\x65"
my_gcm = AES_GCM(master_key) my_gcm = AES_GCM(master_key)
decrypted = my_gcm.decrypt(init_value, ciphertext, auth_tag) decrypted = my_gcm.decrypt(init_value, ciphertext, auth_tag)
''' """
def __init__(self, master_key): def __init__(self, master_key):
self.change_key(master_key) self.change_key(master_key)
@ -248,7 +249,8 @@ class cryptutils:
return plaintext return plaintext
def aes_gcm(self, input, nounce, aes_key, hdr, tag_auth, decrypt=True): @staticmethod
def aes_gcm(input, nounce, aes_key, hdr, tag_auth, decrypt=True):
cipher = AES.new(aes_key, AES.MODE_GCM, nounce) cipher = AES.new(aes_key, AES.MODE_GCM, nounce)
if hdr is not None: if hdr is not None:
cipher.update(hdr) cipher.update(hdr)
@ -268,30 +270,30 @@ class cryptutils:
ciphertext, tag_auth = cipher.encrypt_and_digest(input) ciphertext, tag_auth = cipher.encrypt_and_digest(input)
return ciphertext, tag_auth return ciphertext, tag_auth
def aes_cbc(self, key, iv, data, decrypt=True): @staticmethod
def aes_cbc(key, iv, data, decrypt=True):
if decrypt: if decrypt:
return AES.new(key, AES.MODE_CBC, IV=iv).decrypt(data) return AES.new(key, AES.MODE_CBC, IV=iv).decrypt(data)
else: else:
return AES.new(key, AES.MODE_CBC, IV=iv).encrypt(data) return AES.new(key, AES.MODE_CBC, IV=iv).encrypt(data)
def aes_ecb(self, key, data, decrypt=True): @staticmethod
def aes_ecb(key, data, decrypt=True):
if decrypt: if decrypt:
return AES.new(key, AES.MODE_ECB).decrypt(data) return AES.new(key, AES.MODE_ECB).decrypt(data)
else: else:
return AES.new(key, AES.MODE_ECB).encrypt(data) return AES.new(key, AES.MODE_ECB).encrypt(data)
def aes_ctr(self, key, counter, enc_data, decrypt=True): @staticmethod
def aes_ctr(key, counter, enc_data, decrypt=True):
ctr = Counter.new(128, initial_value=counter) ctr = Counter.new(128, initial_value=counter)
# Create the AES cipher object and decrypt the ciphertext, basically this here is just aes ctr 256 :) # Create the AES cipher object and decrypt the ciphertext, basically this here is just aes ctr 256 :)
cipher = AES.new(key, AES.MODE_CTR, counter=ctr) cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
data = b"" data = cipher.decrypt(enc_data) if decrypt else cipher.encrypt(enc_data)
if decrypt:
data = cipher.decrypt(enc_data)
else:
data = cipher.encrypt(enc_data)
return data return data
def aes_ccm(self, key, nounce, tag_auth, data, decrypt=True): @staticmethod
def aes_ccm(key, nounce, tag_auth, data, decrypt=True):
cipher = AES.new(key, AES.MODE_CCM, nounce) cipher = AES.new(key, AES.MODE_CCM, nounce)
if decrypt: if decrypt:
plaintext = cipher.decrypt(data) plaintext = cipher.decrypt(data)
@ -304,6 +306,7 @@ class cryptutils:
ciphertext = cipher.encrypt(data) ciphertext = cipher.encrypt(data)
return ciphertext return ciphertext
@staticmethod
def aes_cmac_verify(key, plain, compare): def aes_cmac_verify(key, plain, compare):
ctx = CMAC.new(key, ciphermod=AES) ctx = CMAC.new(key, ciphermod=AES)
ctx.update(plain) ctx.update(plain)
@ -347,12 +350,13 @@ class cryptutils:
else: else:
print("Test failed.") print("Test failed.")
def i2osp(self, x, x_len): @staticmethod
'''Converts the integer x to its big-endian representation of length def i2osp(x, x_len):
"""Converts the integer x to its big-endian representation of length
x_len. x_len.
''' """
if x > 256 ** x_len: if x > 256 ** x_len:
raise ("Integer Too Large") raise "Integer Too Large"
h = hex(x)[2:] h = hex(x)[2:]
if h[-1] == 'L': if h[-1] == 'L':
h = h[:-1] h = h[:-1]
@ -361,12 +365,12 @@ class cryptutils:
x = bytes.fromhex(h) x = bytes.fromhex(h)
return b'\x00' * int(x_len - len(x)) + x return b'\x00' * int(x_len - len(x)) + x
def os2ip(self, x): @staticmethod
'''Converts the byte string x representing an integer reprented using the def os2ip(x):
"""Converts the byte string x representing an integer reprented using the
big-endian convient to an integer. big-endian convient to an integer.
''' """
h = hexlify(x) return int(hexlify(x), 16)
return int(h, 16)
# def os2ip(self, X): # def os2ip(self, X):
# return int.from_bytes(X, byteorder='big') # return int.from_bytes(X, byteorder='big')
@ -374,13 +378,14 @@ class cryptutils:
def mgf1(self, input, length): def mgf1(self, input, length):
counter = 0 counter = 0
output = b'' output = b''
while (len(output) < length): while len(output) < length:
C = self.i2osp(counter, 4) C = self.i2osp(counter, 4)
output += self.hash(input + C) output += self.hash(input + C)
counter += 1 counter += 1
return output[:length] return output[:length]
def assert_int(self, var: int, name: str): @staticmethod
def assert_int(var: int, name: str):
if isinstance(var, int): if isinstance(var, int):
return return
raise TypeError('%s should be an integer, not %s' % (name, var.__class__)) raise TypeError('%s should be an integer, not %s' % (name, var.__class__))
@ -428,7 +433,8 @@ class cryptutils:
return self.sign(tosign, D, N, emBits) return self.sign(tosign, D, N, emBits)
# 6B1EAA2042A5C8DA8B1B4A8320111A70A0CBA65233D1C6E418EF8156E82A8F96BD843F047FF25AB9702A6582C8387298753E628F23448B4580E09CBD2A483C623B888F47C4BD2C5EFF09013C6DFF67DB59BAB3037F0BEE05D5660264D28CC6251631FE75CE106D931A04FA032FEA31259715CE0FAB1AE0E2F8130807AF4019A61B9C060ECE59104F22156FEE8108F17DC80D7C2F8397AFB9780994F7C5A0652F93D1B48010B0B248AB9711235787D797FBA4D10A29BCF09628585D405640A866B15EE9D7526A2703E72A19811EF447F6E5C43F915B3808EBC79EA4BCF78903DBDE32E47E239CFB5F2B5986D0CBBFBE6BACDC29B2ADE006D23D0B90775B1AE4DD # 6B1EAA2042A5C8DA8B1B4A8320111A70A0CBA65233D1C6E418EF8156E82A8F96BD843F047FF25AB9702A6582C8387298753E628F23448B4580E09CBD2A483C623B888F47C4BD2C5EFF09013C6DFF67DB59BAB3037F0BEE05D5660264D28CC6251631FE75CE106D931A04FA032FEA31259715CE0FAB1AE0E2F8130807AF4019A61B9C060ECE59104F22156FEE8108F17DC80D7C2F8397AFB9780994F7C5A0652F93D1B48010B0B248AB9711235787D797FBA4D10A29BCF09628585D405640A866B15EE9D7526A2703E72A19811EF447F6E5C43F915B3808EBC79EA4BCF78903DBDE32E47E239CFB5F2B5986D0CBBFBE6BACDC29B2ADE006D23D0B90775B1AE4DD
def ceil_div(self, a, b): @staticmethod
def ceil_div(a, b):
(q, r) = divmod(a, b) (q, r) = divmod(a, b)
if r: if r:
return q + 1 return q + 1
@ -494,10 +500,12 @@ class cryptutils:
return False return False
return maskedDB return maskedDB
def sha1(self, msg): @staticmethod
def sha1(msg):
return hashlib.sha1(msg).digest() return hashlib.sha1(msg).digest()
def sha256(self, msg): @staticmethod
def sha256(msg):
return hashlib.sha256(msg).digest() return hashlib.sha256(msg).digest()

View file

@ -989,9 +989,9 @@ class ErrorHandler:
def status(self, status): def status(self, status):
if status in self.ec: if status in self.ec:
return self.ec[status] + " (" + hex(status) + ")" return f"{self.ec[status]} ({hex(status)})"
if status in self.xec: if status in self.xec:
return self.xec[status] + " (" + hex(status) + ")" return f"{self.xec[status]} ({hex(status)})"
if status in self.lec: if status in self.lec:
return self.lec[status] + " (" + hex(status) + ")" return f"{self.lec[status]} ({hex(status)})"
return "Unknown: " + hex(status) return f"Unknown: {hex(status)}"

View file

@ -328,9 +328,8 @@ class gpt(metaclass=LogBase):
def print_gptfile(self, filename): def print_gptfile(self, filename):
try: try:
filesize = os.stat(filename).st_size
with open(filename, "rb") as rf: with open(filename, "rb") as rf:
size = min(32 * 4096, filesize) size = min(32 * 4096, os.stat(filename).st_size)
data = rf.read(size) data = rf.read(size)
for sectorsize in [512, 4096]: for sectorsize in [512, 4096]:
result = self.parse(data, sectorsize) result = self.parse(data, sectorsize)

View file

@ -59,7 +59,7 @@ class Mtk(metaclass=LogBase):
idx = -1 idx = -1
else: else:
data[idx:idx + len(patchval)] = patchval data[idx:idx + len(patchval)] = patchval
self.info(f"Patched \"{patchval[2]}\" in preloader") self.info(f'Patched "{patchval[2]}" in preloader')
patched = True patched = True
else: else:
pattern = bytes.fromhex(patchval[0]) pattern = bytes.fromhex(patchval[0])
@ -67,7 +67,7 @@ class Mtk(metaclass=LogBase):
if idx != -1: if idx != -1:
patch = bytes.fromhex(patchval[1]) patch = bytes.fromhex(patchval[1])
data[idx:idx + len(patch)] = patch data[idx:idx + len(patch)] = patch
self.info(f"Patched \"{patchval[2]}\" in preloader") self.info(f'Patched "{patchval[2]}" in preloader')
patched = True patched = True
# break # break
i += 1 i += 1
@ -101,7 +101,7 @@ class Mtk(metaclass=LogBase):
if idx != -1: if idx != -1:
patch = bytes.fromhex(patchval[1]) patch = bytes.fromhex(patchval[1])
data[idx:idx + len(patch)] = patch data[idx:idx + len(patch)] = patch
self.info(f"Patched \"{patchval[2]}\" in preloader") self.info(f'Patched "{patchval[2]}" in preloader')
patched = True patched = True
# break # break
i += 1 i += 1

View file

@ -166,7 +166,8 @@ class Main(metaclass=LogBase):
if not os.path.exists("logs"): if not os.path.exists("logs"):
os.mkdir("logs") os.mkdir("logs")
def close(self): @staticmethod
def close():
sys.exit(0) sys.exit(0)
def cmd_stage(self, mtk, filename, stage2addr, stage2file, verifystage2): def cmd_stage(self, mtk, filename, stage2addr, stage2file, verifystage2):
@ -561,7 +562,7 @@ class Main(metaclass=LogBase):
for pos in range(offset, offset + length, rlen): for pos in range(offset, offset + length, rlen):
print("Reading pos %08X" % pos) print("Reading pos %08X" % pos)
res = mtk.preloader.read32(pos, rlen // 4) res = mtk.preloader.read32(pos, rlen // 4)
if res == []: if not res:
break break
print(hexlify(b"".join([pack("<I", val) for val in res])).decode('utf-8')) print(hexlify(b"".join([pack("<I", val) for val in res])).decode('utf-8'))
@ -665,7 +666,7 @@ class Main(metaclass=LogBase):
if logs != b"": if logs != b"":
with open(filename, "wb") as wf: with open(filename, "wb") as wf:
wf.write(logs) wf.write(logs)
self.info(f"Successfully wrote logs to \"{filename}\"") self.info(f'Successfully wrote logs to "{filename}"')
else: else:
self.info("No logs found.") self.info("No logs found.")

View file

@ -1311,7 +1311,8 @@ class Preloader(metaclass=LogBase):
self.config.is_brom = False self.config.is_brom = False
return b"" return b""
def prepare_data(self, data, sigdata=b"", maxsize=0): @staticmethod
def prepare_data(data, sigdata=b"", maxsize=0):
gen_chksum = 0 gen_chksum = 0
data = (data[:maxsize] + sigdata) data = (data[:maxsize] + sigdata)
if len(data + sigdata) % 2 != 0: if len(data + sigdata) % 2 != 0:

View file

@ -61,7 +61,7 @@ class Partition(metaclass=LogBase):
pm.sectors = partinfo.size // self.config.pagesize pm.sectors = partinfo.size // self.config.pagesize
pm.type = 1 pm.type = 1
pm.flags = partinfo.mask_flags pm.flags = partinfo.mask_flags
partitions.add(pm) partitions.append(pm)
return data, partitions return data, partitions
return b"", None return b"", None
@ -116,7 +116,7 @@ class Partition(metaclass=LogBase):
return data, guid_gpt return data, guid_gpt
def get_backup_gpt(self, lun, gpt_num_part_entries, gpt_part_entry_size, gpt_part_entry_start_lba, def get_backup_gpt(self, lun, gpt_num_part_entries, gpt_part_entry_size, gpt_part_entry_start_lba,
parttype="user") -> bytearray: parttype="user") -> bytes:
data = self.readflash(addr=0, length=2 * self.config.pagesize, filename="", parttype=parttype, display=False) data = self.readflash(addr=0, length=2 * self.config.pagesize, filename="", parttype=parttype, display=False)
if data == b"": if data == b"":
return data return data

View file

@ -76,7 +76,7 @@ class PLTools(metaclass=LogBase):
ack = self.exploit.runpayload(payload, ack, addr, dontack) ack = self.exploit.runpayload(payload, ack, addr, dontack)
if ack == ack: if ack == ack:
self.info("Successfully sent payload: " + filename) self.info(f"Successfully sent payload: {filename}")
self.mtk.daloader.patch = True self.mtk.daloader.patch = True
return True return True
elif ack == b"\xc1\xc2\xc3\xc4": elif ack == b"\xc1\xc2\xc3\xc4":
@ -87,20 +87,20 @@ class PLTools(metaclass=LogBase):
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
for pos in range(0, 0x40000, 64): for pos in range(0, 0x40000, 64):
wf.write(self.mtk.port.usbread(64)) wf.write(self.mtk.port.usbread(64))
self.info("Preloader dumped as: " + "preloader.bin") self.info("Preloader dumped as: preloader.bin")
return True return True
else: else:
with open("out.bin", 'wb') as wf: with open("out.bin", 'wb') as wf:
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50) print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
for pos in range(0, 0x20000, 64): for pos in range(0, 0x20000, 64):
wf.write(self.mtk.port.usbread(64)) wf.write(self.mtk.port.usbread(64))
self.info("Bootrom dumped as: " + "out.bin") self.info("Bootrom dumped as: out.bin")
return True return True
self.error("Error on sending payload: " + filename) self.error(f"Error on sending payload: {filename}")
return False return False
else: else:
self.error("Error on sending payload: " + filename) self.error(f"Error on sending payload: {filename}")
self.error("Error, payload answered instead: " + hexlify(ack).decode('utf-8')) self.error(f"Error, payload answered instead: {hexlify(ack).decode('utf-8')}")
return False return False
def runbrute(self, args): def runbrute(self, args):
@ -138,16 +138,16 @@ class PLTools(metaclass=LogBase):
self.info("Kamakiri / DA Run") self.info("Kamakiri / DA Run")
if self.runpayload(filename=pfilename, ack=0xC1C2C3C4, offset=0): if self.runpayload(filename=pfilename, ack=0xC1C2C3C4, offset=0):
if self.exploit.dump_brom(filename): if self.exploit.dump_brom(filename):
self.info("Dumped as: " + filename) self.info(f"Dumped as:{filename} ")
return True return True
else: else:
self.error("Error on sending payload: " + filename) self.error(f"Error on sending payload: {filename}")
else: else:
if self.exploit.dump_brom(filename, length=length): if self.exploit.dump_brom(filename, length=length):
self.info("Dumped as: " + filename) self.info(f"Dumped as: {filename}")
return True return True
else: else:
self.error("Error on sending payload: " + pfilename) self.error(f"Error on sending payload: {pfilename}")
return False return False
def run_dump_preloader(self, filename): def run_dump_preloader(self, filename):
@ -158,11 +158,11 @@ class PLTools(metaclass=LogBase):
data, filename = self.exploit.dump_preloader() data, filename = self.exploit.dump_preloader()
return data, filename return data, filename
else: else:
self.error("Error on sending payload: " + pfilename) self.error(f"Error on sending payload: {pfilename}")
return None, None return None, None
else: else:
if self.exploit.dump_brom(filename): if self.exploit.dump_brom(filename):
self.info("Preloader dumped as: " + filename) self.info(f"Preloader dumped as: {filename}")
return True return True
else: else:
self.error("Error on dumping preloader") self.error("Error on dumping preloader")

View file

@ -1,21 +1,22 @@
#!/usr/bin/python3 #!/usr/bin/python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 # (c) B.Kerler 2018-2023
import sys import codecs
import copy
import datetime as dt
import io
import logging import logging
import logging.config import logging.config
import codecs
import struct
import os import os
import shutil import shutil
import stat import stat
import colorama import struct
import copy import sys
import time import time
import io
import datetime as dt
from struct import unpack, pack
from io import BytesIO from io import BytesIO
from struct import unpack, pack
import colorama
try: try:
from capstone import Cs, CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN from capstone import Cs, CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN
@ -154,10 +155,11 @@ class progress:
else: else:
self.guiprogress = None self.guiprogress = None
def calcProcessTime(self, starttime, cur_iter, max_iter): @staticmethod
def calcProcessTime(starttime, cur_iter, max_iter):
telapsed = time.time() - starttime telapsed = time.time() - starttime
if telapsed > 0 and cur_iter > 0: if telapsed > 0 and cur_iter > 0:
testimated = (telapsed / cur_iter) * (max_iter) testimated = (telapsed / cur_iter) * max_iter
finishtime = starttime + testimated finishtime = starttime + testimated
finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time
lefttime = testimated - telapsed # in seconds lefttime = testimated - telapsed # in seconds
@ -207,21 +209,22 @@ class progress:
if lefttime > 0: if lefttime > 0:
sec = lefttime sec = lefttime
if sec > 60: if sec > 60:
min = sec // 60 minutes = sec // 60
sec = sec % 60 sec = sec % 60
if min > 60: if minutes > 60:
h = min // 24 h = minutes // 24
min = min % 24 minutes = minutes % 24
hinfo = "%02dh:%02dm:%02ds left" % (h, min, sec) hinfo = "%02dh:%02dm:%02ds left" % (h, minutes, sec)
else: else:
hinfo = "%02dm:%02ds left" % (min, sec) hinfo = "%02dm:%02ds left" % (minutes, sec)
else: else:
hinfo = "%02ds left" % sec hinfo = "%02ds left" % sec
print_progress(prog, 100, prefix='Progress:', print_progress(prog, 100, prefix='Progress:',
suffix=prefix + f' (Sector 0x%X of 0x%X, {hinfo}) %0.2f MB/s' % (pos // self.pagesize, suffix=prefix + f' (Sector 0x%X of 0x%X, {hinfo}) %0.2f MB/s' % (pos // self.pagesize,
total // self.pagesize, total // self.pagesize,
throughput), bar_length=50) throughput),
bar_length=50)
self.prog = prog self.prog = prog
self.progpos = pos self.progpos = pos
self.progtime = t0 self.progtime = t0
@ -301,7 +304,7 @@ def do_tcp_server(client, arguments, handler):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = int(arguments.tcpport) port = int(arguments.tcpport)
server_address = ('localhost', port) server_address = ('localhost', port)
print('starting up on %s port %s' % server_address) print(f'starting up on {server_address[0]} port {port}')
sock.bind(server_address) sock.bind(server_address)
sock.listen(1) sock.listen(1)
response = None response = None
@ -314,24 +317,20 @@ def do_tcp_server(client, arguments, handler):
data = connection.recv(4096).decode('utf-8') data = connection.recv(4096).decode('utf-8')
if data == '': if data == '':
break break
print('received %s' % data) print(f'received {data}')
if data: if data:
print('handling request') print('handling request')
lines = data.split("\n") lines = data.split("\n")
for line in lines: for line in lines:
if ":" in line: if ":" in line:
cmd = line.split(":")[0] cmd = line.split(":")[0]
marguments = line.split(":")[1]
try: try:
opts = parse_args(cmd, marguments, arguments) opts = parse_args(cmd, line.split(":")[1], arguments)
except Exception: except Exception:
response = "Wrong arguments\n<NAK>\n" response = "Wrong arguments\n<NAK>\n"
opts = None opts = None
if opts is not None: if opts is not None:
if handler(cmd, opts): response = "<ACK>\n" if handler(cmd, opts) else "<NAK>\n"
response = "<ACK>\n"
else:
response = "<NAK>\n"
connection.sendall(bytes(response, 'utf-8')) connection.sendall(bytes(response, 'utf-8'))
finally: finally:
connection.close() connection.close()
@ -339,11 +338,7 @@ def do_tcp_server(client, arguments, handler):
def parse_args(cmd, args, mainargs): def parse_args(cmd, args, mainargs):
options = {} options = {}
opts = None opts = args.split(",") if "," in args else [args]
if "," in args:
opts = args.split(",")
else:
opts = [args]
for arg in mainargs: for arg in mainargs:
if "--" in arg: if "--" in arg:
options[arg] = mainargs[arg] options[arg] = mainargs[arg]
@ -488,8 +483,8 @@ class LogBase(type):
def __init__(cls, *args): def __init__(cls, *args):
super().__init__(*args) super().__init__(*args)
logger_attribute_name = '_' + cls.__name__ + '__logger' logger_attribute_name = f'_{cls.__name__}__logger'
logger_debuglevel_name = '_' + cls.__name__ + '__debuglevel' logger_debuglevel_name = f'_{cls.__name__}__debuglevel'
logger_name = '.'.join([c.__name__ for c in cls.mro()[-2::-1]]) logger_name = '.'.join([c.__name__ for c in cls.mro()[-2::-1]])
LOG_CONFIG = { LOG_CONFIG = {
"version": 1, "version": 1,
@ -603,7 +598,7 @@ class elf:
elif self.elfclass == 2: # 64Bit elif self.elfclass == 2: # 64Bit
start = 0x34 start = 0x34
else: else:
print("Error on parsing " + self.filename) print(f"Error on parsing {self.filename}")
return ['', ''] return ['', '']
elfheadersize, programheaderentrysize, programheaderentrycount = struct.unpack("<HHH", elfheadersize, programheaderentrysize, programheaderentrycount = struct.unpack("<HHH",
self.data[start:start + 3 * 2]) self.data[start:start + 3 * 2])
@ -625,7 +620,8 @@ class patchtools:
def __init__(self, bdebug=False): def __init__(self, bdebug=False):
self.bDebug = bdebug self.bDebug = bdebug
def has_bad_uart_chars(self, data): @staticmethod
def has_bad_uart_chars(data):
badchars = [b'\x00', b'\n', b'\r', b'\x08', b'\x7f', b'\x20', b'\x09'] badchars = [b'\x00', b'\n', b'\r', b'\x08', b'\x7f', b'\x20', b'\x09']
for idx, c in enumerate(data): for idx, c in enumerate(data):
c = bytes([c]) c = bytes([c])
@ -642,7 +638,7 @@ class patchtools:
badchars = self.has_bad_uart_chars(data) badchars = self.has_bad_uart_chars(data)
if not badchars: if not badchars:
badchars = self.has_bad_uart_chars(data2) badchars = self.has_bad_uart_chars(data2)
if not (badchars): if not badchars:
return div return div
div += 4 div += 4
@ -665,19 +661,17 @@ class patchtools:
abase = ((offset + div) & 0xFFFF0000) >> 16 abase = ((offset + div) & 0xFFFF0000) >> 16
a = ((offset + div) & 0xFFFF) a = ((offset + div) & 0xFFFF)
strasm = "" strasm = ""
strasm += f"# {hex(offset)}\n"
strasm += f"mov {reg}, #{hex(a)};\n"
strasm += f"movk {reg}, #{hex(abase)}, LSL#16;\n"
if div > 0: if div > 0:
strasm += "# " + hex(offset) + "\n" strasm += f"sub {reg}, {reg}, #{hex(div)};\n"
strasm += "mov " + reg + ", #" + hex(a) + ";\n"
strasm += "movk " + reg + ", #" + hex(abase) + ", LSL#16;\n"
strasm += "sub " + reg + ", " + reg + ", #" + hex(div) + ";\n"
else: else:
strasm += "# " + hex(offset) + "\n" strasm += f"add {reg}, {reg}, #{hex(-div)};\n"
strasm += "mov " + reg + ", #" + hex(a) + ";\n"
strasm += "movk " + reg + ", #" + hex(abase) + ", LSL#16;\n"
strasm += "add " + reg + ", " + reg + ", #" + hex(-div) + ";\n"
return strasm return strasm
def uart_valid_sc(self, sc): @staticmethod
def uart_valid_sc(sc):
badchars = [b'\x00', b'\n', b'\r', b'\x08', b'\x7f', b'\x20', b'\x09'] badchars = [b'\x00', b'\n', b'\r', b'\x08', b'\x7f', b'\x20', b'\x09']
for idx, c in enumerate(sc): for idx, c in enumerate(sc):
c = bytes([c]) c = bytes([c])
@ -687,12 +681,11 @@ class patchtools:
return False return False
return True return True
def disasm(self, code, size): @staticmethod
def disasm(code, size):
cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN) cs = Cs(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN)
instr = [] instr = [f"{i.mnemonic}\t{i.op_str}" for i in cs.disasm(code, size)]
for i in cs.disasm(code, size): # print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
# print("0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str))
instr.append("%s\t%s" % (i.mnemonic, i.op_str))
return instr return instr
def assembler(self, code): def assembler(self, code):
@ -735,7 +728,8 @@ class patchtools:
return out return out
def find_binary(self, data, strf, pos=0): @staticmethod
def find_binary(data, strf, pos=0):
t = strf.split(b".") t = strf.split(b".")
pre = 0 pre = 0
offsets = [] offsets = []
@ -752,7 +746,7 @@ class patchtools:
continue continue
rt += 1 rt += 1
prep = data[rt:].find(t[i]) prep = data[rt:].find(t[i])
if (prep != 0): if prep != 0:
error = 1 error = 1
break break
rt += len(t[i]) rt += len(t[i])
@ -766,7 +760,7 @@ class patchtools:
return None return None
def read_object(data: object, definition: object) -> object: def read_object(data: object, definition) -> dict:
""" """
Unpacks a structure using the given data and definition. Unpacks a structure using the given data and definition.
""" """
@ -820,7 +814,7 @@ def print_progress(iteration, total, prefix='', suffix='', decimals=1, bar_lengt
filled_length = int(round(bar_length * iteration / float(total))) filled_length = int(round(bar_length * iteration / float(total)))
bar = '' * filled_length + '-' * (bar_length - filled_length) bar = '' * filled_length + '-' * (bar_length - filled_length)
sys.stdout.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)) sys.stdout.write(f'\r{prefix} |{bar}| {percents}% {suffix}')
if iteration == total: if iteration == total:
sys.stdout.write('\n') sys.stdout.write('\n')

View file

@ -48,7 +48,7 @@ def ldr_lit(curpc, instr):
def ldr_imm(instr): def ldr_imm(instr):
simm5 = (instr >> 6) & 0x1F simm5 = (instr >> 6) & 0x1F
sRt = (instr) & 0x7 sRt = instr & 0x7
sRn = (instr >> 3) & 0x7 sRn = (instr >> 3) & 0x7
return simm5, sRt, sRn return simm5, sRt, sRn
@ -59,28 +59,27 @@ def main():
sys.exit(0) sys.exit(0)
with open(sys.argv[1], "rb") as rf: with open(sys.argv[1], "rb") as rf:
print() print()
print("Using : " + sys.argv[1]) print(f"Using : {sys.argv[1]}")
data = rf.read() data = rf.read()
base = 0 base = 0
mpos = find_binary(data, b"\xA0\x0A\x50\x05.\x00\x00\x00", 0) mpos = find_binary(data, b"\xA0\x0A\x50\x05.\x00\x00\x00", 0)
usbdl_get_dword=None usbdl_get_dword = None
usbdl_put_dword=None usbdl_put_dword = None
usbdl_put_word=None
if mpos is not None: if mpos is not None:
usbdl_put_data = unpack("<I", data[mpos - 0xC:mpos - 0xC + 4])[0] usbdl_put_data = unpack("<I", data[mpos - 0xC:mpos - 0xC + 4])[0]
base = (((usbdl_put_data >> 16) & 0xFFFFF)<<16) base = (((usbdl_put_data >> 16) & 0xFFFFF) << 16)
usbdl_get_data = unpack("<I", data[mpos - 0x10:mpos - 0x10 + 4])[0] usbdl_get_data = unpack("<I", data[mpos - 0x10:mpos - 0x10 + 4])[0]
usbdl_put_dword = unpack("<I", data[mpos - 0x14:mpos - 0x14 + 4])[0] usbdl_put_dword = unpack("<I", data[mpos - 0x14:mpos - 0x14 + 4])[0]
usbdl_get_dword = unpack("<I", data[mpos - 0x18:mpos - 0x18 + 4])[0] usbdl_get_dword = unpack("<I", data[mpos - 0x18:mpos - 0x18 + 4])[0]
usbdl_put_word = unpack("<I", data[mpos - 0x1C:mpos - 0x1C + 4])[0] usbdl_put_word = unpack("<I", data[mpos - 0x1C:mpos - 0x1C + 4])[0]
else: else:
usbdl_get_data = find_binary(data,"2DE9F04780460F46") usbdl_get_data = find_binary(data, "2DE9F04780460F46")
usbdl_put_data = find_binary(data,"10B5064AD4689368") usbdl_put_data = find_binary(data, "10B5064AD4689368")
usbdl_put_word = find_binary(data, b"\x2D\xE9\xF8\x4F\x80\x46\x8a\x46.\x48") usbdl_put_word = find_binary(data, b"\x2D\xE9\xF8\x4F\x80\x46\x8a\x46.\x48")
usbdl_ptr = None usbdl_ptr = None
if usbdl_put_word: if usbdl_put_word:
mpos=(usbdl_put_word&0xFFFFF)+7 mpos = (usbdl_put_word & 0xFFFFF) + 7
offset, Rn = ldr_lit(mpos, offset, Rn = ldr_lit(mpos,
unpack("<H", data[mpos:mpos + 2])[0]) unpack("<H", data[mpos:mpos + 2])[0])
usbdl_ptr = (base | offset) usbdl_ptr = (base | offset)
@ -96,82 +95,82 @@ def main():
pos -= 0x4 pos -= 0x4
if pos is not None: if pos is not None:
pos += 1 pos += 1
send_usb_response=base|pos send_usb_response = base | pos
pos = find_binary(data, b"\x10\xB5.\xF0...\x46", 0) pos = find_binary(data, b"\x10\xB5.\xF0...\x46", 0)
if pos is None: if pos is None:
pos = find_binary(data, b"\xB5.\xF0...\x49", 0) pos = find_binary(data, b"\xB5.\xF0...\x49", 0)
if pos is not None: if pos is not None:
pos-=1 pos -= 1
else: else:
pos2 = find_binary(data, "46FFF7", pos + 8) pos2 = find_binary(data, "46FFF7", pos + 8)
if pos2 != None: if pos2 is not None:
if pos2 - pos < 0x20: if pos2 - pos < 0x20:
pos = pos pos = pos
else: else:
pos = pos2 - 1 pos = pos2 - 1
posr = -1 posr = -1
startpos = 0 startpos = 0
while posr != None: while posr is not None:
posr = find_binary(data, "2DE9F047", startpos) posr = find_binary(data, "2DE9F047", startpos)
if posr == None: if posr is None:
break break
if data[posr + 7] == 0x46 and data[posr + 8] == 0x92: if data[posr + 7] == 0x46 and data[posr + 8] == 0x92:
break break
startpos = posr + 2 startpos = posr + 2
pattern = b"\xB5.\xF0" pattern = b"\xB5.\xF0"
sla=None sla = None
if pos is not None: if pos is not None:
sbcpos = pos sbcpos = pos
print("sbc:\t\t\t\t\t\t0x%08X" % (base|pos)) print("sbc:\t\t\t\t\t\t0x%08X" % (base | pos))
pos = find_binary(data, pattern, pos + 8) pos = find_binary(data, pattern, pos + 8)
if pos is not None: if pos is not None:
pos -= 1 pos -= 1
print("sla:\t\t\t\t\t\t0x%08X" % (base|pos)) print("sla:\t\t\t\t\t\t0x%08X" % (base | pos))
sla=pos sla = pos
if pos is not None: if pos is not None:
pos = find_binary(data, pattern, ((base|pos) + 2)) pos = find_binary(data, pattern, ((base | pos) + 2))
if pos is not None: if pos is not None:
pos -= 1 pos -= 1
print("daa:\t\t\t\t\t\t0x%08X" % (base|pos)) print("daa:\t\t\t\t\t\t0x%08X" % (base | pos))
sec_mode=None sec_mode = None
sec_sbc=None sec_sbc = None
if sla is not None: if sla is not None:
if data[sla+9]&0xF0==0x60: if data[sla + 9] & 0xF0 == 0x60:
offset, Rn = ldr_lit(sla + 6, offset, Rn = ldr_lit(sla + 6,
unpack("<H", data[sla + 6:sla + 6 + 2])[0]) unpack("<H", data[sla + 6:sla + 6 + 2])[0])
sec_sbc=unpack("<I",data[offset:offset+4])[0] sec_sbc = unpack("<I", data[offset:offset + 4])[0]
if data[sla+8]==0x51: if data[sla + 8] == 0x51:
sec_sbc+=4 sec_sbc += 4
sec_mode=0 sec_mode = 0
else: else:
mpos = find_binary(data, "48C16809B1", 0) mpos = find_binary(data, "48C16809B1", 0)
if mpos is not None: if mpos is not None:
mpos-=1 mpos -= 1
sec_mode = 1 sec_mode = 1
offset, Rn = ldr_lit(mpos, offset, Rn = ldr_lit(mpos,
unpack("<H", data[mpos:mpos+2])[0]) unpack("<H", data[mpos:mpos + 2])[0])
rbase=unpack("<I",data[offset:offset+4])[0] rbase = unpack("<I", data[offset:offset + 4])[0]
simm5, sRt, sRn = ldr_imm(unpack("<H", data[mpos+2:mpos + 4])[0]) simm5, sRt, sRn = ldr_imm(unpack("<H", data[mpos + 2:mpos + 4])[0])
sec_sbc = (rbase+(simm5*4)) sec_sbc = (rbase + (simm5 * 4))
instr=unpack("<H", data[sla+0x12:sla+0x12+2])[0] instr = unpack("<H", data[sla + 0x12:sla + 0x12 + 2])[0]
offset, Rn = ldr_lit(sla+0x12,instr) offset, Rn = ldr_lit(sla + 0x12, instr)
rbase=unpack("<I",data[offset:offset+4])[0] rbase = unpack("<I", data[offset:offset + 4])[0]
simm5, sRt, sRn = ldr_imm(unpack("<H", data[sla+0x12+2:sla+0x12 + 4])[0]) simm5, sRt, sRn = ldr_imm(unpack("<H", data[sla + 0x12 + 2:sla + 0x12 + 4])[0])
sec_sla = (rbase + (simm5 * 4)) sec_sla = (rbase + (simm5 * 4))
func_wdt=None func_wdt = None
func_acm=None func_acm = None
pos = find_binary(data, "70B50646A648", 0) pos = find_binary(data, "70B50646A648", 0)
if pos is not None: if pos is not None:
pos += 1 pos += 1
func_acm = base|pos func_acm = base | pos
pos = find_binary(data, "0F4941F6", 0) pos = find_binary(data, "0F4941F6", 0)
if pos is None: if pos is None:
pos = find_binary(data, "124941F6", 0) pos = find_binary(data, "124941F6", 0)
if pos is not None: if pos is not None:
pos += 1 pos += 1
func_wdt=base|pos func_wdt = base | pos
pos = find_binary(data, "F8B50024", 0) pos = find_binary(data, "F8B50024", 0)
if pos is None: if pos is None:
@ -187,8 +186,8 @@ def main():
usb_buffer = unpack("<I", data[offset:offset + 4])[0] usb_buffer = unpack("<I", data[offset:offset + 4])[0]
break break
vulnaddr=None vulnaddr = None
var1=None var1 = None
pos = find_binary(data, b"\xA1..\xD0\x21", 0) pos = find_binary(data, b"\xA1..\xD0\x21", 0)
if pos is not None: if pos is not None:
for i in range(0, 0x100, 2): for i in range(0, 0x100, 2):
@ -209,7 +208,8 @@ def main():
unpack("<H", data[vuln_ctrl_handler + i:vuln_ctrl_handler + i + 2])[0]) unpack("<H", data[vuln_ctrl_handler + i:vuln_ctrl_handler + i + 2])[0])
vulnaddr = unpack("<I", data[offset:offset + 4])[0] vulnaddr = unpack("<I", data[offset:offset + 4])[0]
if data[vuln_ctrl_handler + i + 1] == 0x6A and usb_buffer != 0: if data[vuln_ctrl_handler + i + 1] == 0x6A and usb_buffer != 0:
simm5, sRt, sRn = ldr_imm(unpack("<H", data[vuln_ctrl_handler + i:vuln_ctrl_handler + i + 2])[0]) simm5, sRt, sRn = ldr_imm(
unpack("<H", data[vuln_ctrl_handler + i:vuln_ctrl_handler + i + 2])[0])
vulnoff = (simm5 * 4) vulnoff = (simm5 * 4)
var1 = (usb_buffer - vulnaddr - vulnoff) / 0x34 var1 = (usb_buffer - vulnaddr - vulnoff) / 0x34
if int(var1) != var1: if int(var1) != var1:
@ -225,19 +225,19 @@ def main():
pos = find_binary(data, b"\x10\xB5..\xF4.\x00\x21", 0) pos = find_binary(data, b"\x10\xB5..\xF4.\x00\x21", 0)
if pos is not None: if pos is not None:
pos += 1 pos += 1
cmd_handler=base|pos cmd_handler = base | pos
uart_info = None uart_info = None
pos = find_binary(data, "10B5114A") pos = find_binary(data, "10B5114A")
if pos is not None: if pos is not None:
uart_info=pos uart_info = pos
uart_addr = None uart_addr = None
pos = find_binary(data, "315F454E930F0E00") pos = find_binary(data, "315F454E930F0E00")
if pos is None: if pos is None:
pos = find_binary(data, "0070315F454E00") pos = find_binary(data, "0070315F454E00")
if pos is not None: if pos is not None:
pos+=6 pos += 6
uart_addr = unpack("<I", data[pos:pos + 4])[0] uart_addr = unpack("<I", data[pos:pos + 4])[0]
else: else:
pos += 8 pos += 8
@ -266,8 +266,8 @@ def main():
pos += 8 pos += 8
instr = unpack("<H", data[pos:pos + 2])[0] instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr) offset, Rn = ldr_lit(pos, instr)
blacklist_ptr = unpack("<I", data[offset:offset + 4])[0]&0xFFFFF blacklist_ptr = unpack("<I", data[offset:offset + 4])[0] & 0xFFFFF
blacklist = unpack("<I", data[blacklist_ptr-4:blacklist_ptr-4 + 4])[0] blacklist = unpack("<I", data[blacklist_ptr - 4:blacklist_ptr - 4 + 4])[0]
else: else:
pos += 10 pos += 10
else: else:
@ -282,16 +282,16 @@ def main():
pos = find_binary(data, b"\x02\x4A\x02\x60") pos = find_binary(data, b"\x02\x4A\x02\x60")
if pos is not None: if pos is not None:
pos += 4 pos += 4
blacklistcount = unpack("<H", data[pos:pos + 2])[0]&0xF blacklistcount = unpack("<H", data[pos:pos + 2])[0] & 0xF
blacklist2 = None blacklist2 = None
pos = find_binary(data, b"\x10\xB5..\xD2\xF8\x90\x30\x10\x32") pos = find_binary(data, b"\x10\xB5..\xD2\xF8\x90\x30\x10\x32")
if pos is not None: if pos is not None:
pos+=2 pos += 2
instr = unpack("<H", data[pos:pos + 2])[0] instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr) offset, Rn = ldr_lit(pos, instr)
bl2 = unpack("<I", data[offset:offset + 4])[0] bl2 = unpack("<I", data[offset:offset + 4])[0]
blacklist2 = bl2+0x90 blacklist2 = bl2 + 0x90
pos = 0 pos = 0
memread = None memread = None
@ -314,14 +314,13 @@ def main():
payload_addr = unpack("<I", data[pos:pos + 4])[0] payload_addr = unpack("<I", data[pos:pos + 4])[0]
break break
coffs=(usbdl_put_data&0xFFFFF)+1 coffs = (usbdl_put_data & 0xFFFFF) + 1
try: try:
offset, Rn = ldr_lit(coffs, offset, Rn = ldr_lit(coffs,
unpack("<H", data[coffs:coffs + 2])[0]) unpack("<H", data[coffs:coffs + 2])[0])
except: except:
print("Err:"+sys.argv[1]) print("Err:" + sys.argv[1])
send_ptr_offset=offset send_ptr = unpack("<I", data[offset:offset + 4])[0] + 8
send_ptr=unpack("<I",data[offset:offset+4])[0]+8
send_ptr_offset = base | offset send_ptr_offset = base | offset
ctrl_addr = None ctrl_addr = None
pos = find_binary(data, "41434D2043") pos = find_binary(data, "41434D2043")
@ -329,7 +328,6 @@ def main():
pos -= 0x10 pos -= 0x10
ctrl_addr = unpack("<I", data[pos:pos + 4])[0] ctrl_addr = unpack("<I", data[pos:pos + 4])[0]
socid_addr = None socid_addr = None
pos = find_binary(data, "10B501212020FF") pos = find_binary(data, "10B501212020FF")
if pos is not None: if pos is not None:
@ -346,18 +344,18 @@ def main():
offset, Rn = ldr_lit(pos, instr) offset, Rn = ldr_lit(pos, instr)
meid_addr = unpack("<I", data[offset:offset + 4])[0] meid_addr = unpack("<I", data[offset:offset + 4])[0]
brom_register_access=None brom_register_access = None
brom_register_access_ptr=None brom_register_access_ptr = None
pos2 = find_binary(data, "2DE9F04100244FF001") pos2 = find_binary(data, "2DE9F04100244FF001")
if pos2 is not None: if pos2 is not None:
brom_register_access = base|pos2 brom_register_access = base | pos2
pos = find_binary(data, b"\xA9\x07.\x48", pos2) pos = find_binary(data, b"\xA9\x07.\x48", pos2)
if pos is not None: if pos is not None:
pos += 2 pos += 2
instr = unpack("<H", data[pos:pos + 2])[0] instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr) offset, Rn = ldr_lit(pos, instr)
brom_register_access_ptr=base|pos2 brom_register_access_ptr = base | pos2
brom_register_access_ptr_offset=base|offset brom_register_access_ptr_offset = base | offset
else: else:
pos = find_binary(data, "194D1B49", pos2) pos = find_binary(data, "194D1B49", pos2)
if pos is not None: if pos is not None:
@ -379,7 +377,7 @@ def main():
print("*sec_mode:\t\t\t\t\t0x%08X" % sec_mode) print("*sec_mode:\t\t\t\t\t0x%08X" % sec_mode)
if sec_sbc: if sec_sbc:
print("*sec_sbc:\t\t\t\t\t0x%08X" % sec_sbc) print("*sec_sbc:\t\t\t\t\t0x%08X" % sec_sbc)
if sec_mode==1: if sec_mode == 1:
print("*sec_sla:\t\t\t\t\t0x%08X" % sec_sla) print("*sec_sla:\t\t\t\t\t0x%08X" % sec_sla)
print("*func_usb_buffer:\t\t\t0x%08X" % (func_usb_buffer + 1 | base)) print("*func_usb_buffer:\t\t\t0x%08X" % (func_usb_buffer + 1 | base))
print("usb_buffer:\t\t\t\t\t0x%08X" % usb_buffer) print("usb_buffer:\t\t\t\t\t0x%08X" % usb_buffer)
@ -394,7 +392,7 @@ def main():
if usbdl_ptr: if usbdl_ptr:
print("usbdl_ptr:\t\t\t\t\t\t0x%08X" % usbdl_ptr) print("usbdl_ptr:\t\t\t\t\t\t0x%08X" % usbdl_ptr)
else: else:
print("Uhoh: "+sys.argv[1]) print("Uhoh: " + sys.argv[1])
if memread: if memread:
print("memread:\t\t\t\t\t0x%08X" % memread) print("memread:\t\t\t\t\t0x%08X" % memread)
if payload_addr: if payload_addr:
@ -422,26 +420,27 @@ def main():
if cmd_handler: if cmd_handler:
print("*cmd_handler:\t\t\t\t0x%08X" % cmd_handler) print("*cmd_handler:\t\t\t\t0x%08X" % cmd_handler)
if brom_register_access_ptr: if brom_register_access_ptr:
print(f"brom_register_access_ptr:\t\t\t\t\t({hex(brom_register_access_ptr)},{hex(brom_register_access_ptr_offset)}),") print(
f"brom_register_access_ptr:\t\t\t\t\t({hex(brom_register_access_ptr)},{hex(brom_register_access_ptr_offset)}),")
if meid_addr: if meid_addr:
print(f"meid_addr:\t\t\t\t\t{hex(meid_addr)}") print(f"meid_addr:\t\t\t\t\t{hex(meid_addr)}")
if socid_addr: if socid_addr:
print(f"socid_addr:\t\t\t\t\t{hex(socid_addr)}") print(f"socid_addr:\t\t\t\t\t{hex(socid_addr)}")
print("da_range:\t\t\t\t\t0x%08X" % offset) print("da_range:\t\t\t\t\t0x%08X" % offset)
if sec_mode==1: if sec_mode == 1:
sec_offset=0x28 sec_offset = 0x28
else: else:
sec_offset=0x40 sec_offset = 0x40
sec_sla=0 sec_sla = 0
if blacklist2 is None: if blacklist2 is None:
blacklist2 = 0 blacklist2 = 0
import os import os
socname=os.path.basename(sys.argv[1]).replace(".bin","")[:6] socname = os.path.basename(sys.argv[1]).replace(".bin", "")[:6]
try: try:
if usbdl_ptr: if usbdl_ptr:
header =f""" header = f"""
#include <inttypes.h> #include <inttypes.h>
#define PAYLOAD_2_0 #define PAYLOAD_2_0
char SOC_NAME[] = "{socname}"; char SOC_NAME[] = "{socname}";
@ -455,7 +454,7 @@ volatile uint32_t **SEC_REG2=(volatile uint32_t **){hex(sec_sla)};
volatile uint32_t SEC_OFFSET={hex(sec_offset)}; volatile uint32_t SEC_OFFSET={hex(sec_offset)};
volatile uint32_t *bladdr=(volatile uint32_t *){hex(blacklist)}; volatile uint32_t *bladdr=(volatile uint32_t *){hex(blacklist)};
volatile uint32_t *bladdr2=(volatile uint32_t *){hex(blacklist2)}; volatile uint32_t *bladdr2=(volatile uint32_t *){hex(blacklist2)};
volatile uint32_t *uart_reg0 = (volatile uint32_t*){hex(uart_addr+0x14)}; volatile uint32_t *uart_reg0 = (volatile uint32_t*){hex(uart_addr + 0x14)};
volatile uint32_t *uart_reg1 = (volatile uint32_t*){hex(uart_addr)}; volatile uint32_t *uart_reg1 = (volatile uint32_t*){hex(uart_addr)};
int (*cmd_handler)() = (void*){hex(cmd_handler)}; int (*cmd_handler)() = (void*){hex(cmd_handler)};
@ -464,9 +463,10 @@ int (*cmd_handler)() = (void*){hex(cmd_handler)};
print(header) print(header)
if not os.path.exists("headers"): if not os.path.exists("headers"):
os.mkdir("headers") os.mkdir("headers")
open(os.path.join("headers",socname+".h"),"w").write(header) open(os.path.join("headers", socname + ".h"), "w").write(header)
except: except:
print(sys.argv[1]) print(sys.argv[1])
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -6,6 +6,7 @@ from struct import unpack
from mtkclient.config.payloads import pathconfig from mtkclient.config.payloads import pathconfig
from mtkclient.Library.utils import read_object from mtkclient.Library.utils import read_object
from mtkclient.Library.utils import find_binary from mtkclient.Library.utils import find_binary
entry_region = [ entry_region = [
('m_buf', 'I'), ('m_buf', 'I'),
('m_len', 'I'), ('m_len', 'I'),
@ -27,7 +28,8 @@ DA = [
# vector<entry_region> LoadRegion # vector<entry_region> LoadRegion
] ]
efusedb={} efusedb = {}
def main(): def main():
da_setup = [] da_setup = []
@ -54,7 +56,8 @@ def main():
da.append(entry_tmp) da.append(entry_tmp)
da_setup.append(da) da_setup.append(da)
print(f"Loader: {os.path.basename(loader)}") print(f"Loader: {os.path.basename(loader)}")
dadb[da[0]["hw_code"]]=[("da_payload_addr",da[2]["m_start_addr"]),("pl_payload_addr", da[3]["m_start_addr"])] dadb[da[0]["hw_code"]] = [("da_payload_addr", da[2]["m_start_addr"]),
("pl_payload_addr", da[3]["m_start_addr"])]
print("hwcode: 0x%04X" % da[0]["hw_code"]) print("hwcode: 0x%04X" % da[0]["hw_code"])
print("hw_sub_code: 0x%04X" % da[0]["hw_sub_code"]) print("hw_sub_code: 0x%04X" % da[0]["hw_sub_code"])
print("hw_version: 0x%04X" % da[0]["hw_version"]) print("hw_version: 0x%04X" % da[0]["hw_version"])
@ -62,56 +65,60 @@ def main():
print("Reserved1: 0x%04X" % da[0]["reserved1"]) print("Reserved1: 0x%04X" % da[0]["reserved1"])
print("Reserved3: 0x%04X" % da[0]["reserved3"]) print("Reserved3: 0x%04X" % da[0]["reserved3"])
for i in range(da[0]["entry_region_count"]): for i in range(da[0]["entry_region_count"]):
entry=da[i+1] entry = da[i + 1]
print(f"\t{i}: "+hex(entry['m_start_addr'])) print(f"\t{i}: {hex(entry['m_start_addr'])}")
mbuf=da[3]["m_buf"] mbuf = da[3]["m_buf"]
m_len=da[3]["m_len"] m_len = da[3]["m_len"]
startaddr=da[3]["m_start_addr"] startaddr = da[3]["m_start_addr"]
with open(loader,"rb") as rf: with open(loader, "rb") as rf:
rf.seek(mbuf) rf.seek(mbuf)
da2data=rf.read(m_len) da2data = rf.read(m_len)
fname=os.path.join("loaders",hex(da[0]["hw_code"])[2:]+"_"+hex(startaddr)[2:]+os.path.basename(loader)) fname = os.path.join("loaders",
open(fname,"wb").write(da2data) hex(da[0]["hw_code"])[2:] + "_" + hex(startaddr)[2:] + os.path.basename(
mbuf=da[2]["m_buf"] loader))
m_len=da[2]["m_len"] open(fname, "wb").write(da2data)
startaddr=da[2]["m_start_addr"] mbuf = da[2]["m_buf"]
m_len = da[2]["m_len"]
startaddr = da[2]["m_start_addr"]
sys.stdout.flush() sys.stdout.flush()
with open(loader,"rb") as rf: with open(loader, "rb") as rf:
rf.seek(mbuf) rf.seek(mbuf)
data=rf.read(m_len) data = rf.read(m_len)
hashidx=data.find(int.to_bytes(0xC0070004,4,'little')) hashidx = data.find(int.to_bytes(0xC0070004, 4, 'little'))
if hashidx!=-1: if hashidx != -1:
print("Hash check found.") print("Hash check found.")
else: else:
hashidx = data.find(b"\xCC\xF2\x07\x09") # => b"\x4F\xF0\x00\x09"" hashidx = data.find(b"\xCC\xF2\x07\x09") # => b"\x4F\xF0\x00\x09""
if hashidx != -1: if hashidx != -1:
print("Hash check 2 found.") print("Hash check 2 found.")
else: else:
hashidx = find_binary(data,b"\x14\x2C\xF6.\xFE\xE7") # => b"\x14\x2C\xF6\xD1\x00\x00" hashidx = find_binary(data, b"\x14\x2C\xF6.\xFE\xE7") # => b"\x14\x2C\xF6\xD1\x00\x00"
if hashidx is not None: if hashidx is not None:
print("Hash check 3 found.") print("Hash check 3 found.")
else: else:
print("HASH ERROR !!!!") print("HASH ERROR !!!!")
fname=os.path.join("loaders",hex(da[0]["hw_code"])[2:]+"_"+hex(startaddr)[2:]+os.path.basename(loader)) fname = os.path.join("loaders",
open(fname,"wb").write(data) hex(da[0]["hw_code"])[2:] + "_" + hex(startaddr)[2:] + os.path.basename(
loader))
open(fname, "wb").write(data)
print(f"Offset: {hex(mbuf)}") print(f"Offset: {hex(mbuf)}")
print(f"Length: {hex(m_len)}") print(f"Length: {hex(m_len)}")
print(f"Addr: {hex(startaddr)}") print(f"Addr: {hex(startaddr)}")
bootldr.seek(da[2]["m_buf"]) bootldr.seek(da[2]["m_buf"])
tt=bootldr.read(da[2]["m_len"]) tt = bootldr.read(da[2]["m_len"])
idx = tt.find(bytes.fromhex("70BB442D27D244A7")) idx = tt.find(bytes.fromhex("70BB442D27D244A7"))
#idx = tt.find(bytes.fromhex("01279360D36013615361")) #idx = tt.find(bytes.fromhex("01279360D36013615361"))
if idx!=-1: if idx != -1:
print("V3 Enabled") print("V3 Enabled")
bootldr.seek(da[3]["m_buf"]) bootldr.seek(da[3]["m_buf"])
tt=bootldr.read(da[3]["m_len"]) tt = bootldr.read(da[3]["m_len"])
idx2 = tt.find(bytes.fromhex("03 29 0D D9 07 4B 1B 68 03 60")) idx2 = tt.find(bytes.fromhex("03 29 0D D9 07 4B 1B 68 03 60"))
if idx2!=-1: if idx2 != -1:
efusedb[da[0]["hw_code"]]=hex(int.from_bytes(tt[idx2+0x24:idx2+0x28],'little')&0xFFFFF000) efusedb[da[0]["hw_code"]] = hex(int.from_bytes(tt[idx2 + 0x24:idx2 + 0x28], 'little') & 0xFFFFF000)
else: else:
if not da[0]["hw_code"] in efusedb: if not da[0]["hw_code"] in efusedb:
efusedb[da[0]["hw_code"]]="None" efusedb[da[0]["hw_code"]] = "None"
print() print()
sorted_dict = dict(sorted(efusedb.items())) sorted_dict = dict(sorted(efusedb.items()))
@ -135,5 +142,6 @@ def main():
print(str(idx)+" "+name+": "+hex(fields[2])) print(str(idx)+" "+name+": "+hex(fields[2]))
""" """
if __name__=="__main__":
main() if __name__ == "__main__":
main()

View file

@ -1,2 +1,2 @@
#!/bin/bash #!/bin/bash
for i in `find ./bootrom -name "*.bin"|sort`;do ./mtkclient/Tools/brom_to_offs $i;done for i in $(find ./bootrom -name "*.bin"|sort);do ./mtkclient/Tools/brom_to_offs "$i";done

View file

@ -334,7 +334,7 @@ def hook_mem_write(uc, access, address, size, value, user_data):
elif address == 0x11020000: elif address == 0x11020000:
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
if r0 == 0xa: if r0 == 0xa:
print("UART: " + buffer.decode('utf-8')) print(f"UART: {buffer.decode('utf-8')}")
data += buffer.decode('utf-8') data += buffer.decode('utf-8')
buffer = bytearray() buffer = bytearray()
else: else:
@ -343,7 +343,7 @@ def hook_mem_write(uc, access, address, size, value, user_data):
elif address == 0x11050000: elif address == 0x11050000:
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
if r0 == 0xd: if r0 == 0xd:
print("UART: " + buffer.decode('utf-8')) print(f"UART: {buffer.decode('utf-8')}")
data += buffer.decode('utf-8') data += buffer.decode('utf-8')
buffer = bytearray() buffer = bytearray()
else: else:
@ -352,7 +352,7 @@ def hook_mem_write(uc, access, address, size, value, user_data):
elif address == 0x11002000: elif address == 0x11002000:
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
if r0 == 0xa: if r0 == 0xa:
print("UART: " + buffer.decode('utf-8')) print(f"UART: {buffer.decode('utf-8')}")
data += buffer.decode('utf-8') data += buffer.decode('utf-8')
buffer = bytearray() buffer = bytearray()
else: else:
@ -361,7 +361,7 @@ def hook_mem_write(uc, access, address, size, value, user_data):
elif address == 0x11003000: elif address == 0x11003000:
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
if r0 == 0xa: if r0 == 0xa:
print("UART: " + buffer.decode('utf-8')) print(f"UART: {buffer.decode('utf-8')}")
data += buffer.decode('utf-8') data += buffer.decode('utf-8')
buffer = bytearray() buffer = bytearray()
else: else:
@ -370,7 +370,7 @@ def hook_mem_write(uc, access, address, size, value, user_data):
elif address == 0x11005000: elif address == 0x11005000:
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
if r0 == 0xa: if r0 == 0xa:
print("UART: " + buffer.decode('utf-8')) print(f"UART: {buffer.decode('utf-8')}")
data += buffer.decode('utf-8') data += buffer.decode('utf-8')
buffer = bytearray() buffer = bytearray()
else: else:
@ -389,61 +389,61 @@ def hook_code(uc, access, address, size):
keyslot0 = uc.mem_read(0x701953CC, 0x20) keyslot0 = uc.mem_read(0x701953CC, 0x20)
keyslot1 = uc.mem_read(0x701953EC, 0x20) keyslot1 = uc.mem_read(0x701953EC, 0x20)
keyslot2 = uc.mem_read(0x7019540C, 0x20) keyslot2 = uc.mem_read(0x7019540C, 0x20)
print("Keyslot0: " + hexlify(keyslot0).decode('utf-8')) print(f"Keyslot0: {hexlify(keyslot0).decode('utf-8')}")
print("Keyslot1: " + hexlify(keyslot1).decode('utf-8')) print(f"Keyslot1: {hexlify(keyslot1).decode('utf-8')}")
print("Keyslot2: " + hexlify(keyslot2).decode('utf-8')) print(f"Keyslot2: {hexlify(keyslot2).decode('utf-8')}")
elif pc == 0x70094A5C: # sha256_write elif pc == 0x70094A5C: # sha256_write
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
r1 = uc.reg_read(UC_ARM_REG_R1) r1 = uc.reg_read(UC_ARM_REG_R1)
r2 = uc.reg_read(UC_ARM_REG_R2) r2 = uc.reg_read(UC_ARM_REG_R2)
s1 = uc.mem_read(r1, r2) s1 = uc.mem_read(r1, r2)
print("sha256_write") print("sha256_write")
print("lr: " + hex(lr)) print(f"lr: {hex(lr)}")
print(f"r1: {hex(r1)} " + hexlify(s1).decode('utf-8')) print(f"r1: {hex(r1)} {hexlify(s1).decode('utf-8')}")
print("r2: " + hex(r2) + "\n") print(f"r2: {hex(r2)}\n")
elif pc == 0x70094E3C: # kdflib_get_huk elif pc == 0x70094E3C: # kdflib_get_huk
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
print("kdflib_get_huk") print("kdflib_get_huk")
print("klr: " + hex(lr)) print(f"klr: {hex(lr)}")
print("kr0: " + hex(r0)) print(f"kr0: {hex(r0)}")
elif pc == 0x70095240: elif pc == 0x70095240:
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
r4 = uc.reg_read(UC_ARM_REG_R4) r4 = uc.reg_read(UC_ARM_REG_R4)
print("hmac_sha256") print("hmac_sha256")
print("hlr: " + hex(lr)) print(f"hlr: {hex(lr)}")
print("hr0: " + hex(r0)) print(f"hr0: {hex(r0)}")
print("hr4: " + hex(r4)) print(f"hr4: {hex(r4)}")
elif pc == 0x70087430: # memcpy elif pc == 0x70087430: # memcpy
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
r0 = uc.reg_read(UC_ARM_REG_R0) r0 = uc.reg_read(UC_ARM_REG_R0)
r1 = uc.reg_read(UC_ARM_REG_R0) r1 = uc.reg_read(UC_ARM_REG_R0)
r2 = uc.reg_read(UC_ARM_REG_R0) r2 = uc.reg_read(UC_ARM_REG_R0)
print("memcpy") print("memcpy")
print("lr: " + hex(lr)) print(f"lr: {hex(lr)}")
print("r0: " + hex(r0)) print(f"r0: {hex(r0)}")
print("r1: " + hex(r1)) print(f"r1: {hex(r1)}")
print("r2: " + hex(r2)) print(f"r2: {hex(r2)}")
elif pc == 0x70095084: elif pc == 0x70095084:
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
print("hmac_init") print("hmac_init")
print("lr: " + hex(lr)) print(f"lr: {hex(lr)}")
elif pc == 0x70094CF8: elif pc == 0x70094CF8:
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
r1 = uc.reg_read(UC_ARM_REG_R1) r1 = uc.reg_read(UC_ARM_REG_R1)
debug = r1 debug = r1
print("sha_finish") print("sha_finish")
print("lr: " + hex(lr)) print(f"lr: {hex(lr)}")
print("r1: " + hex(r1)) print(f"r1: {hex(r1)}")
elif pc == 0x70094DB8: elif pc == 0x70094DB8:
lr = uc.reg_read(UC_ARM_REG_LR) lr = uc.reg_read(UC_ARM_REG_LR)
r1 = debug r1 = debug
s1 = uc.mem_read(r1, 0x20) s1 = uc.mem_read(r1, 0x20)
print("sha_finish2") print("sha_finish2")
print("lr: " + hex(lr)) print(f"lr: {hex(lr)}")
print("r1: " + hex(r1)) print(f"r1: {hex(r1)}")
print("s1: " + hexlify(s1).decode('utf-8')) print(f"s1: {hexlify(s1).decode('utf-8')}")
# print("PC %08X" % pc) # print("PC %08X" % pc)
return True return True

View file

@ -96,18 +96,6 @@ class EraseFlashWindow(QObject):
thread.wait() thread.wait()
self.enableButtonsSignal.emit() self.enableButtonsSignal.emit()
def eraseBoot2(self):
self.eraseFlash("boot2")
return
def erasePreloader(self):
self.eraseFlash("boot1")
return
def eraseRpmb(self):
self.eraseFlash("rpmb")
return
def erasePartitionAsync(self, toolkit, parameters): def erasePartitionAsync(self, toolkit, parameters):
self.parent.timeEst.init() self.parent.timeEst.init()
self.parent.timeEstTotal.init() self.parent.timeEstTotal.init()

View file

@ -314,13 +314,13 @@ class Ui_MainWindow(object):
self.gridLayout_2 = QGridLayout(self.keytab) self.gridLayout_2 = QGridLayout(self.keytab)
self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout_2.setObjectName(u"gridLayout_2")
self.keytable = QTableWidget(self.keytab) self.keytable = QTableWidget(self.keytab)
if (self.keytable.columnCount() < 2): if self.keytable.columnCount() < 2:
self.keytable.setColumnCount(2) self.keytable.setColumnCount(2)
__qtablewidgetitem = QTableWidgetItem() __qtablewidgetitem = QTableWidgetItem()
self.keytable.setHorizontalHeaderItem(0, __qtablewidgetitem) self.keytable.setHorizontalHeaderItem(0, __qtablewidgetitem)
__qtablewidgetitem1 = QTableWidgetItem() __qtablewidgetitem1 = QTableWidgetItem()
self.keytable.setHorizontalHeaderItem(1, __qtablewidgetitem1) self.keytable.setHorizontalHeaderItem(1, __qtablewidgetitem1)
if (self.keytable.rowCount() < 7): if self.keytable.rowCount() < 7:
self.keytable.setRowCount(7) self.keytable.setRowCount(7)
__qtablewidgetitem2 = QTableWidgetItem() __qtablewidgetitem2 = QTableWidgetItem()
self.keytable.setVerticalHeaderItem(0, __qtablewidgetitem2) self.keytable.setVerticalHeaderItem(0, __qtablewidgetitem2)

View file

@ -10,14 +10,14 @@ from mtkclient.config.payloads import pathconfig
class TimeEstim: class TimeEstim:
def calcProcessTime(self, starttime, cur_iter, max_iter): @staticmethod
def calcProcessTime(starttime, cur_iter, max_iter):
telapsed = time.time() - starttime telapsed = time.time() - starttime
if telapsed > 0 and cur_iter > 0: if telapsed > 0 and cur_iter > 0:
testimated = (telapsed / cur_iter) * max_iter testimated = (telapsed / cur_iter) * max_iter
finishtime = starttime + testimated finishtime = starttime + testimated
finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time finishtime = dt.datetime.fromtimestamp(finishtime).strftime("%H:%M:%S") # in time
lefttime = testimated - telapsed # in seconds return int(telapsed), int(testimated - telapsed), finishtime
return int(telapsed), int(lefttime), finishtime
else: else:
return 0, 0, "" return 0, 0, ""
@ -34,14 +34,14 @@ class TimeEstim:
if lefttime > 0: if lefttime > 0:
sec = lefttime sec = lefttime
if sec > 60: if sec > 60:
min = sec // 60 minutes = sec // 60
sec = sec % 60 sec = sec % 60
if min > 60: if minutes > 60:
h = min // 24 h = minutes // 24
min = min % 24 minutes = minutes % 24
hinfo = "%02dh:%02dm:%02ds" % (h, min, sec) hinfo = "%02dh:%02dm:%02ds" % (h, minutes, sec)
else: else:
hinfo = "%02dm:%02ds" % (min, sec) hinfo = "%02dm:%02ds" % (minutes, sec)
else: else:
hinfo = "%02ds" % sec hinfo = "%02ds" % sec
@ -97,7 +97,7 @@ def convert_size(size_bytes):
i = int(math.floor(math.log(size_bytes, 1024))) i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i) p = math.pow(1024, i)
s = round(size_bytes / p, 2) s = round(size_bytes / p, 2)
return "%s %s" % (s, size_name[i]) return f"{s} {size_name[i]}"
class asyncThread(QThread): class asyncThread(QThread):
@ -116,7 +116,7 @@ class asyncThread(QThread):
self.function(self, self.parameters) self.function(self, self.parameters)
class FDialog(): class FDialog:
def __init__(self, parent): def __init__(self, parent):
pc = pathconfig() pc = pathconfig()
self.parent = parent self.parent = parent

View file

@ -9,3 +9,5 @@ mock >= 4.0.3
pyserial >= 3.5 pyserial >= 3.5
flake8 flake8
fusepy fusepy
unicorn
capstone

240
stage2
View file

@ -17,6 +17,7 @@ from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto
from mtkclient.config.mtk_config import Mtk_Config from mtkclient.config.mtk_config import Mtk_Config
from mtkclient.config.usb_ids import default_ids from mtkclient.config.usb_ids import default_ids
class Stage2(metaclass=LogBase): class Stage2(metaclass=LogBase):
def __init__(self, args, loglevel=logging.INFO): def __init__(self, args, loglevel=logging.INFO):
self.__logger = self.__logger self.__logger = self.__logger
@ -40,8 +41,8 @@ class Stage2(metaclass=LogBase):
self.__logger.setLevel(logging.INFO) self.__logger.setLevel(logging.INFO)
self.cdc = usb_class(portconfig=default_ids, loglevel=loglevel, devclass=10) self.cdc = usb_class(portconfig=default_ids, loglevel=loglevel, devclass=10)
self.usbread=self.cdc.usbread self.usbread = self.cdc.usbread
self.usbwrite=self.cdc.usbwrite self.usbwrite = self.cdc.usbwrite
def preinit(self): def preinit(self):
try: try:
@ -98,11 +99,10 @@ class Stage2(metaclass=LogBase):
return result return result
def cmd_C8(self, val) -> bool: def cmd_C8(self, val) -> bool:
'Clear cache func' """Clear cache func"""
self.usbwrite(pack(">I", 0xf00dd00d)) self.usbwrite(pack(">I", 0xf00dd00d))
self.usbwrite(pack(">I", 0x5000)) self.usbwrite(pack(">I", 0x5000))
ack = self.usbread(4) if self.usbread(4) == b"\xD0\xD0\xD0\xD0":
if ack == b"\xD0\xD0\xD0\xD0":
return True return True
return False return False
@ -115,8 +115,7 @@ class Stage2(metaclass=LogBase):
self.usbwrite(pack(">I", addr + (pos * 4))) self.usbwrite(pack(">I", addr + (pos * 4)))
self.usbwrite(pack(">I", 4)) self.usbwrite(pack(">I", 4))
self.usbwrite(pack("<I", dwords[pos])) self.usbwrite(pack("<I", dwords[pos]))
ack = self.usbread(4) if self.usbread(4) == b"\xD0\xD0\xD0\xD0":
if ack == b"\xD0\xD0\xD0\xD0":
continue continue
else: else:
return False return False
@ -130,7 +129,7 @@ class Stage2(metaclass=LogBase):
if self.cdc.connected: if self.cdc.connected:
self.cdc.close() self.cdc.close()
def readflash(self, type: int, start, length, display=False, filename: str = None): def readflash(self, type_: int, start, length, display=False, filename: str = None):
if not self.emmc_inited: if not self.emmc_inited:
self.init_emmc() self.init_emmc()
wf = None wf = None
@ -144,7 +143,7 @@ class Stage2(metaclass=LogBase):
# emmc_switch(1) # emmc_switch(1)
self.usbwrite(pack(">I", 0xf00dd00d)) self.usbwrite(pack(">I", 0xf00dd00d))
self.usbwrite(pack(">I", 0x1002)) self.usbwrite(pack(">I", 0x1002))
self.usbwrite(pack(">I", type)) self.usbwrite(pack(">I", type_))
# kick-wdt # kick-wdt
# self.usbwrite(pack(">I", 0xf00dd00d)) # self.usbwrite(pack(">I", 0xf00dd00d))
@ -160,7 +159,7 @@ class Stage2(metaclass=LogBase):
self.usbwrite(pack(">I", sectors)) self.usbwrite(pack(">I", sectors))
if display: 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): for sector in range(sectors):
tmp = self.usbread(0x200) tmp = self.usbread(0x200)
@ -183,14 +182,13 @@ class Stage2(metaclass=LogBase):
else: else:
return buffer[start % 0x200:(start % 0x200) + length] 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 sectors = 0
if length != 0: if length != 0:
sectors = (length // 0x200) + (1 if length % 0x200 else 0) sectors = (length // 0x200) + (1 if length % 0x200 else 0)
self.info("Reading user data...") self.info("Reading user data...")
if self.cdc.connected: if self.cdc.connected:
self.readflash(type=0, start=start, length=length, display=True, filename=filename) self.readflash(type_=0, start=start, length=length, display=True, filename=filename)
def preloader(self, start, length, filename): def preloader(self, start, length, filename):
sectors = 0 sectors = 0
@ -201,7 +199,7 @@ class Stage2(metaclass=LogBase):
self.info("Reading preloader...") self.info("Reading preloader...")
if self.cdc.connected: if self.cdc.connected:
if sectors == 0: if sectors == 0:
buffer = self.readflash(type=1, start=0, length=0x4000, display=False) buffer = self.readflash(type_=1, start=0, length=0x4000, display=False)
if len(buffer) != 0x4000: if len(buffer) != 0x4000:
print("Error on reading boot1 area.") print("Error on reading boot1 area.")
return return
@ -212,7 +210,7 @@ class Stage2(metaclass=LogBase):
st = buffer[start:start + 4] st = buffer[start:start + 4]
if st == b"MMM\x01": if st == b"MMM\x01":
length = unpack("<I", buffer[start + 0x20:start + 0x24])[0] length = unpack("<I", buffer[start + 0x20:start + 0x24])[0]
data = self.readflash(type=1, start=0, length=start + length, display=True) data = self.readflash(type_=1, start=0, length=start + length, display=True)
if len(data) != start + length: if len(data) != start + length:
print("Warning, please rerun command, length doesn't match.") print("Warning, please rerun command, length doesn't match.")
idx = data.find(b"MTK_BLOADER_INFO") idx = data.find(b"MTK_BLOADER_INFO")
@ -220,19 +218,19 @@ class Stage2(metaclass=LogBase):
filename = data[idx + 0x1B:idx + 0x3D].rstrip(b"\x00").decode('utf-8') filename = data[idx + 0x1B:idx + 0x3D].rstrip(b"\x00").decode('utf-8')
with open(os.path.join("logs", filename), "wb") as wf: with open(os.path.join("logs", filename), "wb") as wf:
wf.write(data[start:start + length]) wf.write(data[start:start + length])
print("Done writing to " + os.path.join("logs", filename)) print(f"Done writing to {os.path.join('logs', filename)}")
with open(os.path.join("logs", "hdr_" + filename), "wb") as wf: with open(os.path.join("logs", "hdr_" + filename), "wb") as wf:
wf.write(data[:start]) wf.write(data[:start])
print("Done writing to " + os.path.join("logs", "hdr_" + filename)) print(f"Done writing to {os.path.join('logs', 'hdr_' + filename)}")
return return
else: else:
length = 0x40000 length = 0x40000
self.readflash(type=1, start=0, length=length, display=True, filename=filename) self.readflash(type_=1, start=0, length=length, display=True, filename=filename)
print("Done") print("Done")
print("Error on getting preloader info, aborting.") print("Error on getting preloader info, aborting.")
else: else:
self.readflash(type=1, start=start, length=length, display=True, filename=filename) self.readflash(type_=1, start=start, length=length, display=True, filename=filename)
print("Done") print("Done")
def boot2(self, start, length, filename): def boot2(self, start, length, filename):
@ -244,10 +242,10 @@ class Stage2(metaclass=LogBase):
self.info("Reading boot2...") self.info("Reading boot2...")
if self.cdc.connected: if self.cdc.connected:
if sectors == 0: if sectors == 0:
self.readflash(type=2, start=0, length=0x40000, display=True, filename=filename) self.readflash(type_=2, start=0, length=0x40000, display=True, filename=filename)
print("Done") print("Done")
else: else:
self.readflash(type=1, start=start, length=length, display=True, filename=filename) self.readflash(type_=1, start=start, length=length, display=True, filename=filename)
print("Done") print("Done")
def memread(self, start, length, filename=None): def memread(self, start, length, filename=None):
@ -269,7 +267,7 @@ class Stage2(metaclass=LogBase):
wf.write(self.usbread(size)) wf.write(self.usbread(size))
bytestoread -= size bytestoread -= size
pos += size pos += size
self.info(f"{hex(start)}: " + hexlify(data).decode('utf-8')) self.info(f"{hex(start)}: {hexlify(data).decode('utf-8')}")
if filename is not None: if filename is not None:
wf.close() wf.close()
return data return data
@ -318,8 +316,8 @@ class Stage2(metaclass=LogBase):
start = 0 start = 0
else: else:
start = (start // 0x100) start = (start // 0x100)
if start>0xFFFF: if start > 0xFFFF:
start=0xFFFF start = 0xFFFF
if length == 0: if length == 0:
sectors = 16 * 1024 * 1024 // 0x100 sectors = 16 * 1024 * 1024 // 0x100
else: else:
@ -339,8 +337,8 @@ class Stage2(metaclass=LogBase):
bytestoread = sectors * 0x100 bytestoread = sectors * 0x100
count = sectors count = sectors
pg = progress(pagesize=0x200) pg = progress(pagesize=0x200)
if sectors>0xFFFF: if sectors > 0xFFFF:
count=0xFFFF count = 0xFFFF
with open(filename, "wb") as wf: with open(filename, "wb") as wf:
self.usbwrite(pack(">I", 0xf00dd00d)) self.usbwrite(pack(">I", 0xf00dd00d))
self.usbwrite(pack(">I", 0x2000)) self.usbwrite(pack(">I", 0x2000))
@ -353,145 +351,135 @@ class Stage2(metaclass=LogBase):
if len(tmp) != 0x100: if len(tmp) != 0x100:
self.error("Error on getting data") self.error("Error on getting data")
return return
pg.show_progress(prefix="Progress:",pos=sector,total=sectors) pg.show_progress(prefix="Progress:", pos=sector, total=sectors)
bytesread += 0x100 bytesread += 0x100
size = min(bytestoread, len(tmp)) size = min(bytestoread, len(tmp))
wf.write(tmp[:size]) wf.write(tmp[:size])
bytestoread -= size bytestoread -= size
while bytestoread>0: while bytestoread > 0:
self.usbwrite(pack(">I", 0xf00dd00d)) self.usbwrite(pack(">I", 0xf00dd00d))
self.usbwrite(pack(">I", 0x2000)) self.usbwrite(pack(">I", 0x2000))
self.usbwrite(pack(">H", sector+1)) self.usbwrite(pack(">H", sector + 1))
self.usbwrite(pack(">H", 1)) self.usbwrite(pack(">H", 1))
tmp = self.usbread(0x100) tmp = self.usbread(0x100)
size = min(bytestoread, len(tmp)) size = min(bytestoread, len(tmp))
wf.write(tmp[:size]) wf.write(tmp[:size])
bytestoread -= size bytestoread -= size
pg.show_progress(prefix="Progress:", pos=sector, total=sectors) pg.show_progress(prefix="Progress:", pos=sector, total=sectors)
sector+=1 sector += 1
pg.show_progress(prefix="Progress:", pos=sectors, total=sectors) pg.show_progress(prefix="Progress:", pos=sectors, total=sectors)
print("Done") print("Done")
def keys(self, data=b"", otp=None, mode="dxcc"): def keys(self, data=b"", otp=None, mode="dxcc"):
# self.hwcrypto.disable_range_blacklist("cqdma",self.cmd_C8) # self.hwcrypto.disable_range_blacklist("cqdma",self.cmd_C8)
keyinfo="" keyinfo = ""
retval = {} retval = {}
meid = self.config.get_meid() meid = self.config.get_meid()
socid = self.config.get_socid() socid = self.config.get_socid()
if meid is not None: if meid is not None:
self.info("MEID : " + hexlify(meid).decode('utf-8')) self.info(f"MEID : {hexlify(meid).decode('utf-8')}")
else: else:
try: try:
if self.config.chipconfig.meid_addr is not None: if self.config.chipconfig.meid_addr is not None:
meid = self.memread(self.config.chipconfig.meid_addr, 16) meid = self.memread(self.config.chipconfig.meid_addr, 16)
self.config.set_meid(meid) self.config.set_meid(meid)
self.info("MEID : " + hexlify(meid).decode('utf-8')) self.info(f"MEID : {hexlify(meid).decode('utf-8')}")
retval["meid"] = hexlify(meid).decode('utf-8') retval["meid"] = hexlify(meid).decode('utf-8')
except Exception as err: except Exception as err:
pass pass
if socid is not None: if socid is not None:
self.info("SOCID : " + hexlify(socid).decode('utf-8')) self.info(f"SOCID : {hexlify(socid).decode('utf-8')}")
retval["socid"] = socid retval["socid"] = socid
else: else:
try: try:
if self.config.chipconfig.socid_addr is not None: if self.config.chipconfig.socid_addr is not None:
socid = self.memread(self.config.chipconfig.socid_addr, 32) socid = self.memread(self.config.chipconfig.socid_addr, 32)
self.config.set_socid(socid) self.config.set_socid(socid)
self.info("SOCID : " + hexlify(socid).decode('utf-8')) self.info(f"SOCID : {hexlify(socid).decode('utf-8')}")
retval["socid"] = hexlify(socid).decode('utf-8') retval["socid"] = hexlify(socid).decode('utf-8')
except Exception as err: except Exception as err:
pass 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"]: if self.setup.dxcc_base is not None and mode not in ["sej_aes_decrypt", "sej_aes_encrypt", "sej_sst_decrypt",
rpmbkey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="rpmb") "sej_sst_encrypt", "dxcc_sha256"]:
rpmbkey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="rpmb")
rpmb2key = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="rpmb2") rpmb2key = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="rpmb2")
fdekey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="fde") fdekey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="fde")
ikey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="itrustee") ikey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="itrustee")
platkey, provkey = self.hwcrypto.aes_hwcrypt(btype="dxcc",mode="prov") platkey, provkey = self.hwcrypto.aes_hwcrypt(btype="dxcc", mode="prov")
keyinfo+="\nKeys :\n-----------------------------------------\n" keyinfo += "\nKeys :\n-----------------------------------------\n"
keyinfo+="RPMB: " + hexlify(rpmbkey).decode('utf-8')+"\n" keyinfo += f"RPMB: {hexlify(rpmbkey).decode('utf-8')}\n"
keyinfo+="RPMB2: " + hexlify(rpmb2key).decode('utf-8') + "\n" keyinfo += f"RPMB2: {hexlify(rpmb2key).decode('utf-8')}\n"
keyinfo+="FDE : " + hexlify(fdekey).decode('utf-8')+"\n" keyinfo += f"FDE : {hexlify(fdekey).decode('utf-8')}\n"
keyinfo+="iTrustee: " + hexlify(ikey).decode('utf-8')+"\n" keyinfo += f"iTrustee: {hexlify(ikey).decode('utf-8')}\n"
keyinfo+="Platform: " + hexlify(platkey).decode('utf-8')+"\n" keyinfo += f"Platform: {hexlify(platkey).decode('utf-8')}\n"
keyinfo+="Provisioning: " + hexlify(provkey).decode('utf-8')+"\n" keyinfo += f"Provisioning: {hexlify(provkey).decode('utf-8')}\n"
keyinfo+="\n" keyinfo += "\n"
if rpmbkey is not None: if rpmbkey is not None:
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) self.info(f"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') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
if rpmb2key is not None: if rpmb2key is not None:
self.info("RPMB2 : " + hexlify(rpmb2key).decode('utf-8')) self.info(f"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') retval["rpmb2key"] = hexlify(rpmb2key).decode('utf-8')
if fdekey is not None: if fdekey is not None:
self.info("FDE : " + hexlify(fdekey).decode('utf-8')) self.info(f"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') retval["fdekey"] = hexlify(fdekey).decode('utf-8')
if ikey is not None: if ikey is not None:
self.info("iTrustee : " + hexlify(ikey).decode('utf-8')) self.info(f"iTrustee : {hexlify(ikey).decode('utf-8')}")
self.config.hwparam.writesetting("kmkey", hexlify(ikey).decode('utf-8')) self.config.hwparam.writesetting("kmkey", hexlify(ikey).decode('utf-8'))
retval["kmkey"] = hexlify(ikey).decode('utf-8') retval["kmkey"] = hexlify(ikey).decode('utf-8')
if self.config.chipconfig.prov_addr: if self.config.chipconfig.prov_addr:
provkey = self.memread(self.config.chipconfig.prov_addr, 16) provkey = self.memread(self.config.chipconfig.prov_addr, 16)
self.info("PROV : " + hexlify(provkey).decode('utf-8')) self.info(f"PROV : {hexlify(provkey).decode('utf-8')}")
self.config.hwparam.writesetting("provkey", hexlify(provkey).decode('utf-8')) self.config.hwparam.writesetting("provkey", hexlify(provkey).decode('utf-8'))
retval["provkey"] = hexlify(provkey).decode('utf-8') retval["provkey"] = hexlify(provkey).decode('utf-8')
return retval, keyinfo 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"]: elif self.setup.sej_base is not None and mode not in ["sej_aes_decrypt", "sej_aes_encrypt", "sej_sst_decrypt",
retval={} "sej_sst_encrypt", "dxcc_sha256"]:
retval = {}
rpmbkey = self.hwcrypto.aes_hwcrypt(mode="rpmb", data=meid, otp=otp, btype="sej") rpmbkey = self.hwcrypto.aes_hwcrypt(mode="rpmb", data=meid, otp=otp, btype="sej")
if rpmbkey: if rpmbkey:
self.info("RPMB : " + hexlify(rpmbkey).decode('utf-8')) self.info(f"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') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
self.info("Generating sej mtee...") self.info("Generating sej mtee...")
mtee = self.hwcrypto.aes_hwcrypt(mode="mtee", otp=otp, btype="sej") mtee = self.hwcrypto.aes_hwcrypt(mode="mtee", otp=otp, btype="sej")
if mtee: if mtee:
self.info("MTEE : " + hexlify(mtee).decode('utf-8')) self.info(f"MTEE : {hexlify(mtee).decode('utf-8')}")
self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8')) self.config.hwparam.writesetting("mtee", hexlify(mtee).decode('utf-8'))
retval["mtee"] = hexlify(mtee).decode('utf-8') retval["mtee"] = hexlify(mtee).decode('utf-8')
mtee3 = self.hwcrypto.aes_hwcrypt(mode="mtee3", otp=otp, btype="sej") mtee3 = self.hwcrypto.aes_hwcrypt(mode="mtee3", otp=otp, btype="sej")
if mtee3: if mtee3:
self.info("MTEE3 : " + hexlify(mtee3).decode('utf-8')) self.info(f"MTEE3 : {hexlify(mtee3).decode('utf-8')}")
self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8')) self.config.hwparam.writesetting("mtee3", hexlify(mtee3).decode('utf-8'))
retval["mtee3"] = hexlify(mtee3).decode('utf-8') retval["mtee3"] = hexlify(mtee3).decode('utf-8')
keyinfo+="\nKeys :\n-----------------------------------------\n" keyinfo += "\nKeys :\n-----------------------------------------\n"
keyinfo+="RPMB: " + hexlify(rpmbkey).decode('utf-8') keyinfo += f"RPMB: {hexlify(rpmbkey).decode('utf-8')}\n"
keyinfo+="\n" keyinfo += f"MTEE: {hexlify(mtee).decode('utf-8')}\n"
keyinfo += "MTEE: " + hexlify(mtee).decode('utf-8')
keyinfo += "\n"
retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8') retval["rpmbkey"] = hexlify(rpmbkey).decode('utf-8')
return retval, keyinfo return retval, keyinfo
if mode == "sej_aes_decrypt": if mode == "sej_aes_decrypt":
dec_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=False, otp=otp) dec_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=False, otp=otp)
keyinfo+="\n" keyinfo += f"\nData: {hexlify(dec_data).decode('utf-8')}\n"
keyinfo+="Data: " + hexlify(dec_data).decode('utf-8')
keyinfo+="\n"
return dec_data, keyinfo return dec_data, keyinfo
elif mode == "sej_aes_encrypt": elif mode == "sej_aes_encrypt":
enc_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=True, otp=otp) enc_data = self.hwcrypto.aes_hwcrypt(mode="cbc", data=data, btype="sej", encrypt=True, otp=otp)
keyinfo+="\n" keyinfo += f"\nData: {hexlify(enc_data).decode('utf-8')}\n"
keyinfo+="Data: " + hexlify(enc_data).decode('utf-8')
keyinfo+="\n"
return enc_data, keyinfo return enc_data, keyinfo
elif mode == "sej_sst_decrypt": elif mode == "sej_sst_decrypt":
dec_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=False, otp=otp) dec_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=False, otp=otp)
keyinfo+="\n" keyinfo += f"\nData: {hexlify(dec_data).decode('utf-8')}\n"
keyinfo+="Data: " + hexlify(dec_data).decode('utf-8')
keyinfo+="\n"
return dec_data, keyinfo return dec_data, keyinfo
elif mode == "sej_sst_encrypt": elif mode == "sej_sst_encrypt":
enc_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=True, otp=otp) enc_data = self.hwcrypto.aes_hwcrypt(mode="sst", data=data, btype="sej", encrypt=True, otp=otp)
keyinfo += "\n" keyinfo += f"\nData: {hexlify(enc_data).decode('utf-8')}\n"
keyinfo += "Data: " + hexlify(enc_data).decode('utf-8')
keyinfo += "\n"
return enc_data, keyinfo return enc_data, keyinfo
elif mode == "dxcc_sha256": elif mode == "dxcc_sha256":
sha256val = self.hwcrypto.aes_hwcrypt(mode="sha256", data=data, btype="dxcc") sha256val = self.hwcrypto.aes_hwcrypt(mode="sha256", data=data, btype="dxcc")
keyinfo+="\n" keyinfo += f"\nSHA256: {hexlify(sha256val).decode('utf-8')}\n"
keyinfo+="SHA256: " + hexlify(sha256val).decode('utf-8')
keyinfo+="\n"
return sha256val, keyinfo return sha256val, keyinfo
return None, "" return None, ""
@ -501,7 +489,6 @@ class Stage2(metaclass=LogBase):
self.usbwrite(pack(">I", 0x3000)) self.usbwrite(pack(">I", 0x3000))
def getint(valuestr): def getint(valuestr):
if valuestr == '': if valuestr == '':
return None return None
@ -533,86 +520,78 @@ cmds = {
info = "MTK Stage2 client (c) B.Kerler 2021" info = "MTK Stage2 client (c) B.Kerler 2021"
def showcommands():
print(info)
print("-----------------------------------\n")
print("Available commands are:\n")
for cmd in cmds:
print("%20s" % (cmd) + ":\t" + cmds[cmd])
print()
def main(): def main():
parser = argparse.ArgumentParser(description=info) 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 = subparsers.add_parser("rpmb", help="Dump the rpmb")
parser_rpmb.add_argument('--start', dest='start', type=str, 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, 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", 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, 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 = subparsers.add_parser("preloader", help="Dump the preloader")
parser_preloader.add_argument('--start', dest='start', type=str, 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, 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, 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 = subparsers.add_parser("data", help="Read the mmc")
parser_data.add_argument('--start', dest='start', type=str, 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, 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, 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 = subparsers.add_parser("boot2", help="Dump boot2")
parser_boot2.add_argument('--start', dest='start', type=str, 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, 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, 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 = subparsers.add_parser("memread", help="Read memory")
parser_memread.add_argument(dest='start', type=str, 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, 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, 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 = subparsers.add_parser("memwrite", help="Write memory")
parser_memwrite.add_argument(dest='start', type=str, 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, 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_reboot = subparsers.add_parser("reboot", help="Reboot device")
parser_seccfg = subparsers.add_parser("seccfg", help="Generate seccfg") parser_seccfg = subparsers.add_parser("seccfg", help="Generate seccfg")
parser_seccfg.add_argument('flag', type=str, 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", 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 = subparsers.add_parser("keys", help="Write memory")
parser_keys.add_argument('--otp', dest='otp', type=str, 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, 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, parser_keys.add_argument('--data', dest='data', default=None, type=str,
help='data') help='data')
args = parser.parse_args() args = parser.parse_args()
cmd = args.cmd cmd = args.cmd
if cmd not in cmds: if cmd not in cmds:
showcommands() parser.print_help()
exit(0) exit(0)
if not os.path.exists("logs"): if not os.path.exists("logs"):
@ -673,35 +652,35 @@ def main():
exit(0) exit(0)
start = getint(args.start) start = getint(args.start)
if os.path.exists(args.data): if os.path.exists(args.data):
filename=args.data filename = args.data
data=None data = None
else: else:
if "0x" in args.data: if "0x" in args.data:
data=getint(args.data) data = getint(args.data)
else: else:
data=args.data data = args.data
filename=None filename = None
if st2.memwrite(start, data, filename): if st2.memwrite(start, data, filename):
print(f"Successfully wrote data to {hex(start)}.") print(f"Successfully wrote data to {hex(start)}.")
else: else:
print(f"Failed to write data to {hex(start)}.") print(f"Failed to write data to {hex(start)}.")
elif cmd == "keys": elif cmd == "keys":
keyinfo="" keyinfo = ""
data=b"" data = b""
if args.mode in ["sej_aes_decrypt","sej_aes_encrypt","sej_sst_decrypt","sej_sst_encrypt"]: if args.mode in ["sej_aes_decrypt", "sej_aes_encrypt", "sej_sst_decrypt", "sej_sst_encrypt"]:
if not args.data: if not args.data:
print("Option --data is needed") print("Option --data is needed")
exit(0) exit(0)
data = bytes.fromhex(args.data) data = bytes.fromhex(args.data)
# otp_hisense=bytes.fromhex("486973656E736500000000000000000000000000000000000000000000000000") # otp_hisense=bytes.fromhex("486973656E736500000000000000000000000000000000000000000000000000")
# st2.jump(0x223449) # 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(keyinfo)
print("Wrote keys to logs/hwparam.json") print("Wrote keys to logs/hwparam.json")
elif cmd == "reboot": elif cmd == "reboot":
st2.reboot() st2.reboot()
elif cmd == "seccfg": elif cmd == "seccfg":
if args.flag not in ["unlock","lock"]: if args.flag not in ["unlock", "lock"]:
print("Valid flags are: unlock, lock") print("Valid flags are: unlock, lock")
sys.exit(1) sys.exit(1)
""" """
@ -720,15 +699,15 @@ def main():
SBOOT_RUNTIME_OFF = 0 SBOOT_RUNTIME_OFF = 0
SBOOT_RUNTIME_ON = 1 SBOOT_RUNTIME_ON = 1
""" """
if args.flag=="unlock": if args.flag == "unlock":
lock_state = 3 lock_state = 3
critical_lock_state = 1 critical_lock_state = 1
elif args.flag=="lock": elif args.flag == "lock":
lock_state = 1 lock_state = 1
critical_lock_state = 0 critical_lock_state = 0
with open("seccfg.bin", "wb") as wf: with open("seccfg.bin", "wb") as wf:
seccfg_ver = 4 seccfg_ver = 4
seccfg_size = 0x3C seccfg_size = 0x3C
sboot_runtime = 0 sboot_runtime = 0
seccfg_data = pack("<IIIIIII", 0x4D4D4D4D, seccfg_ver, seccfg_size, lock_state, seccfg_data = pack("<IIIIIII", 0x4D4D4D4D, seccfg_ver, seccfg_size, lock_state,
critical_lock_state, sboot_runtime, 0x45454545) critical_lock_state, sboot_runtime, 0x45454545)
@ -736,12 +715,13 @@ def main():
if args.sw: if args.sw:
enc_hash = st2.hwcrypto.sej.sej_sec_cfg_sw(dec_hash, True) enc_hash = st2.hwcrypto.sej.sej_sec_cfg_sw(dec_hash, True)
else: else:
enc_hash = st2.hwcrypto.sej.sej_sec_cfg_hw(dec_hash,True) enc_hash = st2.hwcrypto.sej.sej_sec_cfg_hw(dec_hash, True)
data = seccfg_data + enc_hash data = seccfg_data + enc_hash
data += b"\x00" * (0x200 - len(data)) data += b"\x00" * (0x200 - len(data))
wf.write(data) wf.write(data)
print("Successfully wrote seccfg to seccfg.bin. You need to write seccfg.bin to partition seccfg.") print("Successfully wrote seccfg to seccfg.bin. You need to write seccfg.bin to partition seccfg.")
st2.close() st2.close()
if __name__ == "__main__": if __name__ == "__main__":
main() main()