-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
74a4c89
commit b1feca3
Showing
54 changed files
with
11,419 additions
and
8,812 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/android.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
6 changes: 6 additions & 0 deletions
6
DeDRM_Macintosh_Application/DeDRM.app/Contents/Resources/android_readme.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.