Stripping DRM from OverDrive Media Console EPUBs – Part 3 of 3
Part 3: Further OverDrive Media Console Analysis and DRM Removal Automation
In the previous article we identified a weakness within the OverDrive Media Console which allows direct access to EPUB data. However, application of public tools for the removal of the ADEPT DRM layer proved to be fruitless due to the specification noncompliant nature of the EPUB data. In this article we will further investigate the inner workings of OverDrive Media Console and outline several vectors which will allow the removal of the ADEPT DRM layer in an automated fashion.
From inspection of the ineptepub tool we can see that the encrypted version of the RSA certificate is stored in an XML tag titled encryptedKey. So lets use our trusty grep tool again and see what we can turn up within OverDrive Media Console’s program directory:
Very interesting. Apparently OverDrive Media Console stores some information in a SQLite database. Using SFTP lets copy this file to our host system and see what goodies are contained within its binary walled garden.

While most of the information contained within the database is not applicable to our efforts the ZMEDIA and ZLICENSE tables contain some choice information. Examining the contents of these tables we find some columns of data that have the information relevant to our interests:
Table Column Description ZMEDIA ZCONTENTID Unique identifier for the fulfilled EPUB request. ZMEDIA ZTITLE Title of the EPUB. ZMEDIA ZBASEURL Download URL for the fulfilled EPUB request. ZLICENSE ZLICENSESTR A mangled version of the ADEPT rights.xml info.
Jackpot! Although there’s much more data to be investigated most of it has to do with business logic associated with the OverDrive Media Console GUI itself. In theory with this data we should be able to generate a rights.xml file from the ZLICENSESTR column data using an XSLT or manual transformation, package that file with the target EPUB file, and use the ineptepub tool to decrypt the archive’s contents.
For purposes of testing I have created just such an EPUB by extracting the corresponding ZLICENSESTR data, converting it to a proper rights.xml file, and archiving it with the test.epub file as test.rights.epub. Now, when executing the ineptepub tool against the file we get the following result:
Success! If we extract the contents of this archive we find that the AES-128-CBC encryption has been removed from the EPUB contents and the result is a completely open standards compliant EPUB that can be loaded into any compatible reader.
When viewing the EPUB even though OverDrive Media Console will decrypt several pages at once every 10 pages or so and cache the results to improve the interaction with the document on the iPad or iPhone there is a pause of up to a full minute while the next batch of pages are decrypted. Now with this encryption layer removed and the EPUB loaded into iBooks the response time is at least several order of magnitudes faster and much more in line with the experience that a publisher would want a customer to have with their product.
So to recap we are able to strip the ADEPT security layer from the titles downloaded through OverDrive Media Console by the following method:
- Copy the unarchived EPUB data from the device.
- Copy the OverDrive.sqlite database from the device.
- Extract the ZLICENSESTR data for the corresponding EPUB title.
- Convert the ZLICENSESTR to the appropriate rights.xml format and create the file in the extracted EPUB’s META-INF directory.
- Zip the extracted archive’s data into a new EPUB.
- Execute the ineptepub tool on the newly created EPUB.
While this method works there should be a much easier way to utilize the data from the OverDrive.sqlite database to automate the process.
Developing Automated DRM Removal Tool
To begin our development it should be noted that every EPUB that is downloaded to OverDrive Media Console is identified with a unique 32 character hexadecimal Content ID of the form:
01234567-9ABC-DEF0-1234-567890ABCDEF
As this ID is present in both the ZMEDIA and corresponsing ZLICENSE entries of the database we should be able to consolidate this information into a single data structure containing all necessary information about the entries. Furthermore recall that there was a ZBASEURL column in the ZMEDIA table that was described as containing a download URL for the fulfilled EPUB request. The URL exists in the form:
http://acs.contentreserve.com/ACSStore1/
0123-4/567/89A/BC/{01234567-9ABC-DEF0-1234-567890ABCDEF}Fmt410.epub
Note that this URL exists per title within the Content Reserve system as the data contained within the EPUB is encrypted with the same AES cipher key for all requests. Also, from testing it can be seen that there is no known user-agent checking or authentication associated with this URL so any method may be used to retrieve the data including but not limited to: regular browser request, cURL, download accelerator, or even a custom download library. By utilizing this field we are negated from having to transfer the uncompressed EPUB archive from our device. Therefore the only transfer to the host system that should be necessary is the OverDrive.sqlite file.
However, there is still one more catch. As it exists the ineptepub tool requires a rights.xml file to be present in the EPUB archive or it will throw an invalid ADEPT EPUB exception. Therefore the proposed solution will automatically modify the specification noncompliant ADEPT EPUB by adding this rights.xml file effectively making a specification compliant ADEPT EPUB and pass execution off to the ineptepub tool to finish the processing.
Finally, since Python is currently being used for execution of the ineptepub tool the solution may as well also execute within the same Python environment. With all these requirements in place we present to you:
OverDrive Media Console DRM Stripper v1.1 (omcstrip.py)
Simply execute this tool passing in the path to your OverDrive.sqlite and adeptkey.der files and the tool will print out a list of EPUBs ready to be downloaded and stripped of the ADEPT DRM layer. Execute the tool along with a desired Content ID and the EPUB will be automatically downloaded from the server, insert the necessary rights.xml file, and delegate the actual removal of the DRM to the ineptepub tool.
OMCStrip Usage Information
python ./omcstrip.py --help OverDrive Media Console DRM Stripper Usage: omcstrip.py [OPTION]... Startup: -h, --help print this help -l, --list list available files for processing and exit -i, --id content id of the asset to be processed. -a, --all process all available assets -d, --debug print debug information -v, --version print script version and exit Input: -s, --sqlfile OverDrive SQLite database (Default: OverDrive.sqlite) -k, --keyfile Extracted Abode ADEPT DER key file (Default: adeptkey.der)
python ./omcstrip.py --list Content ID Title ---------- ------------ 01234567-9ABC-DEF0-1234-567890ABCDEF Test EPUB
Example OMCStrip Excution
python ./omcstrip.py --id 01234567-9ABC-DEF0-1234-567890ABCDEF Content ID Title ---------- ------------ 01234567-9ABC-DEF0-1234-567890ABCDEF Test EPUB Downloading 01234567-9ABC-DEF0-1234-567890ABCDEF.epub (12345678 bytes) Downloading complete. Injecting rights.xml Stripping Adobe ADAPT DRM from 01234567-9ABC-DEF0-1234-567890ABCDEF.epub Saving ePub as 01234567-9ABC-DEF0-1234-567890ABCDEF.decoded.epub
Conclusion
While the ADEPT DRM scheme provides excellent content protection in accordance with the EPUB specification its use as a rights management tool is architecturally flawed. Furthermore, OverDrive Media Console’s unencrypted and trivially obfuscated implementation of its own standard can be easily leveraged to repackage the content into a specification compliant format which can be used in conjunction with existing tools for easy decryption.





