Editing Bootloader

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
On the vita there are several bootloaders (stage bootloaders).


One (or probably 2 stages boot) is used to boot to the TEE (Secure world) and one to load the kernel in the normal world.
Some bootloaders are obfuscated via ARZL algorithm.
= SLB2 Image =
SLB2 is the format used to store the encrypted bootloaders on the device.
== ENC Files ==
{| class="wikitable"
|-
! Offset !! Size !! Description
|-
| 0x0 || 0x4 || <code>0x64B2C8E5</code> magic
|-
| 0x4 || 0x4 || Offset to data
|-
| 0x8 || 0x4 || Unknown
|-
| 0xC || 0x4 || Unknown/Zero
|-
| 0x10 || 0x4 || Data size
|-
| 0x14 || 0xC || Unknown
|-
| 0x20 || 0x20 || Hash ?
|-
| 0x40 || 0x10 || Version in ASCII
|-
| 0x50 || 0x90 || Zero
|-
| 0xE0 || Until Data || Encrypted Header
|-
|}
The last 0x340 bytes is a footer that likely contains a signed MAC of the plaintext data.
= ARZL =
ARZL is a (standard ?) compressed format which is used by the [[Boot Sequence|secure bootloader]] to load the non-secure bootloader and the secure kernel.
== Obfuscation ==
The raw decompressed ARZL output is obfuscated. Although there are three versions of the obfuscation, the basic operation is the same. The obfuscation is just bit swaps as well as some deterministic changes using information from the offset.
<source>
int arzl_deobfuscate(unsigned char *buffer, int len)
{
  unsigned char *buf, *bufend;
  uint32_t data;
  int change_stride;
  buf = buffer;
  bufend = &buffer[len];
  do
  {
    data = *(uint32_t *)buf;
    buf += 4;
    change_stride = (data & 0xF800F800) >> 27;
    if ( (data & 0xF800F800) == 0xF800F000 )
    {
      data = (((data >> 16) & 0xFFC007FF) | ((data & 0x7FF) << 11)) - ((buf - buffer) >> 1);
      *((uint32_t *)buf - 1) = ((((data & 0x7FF) << 16) | 0xF800F000) & 0xFFFFF800) | ((data >> 11) & 0x7FF);
    }
    else if ( change_stride == 30 )
    {
      buf -= 2;
    }
  }
  while ( bufend > buf );
}
</source>
=== Version 1 ===
The only change is that the offset information is added instead of subtracted.
<source>
int arzl_deobfuscate(unsigned char *buffer, int len)
{
  unsigned char *buf, *bufend;
  uint32_t data;
  int change_stride;
  buf = buffer;
  bufend = &buffer[len];
  do
  {
    data = *(uint32_t *)buf;
    buf += 4;
    change_stride = (data & 0xF800F800) >> 27;
    if ( (data & 0xF800F800) == 0xF800F000 )
    {
      data = (((data >> 16) & 0xFFC007FF) | ((data & 0x7FF) << 11)) + ((buf - buffer) >> 1);
      *((uint32_t *)buf - 1) = ((((data & 0x7FF) << 16) | 0xF800F000) & 0xFFFFF800) | ((data >> 11) & 0x7FF);
    }
    else if ( change_stride == 30 )
    {
      buf -= 2;
    }
  }
  while ( bufend > buf );
}
</source>
=== Version 2 ===
Version 2 is the same as version 0 but in addition, there's an additional operation to swap two nibbles in certain conditions. The condition is found through a learning process and may be overfitted.
<source>
int arzl_deobfuscate(unsigned char *buffer, int len)
{
  unsigned char *buf, *bufend;
  uint32_t data;
  int change_stride;
  buf = buffer;
  bufend = &buffer[len];
  do
  {
    data = *(uint32_t *)buf;
    buf += 4;
    change_stride = (data & 0xF800F800) >> 27;
    if ( (data & 0xF800F800) == 0xF800F000 )
    {
      data = (((data >> 16) & 0xFFC007FF) | ((data & 0x7FF) << 11)) + ((buf - buffer) >> 1);
      *((uint32_t *)buf - 1) = ((((data & 0x7FF) << 16) | 0xF800F000) & 0xFFFFF800) | ((data >> 11) & 0x7FF);
    }
    else if ( (data & 0x8000FBF0) == 0x0000F2C0 )
    {
      data = (data & 0xF0FFFFF0) | ((data & 0xF) << 24) | ((data >> 24) & 0xF);
      *((uint32_t *)buf - 1) = data;
    }
    else if ( change_stride == 30 )
    {
      buf -= 2;
    }
  }
  while ( bufend > buf );
}
</source>
Please note that all contributions to Vita Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see Vita Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)