The Binding of Isaac Rebirth (*.a)

Extraction and unpacking of game archives and compression, encryption, obfuscation, decoding of unknown files
happyend
Posts: 157
Joined: Sun Aug 24, 2014 8:54 am

The Binding of Isaac Rebirth (*.a)

Post by happyend »

Can someone help me to extract .a files from this game?
THX!!!

head: ARCH000
Samples:http://www3.zippyshare.com/v/63015759/file.html
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

For the compressed files (config.a) there is no problem, but the others are obfuscated and so are not supported.
The script is here: http://aluigi.org/papers/bms/others/arch000.bms
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by Ekey »

Code: Select all

unsigned long Isaac_Hash(unsigned char *pString)
{
    unsigned long dwHash = 5381;
    int pChar;

    while (pChar = *pString++)
        dwHash = dwHash * 33 + pChar;

    return dwHash;
}
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

djb2 hash :)
Cool I implemented it just yesterday in quickbms beta for the NameCRC command, it looks like we will have lot of fun with that feature.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by Ekey »

Yeah but while reversing found additional hash func. Looks like FNV but with other hval constant

Code: Select all

int MakeSubHash(char *pString)
{
  char String;
  int i;

  String = *pString;
  for ( i = 0x5BB2220Eu; *pString; String = *pString )
  {
    ++pString;
    if ( (unsigned __int8)(String - 65) <= 0x19u )
      String += 32;
    if ( String == 92 )
      String = 47;
    i = 0x1000193 * (i ^ (unsigned __int8)String);
  }
  return i;
}


Also found some table inside executable.

Used like

Code: Select all

    dwHash = Isaac_Hash(pString);
    dwIndex = dwHash & 0x7FFF;
    dwResult = n_Table[dwIndex];
    Hash = dwHash;
    if ( !dwResult )
      goto LABEL_18;
    v7 = MakeSubHash(v4, pString);
    v8 = 0;
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

Ok that makes things complex.
Anyway that MakeSubHash is supported, it's just a FNV-1a
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by Ekey »

My snipped code.

Code: Select all

unsigned long isaac_fnv(unsigned char *pString)
{
    unsigned long dwHash = 0x5BB2220Eu;
    int pChar;

    while (pChar = *pString++)
        dwHash = 0x1000193 * (dwHash ^ pChar);

    return dwHash;
}


Strings must be always in LowerCase
Last edited by Ekey on Wed Nov 05, 2014 4:15 pm, edited 1 time in total.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

For the lower case quickbms automatically pre-calculate the crc of various modifications of the original string, it should help to catch the correct crc in any case.
I have just added the possibility of specifying "" as filelist, so that will be used directly the bms script.
That's a nice idea for putting the list of names directly inside the comments of the script:

Code: Select all

# blah blah
# script for QuickBMS blah
#
# path/file.txt
# \folder1\sub_folder\my file is cool.asdfasdf

idstring "blah"
...
I doubt that someone will make a script containing the list of filenames, anyway it costed me nothing to add this feature.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by Ekey »

I found some names but output hashes from func's not found in any archives.
Ekey
Posts: 1383
Joined: Sat Aug 09, 2014 2:34 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by Ekey »

Well i found decryption algorithm but one problem. For each data, various decryption keys (DWORD). Idk how it generate. I checked entry table but without good results.

Code: Select all

int isaac_decrypt(int dwKey, int pBuffer)
{
  int Buffer; // ecx@1
  signed int dwBlockSize; // esi@1
  char v4; // bl@5
  char v5; // dl@5
  char v6; // bl@5
  char v7; // dl@6
  char v8; // bl@6
  char v9; // dl@6
  char v10; // bl@7
  char v11; // dl@7

  Buffer = pBuffer + 1;
  dwBlockSize = 256;
  do
  {
    *(DWORD *)(Buffer - 1) ^= dwKey;
    if ( (dwKey & 0xF) == 2 )
    {
      v10 = *(BYTE *)(Buffer + 2);
      *(BYTE *)(Buffer + 2) = *(BYTE *)(Buffer - 1);
      v11 = *(BYTE *)Buffer;
      *(BYTE *)(Buffer - 1) = v10;
      v6 = *(BYTE *)(Buffer + 1);
      *(BYTE *)(Buffer + 1) = v11;
    }
    else
    {
      if ( (dwKey & 0xF) == 9 )
      {
        v7 = *(BYTE *)(Buffer - 1);
        *(BYTE *)(Buffer - 1) = *(BYTE *)Buffer;
        v8 = *(BYTE *)(Buffer + 2);
        *(BYTE *)Buffer = v7;
        v9 = *(BYTE *)(Buffer + 1);
        *(BYTE *)(Buffer + 1) = v8;
        *(BYTE *)(Buffer + 2) = v9;
        goto LABEL_9;
      }
      if ( (dwKey & 0xF) != 13 )
        goto LABEL_9;
      v4 = *(BYTE *)(Buffer + 1);
      *(BYTE *)(Buffer + 1) = *(BYTE *)(Buffer - 1);
      v5 = *(BYTE *)Buffer;
      *(BYTE *)(Buffer - 1) = v4;
      v6 = *(BYTE *)(Buffer + 2);
      *(BYTE *)(Buffer + 2) = v5;
    }
    *(BYTE *)Buffer = v6;
LABEL_9:
    dwKey ^= ((dwKey ^ (unsigned int)(dwKey << 8)) >> 9) ^ (dwKey << 8) ^ ((((dwKey ^ (unsigned int)(dwKey << 8)) >> 9) ^ dwKey ^ (dwKey << 8)) << 23);
    Buffer += 4;
    --dwBlockSize;
  }
  while ( dwBlockSize );
  return dwKey;
}


