diff --git a/DeDRM_plugin/kindlekey.py b/DeDRM_plugin/kindlekey.py index 9a00b1f..9a299e6 100644 --- a/DeDRM_plugin/kindlekey.py +++ b/DeDRM_plugin/kindlekey.py @@ -1449,6 +1449,18 @@ elif isosx: kInfoFiles=[] found = False home = os.getenv('HOME') + # check for .kinf2018 file in new location (App Store Kindle for Mac) + testpath = home + '/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/storage/.kinf2018' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kinf2018 file: ' + testpath) + found = True + # check for .kinf2018 files + testpath = home + '/Library/Application Support/Kindle/storage/.kinf2018' + if os.path.isfile(testpath): + kInfoFiles.append(testpath) + print('Found k4Mac kinf2018 file: ' + testpath) + found = True # check for .kinf2011 file in new location (App Store Kindle for Mac) testpath = home + '/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/storage/.kinf2011' if os.path.isfile(testpath): @@ -1529,12 +1541,21 @@ elif isosx: cleartext = UnprotectHeaderData(encryptedValue) # now extract the pieces in the same way - # this version is different from K4PC it scales the build number by multipying by 735 pattern = re.compile(r'''\[Version:(\d+)\]\[Build:(\d+)\]\[Cksum:([^\]]+)\]\[Guid:([\{\}a-z0-9\-]+)\]''', re.IGNORECASE) for m in re.finditer(pattern, cleartext): - entropy = str(int(m.group(2)) * 0x2df) + m.group(4) + version = int(m.group(1)) + build = m.group(2) + guid = m.group(4) - cud = CryptUnprotectData(entropy,IDString) + if version == 5: # .kinf2011: identical to K4PC, except the build number gets multiplied + entropy = str(0x2df * int(build)) + guid + cud = CryptUnprotectData(entropy,IDString) + + elif version == 6: # .kinf2018: identical to K4PC + salt = str(0x6d8 * int(build)) + guid + sp = GetUserName() + '+@#$%+' + IDString + passwd = encode(SHA256(sp), charMap5) + key = LibCrypto().keyivgen(passwd, salt, 10000, 0x400)[:32] # loop through the item records until all are processed while len(items) > 0: @@ -1595,9 +1616,28 @@ elif isosx: encdata = encdata[noffset:] encdata = encdata + pfx - # decode using testMap8 to get the CryptProtect Data - encryptedValue = decode(encdata,testMap8) - cleartext = cud.decrypt(encryptedValue) + if version == 5: + # decode using testMap8 to get the CryptProtect Data + encryptedValue = decode(encdata,testMap8) + cleartext = cud.decrypt(encryptedValue) + + elif version == 6: + from Crypto.Cipher import AES + from Crypto.Util import Counter + # decode using new testMap8 to get IV + ciphertext + iv_ciphertext = decode(encdata, testMap8) + # pad IV so that we can substitute AES-CTR for GCM + iv = iv_ciphertext[:12] + b'\x00\x00\x00\x02' + ciphertext = iv_ciphertext[12:] + # convert IV to int for use with pycrypto + iv_ints = unpack('>QQ', iv) + iv = iv_ints[0] << 64 | iv_ints[1] + # set up AES-CTR + ctr = Counter.new(128, initial_value=iv) + cipher = AES.new(key, AES.MODE_CTR, counter=ctr) + # decrypt and decode + cleartext = decode(cipher.decrypt(ciphertext), charMap5) + # print keyname # print cleartext if len(cleartext) > 0: