Updated version number, copied fix to all tools, updated READMEs and FAQs

This commit is contained in:
Apprentice Harper 2017-10-20 08:09:16 +01:00
parent 8d9f384492
commit f04f9eca04
16 changed files with 247 additions and 160 deletions

View File

@ -24,7 +24,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>droplet</string> <string>droplet</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>DeDRM AppleScript 6.5.4 Written 20102017 by Apprentice Alf et al.</string> <string>DeDRM AppleScript 6.5.5 Written 20102017 by Apprentice Alf et al.</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>DeDRM</string> <string>DeDRM</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -36,7 +36,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>6.5.4</string> <string>6.5.5</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>dplt</string> <string>dplt</string>
<key>LSRequiresCarbon</key> <key>LSRequiresCarbon</key>

View File

@ -2,6 +2,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import with_statement from __future__ import with_statement
# __init__.py for DeDRM_plugin
# Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3' __license__ = 'GPL v3'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@ -58,6 +62,7 @@ __docformat__ = 'restructuredtext en'
# 6.5.2 - Another Topaz fix # 6.5.2 - Another Topaz fix
# 6.5.3 - Warn about KFX files explicitly # 6.5.3 - Warn about KFX files explicitly
# 6.5.4 - Mac App Fix, improve PDF decryption, handle latest tcl changes in ActivePython # 6.5.4 - Mac App Fix, improve PDF decryption, handle latest tcl changes in ActivePython
# 6.5.5 - Finally a fix for the Windows non-ASCII user names.
""" """
@ -65,7 +70,7 @@ Decrypt DRMed ebooks.
""" """
PLUGIN_NAME = u"DeDRM" PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 5, 4) PLUGIN_VERSION_TUPLE = (6, 5, 5)
PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE]) 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. # Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME = PLUGIN_NAME + '_Help.htm' RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@ -289,8 +294,8 @@ class DeDRM(FileTypePlugin):
except Exception, e: except Exception, e:
pass pass
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
# import the Adobe Adept ePub handler # import the Adobe Adept ePub handler
import calibre_plugins.dedrm.ineptepub as ineptepub import calibre_plugins.dedrm.ineptepub as ineptepub
@ -380,17 +385,19 @@ class DeDRM(FileTypePlugin):
except: except:
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime) print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc() traceback.print_exc()
print u"{0} v{1}: Decrypted with new default key after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Decrypted with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
return of.name return of.name
print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
except Exception, e: except Exception, e:
print u"{0} v{1}: Unexpected Exception trying a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc()
pass pass
# Something went wrong with decryption. # Something went wrong with decryption.
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
# Not a Barnes & Noble nor an Adobe Adept # Not a Barnes & Noble nor an Adobe Adept
# Import the fixed epub. # Import the fixed epub.
@ -489,8 +496,8 @@ class DeDRM(FileTypePlugin):
pass pass
# Something went wrong with decryption. # Something went wrong with decryption.
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
def KindleMobiDecrypt(self,path_to_ebook): def KindleMobiDecrypt(self,path_to_ebook):
@ -557,8 +564,8 @@ class DeDRM(FileTypePlugin):
pass pass
if not decoded: if not decoded:
#if you reached here then no luck raise and exception #if you reached here then no luck raise and exception
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
of = self.temporary_file(book.getBookExtension()) of = self.temporary_file(book.getBookExtension())
book.getFile(of.name) book.getFile(of.name)
@ -592,8 +599,8 @@ class DeDRM(FileTypePlugin):
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime)
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
def run(self, path_to_ebook): def run(self, path_to_ebook):

View File

@ -3,10 +3,13 @@
from __future__ import with_statement from __future__ import with_statement
# k4mobidedrm.py, version 5.3 # k4mobidedrm.py
# Copyright © 2009-2015 by ApprenticeHarper et al. # Copyright © 2008-2017 by Apprentice Harper et al.
# engine to remove drm from Kindle and Mobipocket ebooks __license__ = 'GPL v3'
__version__ = '5.5'
# Engine to remove drm from Kindle and Mobipocket ebooks
# for personal use for archiving and converting your ebooks # for personal use for archiving and converting your ebooks
# PLEASE DO NOT PIRATE EBOOKS! # PLEASE DO NOT PIRATE EBOOKS!
@ -17,12 +20,11 @@ from __future__ import with_statement
# readable for a long, long time # readable for a long, long time
# This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle, # This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle,
# unswindle, DarkReverser, ApprenticeAlf, DiapDealer, some_updates # unswindle, DarkReverser, ApprenticeAlf, and many many others
# and many many others
# Special thanks to The Dark Reverser for MobiDeDrm and CMBDTC for cmbdtc_dump # Special thanks to The Dark Reverser for MobiDeDrm and CMBDTC for cmbdtc_dump
# from which this script borrows most unashamedly. # from which this script borrows most unashamedly.
# Changelog # Changelog
# 1.0 - Name change to k4mobidedrm. Adds Mac support, Adds plugin code # 1.0 - Name change to k4mobidedrm. Adds Mac support, Adds plugin code
# 1.1 - Adds support for additional kindle.info files # 1.1 - Adds support for additional kindle.info files
@ -57,9 +59,7 @@ from __future__ import with_statement
# 5.2 - Fixed error in command line processing of unicode arguments # 5.2 - Fixed error in command line processing of unicode arguments
# 5.3 - Changed Android support to allow passing of backup .ab files # 5.3 - Changed Android support to allow passing of backup .ab files
# 5.4 - Recognise KFX files masquerading as azw, even if we can't decrypt them yet. # 5.4 - Recognise KFX files masquerading as azw, even if we can't decrypt them yet.
# 5.5 - Added GPL v3 licence explicitly.
__version__ = '5.4'
import sys, os, re import sys, os, re
import csv import csv
@ -295,7 +295,7 @@ def usage(progname):
def cli_main(): def cli_main():
argv=unicode_argv() argv=unicode_argv()
progname = os.path.basename(argv[0]) progname = os.path.basename(argv[0])
print u"K4MobiDeDrm v{0}.\nCopyright © 2008-2013 The Dark Reverser et al.".format(__version__) print u"K4MobiDeDrm v{0}.\nCopyright © 2008-2017 Apprentice Harper et al.".format(__version__)
try: try:
opts, args = getopt.getopt(argv[1:], "k:p:s:a:") opts, args = getopt.getopt(argv[1:], "k:p:s:a:")