Forgive me for necro-posting. Is there a n00b-friendly guide on this for windows?
This is fine article. Thank you. I’ve got an Android tablet and the OverDrive Media Console file and database structure is nothing like the above. I’m not up to speed on public key and epub, it make my head swim so cracking the Android scheme will take me a long time. If the author is willing to help, please email me (the email address with this comment is good) or you can find my email addr at my Website. I’ve got an sqlite db from the tablet and an intriguing authorization.xml file that I can email.
Mike,
when I use inetpkey.pyw to extract my key I get the following ADEPT KEY Unexpected error. I search online but can’t find what this might mean. Any help would be greatly appreciated. I tried this with ADE 2.0 and 1.7.2 Same result.
Traceback (most recent call last):
File “C:\Python Script for DRM stripping\inetpkey.pyw”, line 361, in main
success = retrieve_key(keypath)
File “C:\Python Script for DRM stripping\inetpkey.pyw”, line 277, in retrieve_key
userkey = AES.new(keykey, AES.MODE_CBC).decrypt(userkey)
File “C:\Python26\lib\site-packages\Crypto\Cipher\AES.py”, line 95, in new
return AESCipher(key, *args, **kwargs)
File “C:\Python26\lib\site-packages\Crypto\Cipher\AES.py”, line 59, in __init__
blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs)
File “C:\Python26\lib\site-packages\Crypto\Cipher\blockalgo.py”, line 141, in __init__
self._cipher = factory.new(key, *args, **kwargs)
ValueError: IV must be 16 bytes long
I am in the same boat. Got almost the same errors, I thought it is ADE 2.0 but if you say you tried lower version it may be somewhere else…
I wonder if anybody has an idea
Had the same error, then found ineptkey_v5.5.pyw and it worked. Had an older version before.