[ot][spam][personal] uhhh should I understand the exploits my new phone is vulnerable to

Undiscussed Horrific Abuse, One Victim of Many gmkarl at gmail.com
Sat May 7 01:46:00 PDT 2022


On Sat, May 7, 2022, 3:01 AM Undiscussed Horrific Abuse, One Victim of Many
<gmkarl at gmail.com> wrote:

> I'm not near this system and phone at this time, but that doesn't mean I
> can't keep learning about it.
>
> Here's the deployment script for the bootrom phase from the amonet
> kamakiri source:
>
> #!/usr/bin/env python3
>
> import sys
> import time
>
> from common import Device
> from logger import log
> from load_payload import load_payload
> from functions import *
>
> import usb.core
> import usb.util
>
> import ctypes
>
> import traceback
>
>
> import struct
> import os
>
> def main(dev):
>
>     load_payload(dev)
>

This uses a hack to get the 0xf00dd00d payload running on the device,
roughly by uploading the stages and jumping to their addresses. The first
stage involves some register and usb twiddling, and is size-limited; it may
be an exploit, unsure.

    if len(sys.argv) == 2 and sys.argv[1] == "fixgpt":
>         dev.emmc_switch(0)
>         log("Flashing GPT")
>         flash_binary(dev, "../bin/gpt-mantis.bin", 0, 34 * 0x200)
>

This likely replaces the partition table if requested. I don't see the
gpt-mantis.bin file in the repository yet.

That size of 0x34 x 0x200 ... I've seen that before I think?


>     # 1) Sanity check GPT
>     log("Check GPT")
>     switch_user(dev)
>

This switches the device to partition 0 and verifies two expected bytes in
that partition.


>     # 1.1) Parse gpt
>     gpt = parse_gpt(dev)
>

def parse_gpt(dev):
    data = dev.emmc_read(0x400 // 0x200) + dev.emmc_read(0x600 // 0x200) +
dev.emmc_read(0x800 // 0x200) + dev.emmc_read(0xA00 // 0x200)
    num = len(data) // 0x80
    parts = dict()
    for x in range(num):
        part = data[x * 0x80:(x + 1) * 0x80]
        part_name = part[0x38:].decode("utf-16le").rstrip("\x00")
        part_start = struct.unpack("<Q", part[0x20:0x28])[0]
        part_end = struct.unpack("<Q", part[0x28:0x30])[0]
        parts[part_name] = (part_start, part_end - part_start + 1)
    return parts

I'm guessing that partition 0 is either the partition table or the entire
flash, and that the above code manually parses a GPT partition table (into
a python dict of offset size pairs).

    log("gpt_parsed = {}".format(gpt))
>     if "lk" not in gpt or "tee1" not in gpt or "boot" not in gpt or
> "recovery" not in gpt:
>         raise RuntimeError("bad gpt")
>
>     # 2) Sanity check boot0
>     log("Check boot0")
>     switch_boot0(dev)
>

This switches to partition 1 and verifies that it starts with either
"EMMC_BOOT" or nul bytes.


>     # 3) Sanity check rpmb
>     log("Check rpmb")
>     rpmb = dev.rpmb_read()
>     if rpmb[0:4] != b"AMZN":
>         thread = UserInputThread(msg = "rpmb looks broken; if this is
> expected (i.e. you're retrying the exploit) press enter, otherwise
> terminate with Ctrl+C")
>         thread.start()
>         while not thread.done:
>             dev.kick_watchdog()
>             time.sleep(1)
>

I'm not sure what rpmb is, immediately.


>     # Clear preloader so, we get into bootrom without shorting, should the
> script stall (we flash preloader as last step)
>     # 4) Downgrade preloader
>     log("Clear preloader header")
>     switch_boot0(dev)
>     flash_data(dev, b"EMMC_BOOT" + b"\x00" * ((0x200 * 4) - 9), 0)
>

Places null bytes in partition 1.


>     # 5) Zero out rpmb to enable downgrade
>     log("Downgrade rpmb")
>     dev.rpmb_write(b"\x00" * 0x100)
>

Whatever the rpmb is, this zeros it.

    log("Recheck rpmb")
>     rpmb = dev.rpmb_read()
>     if rpmb != b"\x00" * 0x100:
>         dev.reboot()
>         raise RuntimeError("downgrade failure, giving up")
>     log("rpmb downgrade ok")
>     dev.kick_watchdog()
>
>     # 6) Downgrade tz
>     log("Flash tz")
>     switch_user(dev)
>     flash_binary(dev, "../bin/tz.img", gpt["tee1"][0], gpt["tee1"][1] *
> 0x200)
>

Okay, it sounds like partition 0 is not the partition table, but rather
partition "tz" ....

I don't yet understand why it seems to read as if the GPT table was parsed
0x400 bytes after the start of the tz partition. Could the GPT table be
located at the end or inside of a partition?

Ohhhh I see -- gpt["tee1"] stores the offset of the tee1 partition. The
partitions are flashed relative to the start of the emmc.


>     # 7) Downgrade lk
>     log("Flash lk")
>     switch_user(dev)
>     flash_binary(dev, "../bin/lk.bin", gpt["lk"][0], gpt["lk"][1] * 0x200)
>

So this code replaces two partitions with binary images. Maybe
user-provided old ones, unsure.

    # 6) Install lk-payload
>     log("Flash lk-payload")
>     switch_boot0(dev)
>     flash_binary(dev, "../lk-payload/build/payload.bin", 1024)
>

And here's the next payload, contents not reviewed yet. It's interesting
that this is flashed at offset 1024 rather than the offset of the actual lk
partition. I think is bytes rather than 0x200 sectors, not sure.

...

>
>     # 8) Flash microloader
>     log("Inject microloader")
>     switch_user(dev)
>     boot_hdr1 = dev.emmc_read(gpt["boot"][0]) +
> dev.emmc_read(gpt["boot"][0] + 1)
>     boot_hdr2 = dev.emmc_read(gpt["boot"][0] + 2) +
> dev.emmc_read(gpt["boot"][0] + 3)
>     flash_binary(dev, "../bin/microloader.bin", gpt["boot"][0], 2 * 0x200)
>     if boot_hdr2[0:8] != b"ANDROID!":
>         flash_data(dev, boot_hdr1, gpt["boot"][0] + 2, 2 * 0x200)
>
>     log("Force fastboot")
>     force_fastboot(dev, gpt)
>
>     # 9) Install preloader
>     log("Flash preloader")
>     switch_boot0(dev)
>     flash_binary(dev, "../bin/preloader.img", 0)
>
>     # 9.1) Wait some time so data is flushed to EMMC
>     time.sleep(5)
>
>     # Reboot (to fastboot or recovery)
>     log("Reboot")
>     dev.reboot()
>
>
> if __name__ == "__main__":
>
>     check_modemmanager()
>
>     dev = Device()
>     dev.find_device()
>
>     main(dev)
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: text/html
Size: 13253 bytes
Desc: not available
URL: <https://lists.cpunks.org/pipermail/cypherpunks/attachments/20220507/20e4e294/attachment.txt>


More information about the cypherpunks mailing list