View File

@ -4,10 +4,14 @@
from __future__ import with_statement from __future__ import with_statement
# kgenpids.py # kgenpids.py
# Copyright © 2010-2015 by some_updates, Apprentice Alf and Apprentice Harper # Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '2.1'
# Revision history: # Revision history:
# 2.0 - Fix for non-ascii Windows user names # 2.0 - Fix for non-ascii Windows user names
# 2.1 - Actual fix for non-ascii WIndows user names.
import sys import sys
import os, csv import os, csv
@ -194,21 +198,7 @@ keynames = ['kindle.account.tokens','kindle.cookie.item','eulaVersionAccepted','
def getK4Pids(rec209, token, kindleDatabase): def getK4Pids(rec209, token, kindleDatabase):
global charMap1 global charMap1
pids = [] pids = []
try:
# Get the Mazama Random number
MazamaRandomNumber = (kindleDatabase[1])['MazamaRandomNumber'].decode('hex')
# Get the IDString used to decode the Kindle Info file
IDString = (kindleDatabase[1])['IDString'].decode('hex')
# Get the UserName stored when the Kindle Info file was decoded
UserName = (kindleDatabase[1])['UserName'].decode('hex')
except KeyError:
print u"Keys not found in the database {0}.".format(kindleDatabase[0])
return pids
try: try:
# Get the kindle account token, if present # Get the kindle account token, if present
kindleAccountToken = (kindleDatabase[1])['kindle.account.tokens'].decode('hex') kindleAccountToken = (kindleDatabase[1])['kindle.account.tokens'].decode('hex')
@ -217,14 +207,47 @@ def getK4Pids(rec209, token, kindleDatabase):
kindleAccountToken="" kindleAccountToken=""
pass pass
# Get the ID string used try:
encodedIDString = encodeHash(IDString,charMap1) # Get the DSN token, if present
DSN = (kindleDatabase[1])['DSN'].decode('hex')
print u"Got DSN key from database {0}".format(kindleDatabase[0])
except KeyError:
# See if we have the info to generate the DSN
try:
# Get the Mazama Random number
MazamaRandomNumber = (kindleDatabase[1])['MazamaRandomNumber'].decode('hex')
#print u"Got MazamaRandomNumber from database {0}".format(kindleDatabase[0])
try:
# Get the SerialNumber token, if present
IDString = (kindleDatabase[1])['SerialNumber'].decode('hex')
print u"Got SerialNumber from database {0}".format(kindleDatabase[0])
except KeyError:
# Get the IDString we added
IDString = (kindleDatabase[1])['IDString'].decode('hex')
# Get the current user name try:
encodedUsername = encodeHash(UserName,charMap1) # Get the UsernameHash token, if present
encodedUsername = (kindleDatabase[1])['UsernameHash'].decode('hex')
print u"Got UsernameHash from database {0}".format(kindleDatabase[0])
except KeyError:
# Get the UserName we added
UserName = (kindleDatabase[1])['UserName'].decode('hex')
# encode it
encodedUsername = encodeHash(UserName,charMap1)
#print u"encodedUsername",encodedUsername.encode('hex')
except KeyError:
print u"Keys not found in the database {0}.".format(kindleDatabase[0])
return pids
# concat, hash and encode to calculate the DSN # Get the ID string used
DSN = encode(SHA1(MazamaRandomNumber+encodedIDString+encodedUsername),charMap1) encodedIDString = encodeHash(IDString,charMap1)
#print u"encodedIDString",encodedIDString.encode('hex')
# concat, hash and encode to calculate the DSN
DSN = encode(SHA1(MazamaRandomNumber+encodedIDString+encodedUsername),charMap1)
#print u"DSN",DSN.encode('hex')
pass
# Compute the device PID (for which I can tell, is used for nothing). # Compute the device PID (for which I can tell, is used for nothing).
table = generatePidEncryptionTable() table = generatePidEncryptionTable()

View File

@ -4,7 +4,10 @@
from __future__ import with_statement from __future__ import with_statement
# kindlekey.py # kindlekey.py
# Copyright © 2010-2017 by some_updates, Apprentice Alf and Apprentice Harper # Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '2.5'
# Revision history: # Revision history:
# 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc. # 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc.
@ -24,15 +27,13 @@ from __future__ import with_statement
# Also removed old .kinfo file support (pre-2011) # Also removed old .kinfo file support (pre-2011)
# 2.3 - Added more field names thanks to concavegit's KFX code. # 2.3 - Added more field names thanks to concavegit's KFX code.
# 2.4 - Fix for complex Mac disk setups, thanks to Tibs # 2.4 - Fix for complex Mac disk setups, thanks to Tibs
# 2.5 - Final Fix for Windows user names with non-ascii characters, thanks to oneofusoneofus
""" """
Retrieve Kindle for PC/Mac user key. Retrieve Kindle for PC/Mac user key.
""" """
__license__ = 'GPL v3'
__version__ = '2.4'
import sys, os, re import sys, os, re
from struct import pack, unpack, unpack_from from struct import pack, unpack, unpack_from
import json import json
@ -887,10 +888,18 @@ if iswindows:
if errcd == 234: if errcd == 234:
# bad wine implementation up through wine 1.3.21 # bad wine implementation up through wine 1.3.21
return "AlternateUserName" return "AlternateUserName"
# double the buffer size
buffer = create_unicode_buffer(len(buffer) * 2) buffer = create_unicode_buffer(len(buffer) * 2)
size.value = len(buffer) size.value = len(buffer)
# return low byte of the unicode value of each character of the username
return buffer.value.encode('utf-16-le')[::2] # replace any non-ASCII values with 0xfffd
for i in xrange(0,len(buffer)):
if buffer[i]>u"\u007f":
#print u"swapping char "+str(i)+" ("+buffer[i]+")"
buffer[i] = u"\ufffd"
# return utf-8 encoding of modified username
#print u"modified username:"+buffer.value
return buffer.value.encode('utf-8')
return GetUserName return GetUserName
GetUserName = GetUserName() GetUserName = GetUserName()
@ -1015,7 +1024,12 @@ if iswindows:
'SerialNumber',\ 'SerialNumber',\
'UsernameHash',\ 'UsernameHash',\
'kindle.directedid.info',\ 'kindle.directedid.info',\
'DSN' 'DSN',\
'kindle.accounttype.info',\
'krx.flashcardsplugin.data.encryption_key',\
'krx.notebookexportplugin.data.encryption_key',\
'proxy.http.password',\
'proxy.http.username'
] ]
DB = {} DB = {}
with open(kInfoFile, 'rb') as infoReader: with open(kInfoFile, 'rb') as infoReader:

