summaryrefslogtreecommitdiffstats
path: root/Other_Tools
diff options
context:
space:
mode:
authorApprentice Alf <[email protected]>2015-03-07 21:18:50 +0000
committerApprentice Alf <[email protected]>2015-03-07 21:18:50 +0000
commita30aace99c61c30050f8fee8c3444f2d355c8bd6 (patch)
tree6f1375e8af821784e83766331097cf42648dba7e /Other_Tools
parentb1feca321df4804b0f178ce96c476a70b9016113 (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.patch238
-rw-r--r--Other_Tools/Kobo/obok_2.01.py231
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