Vindictus

From XentaxWiki
Jump to: navigation, search

Back to index | Edit this page

HFS

Format Specifications (ZIP-like)

// for each local file header
char {4}     - Signature (HF) (0x02014648)
uint16 {2}   - Version needed to extract (seen as 20)
uint16 {2}   - General purpose bit flag
uint16 {2}   - Compression method (always 'Stored')
uint16 {2}   - Last mod file time
uint16 {2}   - Last mod file date
uint32 {4}   - CRC32
uint32 {4}   - Compressed File Size
uint32 {4}   - Decompressed File Size
uint16 {2}   - Filename Length
uint16 {2}   - Extra Field Length
char {X}     - Filename (Obfuscated)
char {X}     - Extra field
byte {X}     - File Data (Obfuscated, Compressed)

// for each central directory header

char {4}     - Signature (HF) (0x02014648)
uint16 {2}   - Version created with (seen as 20)
uint16 {2}   - Version needed to extract (seen as 20)
uint16 {2}   - General purpose bit flag
uint16 {2}   - Compression method (always 'Stored')
uint16 {2}   - Last mod file time
uint16 {2}   - Last mod file date
uint32 {4}   - CRC32
uint32 {4}   - Compressed File Size
uint32 {4}   - Decompressed File Size
uint16 {2}   - Filename Length
uint16 {2}   - Extra Field Length
uint16 {2}   - Comment Length
uint16 {2}   - Disk number
uint16 {2}   - Internal attributes
uint32 {4}   - External attributes
uint32 {4}   - Relative offset of local file header
char {X}     - Filename (Obfuscated)
char {X}     - Extra field
char {X}     - comment

// end of central directory

char {4}     - Signature (HF) (0x06054648)
uint16 {2}   - Number of disk
uint16 {2}   - Disk where CD starts
uint16 {2}   - Number of CD records
uint16 {2}   - Count of CD records
uint32 {4}   - Size of central directory
uint32 {4}   - offset to start of CD
uint16 {2}   - Zip comment length
char {X}     - comment
uint32 {4}   - Second-pass Checksum (DEPRECATED, Optional, changes handling)

Obfuscation

  • The base cipher is the "Xor Cipher" as described:
public static void XorBlockWithKey(byte[] buffer, byte[] key, int src_position)
{
    Debug.Assert(key.Length == 4 || key.Length == 4096);

    for (int x = 0; x < buffer.Length; x++)
    {
        buffer[x] ^= key[(src_position + x) & (key.Length - 1)];
    }
}


  • All archives are obfuscated with atleast one pass of the Xor cipher, with the source position as the file position of the block. The file names and data in the Local File Header, and the file name in the Central Directory Header are obfuscated.
  • The key is constant, but encrypted in game files, available in the tool "VZipFlip" as XorTruths.bin
  • If the Second-pass checksum in the End of Central Directory Header exists, then a second pass of the Xor Cipher is performed with the 32-bit key: EndOfCentralDirectory.CentralDirectorySize * EndOfCentralDirectory.OffsetOfCentralDirectory.
  • The second pass checksum uses a key that is located within the game files, available in the tool "hfssign" as ChecksumTruths.bin. The algorithm is a xor/shift checksum, described as
public static UInt32 XorRollWithKey(byte[] buffer, int limit, UInt32[] key, UInt32 checksum)
{
    for (int x = 0; x < limit; x++)
    {
        checksum = key[buffer[x] ^ (byte)(checksum & 0xFF)] ^ (checksum >> 8);
    }

    return checksum;
}

Notes and Comments

  • The game is also called "Mabinogi Heroes"
  • The game should be considered Episode 1 of the Source engine as far as file formats used.
  • The file name of the HFS is likely a 160-bit hash, likely SHA-1, perhaps of the path.
  • Some files have the extension ".comp". The file data will have a "COMP" header. The data is compressed with DEFLATE (RFC 1951).
  • The secondary checksum member no longer exists.

MultiEx BMS Script

  • Not supported

Supported by Programs