View File

@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# mobidedrm.py, version 0.38 # mobidedrm.py
# Copyright © 2008 The Dark Reverser # Copyright © 2008 The Dark Reverser
# # Portions © 20082017 Apprentice Harper et al.
# Modified 20082012 by some_updates, DiapDealer and Apprentice Alf
__license__ = 'GPL v3'
__version__ = u"0.42"
# This is a python script. You need a Python interpreter to run it. # This is a python script. You need a Python interpreter to run it.
# For example, ActiveState Python, which exists for windows. # For example, ActiveState Python, which exists for windows.
@ -69,9 +71,7 @@
# 0.39 - Fixed problem with TEXtREAd and getBookType interface # 0.39 - Fixed problem with TEXtREAd and getBookType interface
# 0.40 - moved unicode_argv call inside main for Windows DeDRM compatibility # 0.40 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 0.41 - Fixed potential unicode problem in command line calls # 0.41 - Fixed potential unicode problem in command line calls
# 0.42 - Added GPL v3 licence. updated/removed some print statements
__version__ = u"0.41"
import sys import sys
import os import os
@ -244,7 +244,7 @@ class MobiBook:
pass pass
def __init__(self, infile): def __init__(self, infile):
print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2012 The Dark Reverser et al.".format(__version__) print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
try: try:
from alfcrypto import Pukall_Cipher from alfcrypto import Pukall_Cipher
@ -288,10 +288,10 @@ class MobiBook:
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18]) self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20]) self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20])
self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C]) self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C])
print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length) #print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length)
if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5): if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5):
self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4]) self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4])
print u"Extra Data Flags: {0:d}".format(self.extra_data_flags) #print u"Extra Data Flags: {0:d}".format(self.extra_data_flags)
if (self.compression != 17480): if (self.compression != 17480):
# multibyte utf8 data is included in the encryption for PalmDoc compression # multibyte utf8 data is included in the encryption for PalmDoc compression
# so clear that byte so that we leave it to be decrypted. # so clear that byte so that we leave it to be decrypted.
@ -516,7 +516,7 @@ def cli_main():
argv=unicode_argv() argv=unicode_argv()
progname = os.path.basename(argv[0]) progname = os.path.basename(argv[0])
if len(argv)<3 or len(argv)>4: if len(argv)<3 or len(argv)>4:
print u"MobiDeDrm v{0}.\nCopyright © 2008-2012 The Dark Reverser et al.".format(__version__) print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
print u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks" print u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks"
print u"Usage:" print u"Usage:"
print u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname) print u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname)

View File

@ -30,8 +30,9 @@
# 6.5.2 - Fix for a new tag in Topaz ebooks # 6.5.2 - Fix for a new tag in Topaz ebooks
# 6.5.3 - Explicitly warn about KFX files # 6.5.3 - Explicitly warn about KFX files
# 6.5.4 - PDF float fix. # 6.5.4 - PDF float fix.
# 6.5.5 - Kindle for PC/Accented characters in username fix.
__version__ = '6.5.4' __version__ = '6.5.5'
import sys import sys
import os, os.path import os, os.path

View File

@ -2,6 +2,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import with_statement from __future__ import with_statement
# __init__.py for DeDRM_plugin
# Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3' __license__ = 'GPL v3'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
@ -58,6 +62,7 @@ __docformat__ = 'restructuredtext en'
# 6.5.2 - Another Topaz fix # 6.5.2 - Another Topaz fix
# 6.5.3 - Warn about KFX files explicitly # 6.5.3 - Warn about KFX files explicitly
# 6.5.4 - Mac App Fix, improve PDF decryption, handle latest tcl changes in ActivePython # 6.5.4 - Mac App Fix, improve PDF decryption, handle latest tcl changes in ActivePython
# 6.5.5 - Finally a fix for the Windows non-ASCII user names.
""" """
@ -65,7 +70,7 @@ Decrypt DRMed ebooks.
""" """
PLUGIN_NAME = u"DeDRM" PLUGIN_NAME = u"DeDRM"
PLUGIN_VERSION_TUPLE = (6, 5, 4) PLUGIN_VERSION_TUPLE = (6, 5, 5)
PLUGIN_VERSION = u".".join([unicode(str(x)) for x in PLUGIN_VERSION_TUPLE]) 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. # Include an html helpfile in the plugin's zipfile with the following name.
RESOURCE_NAME = PLUGIN_NAME + '_Help.htm' RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@ -289,8 +294,8 @@ class DeDRM(FileTypePlugin):
except Exception, e: except Exception, e:
pass pass
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
# import the Adobe Adept ePub handler # import the Adobe Adept ePub handler
import calibre_plugins.dedrm.ineptepub as ineptepub import calibre_plugins.dedrm.ineptepub as ineptepub
@ -380,17 +385,19 @@ class DeDRM(FileTypePlugin):
except: except:
print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime) print u"{0} v{1}: Exception when saving a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc() traceback.print_exc()
print u"{0} v{1}: Decrypted with new default key after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Decrypted with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
# Return the modified PersistentTemporary file to calibre. # Return the modified PersistentTemporary file to calibre.
return of.name return of.name
print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
except Exception, e: except Exception, e:
print u"{0} v{1}: Unexpected Exception trying a new default key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)
traceback.print_exc()
pass pass
# Something went wrong with decryption. # Something went wrong with decryption.
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
# Not a Barnes & Noble nor an Adobe Adept # Not a Barnes & Noble nor an Adobe Adept
# Import the fixed epub. # Import the fixed epub.
@ -489,8 +496,8 @@ class DeDRM(FileTypePlugin):
pass pass
# Something went wrong with decryption. # Something went wrong with decryption.
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
def KindleMobiDecrypt(self,path_to_ebook): def KindleMobiDecrypt(self,path_to_ebook):
@ -557,8 +564,8 @@ class DeDRM(FileTypePlugin):
pass pass
if not decoded: if not decoded:
#if you reached here then no luck raise and exception #if you reached here then no luck raise and exception
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime))
of = self.temporary_file(book.getBookExtension()) of = self.temporary_file(book.getBookExtension())
book.getFile(of.name) book.getFile(of.name)
@ -592,8 +599,8 @@ class DeDRM(FileTypePlugin):
print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime) print u"{0} v{1}: Failed to decrypt with key {2:s} after {3:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION,keyname_masked,time.time()-self.starttime)
print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.\nRead the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime) print u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION,time.time()-self.starttime)
raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime)) raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds. Read the FAQs at Harper's repository: https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
def run(self, path_to_ebook): def run(self, path_to_ebook):

View File

