Decryption of bin and ogg files

Codecs, formats, encoding/decoding of game audio, video and music
Parasite
Posts: 48
Joined: Tue Oct 18, 2022 10:49 pm

Decryption of bin and ogg files

Post by Parasite »

Games affected : Pスーパー海物語 IN JAPAN2 / Super Sea Story in Japan 2
Device : Android game

In this game there are 3 files, snd.bin, snd_add.bin and sound_id.dat. Most of the audios are in snd.bin.

The files are in ogg format, the problem is every ogg extracted have encryption but only the 24 bytes after OggS (first 4 bytes of every ogg) seem encrypted.
The files included in the archive contains every ogg (albeit unplayable because of the small encryption) : https://mega.nz/file/VRkC1bxZ#uPyeVp4ht ... 3ESBFN8yrI
If somebody knows how to decrypt those bytes, thanks.
atom0s
Posts: 250
Joined: Sat Dec 27, 2014 8:49 pm

Re: Decryption of bin and ogg files

Post by atom0s »

The game uses a modified libvorbis setup that is wrapped into two parts in the other modules of the game engine.

- libcmslib
- libGameProc

libcmslib is used to load and read the ogg files and feed the information into the libvorbis decoder. This is done using a custom loader/reader/decoder that has a special xor key setup. This lib exposes a call 'CBinCtrl::SetSoundKey' which other libs can call and set before attempting to load the sound files.

libGameProc is the main game library which is what imports and makes use of libcmslib. The key for this game is:

Code: Select all

25NuVMrNZP899VviPeyGZ9GK
The loader call inside of libcmslib looks like this:

Code: Select all

__int64 __fastcall COggVorbis::load_ogg_file(COggVorbis *this)
{
  int v1; // w20
  __int64 v2; // x19
  __int64 v3; // x21
  char *v4; // x1
  std::__node_alloc *v5; // x9
  unsigned __int64 v6; // x8
  char *v7; // x8
  char *v8; // x8
  __int64 v9; // x0
  unsigned __int64 v10; // x2
  __int64 v11; // x21
  CBinCtrl *v12; // x0
  _QWORD *SoundKey; // x0
  _BYTE *v14; // x10
  unsigned __int64 v15; // x9
  __int64 v16; // x8
  __int64 v17; // x9
  std::__node_alloc *v18; // x0
  void *v19; // x1
  char v21; // [xsp+4h] [xbp-3Ch] BYREF
  int v22; // [xsp+8h] [xbp-38h] BYREF
  int v23; // [xsp+Ch] [xbp-34h] BYREF
  char v24; // [xsp+10h] [xbp-30h] BYREF
  __int64 v25; // [xsp+18h] [xbp-28h]

  v1 = (int)this;
  v25 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  v2 = operator new(0x20u);
  *(_QWORD *)(v2 + 8) = 0LL;
  *(_QWORD *)(v2 + 16) = 0LL;
  *(_QWORD *)v2 = 0LL;
  *(_BYTE *)(v2 + 28) = 0;
  *(_DWORD *)(v2 + 24) = -1;
  v3 = FileReader_OpenBySearch("snd_add.bin");
  if ( !v3 )
  {
LABEL_21:
    operator delete((void *)v2);
    return 0LL;
  }
  FileReader_Seek();
  FileReader_Read(v3, &v23, 4LL);
  FileReader_Read(v3, &v22, 4LL);
  FileReader_Close(v3);
  v5 = *(std::__node_alloc **)v2;
  v4 = *(char **)(v2 + 8);
  v21 = 0;
  v6 = (unsigned int)(v22 - v23);
  if ( v4 - (char *)v5 <= v6 )
  {
    v8 = (char *)(v6 - (v4 - (char *)v5));
    if ( v8 )
    {
      if ( *(_QWORD *)(v2 + 16) - (_QWORD)v4 >= (unsigned __int64)v8 )
        std::vector<unsigned char>::_M_fill_insert_aux(v2, v4, (size_t)v8);
      else
        std::vector<unsigned char>::_M_insert_overflow(v2, (int)v4, (int)&v21, (int)&v24, (size_t)v8);
    }
  }
  else
  {
    v7 = (char *)v5 + v6;
    if ( v7 != v4 )
      *(_QWORD *)(v2 + 8) = v7;
  }
  v9 = FileReader_OpenBySearch("snd.bin");
  v11 = v9;
  if ( !v9 )
  {
    v18 = *(std::__node_alloc **)v2;
    if ( *(_QWORD *)v2 )
    {
      v19 = (void *)(*(_QWORD *)(v2 + 16) - (_QWORD)v18);
      if ( (unsigned __int64)v19 < 0x101 )
        std::__node_alloc::_M_deallocate(v18, v19, v10);
      else
        operator delete(v18);
    }
    goto LABEL_21;
  }
  ((void (__fastcall *)(int, int, int))FileReader_Seek)(v9, v23, 0);
  FileReader_Read(v11, *(_QWORD *)v2, *(_QWORD *)(v2 + 8) - *(_QWORD *)v2);
  v12 = (CBinCtrl *)FileReader_Close(v11);
  SoundKey = CBinCtrl::GetSoundKey(v12);
  v14 = (_BYTE *)SoundKey[5];
  v15 = *(_QWORD *)(v2 + 8) - *(_QWORD *)v2;
  if ( SoundKey[4] - (_QWORD)v14 < v15 )
    v15 = SoundKey[4] - (_QWORD)v14;
  if ( (int)v15 >= 1 )
  {
    **(_BYTE **)v2 ^= *v14;
    if ( (__int64)(v15 << 32) >= 0x100000001LL )
    {
      v16 = (int)v15;
      v17 = 1LL;
      do
      {
        *(_BYTE *)(*(_QWORD *)v2 + v17) ^= *(_BYTE *)(SoundKey[5] + v17);
        ++v17;
      }
      while ( v17 < v16 );
    }
  }
  *(_DWORD *)(v2 + 24) = v1;
  return v2;
}
You would need to reimplement this code to properly read the ogg files with the xor decoding applied to the proper sections of each file being decoded.
Parasite
Posts: 48
Joined: Tue Oct 18, 2022 10:49 pm

Re: Decryption of bin and ogg files

Post by Parasite »

Thank you very much. I will ask again if I am not sure.
atom0s
Posts: 250
Joined: Sat Dec 27, 2014 8:49 pm

Re: Decryption of bin and ogg files

Post by atom0s »

Here's a basic Python 3 script to dump and decrypt all the files.

Simply place this script within the same folder as the 'snd_add.bin' and 'snd.bin' files then run it via:
py sssij2_ogg_dump.py

This will dump all the files found inside of snd.bin into a new /dump/ folder. Files will be named the index they were at inside of the 'snd.bin' file.