For example:

Archive: resources\packed\graphics.a
Data Offset: 0xE
Key: 0x62E1B187
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

Maybe it's a crc calculated on the filename.
Only rarely I have seen a number derived from the offset.
Cryo
Posts: 5
Joined: Fri Nov 07, 2014 7:14 am

Re: The Binding of Isaac Rebirth (*.a)

Post by Cryo »

For some reason bms is only outputting 1kb files. Any ideas on what I did wrong?
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

Do you have the latest version of quickbms 0.6?

Have you saved the script to disk? (rarely it may get corrupted when copy&pasted)
Cryo
Posts: 5
Joined: Fri Nov 07, 2014 7:14 am

Re: The Binding of Isaac Rebirth (*.a)

Post by Cryo »

I'm not sure how I'm supposed to download it other than copy-pasta. FTP?
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

With the right-button mouse and "save as".
Anyway to know if everything is correct it's enough that you check the size of the output folder, if it's big almost like the input archive then it's all ok.
Cryo
Posts: 5
Joined: Fri Nov 07, 2014 7:14 am

Re: The Binding of Isaac Rebirth (*.a)

Post by Cryo »

The input is correct as far as I know. http://i.imgur.com/n0ffpmZ.png
But it's outputting like this: http://i.imgur.com/29JbY6o.png
And yes, I'm using bms 0.6 on Windows 8 64 bit.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

You are right, it's not a single compression but it's a chunked compression.
And the real problem is that only the first chunk can be decompressed without problems so probably the other chunks are encrypted.
I have updated the script only to add this additional information and to exit with an error message, because it's not complete and is useless.
Sorry.
Cryo
Posts: 5
Joined: Fri Nov 07, 2014 7:14 am

Re: The Binding of Isaac Rebirth (*.a)

Post by Cryo »

I'm not sure that's the problem. BMS is outputting a 1024byte file for each chunk, yet in the program it reads more. The script is working, I just need to know why I'm losing data.
Also, I'm fairly new at this whole thing. Is there anything I can do to make this script work? I have time to help, and I can learn quite fast. Can you tell I'm desperate? xD
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: The Binding of Isaac Rebirth (*.a)

Post by aluigi »

The problem is that I don't know how to finish the script.
Basically the files are stored not as single data, they are splitted in multiple parts (chunks):

Code: Select all

#### first 1024 bytes chunk, no problem to decompress it
#### second 1024 bytes chunk, it doesn't decompress so I think it's encrypted
#### third 1024 bytes chunk, just as above
...
Without the decryption of the non-compressed files and the chunks from the second one, it's not possible to finish the script.
Cryo
Posts: 5
Joined: Fri Nov 07, 2014 7:14 am

Re: The Binding of Isaac Rebirth (*.a)

Post by Cryo »

I was scanning through the hex on a memory viewer and this caught my eye:

Code: Select all

56 4C 56 00 01 00 00 00 10 D4 29 00 E2 7C 5D 54 4C F9 AB 7C 13 C7 AF 35 FB 99 FF FB A2 99 FA 40 80 46 0B 92 9A 7C C3 34 38 3E D4 99 0C 7B 1C 8F DD 21 B2 F5 DE 27 8F C5 4A 30 CE 56 F5 E5 C0 34 23 94 26 06 E4 04 6E B2 A6 CD 08 DB BF 1E C7 B5 D7 79 C6 9D F1 46 BF B6 9D EC CC C2 8F 18 25 FC 08 DB 49 8D 94 BF C3 49 FC 80 26 CF 99 79 0D FE 50 B7 ED 89 C5 CB FA 3F F5 11 2B 0E C4 A0 65 89 82 9A 6B 64 74 C4 3A 2C 0C A7 8D 93 26 13 8C A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 45 00 00 4C 01 06 00 03 7B 5D 54 00 00 00 00 00 00 00 00 E0 00 02 01 0B 01 0A 00 00 1C 1C 00 00 8E 07 00 00 00 00 00 F0 42 24 00 00 10 00 00 00 30 1C 00 00 00 9C 00 00 10 00 00 00 02 00 00 05 00 01 00 00 00 00 00 05 00 01 00 00 00 00 00 00 70 2A 00 00 04 00 00 32 46 24 00 02 00 40 81 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 CC 6D 1F 00 F0 00 00 00 00 60 22 00 A4 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 22 00 0C 85 01 00 00 37 1C 00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0 64 1E 00 40 00 00 00 00 00 00 00 00 00 00 00 00 30 1C 00 30 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2E 74 65 78 74 00 00 00 35 1A 1C 00 00 10 00 00 00 1C 1C 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 60 2E 72 64 61 74 61 00 00 6E 6C 03 00 00 30 1C 00 00 6E 03 00 00 20 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 40 2E 64 61 74 61 00 00 00 78 B1 02 00 00 A0 1F 00 00 54 02 00 00 8E 1F 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 C0 2E 72 73 72 63 00 00 00 A4 13 00 00 00 60 22 00 00 14 00 00 00 E2 21 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 40 2E 72 65 6C 6F 63 00 00 2E B6 01 00 00 80 22 00 00 B8 01 00 00 F6 21 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 42 2E 62 69 6E 64 00 00 00 10 26 06 00 00 40 24 00 10 26 06 00 00 AE 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 00 00 00 00 00 00 00

Does it mean anything to you? There are a few things in there that makes me think this is some obfuscated file names or something of the sort, as apposed to being just gibberish.