-
Notifications
You must be signed in to change notification settings - Fork 14
Home
In order to play a track, dzr need to execute the following steps (the DZR keys are in bold):
-
DZR_SID
(unique to your account, and regenerated everyday) is necessary to get theMD5_SUM
field returned in the track info -
DZR_AES
and the trackMD5_SUM
are used to generate the track URL -
DZR_CBC
is used to decrypt the track
In order to get those keys we must extract them from the player sources. I highly recommend using the chrome/chromium debugger to compare with the following screenshots. You can look at the sources of the player webworker using the "Sources" tab:
Note that the first line of this worker code is a symbol table, and a few lines later we got the symbol resolver function, which is called each time the script need to call a names function.
In the following sections we will use this translation function a lot.
With this ID, dzr
can now get the full track MD5, otherwise it could only get 30 seconds.
Your Session ID is very easy to find. Just look at the network request panel
of your debugger and you shall see a Set-Cookie line with sid=yoursidnumber
The URL Generation key, aka the 'Jo' Key (because it start with "Jo" character)
Since the track URL was not part of any JSON we can assume that it was generated by the JS. By looking at the symbol table, we see that we have an 'encrypt' function. Let's have a conditional breakpoint on the resolver when it resolve 'encrypt'. After pressing play on the HTML5 player, out "encrypt" breakpoint is triggered. Now let's take a look at the function scope values we have the following params:
- cdn
- format
- id
- md5
That's all the ingredients required to generate the CDN URL. A closer look to the AES cyphering scope will give us the 16 Bytes AES key.
Congratulation, you just found the AES key, aka the "jo" key, just convert it in ASCII.
[...key].map(e=>String.fromCharCode(e)).join('')
aka the 'Gael' Key for Track deciphering
First, add a logpoint on the translator and play a track for 30 seconds.
This will give you an overview of the function in charge of the deciphering.
You can then, traceback those name (for example decipher
)
to they function and have a look at they closure.
The keys are unziped into 2 UInt8Array, in little endian. Zip them back to get the Blowfish/CBC key, aka the "Gaël" key:
a=[97, ... 103]
b=[49, ... 52]
[].concat(...a.map((c,i)=>[a[i],b[i]]).reverse()).map(e=>String.fromCharCode(e)).join('')