Skip to content
This repository has been archived by the owner on Sep 4, 2019. It is now read-only.

Commit

Permalink
Updated to v6.0.8
Browse files Browse the repository at this point in the history
  • Loading branch information
Larry Gordon committed Jan 13, 2014
1 parent 7f2127d commit abe3a85
Show file tree
Hide file tree
Showing 125 changed files with 1,061 additions and 261 deletions.
Empty file modified DeDRM_Macintosh_Application/DeDRM ReadMe.rtf
100644 → 100755
Empty file.
6 changes: 3 additions & 3 deletions DeDRM_Macintosh_Application/DeDRM.app/Contents/Info.plist
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@
<key>CFBundleExecutable</key>
<string>droplet</string>
<key>CFBundleGetInfoString</key>
<string>DeDRM AppleScript 6.0.4. Written 2010–2013 by Apprentice Alf and others.</string>
<string>DeDRM AppleScript 6.0.8. Written 2010–2013 by Apprentice Alf and others.</string>
<key>CFBundleIconFile</key>
<string>DeDRM</string>
<key>CFBundleIdentifier</key>
<string>com.apple.ScriptEditor.id.707CCCD5-0C6C-4BEB-B67C-B6E866ADE85A</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<string>6.0.8</string>
<key>CFBundleName</key>
<string>DeDRM</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>6.0.4</string>
<string>6.0.8</string>
<key>CFBundleSignature</key>
<string>dplt</string>
<key>LSRequiresCarbon</key>
Expand Down
Empty file modified DeDRM_Macintosh_Application/DeDRM.app/Contents/PkgInfo
100644 → 100755
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
25 changes: 16 additions & 9 deletions DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@
# Revision history:
# 6.0.0 - Initial release
# 6.0.1 - Bug Fixes for Windows App, Kindle for Mac and Windows Adobe Digital Editions
# 6.0.2 - Restored call to Wine to get Kindle for PC keys
# 6.0.2 - Restored call to Wine to get Kindle for PC keys, added for ADE
# 6.0.3 - Fixes for Kindle for Mac and Windows non-ascii user names
# 6.0.4 - Fixes for stand-alone scripts and applications
# and pdb files in plugin and initial conversion of prefs.
# 6.0.5 - Fix a key issue
# 6.0.6 - Fix up an incorrect function call
# 6.0.7 - Error handling for incomplete PDF metadata
# 6.0.8 - Fixes a Wine key issue and topaz support

"""
Decrypt DRMed ebooks.
"""

PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 0, 2)
PLUGIN_VERSION_TUPLE = (6, 0, 8)
PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE])
# Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
Expand Down Expand Up @@ -213,10 +220,10 @@ def ePubDecrypt(self,path_to_ebook):
else: # linux
from wineutils import WineGetKeys

scriptpath = os.join(self.alfdir,u"adobekey.py")
scriptpath = os.path.join(self.alfdir,u"adobekey.py")
defaultkeys = WineGetKeys(scriptpath, u".der",dedrmprefs['adobewineprefix'])

self.default_key = default_keys[0]
self.default_key = defaultkeys[0]
except:
traceback.print_exc()
self.default_key = u""
Expand Down Expand Up @@ -308,8 +315,8 @@ def PDFDecrypt(self,path_to_ebook):
try:
from wineutils import WineGetKeys

scriptpath = os.join(self.alfdir,u"adobekey.py")
defaultkeys = self.WineGetKeys(scriptpath, u".der",dedrmprefs['adobewineprefix'])
scriptpath = os.path.join(self.alfdir,u"adobekey.py")
defaultkeys = WineGetKeys(scriptpath, u".der",dedrmprefs['adobewineprefix'])
except:
pass

Expand Down Expand Up @@ -386,8 +393,8 @@ def KindleMobiDecrypt(self,path_to_ebook):
else: # linux
from wineutils import WineGetKeys

scriptpath = os.join(self.alfdir,u"kindlekey.py")
defaultkeys = self.WineGetKeys(scriptpath, u".k4i",dedrmprefs['kindlewineprefix'])
scriptpath = os.path.join(self.alfdir,u"kindlekey.py")
defaultkeys = WineGetKeys(scriptpath, u".k4i",dedrmprefs['kindlewineprefix'])
except:
pass

Expand Down Expand Up @@ -426,7 +433,7 @@ def eReaderDecrypt(self,path_to_ebook):
import calibre_plugins.dedrm.prefs as prefs
import calibre_plugins.dedrm.erdr2pml

dedrmrefs = prefs.DeDRM_Prefs()
dedrmprefs = prefs.DeDRM_Prefs()
# Attempt to decrypt epub with each encryption key (generated or provided).
for keyname, userkey in dedrmprefs['ereaderkeys'].items():
keyname_masked = u"".join((u'X' if (x.isdigit()) else x) for x in keyname)
Expand Down
Empty file.
157 changes: 157 additions & 0 deletions DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/android.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/usr/bin/env python
#fileencoding: utf-8

import os
import sys
import zlib
import tarfile
from hashlib import md5
from cStringIO import StringIO
from binascii import a2b_hex, b2a_hex

STORAGE = 'AmazonSecureStorage.xml'

class AndroidObfuscation(object):
'''AndroidObfuscation
For the key, it's written in java, and run in android dalvikvm
'''

key = a2b_hex('0176e04c9408b1702d90be333fd53523')

def encrypt(self, plaintext):
cipher = self._get_cipher()
padding = len(self.key) - len(plaintext) % len(self.key)
plaintext += chr(padding) * padding
return b2a_hex(cipher.encrypt(plaintext))

def decrypt(self, ciphertext):
cipher = self._get_cipher()
plaintext = cipher.decrypt(a2b_hex(ciphertext))
return plaintext[:-ord(plaintext[-1])]

def _get_cipher(self):
try:
from Crypto.Cipher import AES
return AES.new(self.key)
except ImportError:
from aescbc import AES, noPadding
return AES(self.key, padding=noPadding())

class AndroidObfuscationV2(AndroidObfuscation):
'''AndroidObfuscationV2
'''

count = 503
password = 'Thomsun was here!'

def __init__(self, salt):
key = self.password + salt
for _ in range(self.count):
key = md5(key).digest()
self.key = key[:8]
self.iv = key[8:16]

def _get_cipher(self):
try :
from Crypto.Cipher import DES
return DES.new(self.key, DES.MODE_CBC, self.iv)
except ImportError:
from python_des import Des, CBC
return Des(self.key, CBC, self.iv)

def parse_preference(path):
''' parse android's shared preference xml '''
storage = {}
read = open(path)
for line in read:
line = line.strip()
# <string name="key">value</string>
if line.startswith('<string name="'):
index = line.find('"', 14)
key = line[14:index]
value = line[index+2:-9]
storage[key] = value
read.close()
return storage

def get_serials(path=None):
''' get serials from android's shared preference xml '''
if path is None:
if not os.path.isfile(STORAGE):
if os.path.isfile("backup.ab"):
get_storage()
else:
return []
path = STORAGE

if not os.path.isfile(path):
return []

storage = parse_preference(path)
salt = storage.get('AmazonSaltKey')
if salt and len(salt) == 16:
sys.stdout.write('Using AndroidObfuscationV2\n')
obfuscation = AndroidObfuscationV2(a2b_hex(salt))
else:
sys.stdout.write('Using AndroidObfuscation\n')
obfuscation = AndroidObfuscation()

def get_value(key):
encrypted_key = obfuscation.encrypt(key)
encrypted_value = storage.get(encrypted_key)
if encrypted_value:
return obfuscation.decrypt(encrypted_value)
return ''

# also see getK4Pids in kgenpids.py
try:
dsnid = get_value('DsnId')
except:
sys.stderr.write('cannot get DsnId\n')
return []

try:
tokens = set(get_value('kindle.account.tokens').split(','))
except:
return [dsnid]

serials = []
for token in tokens:
if token:
serials.append('%s%s' % (dsnid, token))
serials.append(dsnid)
for token in tokens:
if token:
serials.append(token)
return serials

def get_storage(path='backup.ab'):
'''get AmazonSecureStorage.xml from android backup.ab
backup.ab can be get using adb command:
shell> adb backup com.amazon.kindle
'''
output = None
read = open(path, 'rb')
head = read.read(24)
if head == 'ANDROID BACKUP\n1\n1\nnone\n':
output = StringIO(zlib.decompress(read.read()))
read.close()

if not output:
return False

tar = tarfile.open(fileobj=output)
for member in tar.getmembers():
if member.name.strip().endswith(STORAGE):
write = open(STORAGE, 'w')
write.write(tar.extractfile(member).read())
write.close()
break

return True

__all__ = [ 'get_storage', 'get_serials', 'parse_preference',
'AndroidObfuscation', 'AndroidObfuscationV2', 'STORAGE']

if __name__ == '__main__':
print get_serials()
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
1.1 get AmazonSecureStorage.xml from /data/data/com.amazon.kindle/shared_prefs/AmazonSecureStorage.xml

1.2 on android 4.0+, run `adb backup com.amazon.kindle` from PC will get backup.ab
now android.py can convert backup.ab to AmazonSecureStorage.xml

2. run `k4mobidedrm.py -a AmazonSecureStorage.xml <infile> <outdir>'
8 changes: 4 additions & 4 deletions DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/config.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__license__ = 'GPL v3'

# Standard Python modules.
import os, traceback
import os, traceback, json

# PyQT4 modules (part of calibre).
from PyQt4.Qt import (Qt, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
Expand Down Expand Up @@ -178,8 +178,8 @@ def __init__(self, parent, key_type_name, plugin_keys, create_key, keyfile_ext =
self.create_key = create_key
self.keyfile_ext = keyfile_ext
self.import_key = (keyfile_ext != u"")
self.binary_file = (keyfile_ext == u".der")
self.json_file = (keyfile_ext == u".k4i")
self.binary_file = (keyfile_ext == u"der")
self.json_file = (keyfile_ext == u"k4i")
self.wineprefix = wineprefix

self.setWindowTitle("{0} {1}: Manage {2}s".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name))
Expand Down Expand Up @@ -676,7 +676,7 @@ def __init__(self, parent=None,):
from calibre_plugins.dedrm.adobekey import adeptkeys

defaultkeys = adeptkeys()
else: # linux
else: # linux
from wineutils import WineGetKeys

scriptpath = os.path.join(parent.parent.alfdir,u"adobekey.py")
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,11 @@ def buildParagraph(self, pclass, pdesc, type, regtype) :
(wtype, num) = pdesc[j]

if wtype == 'ocr' :
word = self.ocrtext[num]
try:
word = self.ocrtext[num]
except:
word = ""

sep = ' '

if handle_links:
Expand Down
Empty file.
Empty file.
2 changes: 1 addition & 1 deletion DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/ineptepub.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from __future__ import with_statement

# ineptepub.pyw, version 5.9
# ineptepub.pyw, version 6.1
# Copyright © 2009-2010 by i♥cabbages

# Released under the terms of the GNU General Public Licence, version 3
Expand Down
12 changes: 8 additions & 4 deletions DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/ineptpdf.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@
# 7.12 - Revised to allow use in calibre plugins to eliminate need for duplicate code
# 7.13 - Fixed erroneous mentions of ineptepub
# 7.14 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 8.0 - Work if TkInter is missing
# 8.0 - Work if TkInter is missing
# 8.0.1 - Broken Metadata fix.

"""
Decrypts Adobe ADEPT-encrypted PDF files.
"""

__license__ = 'GPL v3'
__version__ = "8.0"
__version__ = "8.0.1"

import sys
import os
Expand Down Expand Up @@ -949,8 +950,11 @@ def nextobject(self, direct=False):
try:
(pos, objs) = self.end_type('d')
if len(objs) % 2 != 0:
raise PSSyntaxError(
'Invalid dictionary construct: %r' % objs)
print "Incomplete dictionary construct"
objs.append("") # this isn't necessary.
# temporary fix. is this due to rental books?
# raise PSSyntaxError(
# 'Invalid dictionary construct: %r' % objs)
d = dict((literal_name(k), v) \
for (k,v) in choplist(2, objs))
self.push((pos, d))
Expand Down
13 changes: 10 additions & 3 deletions DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/k4mobidedrm.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ class DrmException(Exception):
from calibre_plugins.dedrm import mobidedrm
from calibre_plugins.dedrm import topazextract
from calibre_plugins.dedrm import kgenpids
from calibre_plugins.dedrm import android
else:
import mobidedrm
import topazextract
import kgenpids
import android

# Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get
Expand Down Expand Up @@ -188,7 +190,7 @@ def fixup(m):
def GetDecryptedBook(infile, kDatabases, serials, pids, starttime = time.time()):
# handle the obvious cases at the beginning
if not os.path.isfile(infile):
raise DRMException (u"Input file does not exist.")
raise DrmException(u"Input file does not exist.")

mobi = True
magic3 = open(infile,'rb').read(3)
Expand Down Expand Up @@ -273,7 +275,7 @@ def decryptBook(infile, outdir, kDatabaseFiles, serials, pids):
def usage(progname):
print u"Removes DRM protection from Mobipocket, Amazon KF8, Amazon Print Replica and Amazon Topaz ebooks"
print u"Usage:"
print u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] <infile> <outdir>".format(progname)
print u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] [ -a <AmazonSecureStorage.xml> ] <infile> <outdir>".format(progname)

#
# Main
Expand All @@ -284,7 +286,7 @@ def cli_main():
print u"K4MobiDeDrm v{0}.\nCopyright © 2008-2013 The Dark Reverser et al.".format(__version__)

try:
opts, args = getopt.getopt(argv[1:], "k:p:s:")
opts, args = getopt.getopt(argv[1:], "k:p:s:a:")
except getopt.GetoptError, err:
print u"Error in options or arguments: {0}".format(err.args[0])
usage(progname)
Expand Down Expand Up @@ -312,6 +314,11 @@ def cli_main():
if a == None :
raise DrmException("Invalid parameter for -s")
serials = a.split(',')
if o == '-a':
if a == None:
continue
serials.extend(android.get_serials(a))
serials.extend(android.get_serials())

# try with built in Kindle Info files if not on Linux
k4 = not sys.platform.startswith('linux')
Expand Down
Empty file.
Loading

0 comments on commit abe3a85

Please sign in to comment.