@ -3,10 +3,13 @@
from __future__ import with_statement from __future__ import with_statement
# k4mobidedrm.py, version 5.5 # k4mobidedrm.py
# Copyright © 2009-2017 by ApprenticeHarper et al. # Copyright © 2008-2017 by Apprentice Harper et al.
# engine to remove drm from Kindle and Mobipocket ebooks __license__ = 'GPL v3'
__version__ = '5.5'
# Engine to remove drm from Kindle and Mobipocket ebooks
# for personal use for archiving and converting your ebooks # for personal use for archiving and converting your ebooks
# PLEASE DO NOT PIRATE EBOOKS! # PLEASE DO NOT PIRATE EBOOKS!
@ -17,12 +20,11 @@ from __future__ import with_statement
# readable for a long, long time # readable for a long, long time
# This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle, # This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle,
# unswindle, DarkReverser, ApprenticeAlf, DiapDealer, some_updates # unswindle, DarkReverser, ApprenticeAlf, and many many others
# and many many others
# Special thanks to The Dark Reverser for MobiDeDrm and CMBDTC for cmbdtc_dump # Special thanks to The Dark Reverser for MobiDeDrm and CMBDTC for cmbdtc_dump
# from which this script borrows most unashamedly. # from which this script borrows most unashamedly.
# Changelog # Changelog
# 1.0 - Name change to k4mobidedrm. Adds Mac support, Adds plugin code # 1.0 - Name change to k4mobidedrm. Adds Mac support, Adds plugin code
# 1.1 - Adds support for additional kindle.info files # 1.1 - Adds support for additional kindle.info files
@ -57,15 +59,11 @@ from __future__ import with_statement
# 5.2 - Fixed error in command line processing of unicode arguments # 5.2 - Fixed error in command line processing of unicode arguments
# 5.3 - Changed Android support to allow passing of backup .ab files # 5.3 - Changed Android support to allow passing of backup .ab files
# 5.4 - Recognise KFX files masquerading as azw, even if we can't decrypt them yet. # 5.4 - Recognise KFX files masquerading as azw, even if we can't decrypt them yet.
# 5.5 - Support multiple input files # 5.5 - Added GPL v3 licence explicitly.
__version__ = '5.5'
import sys, os, re import sys, os, re
import csv import csv
import getopt import getopt
import glob
import re import re
import traceback import traceback
import time import time
@ -289,7 +287,7 @@ def decryptBook(infile, outdir, kDatabaseFiles, androidFiles, serials, pids):
def usage(progname): def usage(progname):
print u"Removes DRM protection from Mobipocket, Amazon KF8, Amazon Print Replica and Amazon Topaz ebooks" print u"Removes DRM protection from Mobipocket, Amazon KF8, Amazon Print Replica and Amazon Topaz ebooks"
print u"Usage:" print u"Usage:"
print u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] [ -a <AmazonSecureStorage.xml|backup.ab> ] <infile, infiles, or indir> <outdir>".format(progname) print u" {0} [-k <kindle.k4i>] [-p <comma separated PIDs>] [-s <comma separated Kindle serial numbers>] [ -a <AmazonSecureStorage.xml|backup.ab> ] <infile> <outdir>".format(progname)
# #
# Main # Main
@ -297,7 +295,7 @@ def usage(progname):
def cli_main(): def cli_main():
argv=unicode_argv() argv=unicode_argv()
progname = os.path.basename(argv[0]) progname = os.path.basename(argv[0])
print u"K4MobiDeDrm v{0}.\nCopyright © 2008-2013 The Dark Reverser et al.".format(__version__) print u"K4MobiDeDrm v{0}.\nCopyright © 2008-2017 Apprentice Harper et al.".format(__version__)
try: try:
opts, args = getopt.getopt(argv[1:], "k:p:s:a:") opts, args = getopt.getopt(argv[1:], "k:p:s:a:")
@ -309,7 +307,8 @@ def cli_main():
usage(progname) usage(progname)
sys.exit(2) sys.exit(2)
outdir = args.pop() infile = args[0]
outdir = args[1]
kDatabaseFiles = [] kDatabaseFiles = []
androidFiles = [] androidFiles = []
serials = [] serials = []
@ -336,21 +335,7 @@ def cli_main():
# try with built in Kindle Info files if not on Linux # try with built in Kindle Info files if not on Linux
k4 = not sys.platform.startswith('linux') k4 = not sys.platform.startswith('linux')
filenames = [] return decryptBook(infile, outdir, kDatabaseFiles, androidFiles, serials, pids)
for filename in args:
if os.path.isdir(filename):
for file_extension in ['.azw', '.azw1', '.azw3', '.azw4', '.prc', '.mobi', '.pobi']:
filenames += glob.glob(os.path.join(filename, '*%s' % file_extension))
else:
# Assume a filename
filenames.append(filename)
for infile in filenames:
result = decryptBook(infile, outdir, kDatabaseFiles, androidFiles, serials, pids)
if result != 0:
print u'Error with %r' % infile
# return last result only
return result
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -4,10 +4,14 @@
from __future__ import with_statement from __future__ import with_statement
# kgenpids.py # kgenpids.py
# Copyright © 2010-2015 by some_updates, Apprentice Alf and Apprentice Harper # Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '2.1'
# Revision history: # Revision history:
# 2.0 - Fix for non-ascii Windows user names # 2.0 - Fix for non-ascii Windows user names
# 2.1 - Actual fix for non-ascii WIndows user names.
import sys import sys
import os, csv import os, csv
@ -194,21 +198,7 @@ keynames = ['kindle.account.tokens','kindle.cookie.item','eulaVersionAccepted','
def getK4Pids(rec209, token, kindleDatabase): def getK4Pids(rec209, token, kindleDatabase):
global charMap1 global charMap1
pids = [] pids = []
try:
# Get the Mazama Random number
MazamaRandomNumber = (kindleDatabase[1])['MazamaRandomNumber'].decode('hex')
# Get the IDString used to decode the Kindle Info file
IDString = (kindleDatabase[1])['IDString'].decode('hex')
# Get the UserName stored when the Kindle Info file was decoded
UserName = (kindleDatabase[1])['UserName'].decode('hex')
except KeyError:
print u"Keys not found in the database {0}.".format(kindleDatabase[0])
return pids
try: try:
# Get the kindle account token, if present # Get the kindle account token, if present
kindleAccountToken = (kindleDatabase[1])['kindle.account.tokens'].decode('hex') kindleAccountToken = (kindleDatabase[1])['kindle.account.tokens'].decode('hex')
@ -217,14 +207,47 @@ def getK4Pids(rec209, token, kindleDatabase):
kindleAccountToken="" kindleAccountToken=""
pass pass
# Get the ID string used try:
encodedIDString = encodeHash(IDString,charMap1) # Get the DSN token, if present
DSN = (kindleDatabase[1])['DSN'].decode('hex')
print u"Got DSN key from database {0}".format(kindleDatabase[0])
except KeyError:
# See if we have the info to generate the DSN
try:
# Get the Mazama Random number
MazamaRandomNumber = (kindleDatabase[1])['MazamaRandomNumber'].decode('hex')
#print u"Got MazamaRandomNumber from database {0}".format(kindleDatabase[0])
try:
# Get the SerialNumber token, if present
IDString = (kindleDatabase[1])['SerialNumber'].decode('hex')
print u"Got SerialNumber from database {0}".format(kindleDatabase[0])
except KeyError:
# Get the IDString we added
IDString = (kindleDatabase[1])['IDString'].decode('hex')
# Get the current user name try:
encodedUsername = encodeHash(UserName,charMap1) # Get the UsernameHash token, if present
encodedUsername = (kindleDatabase[1])['UsernameHash'].decode('hex')
print u"Got UsernameHash from database {0}".format(kindleDatabase[0])
except KeyError:
# Get the UserName we added
UserName = (kindleDatabase[1])['UserName'].decode('hex')
# encode it
encodedUsername = encodeHash(UserName,charMap1)
#print u"encodedUsername",encodedUsername.encode('hex')
except KeyError:
print u"Keys not found in the database {0}.".format(kindleDatabase[0])
return pids
# concat, hash and encode to calculate the DSN # Get the ID string used
DSN = encode(SHA1(MazamaRandomNumber+encodedIDString+encodedUsername),charMap1) encodedIDString = encodeHash(IDString,charMap1)
#print u"encodedIDString",encodedIDString.encode('hex')
# concat, hash and encode to calculate the DSN
DSN = encode(SHA1(MazamaRandomNumber+encodedIDString+encodedUsername),charMap1)
#print u"DSN",DSN.encode('hex')
pass
# Compute the device PID (for which I can tell, is used for nothing). # Compute the device PID (for which I can tell, is used for nothing).
table = generatePidEncryptionTable() table = generatePidEncryptionTable()

View File

@ -4,7 +4,10 @@
from __future__ import with_statement from __future__ import with_statement
# kindlekey.py # kindlekey.py
# Copyright © 2010-2017 by some_updates, Apprentice Alf and Apprentice Harper # Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '2.5'
# Revision history: # Revision history:
# 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc. # 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc.
@ -24,15 +27,13 @@ from __future__ import with_statement
# Also removed old .kinfo file support (pre-2011) # Also removed old .kinfo file support (pre-2011)
# 2.3 - Added more field names thanks to concavegit's KFX code. # 2.3 - Added more field names thanks to concavegit's KFX code.
# 2.4 - Fix for complex Mac disk setups, thanks to Tibs # 2.4 - Fix for complex Mac disk setups, thanks to Tibs
# 2.5 - Final Fix for Windows user names with non-ascii characters, thanks to oneofusoneofus
""" """
Retrieve Kindle for PC/Mac user key. Retrieve Kindle for PC/Mac user key.
""" """
__license__ = 'GPL v3'
__version__ = '2.4'
import sys, os, re import sys, os, re
from struct import pack, unpack, unpack_from from struct import pack, unpack, unpack_from
import json import json
@ -887,10 +888,18 @@ if iswindows:
if errcd == 234: if errcd == 234:
# bad wine implementation up through wine 1.3.21 # bad wine implementation up through wine 1.3.21
return "AlternateUserName" return "AlternateUserName"
# double the buffer size
buffer = create_unicode_buffer(len(buffer) * 2) buffer = create_unicode_buffer(len(buffer) * 2)
size.value = len(buffer) size.value = len(buffer)
# return low byte of the unicode value of each character of the username
return buffer.value.encode('utf-16-le')[::2] # replace any non-ASCII values with 0xfffd
for i in xrange(0,len(buffer)):
if buffer[i]>u"\u007f":
#print u"swapping char "+str(i)+" ("+buffer[i]+")"
buffer[i] = u"\ufffd"
# return utf-8 encoding of modified username
#print u"modified username:"+buffer.value
return buffer.value.encode('utf-8')
return GetUserName return GetUserName
GetUserName = GetUserName() GetUserName = GetUserName()
@ -1015,7 +1024,12 @@ if iswindows:
'SerialNumber',\ 'SerialNumber',\
'UsernameHash',\ 'UsernameHash',\
'kindle.directedid.info',\ 'kindle.directedid.info',\
'DSN' 'DSN',\
'kindle.accounttype.info',\
'krx.flashcardsplugin.data.encryption_key',\
'krx.notebookexportplugin.data.encryption_key',\
'proxy.http.password',\
'proxy.http.username'
] ]
DB = {} DB = {}
with open(kInfoFile, 'rb') as infoReader: with open(kInfoFile, 'rb') as infoReader:

View File

@ -1,10 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# mobidedrm.py, version 0.38 # mobidedrm.py
# Copyright © 2008 The Dark Reverser # Copyright © 2008 The Dark Reverser
# # Portions © 20082017 Apprentice Harper et al.
# Modified 20082012 by some_updates, DiapDealer and Apprentice Alf
__license__ = 'GPL v3'
__version__ = u"0.42"
# This is a python script. You need a Python interpreter to run it. # This is a python script. You need a Python interpreter to run it.
# For example, ActiveState Python, which exists for windows. # For example, ActiveState Python, which exists for windows.
@ -69,9 +71,7 @@
# 0.39 - Fixed problem with TEXtREAd and getBookType interface # 0.39 - Fixed problem with TEXtREAd and getBookType interface
# 0.40 - moved unicode_argv call inside main for Windows DeDRM compatibility # 0.40 - moved unicode_argv call inside main for Windows DeDRM compatibility
# 0.41 - Fixed potential unicode problem in command line calls # 0.41 - Fixed potential unicode problem in command line calls
# 0.42 - Added GPL v3 licence. updated/removed some print statements
__version__ = u"0.41"
import sys import sys
import os import os
@ -244,7 +244,7 @@ class MobiBook:
pass pass
def __init__(self, infile): def __init__(self, infile):
print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2012 The Dark Reverser et al.".format(__version__) print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
try: try:
from alfcrypto import Pukall_Cipher from alfcrypto import Pukall_Cipher
@ -288,10 +288,10 @@ class MobiBook:
self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18]) self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20]) self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20])
self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C]) self.mobi_version, = struct.unpack('>L',self.sect[0x68:0x6C])
print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length) #print u"MOBI header version {0:d}, header length {1:d}".format(self.mobi_version, self.mobi_length)
if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5): if (self.mobi_length >= 0xE4) and (self.mobi_version >= 5):
self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4]) self.extra_data_flags, = struct.unpack('>H', self.sect[0xF2:0xF4])
print u"Extra Data Flags: {0:d}".format(self.extra_data_flags) #print u"Extra Data Flags: {0:d}".format(self.extra_data_flags)
if (self.compression != 17480): if (self.compression != 17480):
# multibyte utf8 data is included in the encryption for PalmDoc compression # multibyte utf8 data is included in the encryption for PalmDoc compression
# so clear that byte so that we leave it to be decrypted. # so clear that byte so that we leave it to be decrypted.
@ -516,7 +516,7 @@ def cli_main():
argv=unicode_argv() argv=unicode_argv()
progname = os.path.basename(argv[0]) progname = os.path.basename(argv[0])
if len(argv)<3 or len(argv)>4: if len(argv)<3 or len(argv)>4:
print u"MobiDeDrm v{0}.\nCopyright © 2008-2012 The Dark Reverser et al.".format(__version__) print u"MobiDeDrm v{0:s}.\nCopyright © 2008-2017 The Dark Reverser, Apprentice Harper et al.".format(__version__)
print u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks" print u"Removes protection from Kindle/Mobipocket, Kindle/KF8 and Kindle/Print Replica ebooks"
print u"Usage:" print u"Usage:"
print u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname) print u" {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname)

