pyrekordbox: Update to the ``app.asar`` file in Rekordbox v6.6.5 breaks database unlocking

Pioneer changed the app.asar file contents in Rekordbox version 6.6.5. The encryption password of the database key is no longer stored in plain text, which breaks the database unlocking.

Previously, the app.asar file contained JS files in plain text. Since update 6.6.5 the JS files are now stored in a compiled format (.jsc). The password should still be somewhere in the content of the file (jsc/controllers/auth_manager.jsc), but it can no longer be extracted easily.

Please feel free to join the discussion if you have any ideas!

Environment

  • Rekordbox version: >=6.6.5

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 3
  • Comments: 19 (8 by maintainers)

Commits related to this issue

Most upvoted comments

The key of the Rekordbox v6 database can now be downloaded and cached from external sources (mainly the projects in #77) using the command line interface:

python -m pyrekordbox download-key

This is still just a workaround, it still would be nice to find a way to extract the key from the .jsc-files, especially if Pioneer decides to change the key (maybe in Rekordbox v7?). In the mean time this fix should get the project running for everyone:)

If anyone finds some more sources for the key, feel free to add them to the CLI or post the links here in case the other projects remove the key!

One could pass the key to the db handler. This is how it would look:

from pyrekordbox import Rekordbox6Database

db = Rekordbox6Database(key="<insert key here>")

for content in db.get_content():
    print(content.Title, content.Artist.Name)

playlist = db.get_playlist()[0]
for song in playlist.Songs:
    content = song.Content
    print(content.Title, content.Artist.Name)

if you had an old installation, rb.cache file, or the key noted down, you can just use it like thit.

If not one could go to #77 where someone linked to another repository where the developer(s) have embedded the key into the code.

The disassembly of a simple hello world shows that the string “Hello World!” is stored in a “Constant pool” as-is, like other usual executables.

$ cat app.js
function foo() {
    console.log("Hello World!")
}

foo()

$ node --print-bytecode --print-bytecode-filter=foo app.js
[generated bytecode for function: foo (0x1f66e1498a39 <SharedFunctionInfo foo>)]
Bytecode length: 19
Parameter count 1
Register count 3
Frame size 24
OSR urgency: 0
Bytecode age: 0
   21 S> 0x1f66e1499ac0 @    0 : 21 00 00          LdaGlobal [0], [0]
         0x1f66e1499ac3 @    3 : c3                Star1
   29 E> 0x1f66e1499ac4 @    4 : 2d f9 01 02       GetNamedProperty r1, [1], [2]
         0x1f66e1499ac8 @    8 : c4                Star0
         0x1f66e1499ac9 @    9 : 13 02             LdaConstant [2]
         0x1f66e1499acb @   11 : c2                Star2
   29 E> 0x1f66e1499acc @   12 : 5e fa f9 f8 04    CallProperty1 r0, r1, r2, [4]
         0x1f66e1499ad1 @   17 : 0e                LdaUndefined
   49 S> 0x1f66e1499ad2 @   18 : a9                Return
Constant pool (size = 3)
0x1f66e1499a61: [FixedArray] in OldSpace
 - map: 0x12fa427812e1 <Map>
 - length: 3
           0: 0x12fa42784a01 <String[7]: #console>
           1: 0x32d47820c731 <String[3]: #log>
           2: 0x1f66e14999f9 <String[12]: #Hello World!>
Handler Table (size = 0)
Source Position Table (size = 10)
0x1f66e1499ad9 <ByteArray[10]>
Hello World!

I compiled the app.js into jsc and the constant is still intact in the binary.

$ npm install -g bytenode
$ bytenode -n -c app.js
$ grep "Hello World!" app.jsc
Binary file app.jsc matches

As @dylanljones pointed out, the key is the same as in the previous version, and the key may be stored in the jsc intact if it is not obfuscated in a way we don’t expect.

Expecting that the key is a string literal, this gives us a way to “match” the key string that fulfills the known format with surrounding fingerprints of constants. Embedding the match condition (not the key itself) in this repository will not cause any legal concerns.

How about this idea?

Could we use blackbox for credentials?

On Wed, 26 Jul 2023 at 23:04, Dylan @.***> wrote:

Hey, sorry for the inactivity, have a lot of other stuff going on right now. Sadly no progress so far, but I am looking into a few things! The key is still the same as in earlier Rekordbox versions, but i would really like to avoid just hard-coding it for legal reasons (as discussed at the end of this https://rekord.cloud/blog/technical-inspection-of-rekordbox-6-and-its-new-internals blog of rekordcloud).

— Reply to this email directly, view it on GitHub https://github.com/dylanljones/pyrekordbox/issues/64#issuecomment-1652559666, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKXEGX3WRCOYZEHVZUUDUY3XSGH5XANCNFSM6AAAAAARRGJTAQ . You are receiving this because you commented.Message ID: @.***>

Hey Dylan I might have a idea, can I contact you somehow?

Apparently .jsc is compiled v8 bytecode. We can disassemble v8 bytecode, but it will not bring back javascript, but instead human readable v8 instructions: https://github.com/noelex/v8dasm. Maybe then we can look through it look for something that might look like the password.

Another route would be if you knew the format of the password (assuming it has not changed since rekordbox 6.4, you could search in the hex dump for a string which has roughly the same length and type of characters.)

I am not sure if it is a good idea to share parts of the source code of Pioneer here, but i can send you an Email if you want to have a look at the auth_manager.jsc file. If you have Rekordbox 6.6.5 installed, it is also really easy to extract the file from the asar archive yourself. I made a little tool to print out or extract single files form an archive, if you are interested, it is here. The app.asar file is located in RBv6 program data directory in .../rekordbox 6.6.5/rekordboxAgent-win32-x64/resources