small docs update

This commit is contained in:
Jonathan Herrewijnen 2024-08-06 07:58:47 +02:00
parent d991625f9f
commit 9489692586
2 changed files with 39 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -34,8 +34,9 @@ When the ROM is unable to boot from the internal storage, it enters ``Exynos Rec
In this mode the bootROM accepts data over USB.
There is little functionality other than receiving data, meaning almost no additional attack surface except for the download protocol.
The Exynos BootROM uses a custom protocol to download a bootable image over USB.
This image is verified and executed by the BootROM. Unauthorized images are rejected. (TODO verify and document)
The Exynos BootROM uses a custom protocol to download a bootable image over USB. This image is verified and executed by the BootROM. Unauthorized images are rejected. Initial authorisation is done using the '_auth_bl1' function.
(TODO verify and document)
dldata
------
@ -77,15 +78,48 @@ The base address of the usb controller (dwusb3) is mapped at 0x1540000, with a s
};
};c
This is a basic USB controller, but some functions, that are also present in the linux kernel, should be visible in the bootROM as well. Available functions could be: `linux-kernel-dwc3 <https://android.googlesource.com/kernel/msm/+/android-msm-dory-3.10-kitkat-wear/drivers/usb/dwc3/core.h>`_.
The USB host sends a USB_REQ_SET_ADDRESS, `'0x05' <https://asf.microchip.com/docs/latest/common.services.usb.class.composite.device.example.hidms_msc.saml21_xplained_pro/html/group__usb__protocol__group.html>`_, which the connected device has to acknowledge, and will then start sending data to this address. Initially, the device will send data to '0x00'.
.. code:: c
usb_reqid {
USB_REQ_GET_STATUS = 0,
USB_REQ_CLEAR_FEATURE = 1,
USB_REQ_SET_FEATURE = 3,
USB_REQ_SET_ADDRESS = 5,
USB_REQ_GET_DESCRIPTOR = 6,
USB_REQ_SET_DESCRIPTOR = 7,
USB_REQ_GET_CONFIGURATION = 8,
USB_REQ_SET_CONFIGURATION = 9,
USB_REQ_GET_INTERFACE = 10,
USB_REQ_SET_INTERFACE = 11,
USB_REQ_SYNCH_FRAME = 12
}
Ghidra shows `DWC3_DCFG & 0xfffffc00 | DWC3_DCFG & 7 | (param_1 & 0x7f) << 3;`, essentially preserves bits 0-2 and 10-31, and sets bits 3-9 to the value of param_1, which is then likely the address of the device.
.. figure:: images/ghidra_dwc3_dcfg_devaddr.png
bootrom exynos 8890 dwc3_dcfg_devaddr
Other general device descriptors are also sent from the device to the host (to describe the device), these are visible in/at 'usb_init_device_descriptor' (6098) and usb_init_descriptors (610c). Two end point addresses are visible: bEndpointAddress 0x81 and 0x02. 0x81 is 10000001 in binary, with bit 7 being '1', which means that the bulk transfer direction is IN. 0x02 is 00000010 in binary, with bit '7' being '0', which means that the bulk transfer direction is OUT.
Data is transferred via Transfer Request Blocks (TRB), dwc3_depcmd_starttransfer is used. The TRB then contains a buffer address, where transferred data from the host is written to. The buffer allocation is done by 'usb_setup_event_buffer', which sets bufferHigh (DWC3_GEVNTADRLO), bufferLow (DWC3_GEVNTADRHI) and bufferSize (DWC3_GEVNTSIZ).
Bug 1(Integer underflow)
------------------------
Originally described in this `blogpost <https://fredericb.info/2020/06/exynos-usbdl-unsigned-code-loader-for-exynos-bootrom.html#exynos-usbdl-unsigned-code-loader-for-exynos-bootrom>`_.
https://github.com/LineageOS/android_kernel_samsung_universal8890/blob/lineage-18.1/arch/arm64/boot/dts/exynos8890.dtsi
The exynos bootrom uses a simple USB protocol to receive a bootloader binary from a USB host. The binary sent is called 'dldata'. In Ghidra, at 21518, we can see that it consists of unit32_t: ready?, uint32: size, ? : data, uint16: footer. The contents of this data are checked before being being written.
@TODO better explain frederick's bug. @JONHE
.. code:: c
if ((pdVar1->size < 0x206ffff) && (0x206ffff < pdVar1->size + remaining)) {
*(undefined *)&pdVar1->ready = 2;
}
In essence, in the first conditions, it checks whether the size is smaller than 0x206fff (`pdVar1->size < 0x206ffff`) (34013183 in decimal), and in the second condition, it checks whether 0x206ffff is smaller than the size + remaining (`0x206ffff < pdVar1->size + remaining`). If both conditions are met, the ready flag is set to 2, and the function below to execute the *payload*, will NOT execute!
Bug 2