View File

@ -17,7 +17,7 @@ These tools do NOT work with kepubs downloaded using Kobo's desktop app (see the
** Some later Kindles support Amazon's new KFX format which uses a new DRM scheme that these tools cannot remove. To avoid this problem, instead of using files downloaded directly to your Kindle, download from Amazon's web site 'for transfer via USB'. This will give you an older format file that the tools can decrypt. ** Some later Kindles support Amazon's new KFX format which uses a new DRM scheme that these tools cannot remove. To avoid this problem, instead of using files downloaded directly to your Kindle, download from Amazon's web site 'for transfer via USB'. This will give you an older format file that the tools can decrypt.
*** With Adobe Digital Editions 3.0 and later, Adobe have introduced a new, optional, DRM scheme. To avoid this new scheme, you should use Adobe Digital Editions 2.0.1. Some books are required to use the new DRM scheme and so will not download with ADE 2.0.1. If you still want such a book, you will need to use ADE 3.0 or later to download it, but you should remember that no tools to remove Adobe's new DRM scheme exist as of April 2017. *** With Adobe Digital Editions 3.0 and later, Adobe have introduced a new, optional, DRM scheme. To avoid this new scheme, you should use Adobe Digital Editions 2.0.1. Some books are required to use the new DRM scheme and so will not download with ADE 2.0.1. If you still want such a book, you will need to use ADE 3.0 or later to download it, but you should remember that no tools to remove Adobe's new DRM scheme exist as of October 2017.
Installation Installation
@ -82,7 +82,7 @@ Linux Systems Only
Instructions for installing Wine, Kindle for PC, Adobe Digital Editions, Python and PyCrypto Instructions for installing Wine, Kindle for PC, Adobe Digital Editions, Python and PyCrypto
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
These instructions have been tested with Wine 1.4 on Ubuntu. These instructions have been tested with Wine 1.4 on Ubuntu but may now be a bit out of date..
1. First download the software you're going to to have to install. 1. First download the software you're going to to have to install.
a. Adobe Digital Editions 1.7.x from http://helpx.adobe.com/digital-editions/kb/cant-install-digital-editions.html a. Adobe Digital Editions 1.7.x from http://helpx.adobe.com/digital-editions/kb/cant-install-digital-editions.html

View File

@ -21,7 +21,7 @@ But otherwise, if your ebook is from Amazon, Kobo, Barnes & Noble or any of the
### A Recent Change to Kindle for PC/Kindle for Mac ### A Recent Change to Kindle for PC/Kindle for Mac
Starting with version 1.19, Kindle for PC/Mac uses Amazon's new KFX format which these tools can't handle. Stick with version 1.17 or earlier. Kindle for PC 1.17 can be downloaded from https://s3.amazonaws.com/kindleforpc/44183/KindleForPC-installer-1.17.44183.exe and Kindle for Mac 1.17 can be downloaded from https://s3.amazonaws.com/kindleformac/44182/KindleForMac-44182.dmg Starting with version 1.19, Kindle for PC/Mac uses Amazon's new KFX format which these tools can't handle. Stick with version 1.17 or earlier. Kindle for PC 1.17 can be downloaded from https://s3.amazonaws.com/kindleforpc/44183/KindleForPC-installer-1.17.44183.exe and Kindle for Mac 1.17 can be downloaded from https://s3.amazonaws.com/kindleformac/44182/KindleForMac-44182.dmg
If you have already installed or have been updated to 1.19, just go to the preferences and uncheck the auto update checkbox. The download and install 1.17 over the top of the 1.19 installation. You'll also need to delete the KFX folders from your My Kindle Content folder. If you have already installed or have been updated to 1.19 or later, just go to the preferences and uncheck the auto update checkbox. The download and install 1.17 over the top of the 1.19 installation. You'll also need to delete the KFX folders from your My Kindle Content folder.
A second possible solution is to use 1.19 or later, but disable KFX by renaming or disabling a necessary component of the application. This may or may not work on versions after 1.20. In a command window, enter the following commands when Kindle for PC/Mac is not running: A second possible solution is to use 1.19 or later, but disable KFX by renaming or disabling a necessary component of the application. This may or may not work on versions after 1.20. In a command window, enter the following commands when Kindle for PC/Mac is not running:
@ -100,8 +100,6 @@ If you cannot read the ebook on your current device or installed software, the t
## I have installed the calibre plugin, and the book is not already in calibre, but the DRM does not get removed. It is a Kindle book. ## I have installed the calibre plugin, and the book is not already in calibre, but the DRM does not get removed. It is a Kindle book.
If you are on Windows 8 and using the Windows 8 AppStore Kindle app, you must download and install the Kindle for PC application directly from the Amazon website. The tools do not work with the Windows 8 AppStore Kindle app. If you are on Windows 8 and using the Windows 8 AppStore Kindle app, you must download and install the Kindle for PC application directly from the Amazon website. The tools do not work with the Windows 8 AppStore Kindle app.
If you are on Windows, using the Kindle for PC application, and your windows user name has accented or other non-ASCII characters in it, this will cause the plugin to fail. Create a new user account with an ASCII-only username. Install and register Kindle for PC there, and see if things work running calibre and the plugin in that user account.
If this book is from an eInk Kindle (e.g. Paperwhite), you must enter the serial number into the configuration dialog. The serial number is sixteen characters long, and is case-sensitive. If this book is from an eInk Kindle (e.g. Paperwhite), you must enter the serial number into the configuration dialog. The serial number is sixteen characters long, and is case-sensitive.
If this book is from Kindle for Mac or Kindle for PC, you must have the Kindle Software installed on the same computer and user account as your copy of calibre. If this book is from Kindle for Mac or Kindle for PC, you must have the Kindle Software installed on the same computer and user account as your copy of calibre.

