diff options
author | Apprentice Alf <[email protected]> | 2015-03-07 21:18:50 +0000 |
---|---|---|
committer | Apprentice Alf <[email protected]> | 2015-03-07 21:18:50 +0000 |
commit | a30aace99c61c30050f8fee8c3444f2d355c8bd6 (patch) | |
tree | 6f1375e8af821784e83766331097cf42648dba7e /Other_Tools | |
parent | b1feca321df4804b0f178ce96c476a70b9016113 (diff) |
tools v6.0.9
obok added to other tools
Diffstat (limited to 'Other_Tools')
-rw-r--r-- | Other_Tools/Kindle_for_Android_Patches/kindle_version_4.0.2.1/kindle4.0.2.1.patch | 238 | ||||
-rw-r--r-- | Other_Tools/Kobo/obok_2.01.py | 231 |
2 files changed, 469 insertions, 0 deletions
diff --git a/Other_Tools/Kindle_for_Android_Patches/kindle_version_4.0.2.1/kindle4.0.2.1.patch b/Other_Tools/Kindle_for_Android_Patches/kindle_version_4.0.2.1/kindle4.0.2.1.patch new file mode 100644 index 0000000..010f68f --- /dev/null +++ b/Other_Tools/Kindle_for_Android_Patches/kindle_version_4.0.2.1/kindle4.0.2.1.patch @@ -0,0 +1,238 @@ +Only in kindle4.0.2.1: build +diff -r -u10 kindle4.0.2.1_orig/smali/com/amazon/kcp/application/AndroidDeviceInformationProvider.smali kindle4.0.2.1/smali/com/amazon/kcp/application/AndroidDeviceInformationProvider.smali +--- kindle4.0.2.1_orig/smali/com/amazon/kcp/application/AndroidDeviceInformationProvider.smali 2013-05-22 18:39:03.000000000 -0500 ++++ kindle4.0.2.1/smali/com/amazon/kcp/application/AndroidDeviceInformationProvider.smali 2013-05-23 16:54:53.000000000 -0500 +@@ -36,20 +36,22 @@ + .field private maxCpuSpeed:J + + .field private maxMemory:J + + .field private minCpuSpeed:J + + .field private resources:Landroid/content/res/Resources; + + .field private security:Lcom/mobipocket/android/library/reader/AndroidSecurity; + ++.field private pidList:Ljava/lang/String; ++ + .field private totalMemory:J + + + # direct methods + .method static constructor <clinit>()V + .locals 1 + + .prologue + .line 30 + const-class v0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider; +@@ -72,20 +74,24 @@ + .prologue + .line 130 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + + .line 131 + iput-object p1, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->security:Lcom/mobipocket/android/library/reader/AndroidSecurity; + + .line 132 + iput-object p2, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->deviceType:Lcom/amazon/kcp/application/AmazonDeviceType; + ++ const-string v0, "Open DRMed book to show PID list." ++ ++ iput-object v0, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->pidList:Ljava/lang/String; ++ + .line 133 + sget-object v0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->TAG:Ljava/lang/String; + + new-instance v0, Ljava/lang/StringBuilder; + + invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V + + const-string v1, "Device Type is set to \"" + + invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; +@@ -1235,10 +1241,33 @@ + move-result-wide v0 + + iput-wide v0, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->totalMemory:J + + .line 308 + :cond_0 + iget-wide v0, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->totalMemory:J + + return-wide v0 + .end method ++ ++.method public getPidList()Ljava/lang/String; ++ .locals 1 ++ ++ .prologue ++ .line 15 ++ iget-object v0, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->pidList:Ljava/lang/String; ++ ++ return-object v0 ++.end method ++ ++.method public setPidList(Ljava/lang/String;)V ++ .locals 0 ++ .parameter "value" ++ ++ .prologue ++ .line 11 ++ iput-object p1, p0, Lcom/amazon/kcp/application/AndroidDeviceInformationProvider;->pidList:Ljava/lang/String; ++ ++ .line 12 ++ return-void ++.end method ++ +diff -r -u10 kindle4.0.2.1_orig/smali/com/amazon/kcp/application/IDeviceInformationProvider.smali kindle4.0.2.1/smali/com/amazon/kcp/application/IDeviceInformationProvider.smali +--- kindle4.0.2.1_orig/smali/com/amazon/kcp/application/IDeviceInformationProvider.smali 2013-05-22 18:39:03.000000000 -0500 ++++ kindle4.0.2.1/smali/com/amazon/kcp/application/IDeviceInformationProvider.smali 2013-05-23 16:55:58.000000000 -0500 +@@ -23,10 +23,16 @@ + .end method + + .method public abstract getDeviceTypeId()Ljava/lang/String; + .end method + + .method public abstract getOsVersion()Ljava/lang/String; + .end method + + .method public abstract getPid()Ljava/lang/String; + .end method ++ ++.method public abstract getPidList()Ljava/lang/String; ++.end method ++ ++.method public abstract setPidList(Ljava/lang/String;)V ++.end method +diff -r -u10 kindle4.0.2.1_orig/smali/com/amazon/kcp/info/AboutActivity.smali kindle4.0.2.1/smali/com/amazon/kcp/info/AboutActivity.smali +--- kindle4.0.2.1_orig/smali/com/amazon/kcp/info/AboutActivity.smali 2013-05-22 18:39:03.000000000 -0500 ++++ kindle4.0.2.1/smali/com/amazon/kcp/info/AboutActivity.smali 2013-05-23 17:18:14.000000000 -0500 +@@ -486,20 +486,71 @@ + .end local v2 #screenDpi:Ljava/lang/String; + :cond_0 + iget-object v5, p0, Lcom/amazon/kcp/info/AboutActivity;->detailItemList:Ljava/util/List; + + invoke-interface {v5, v0}, Ljava/util/List;->add(Ljava/lang/Object;)Z + + .line 317 + return-void + .end method + ++.method private populatePIDList()V ++ .locals 7 ++ ++ .prologue ++ .line 313 ++ invoke-static {}, Lcom/amazon/kcp/application/DeviceInformationProviderFactory;->getProvider()Lcom/amazon/kcp/application/IDeviceInformationProvider; ++ ++ move-result-object v0 ++ ++ invoke-interface {v0}, Lcom/amazon/kcp/application/IDeviceInformationProvider;->getPidList()Ljava/lang/String; ++ ++ move-result-object v1 ++ ++ .line 314 ++ .local v1, PidList:Ljava/lang/String; ++ iget-object v3, p0, Lcom/amazon/kcp/info/AboutActivity;->groupItemList:Ljava/util/List; ++ ++ new-instance v4, Lcom/amazon/kcp/info/AboutActivity$GroupItem; ++ ++ const-string v5, "PID List" ++ ++ const v6, 0x1 ++ ++ invoke-direct {v4, p0, v5, v6}, Lcom/amazon/kcp/info/AboutActivity$GroupItem;-><init>(Lcom/amazon/kcp/info/AboutActivity;Ljava/lang/String;Z)V ++ ++ invoke-interface {v3, v4}, Ljava/util/List;->add(Ljava/lang/Object;)Z ++ ++ .line 315 ++ new-instance v2, Ljava/util/ArrayList; ++ ++ invoke-direct {v2}, Ljava/util/ArrayList;-><init>()V ++ ++ .line 316 ++ .local v2, children:Ljava/util/List;,"Ljava/util/List<Lcom/amazon/kcp/info/AboutActivity$DetailItem;>;" ++ new-instance v3, Lcom/amazon/kcp/info/AboutActivity$DetailItem; ++ ++ const-string v4, "PIDs" ++ ++ invoke-direct {v3, p0, v4, v1}, Lcom/amazon/kcp/info/AboutActivity$DetailItem;-><init>(Lcom/amazon/kcp/info/AboutActivity;Ljava/lang/String;Ljava/lang/String;)V ++ ++ invoke-interface {v2, v3}, Ljava/util/List;->add(Ljava/lang/Object;)Z ++ ++ .line 317 ++ iget-object v3, p0, Lcom/amazon/kcp/info/AboutActivity;->detailItemList:Ljava/util/List; ++ ++ invoke-interface {v3, v2}, Ljava/util/List;->add(Ljava/lang/Object;)Z ++ ++ .line 318 ++ return-void ++.end method ++ + .method private populateDisplayItems()V + .locals 1 + + .prologue + .line 171 + iget-object v0, p0, Lcom/amazon/kcp/info/AboutActivity;->groupItemList:Ljava/util/List; + + if-nez v0, :cond_0 + + .line 173 +@@ -531,20 +582,22 @@ + + .line 192 + invoke-direct {p0}, Lcom/amazon/kcp/info/AboutActivity;->populateRamInformation()V + + .line 193 + invoke-direct {p0}, Lcom/amazon/kcp/info/AboutActivity;->populateStorageInformation()V + + .line 194 + invoke-direct {p0}, Lcom/amazon/kcp/info/AboutActivity;->populateDisplayInformation()V + ++ invoke-direct {p0}, Lcom/amazon/kcp/info/AboutActivity;->populatePIDList()V ++ + .line 195 + return-void + + .line 177 + :cond_0 + iget-object v0, p0, Lcom/amazon/kcp/info/AboutActivity;->groupItemList:Ljava/util/List; + + invoke-interface {v0}, Ljava/util/List;->clear()V + + goto :goto_0 +diff -r -u10 kindle4.0.2.1_orig/smali/com/amazon/system/security/Security.smali kindle4.0.2.1/smali/com/amazon/system/security/Security.smali +--- kindle4.0.2.1_orig/smali/com/amazon/system/security/Security.smali 2013-05-22 18:39:04.000000000 -0500 ++++ kindle4.0.2.1/smali/com/amazon/system/security/Security.smali 2013-05-23 17:19:05.000000000 -0500 +@@ -920,20 +920,30 @@ + + .line 350 + :cond_2 + add-int/lit8 v8, v8, 0x1 + + .line 351 + sget-object v0, Lcom/amazon/system/security/Security;->CUSTOM_PID_FOR_BUNDLED_DICTIONARY_DRM:Ljava/lang/String; + + aput-object v0, v6, v8 + ++ invoke-static {}, Lcom/amazon/kcp/application/DeviceInformationProviderFactory;->getProvider()Lcom/amazon/kcp/application/IDeviceInformationProvider; ++ ++ move-result-object v5 ++ ++ invoke-static {v6}, Ljava/util/Arrays;->toString([Ljava/lang/Object;)Ljava/lang/String; ++ ++ move-result-object v2 ++ ++ invoke-interface {v5, v2}, Lcom/amazon/kcp/application/IDeviceInformationProvider;->setPidList(Ljava/lang/String;)V ++ + .line 353 + return-object v6 + .end method + + + # virtual methods + .method public customDrmOnly()I + .locals 1 + + .prologue diff --git a/Other_Tools/Kobo/obok_2.01.py b/Other_Tools/Kobo/obok_2.01.py new file mode 100644 index 0000000..3ed7cbd --- /dev/null +++ b/Other_Tools/Kobo/obok_2.01.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python +# +# Updated September 2013 by Anon +# Version 2.01 +# Incorporated minor fixes posted at Apprentice Alf's. +# +# Updates July 2012 by Michael Newton +# PWSD ID is no longer a MAC address, but should always +# be stored in the registry. Script now works with OS X +# and checks plist for values instead of registry. Must +# have biplist installed for OS X support. +# +########################################################## +# KOBO DRM CRACK BY # +# PHYSISTICATED # +########################################################## +# This app was made for Python 2.7 on Windows 32-bit +# +# This app needs pycrypto - get from here: +# http://www.voidspace.org.uk/python/modules.shtml +# +# Usage: obok.py +# Choose the book you want to decrypt +# +# Shouts to my krew - you know who you are - and one in +# particular who gave me a lot of help with this - thank +# you so much! +# +# Kopimi /K\ +# Keep sharing, keep copying, but remember that nothing is +# for free - make sure you compensate your favorite +# authors - and cut out the middle man whenever possible +# ;) ;) ;) +# +# DRM AUTOPSY +# The Kobo DRM was incredibly easy to crack, but it took +# me months to get around to making this. Here's the +# basics of how it works: +# 1: Get MAC address of first NIC in ipconfig (sometimes +# stored in registry as pwsdid) +# 2: Get user ID (stored in tons of places, this gets it +# from HKEY_CURRENT_USER\Software\Kobo\Kobo Desktop +# Edition\Browser\cookies) +# 3: Concatenate and SHA256, take the second half - this +# is your master key +# 4: Open %LOCALAPPDATA%\Kobo Desktop Editions\Kobo.sqlite +# and dump content_keys +# 5: Unbase64 the keys, then decode these with the master +# key - these are your page keys +# 6: Unzip EPUB of your choice, decrypt each page with its +# page key, then zip back up again +# +# WHY USE THIS WHEN INEPT WORKS FINE? (adobe DRM stripper) +# Inept works very well, but authors on Kobo can choose +# what DRM they want to use - and some have chosen not to +# let people download them with Adobe Digital Editions - +# they would rather lock you into a single platform. +# +# With Obok, you can sync Kobo Desktop, decrypt all your +# ebooks, and then use them on whatever device you want +# - you bought them, you own them, you can do what you +# like with them. +# +# Obok is Kobo backwards, but it is also means "next to" +# in Polish. +# When you buy a real book, it is right next to you. You +# can read it at home, at work, on a train, you can lend +# it to a friend, you can scribble on it, and add your own +# explanations/translations. +# +# Obok gives you this power over your ebooks - no longer +# are you restricted to one device. This allows you to +# embed foreign fonts into your books, as older Kobo's +# can't display them properly. You can read your books +# on your phones, in different PC readers, and different +# ereader devices. You can share them with your friends +# too, if you like - you can do that with a real book +# after all. +# +""" +Decrypt Kobo encrypted EPUB books. +""" + +import os +import sys +if sys.platform.startswith('win'): + import _winreg +elif sys.platform.startswith('darwin'): + from biplist import readPlist +import re +import string +import hashlib +import sqlite3 +import base64 +import binascii +import zipfile +from Crypto.Cipher import AES + +def SHA256(raw): + return hashlib.sha256(raw).hexdigest() + +def RemoveAESPadding(contents): + lastchar = binascii.b2a_hex(contents[-1:]) + strlen = int(lastchar, 16) + padding = strlen + if(strlen == 1): + return contents[:-1] + if(strlen < 16): + for i in range(strlen): + testchar = binascii.b2a_hex(contents[-strlen:-(strlen-1)]) + if(testchar != lastchar): + padding = 0 + if(padding > 0): + contents = contents[:-padding] + return contents + +def GetVolumeKeys(dbase, enc): + volumekeys = {} + for row in dbase.execute("SELECT * from content_keys"): + if(row[0] not in volumekeys): + volumekeys[row[0]] = {} + volumekeys[row[0]][row[1]] = {} + volumekeys[row[0]][row[1]]["encryptedkey"] = base64.b64decode(row[2]) + volumekeys[row[0]][row[1]]["decryptedkey"] = enc.decrypt(volumekeys[row[0]][row[1]]["encryptedkey"]) + # get book name + for key in volumekeys.keys(): + volumekeys[key]["title"] = dbase.execute("SELECT Title from content where ContentID = '%s'" % (key)).fetchone()[0] + return volumekeys + +def ByteArrayToString(bytearr): + wincheck = re.match("@ByteArray\\((.+)\\)", bytearr) + if wincheck: + return wincheck.group(1) + return bytearr + +def GetUserHexKey(prefs = ""): + "find wsuid and pwsdid" + wsuid = "" + pwsdid = "" + if sys.platform.startswith('win'): + regkey_browser = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, "Software\\Kobo\\Kobo Desktop Edition\\Browser") + cookies = _winreg.QueryValueEx(regkey_browser, "cookies") + bytearrays = cookies[0] + elif sys.platform.startswith('darwin'): + cookies = readPlist(prefs) + bytearrays = cookies["Browser.cookies"] + for bytearr in bytearrays: + cookie = ByteArrayToString(bytearr) + print cookie + wsuidcheck = re.match("^wsuid=([0-9a-f-]+)", cookie) + if(wsuidcheck): + wsuid = wsuidcheck.group(1) + pwsdidcheck = re.match("^pwsdid=([0-9a-f-]+)", cookie) + if (pwsdidcheck): + pwsdid = pwsdidcheck.group(1) + + if(wsuid == "" or pwsdid == ""): + print "wsuid or pwsdid key not found :/" + exit() + preuserkey = string.join((pwsdid, wsuid), "") + print SHA256(pwsdid) + userkey = SHA256(preuserkey) + return userkey[32:] + +# get dirs +if sys.platform.startswith('win'): + delim = "\\" + if (sys.getwindowsversion().major > 5): + kobodir = string.join((os.environ['LOCALAPPDATA'], "Kobo\\Kobo Desktop Edition"), delim) + else: + kobodir = string.join((os.environ['USERPROFILE'], "Local Settings\\Application Data\\Kobo\\Kobo Desktop Edition"), delim) + prefs = "" +elif sys.platform.startswith('darwin'): + delim = "/" + kobodir = string.join((os.environ['HOME'], "Library/Application Support/Kobo/Kobo Desktop Edition"), delim) + prefs = string.join((os.environ['HOME'], "Library/Preferences/com.kobo.Kobo Desktop Edition.plist"), delim) +sqlitefile = string.join((kobodir, "Kobo.sqlite"), delim) +bookdir = string.join((kobodir, "kepub"), delim) + +# get key +userkeyhex = GetUserHexKey(prefs) +# load into AES +userkey = binascii.a2b_hex(userkeyhex) +enc = AES.new(userkey, AES.MODE_ECB) + +# open sqlite +conn = sqlite3.connect(sqlitefile) +dbcursor = conn.cursor() +# get volume keys +volumekeys = GetVolumeKeys(dbcursor, enc) + +# choose a volumeID + +volumeid = "" +print "Choose a book to decrypt:" +i = 1 +for key in volumekeys.keys(): + print "%d: %s" % (i, volumekeys[key]["title"]) + i += 1 + +num = input("...") + +i = 1 +for key in volumekeys.keys(): + if(i == num): + volumeid = key + i += 1 + +if(volumeid == ""): + exit() + +zippath = string.join((bookdir, volumeid), delim) + +z = zipfile.ZipFile(zippath, "r") +# make filename out of Unicode alphanumeric and whitespace equivalents from title +outname = "%s.epub" % (re.sub("[^\s\w]", "", volumekeys[volumeid]["title"], 0, re.UNICODE)) +zout = zipfile.ZipFile(outname, "w", zipfile.ZIP_DEFLATED) +for filename in z.namelist(): + #print filename + # read in and decrypt + if(filename in volumekeys[volumeid]): + # do decrypted version + pagekey = volumekeys[volumeid][filename]["decryptedkey"] + penc = AES.new(pagekey, AES.MODE_ECB) + contents = RemoveAESPadding(penc.decrypt(z.read(filename))) + # need to fix padding + zout.writestr(filename, contents) + else: + zout.writestr(filename, z.read(filename)) + +print "Book saved as %s%s%s" % (os.getcwd(), delim, outname)
\ No newline at end of file |