]> xmof Git - DeDRM.git/commitdiff
Finally, a proper fix for the accented user name problem
authorApprentice Harper <apprenticeharper@gmail.com>
Tue, 4 Jul 2017 06:05:51 +0000 (07:05 +0100)
committerApprentice Harper <apprenticeharper@gmail.com>
Tue, 4 Jul 2017 06:05:51 +0000 (07:05 +0100)
DeDRM_calibre_plugin/DeDRM_plugin.zip
DeDRM_calibre_plugin/DeDRM_plugin/__init__.py
DeDRM_calibre_plugin/DeDRM_plugin/k4mobidedrm.py
DeDRM_calibre_plugin/DeDRM_plugin/kgenpids.py
DeDRM_calibre_plugin/DeDRM_plugin/kindlekey.py
DeDRM_calibre_plugin/DeDRM_plugin/mobidedrm.py

index a2ea798a47412c7f3e56e4987601d7f4e3edea89..2cce48341a9df5d00cf921c8d7b944c85ab38022 100644 (file)
Binary files a/DeDRM_calibre_plugin/DeDRM_plugin.zip and b/DeDRM_calibre_plugin/DeDRM_plugin.zip differ
index 4592aabb06d931b8601258c82db3d20c38c85b64..19eee96ef3440e2239da4f9aad53674d6c153979 100644 (file)
@@ -2,6 +2,10 @@
 # -*- coding: utf-8 -*-
 
 from __future__ import with_statement
+
+# __init__.py for DeDRM_plugin
+# Copyright © 2008-2017 Apprentice Harper et al.
+
 __license__   = 'GPL v3'
 __docformat__ = 'restructuredtext en'
 
@@ -58,6 +62,7 @@ __docformat__ = 'restructuredtext en'
 #   6.5.2 - Another Topaz fix
 #   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.5 - Finally a fix for the Windows non-ASCII user names.
 
 
 """
@@ -65,7 +70,7 @@ Decrypt DRMed ebooks.
 """
 
 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])
 # Include an html helpfile in the plugin's zipfile with the following name.
 RESOURCE_NAME = PLUGIN_NAME + '_Help.htm'
@@ -289,8 +294,8 @@ class DeDRM(FileTypePlugin):
                 except Exception, e:
                     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)
-            raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".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. 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 calibre_plugins.dedrm.ineptepub as ineptepub
@@ -380,17 +385,19 @@ class DeDRM(FileTypePlugin):
                             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)
                                 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 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)
                 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
 
             # 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)
-            raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".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. 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
         # Import the fixed epub.
@@ -489,8 +496,8 @@ class DeDRM(FileTypePlugin):
                 pass
 
         # 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)
-        raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".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. 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):
@@ -557,8 +564,8 @@ class DeDRM(FileTypePlugin):
                     pass
             if not decoded:
                 #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)
-                raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds".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. 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())
         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}: 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)
-        raise DeDRMError(u"{0} v{1}: Ultimately failed to decrypt after {2:.1f} seconds.".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. 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):
index c3e475cdfeb854d6e3a6c3202514805dd0ec468f..941a134261b8d654e17d851dcfead371e6ce81ca 100644 (file)
@@ -3,10 +3,13 @@
 
 from __future__ import with_statement
 
-# k4mobidedrm.py, version 5.3
-# Copyright © 2009-2015 by ApprenticeHarper et al.
+# k4mobidedrm.py
+# 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
 
 # PLEASE DO NOT PIRATE EBOOKS!
@@ -17,12 +20,11 @@ from __future__ import with_statement
 # readable for a long, long time
 
 # This borrows very heavily from works by CMBDTC, IHeartCabbages, skindle,
-#    unswindle, DarkReverser, ApprenticeAlf, DiapDealer, some_updates
-#    and many many others
+#    unswindle, DarkReverser, ApprenticeAlf, and many many others
+
 # Special thanks to The Dark Reverser for MobiDeDrm and CMBDTC for cmbdtc_dump
 # from which this script borrows most unashamedly.
 
-
 # Changelog
 #  1.0 - Name change to k4mobidedrm. Adds Mac support, Adds plugin code
 #  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.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.
-
-__version__ = '5.4'
-
+#  5.5 - Added GPL v3 licence explicitly.
 
 import sys, os, re
 import csv
@@ -295,7 +295,7 @@ def usage(progname):
 def cli_main():
     argv=unicode_argv()
     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:
         opts, args = getopt.getopt(argv[1:], "k:p:s:a:")
index e99857aae948abdb54a186eee9fce4783d95ab8b..d8991935506c2d05f84dcb640735986cae6eef1c 100644 (file)
@@ -4,10 +4,14 @@
 from __future__ import with_statement
 
 # 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:
 #  2.0   - Fix for non-ascii Windows user names
+#  2.1   - Actual fix for non-ascii WIndows user names.
 
 import sys
 import os, csv
@@ -194,21 +198,7 @@ keynames = ['kindle.account.tokens','kindle.cookie.item','eulaVersionAccepted','
 def getK4Pids(rec209, token, kindleDatabase):
     global charMap1
     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:
         # Get the kindle account token, if present
         kindleAccountToken = (kindleDatabase[1])['kindle.account.tokens'].decode('hex')
@@ -217,14 +207,47 @@ def getK4Pids(rec209, token, kindleDatabase):
         kindleAccountToken=""
         pass
 
-    # Get the ID string used
-    encodedIDString = encodeHash(IDString,charMap1)
-
-    # Get the current user name
-    encodedUsername = encodeHash(UserName,charMap1)
-
-    # concat, hash and encode to calculate the DSN
-    DSN = encode(SHA1(MazamaRandomNumber+encodedIDString+encodedUsername),charMap1)
+    try:
+        # 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')
+
+            try:
+                # 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
+
+        # Get the ID string used
+        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).
     table =  generatePidEncryptionTable()
index 20979c842dec710c755dae3f5eb1bedba3718fc4..e20b7c95b0825fdb3809d53295d20fa914c9a794 100644 (file)
@@ -4,7 +4,10 @@
 from __future__ import with_statement
 
 # 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:
 #  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)
 #  2.3   - Added more field names thanks to concavegit's KFX code.
 #  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.
 """
 
-__license__ = 'GPL v3'
-__version__ = '2.4'
-
 import sys, os, re
 from struct import pack, unpack, unpack_from
 import json
@@ -887,10 +888,18 @@ if iswindows:
                 if errcd == 234:
                     # bad wine implementation up through wine 1.3.21
                     return "AlternateUserName"
+                # double the buffer size
                 buffer = create_unicode_buffer(len(buffer) * 2)
                 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
     GetUserName = GetUserName()
 
@@ -1015,7 +1024,12 @@ if iswindows:
             'SerialNumber',\
             'UsernameHash',\
             '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 = {}
         with open(kInfoFile, 'rb') as infoReader:
index 67e93551a4c1863c3bf250d95dc9a04b65407234..501aa2d5e71f8b31aca3616daf70d5c9898d81d7 100644 (file)
@@ -1,10 +1,12 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-# mobidedrm.py, version 0.38
+# mobidedrm.py
 # Copyright © 2008 The Dark Reverser
-#
-# Modified 2008–2012 by some_updates, DiapDealer and Apprentice Alf
+# Portions © 2008–2017 Apprentice Harper et al.
+
+__license__ = 'GPL v3'
+__version__ = u"0.42"
 
 # This is a python script. You need a Python interpreter to run it.
 # For example, ActiveState Python, which exists for windows.
@@ -69,9 +71,7 @@
 #  0.39 - Fixed problem with TEXtREAd and getBookType interface
 #  0.40 - moved unicode_argv call inside main for Windows DeDRM compatibility
 #  0.41 - Fixed potential unicode problem in command line calls
-
-
-__version__ = u"0.41"
+#  0.42 - Added GPL v3 licence. updated/removed some print statements
 
 import sys
 import os
@@ -244,7 +244,7 @@ class MobiBook:
         pass
 
     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:
             from alfcrypto import Pukall_Cipher
@@ -288,10 +288,10 @@ class MobiBook:
         self.mobi_length, = struct.unpack('>L',self.sect[0x14:0x18])
         self.mobi_codepage, = struct.unpack('>L',self.sect[0x1c:0x20])
         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):
             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):
             # multibyte utf8 data is included in the encryption for PalmDoc compression
             # so clear that byte so that we leave it to be decrypted.
@@ -516,7 +516,7 @@ def cli_main():
     argv=unicode_argv()
     progname = os.path.basename(argv[0])
     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"Usage:"
         print u"    {0} <infile> <outfile> [<Comma separated list of PIDs to try>]".format(progname)