View File

@ -4,7 +4,10 @@
from __future__ import with_statement from __future__ import with_statement
# kindlekey.py # kindlekey.py
# Copyright © 2010-2017 by some_updates, Apprentice Alf and Apprentice Harper # Copyright © 2008-2017 Apprentice Harper et al.
__license__ = 'GPL v3'
__version__ = '2.5'
# Revision history: # Revision history:
# 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc. # 1.0 - Kindle info file decryption, extracted from k4mobidedrm, etc.
@ -24,15 +27,13 @@ from __future__ import with_statement
# Also removed old .kinfo file support (pre-2011) # Also removed old .kinfo file support (pre-2011)
# 2.3 - Added more field names thanks to concavegit's KFX code. # 2.3 - Added more field names thanks to concavegit's KFX code.
# 2.4 - Fix for complex Mac disk setups, thanks to Tibs # 2.4 - Fix for complex Mac disk setups, thanks to Tibs
# 2.5 - Final Fix for Windows user names with non-ascii characters, thanks to oneofusoneofus
""" """
Retrieve Kindle for PC/Mac user key. Retrieve Kindle for PC/Mac user key.
""" """
__license__ = 'GPL v3'
__version__ = '2.4'
import sys, os, re import sys, os, re
from struct import pack, unpack, unpack_from from struct import pack, unpack, unpack_from
import json import json
@ -887,10 +888,18 @@ if iswindows:
if errcd == 234: if errcd == 234:
# bad wine implementation up through wine 1.3.21 # bad wine implementation up through wine 1.3.21
return "AlternateUserName" return "AlternateUserName"
# double the buffer size
buffer = create_unicode_buffer(len(buffer) * 2) buffer = create_unicode_buffer(len(buffer) * 2)
size.value = len(buffer) size.value = len(buffer)
# return low byte of the unicode value of each character of the username
return buffer.value.encode('utf-16-le')[::2] # replace any non-ASCII values with 0xfffd
for i in xrange(0,len(buffer)):
if buffer[i]>u"\u007f":
#print u"swapping char "+str(i)+" ("+buffer[i]+")"
buffer[i] = u"\ufffd"
# return utf-8 encoding of modified username
#print u"modified username:"+buffer.value
return buffer.value.encode('utf-8')
return GetUserName return GetUserName
GetUserName = GetUserName() GetUserName = GetUserName()
@ -1015,7 +1024,12 @@ if iswindows:
'SerialNumber',\ 'SerialNumber',\
'UsernameHash',\ 'UsernameHash',\
'kindle.directedid.info',\ 'kindle.directedid.info',\
'DSN' 'DSN',\
'kindle.accounttype.info',\
'krx.flashcardsplugin.data.encryption_key',\
'krx.notebookexportplugin.data.encryption_key',\
'proxy.http.password',\
'proxy.http.username'
] ]
DB = {} DB = {}
with open(kInfoFile, 'rb') as infoReader: with open(kInfoFile, 'rb') as infoReader:

View File

@ -1,7 +1,7 @@
Welcome to the tools! Welcome to the tools!
===================== =====================
This ReadMe_First.txt is meant to give users a quick overview of what is available and how to get started. This document is part of the Tools v6.5.4 archive from Apprentice Harper's github repository: https://github.com/apprenticeharper/DeDRM_tools/ This ReadMe_First.txt is meant to give users a quick overview of what is available and how to get started. This document is part of the Tools v6.5.5 archive from Apprentice Harper's github repository: https://github.com/apprenticeharper/DeDRM_tools/
The is archive includes tools to remove DRM from: The is archive includes tools to remove DRM from:
@ -90,12 +90,13 @@ A link to the tool for removing DRM from ScuolaBooks PDFs, created by "Hex".
Windows and Python Windows and Python
------------------ ------------------
We **strongly** recommend ActiveState's Active Python 2.7 Community Edition for Windows. This can be downloaded for free from: We **strongly** recommend using calibre and the plugin.
If you really want to use the WIndows app or the individual scripts, you'll need to install python.
ActiveState's Active Python 2.7 Community Edition for Windowscan be downloaded for free from:
http://www.activestate.com/activepython/downloads http://www.activestate.com/activepython/downloads
We do **NOT** recommend the version of Python from python.org as it is missing various Windows specific libraries, does not install the Tk Widget kit (for graphical user interfaces) by default, and does not properly update the system PATH environment variable. Therefore using the default python.org build on Windows is simply an exercise in frustration for most Windows users.
In addition, Windows Users need PyCrypto: In addition, Windows Users need PyCrypto:
There are many places to get PyCrypto installers for Windows. One such place is: There are many places to get PyCrypto installers for Windows. One such place is: