Skip to content
Rémy F edited this page Mar 4, 2020 · 12 revisions

DZR_SID, DZR_AES and DZR_CBC keys

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 the MD5_SUM field returned in the track info
  • DZR_AES and the track MD5_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.

DZR_SID

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

DZR_AES

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('')

DZR_CBC

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('')
Clone this wiki locally