Difference between revisions of "ARZL"

From Vita Development Wiki
Jump to navigation Jump to search
Line 1: Line 1:
ARZL is a (standard ?) compression format used for example by the [[Boot Sequence|secure kernel bootloader]] to load the non-secure kernel bootloader and the secure kernel. It is also used by /sce_sys/right/right.suprx for embedding GIM texture data.
+
LZRA (ARZL in big-endian) is a compression and encoding format used on PS Vita. It is used for example to store files used by the [[SKBL]] like the [[NSKBL]] and some [[Tzs]] modules. It is also used on GIM texture data used by /sce_sys/right/right.suprx.
 +
 
 +
== Naming ==
 +
 
 +
It might be similar to LZMA. See [https://tukaani.org/xz/].
 +
 
 +
There is a typo in [[SKBL]] functions names where it is named ARLZ instead of ARZL.
  
 
== Header ==
 
== Header ==
Line 8: Line 14:
  
 
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.
 
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.
 +
 +
=== Version 0 ===
  
 
<source lang="c">
 
<source lang="c">
int arzl_deobfuscate(unsigned char *buffer, int len)
+
int arzl_deobfuscate(unsigned char *buffer, int len) {
{
 
 
   unsigned char *buf, *bufend;
 
   unsigned char *buf, *bufend;
 
   uint32_t data;
 
   uint32_t data;
 
   int change_stride;
 
   int change_stride;
 
 
   buf = buffer;
 
   buf = buffer;
 
   bufend = &buffer[len];
 
   bufend = &buffer[len];
 
+
   do {
   do
 
  {
 
 
     data = *(uint32_t *)buf;
 
     data = *(uint32_t *)buf;
 
     buf += 4;
 
     buf += 4;
 
     change_stride = (data & 0xF800F800) >> 27;
 
     change_stride = (data & 0xF800F800) >> 27;
     if ( (data & 0xF800F800) == 0xF800F000 )
+
     if ((data & 0xF800F800) == 0xF800F000) {
    {
 
 
       data = (((data >> 16) & 0xFFC007FF) | ((data & 0x7FF) << 11)) - ((buf - buffer) >> 1);
 
       data = (((data >> 16) & 0xFFC007FF) | ((data & 0x7FF) << 11)) - ((buf - buffer) >> 1);
 
       *((uint32_t *)buf - 1) = ((((data & 0x7FF) << 16) | 0xF800F000) & 0xFFFFF800) | ((data >> 11) & 0x7FF);
 
       *((uint32_t *)buf - 1) = ((((data & 0x7FF) << 16) | 0xF800F000) & 0xFFFFF800) | ((data >> 11) & 0x7FF);
     }
+
     } else if (change_stride == 30)
    else if ( change_stride == 30 )
 
    {
 
 
       buf -= 2;
 
       buf -= 2;
    }
+
   } while (bufend > buf);
   }
 
  while ( bufend > buf );
 
 
}
 
}
 
</source>
 
</source>
Line 48: Line 47:
 
=== Version 2 ===
 
=== 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.
+
Version 2 is the same as version 0 but in addition, there is an additional operation to swap two nibbles in certain conditions. The condition is found through a learning process and may be overfitted.
 +
 
 
<source lang="c">
 
<source lang="c">
       else if ( (data & 0x8000FBF0) == 0x0000F2C0 )
+
       else if ((data & 0x8000FBF0) == 0x0000F2C0) {
      {
 
 
         data = (data & 0xF0FFFFF0) | ((data & 0xF) << 24) | ((data >> 24) & 0xF);
 
         data = (data & 0xF0FFFFF0) | ((data & 0xF) << 24) | ((data >> 24) & 0xF);
 
         *((uint32_t *)buf - 1) = data;
 
         *((uint32_t *)buf - 1) = data;
 
       }
 
       }
 
</source>
 
</source>
 +
  
 
[[Category:Formats]]
 
[[Category:Formats]]

Revision as of 21:15, 23 January 2022

LZRA (ARZL in big-endian) is a compression and encoding format used on PS Vita. It is used for example to store files used by the SKBL like the NSKBL and some Tzs modules. It is also used on GIM texture data used by /sce_sys/right/right.suprx.

Naming

It might be similar to LZMA. See [1].

There is a typo in SKBL functions names where it is named ARLZ instead of ARZL.

Header

It is simply the string "ARZL" (41 52 5A 4C).

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.

Version 0

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);
}

Version 1

The only change is that the offset information is added instead of subtracted.

data = (((data >> 16) & 0xFFC007FF) | ((data & 0x7FF) << 11)) + ((buf - buffer) >> 1);

Version 2

Version 2 is the same as version 0 but in addition, there is an additional operation to swap two nibbles in certain conditions. The condition is found through a learning process and may be overfitted.

else if ((data & 0x8000FBF0) == 0x0000F2C0) {
        data = (data & 0xF0FFFFF0) | ((data & 0xF) << 24) | ((data >> 24) & 0xF);
        *((uint32_t *)buf - 1) = data;
      }