mirror of
https://github.com/noDRM/DeDRM_tools.git
synced 2026-03-20 04:58:56 +00:00
Compare commits
6 Commits
a4689f6ac0
...
7eb8f07a33
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7eb8f07a33 | ||
|
|
e4fe032e47 | ||
|
|
bb170688ba | ||
|
|
b283777c0a | ||
|
|
cf095a4171 | ||
|
|
263cc1d2cf |
@@ -96,8 +96,14 @@ import traceback
|
||||
|
||||
try:
|
||||
import __version
|
||||
except ModuleNotFoundError:
|
||||
except:
|
||||
print("#############################")
|
||||
print("Failed to load the DeDRM plugin")
|
||||
print("Did you bundle this from source code yourself? If so, you'll need to run make_release.py instead to generate a valid plugin file.")
|
||||
print("If you have no idea what the above means, please redownload the most recent version of the plugin from the Github Releases page.")
|
||||
print("If you still receive this error with the released version, please open a bug report and attach the following information:")
|
||||
print("#############################")
|
||||
print("Debug information:")
|
||||
print("__version not found, path is:")
|
||||
print(sys.path)
|
||||
print("I'm at:")
|
||||
@@ -158,7 +164,7 @@ PLUGIN_VERSION_TUPLE = __version.PLUGIN_VERSION_TUPLE
|
||||
|
||||
class DeDRM(FileTypePlugin):
|
||||
name = PLUGIN_NAME
|
||||
description = "Removes DRM from Amazon Kindle, Adobe Adept (including Kobo), Readium LCP, Barnes & Noble, Mobipocket and eReader ebooks. Credit given to i♥cabbages and The Dark Reverser for the original stand-alone scripts."
|
||||
description = "Removes DRM from Adobe Adept (including Kobo), Barnes & Noble, Amazon Kindle, Mobipocket and eReader ebooks. Credit given to i♥cabbages and The Dark Reverser for the original stand-alone scripts."
|
||||
supported_platforms = ['linux', 'osx', 'windows']
|
||||
author = "Apprentice Alf, Apprentice Harper, NoDRM, The Dark Reverser and i♥cabbages"
|
||||
version = PLUGIN_VERSION_TUPLE
|
||||
@@ -376,7 +382,7 @@ class DeDRM(FileTypePlugin):
|
||||
from wineutils import WineGetKeys
|
||||
|
||||
scriptpath = os.path.join(self.alfdir,"ignoblekeyNookStudy.py")
|
||||
defaultkeys_study = WineGetKeys(scriptpath, ".b64",dedrmprefs['adobewineprefix'])
|
||||
defaultkeys_study, defaultnames_study = WineGetKeys(scriptpath, ".b64",dedrmprefs['adobewineprefix'])
|
||||
|
||||
except:
|
||||
print("{0} v{1}: Exception when getting default NOOK Study Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||
@@ -942,21 +948,30 @@ class DeDRM(FileTypePlugin):
|
||||
from kindlekey import kindlekeys
|
||||
|
||||
defaultkeys = kindlekeys()
|
||||
defaultnames = []
|
||||
else: # linux
|
||||
from wineutils import WineGetKeys
|
||||
|
||||
scriptpath = os.path.join(self.alfdir,"kindlekey.py")
|
||||
defaultkeys = WineGetKeys(scriptpath, ".k4i",dedrmprefs['kindlewineprefix'])
|
||||
defaultkeys, defaultnames = WineGetKeys(scriptpath, ".k4i",dedrmprefs['kindlewineprefix'])
|
||||
except:
|
||||
print("{0} v{1}: Exception when getting default Kindle Key after {2:.1f} seconds".format(PLUGIN_NAME, PLUGIN_VERSION, time.time()-self.starttime))
|
||||
traceback.print_exc()
|
||||
pass
|
||||
|
||||
newkeys = {}
|
||||
newkeys = []
|
||||
newnames = []
|
||||
|
||||
for i,keyvalue in enumerate(defaultkeys):
|
||||
try:
|
||||
keyname = "default_key_" + defaultnames[i]
|
||||
except:
|
||||
keyname = "default_key_{0:d}".format(i+1)
|
||||
|
||||
if keyvalue not in dedrmprefs['kindlekeys'].values():
|
||||
newkeys[keyname] = keyvalue
|
||||
newkeys.append(keyvalue)
|
||||
newnames.append(keyname)
|
||||
|
||||
if len(newkeys) > 0:
|
||||
print("{0} v{1}: Found {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), "key" if len(newkeys)==1 else "keys"))
|
||||
try:
|
||||
@@ -964,8 +979,8 @@ class DeDRM(FileTypePlugin):
|
||||
decoded = True
|
||||
# store the new successful keys in the defaults
|
||||
print("{0} v{1}: Saving {2} new {3}".format(PLUGIN_NAME, PLUGIN_VERSION, len(newkeys), "key" if len(newkeys)==1 else "keys"))
|
||||
for keyvalue in newkeys.values():
|
||||
dedrmprefs.addnamedvaluetoprefs('kindlekeys','default_key',keyvalue)
|
||||
for i,keyvalue in enumerate(newkeys):
|
||||
dedrmprefs.addnamedvaluetoprefs('kindlekeys',newnames[i],keyvalue)
|
||||
dedrmprefs.writeprefs()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
@@ -39,7 +39,7 @@ Retrieve Adobe ADEPT user key.
|
||||
"""
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__version__ = '7.3'
|
||||
__version__ = '7.4'
|
||||
|
||||
import sys, os, struct, getopt
|
||||
from base64 import b64decode
|
||||
@@ -128,10 +128,16 @@ if iswindows:
|
||||
|
||||
try:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
DEVICE_KEY_PATH = r'Software\Adobe\Adept\Device'
|
||||
PRIVATE_LICENCE_KEY_PATH = r'Software\Adobe\Adept\Activation'
|
||||
@@ -381,7 +387,7 @@ if iswindows:
|
||||
pass
|
||||
if ktype == 'privateLicenseKey':
|
||||
userkey = winreg.QueryValueEx(plkkey, 'value')[0]
|
||||
userkey = unpad(AES.new(keykey, AES.MODE_CBC, b'\x00'*16).decrypt(b64decode(userkey)), 16)[26:]
|
||||
userkey = unpad(AES.new(keykey, AES.MODE_CBC, b'\x00'*16).decrypt(b64decode(userkey)))[26:]
|
||||
# print ("found " + uuid_name + " key: " + str(userkey))
|
||||
keys.append(userkey)
|
||||
|
||||
|
||||
@@ -23,10 +23,17 @@ import sys, os, time
|
||||
import base64, hashlib
|
||||
try:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
PASS_HASH_SECRET = "9ca588496a1bc4394553d9e018d70b9e"
|
||||
|
||||
@@ -48,7 +55,7 @@ def decrypt_passhash(passhash, fp):
|
||||
hash_key = hashlib.sha1(bytearray.fromhex(serial_number + PASS_HASH_SECRET)).digest()[:16]
|
||||
|
||||
encrypted_cc_hash = base64.b64decode(passhash)
|
||||
cc_hash = unpad(AES.new(hash_key, AES.MODE_CBC, encrypted_cc_hash[:16]).decrypt(encrypted_cc_hash[16:]), 16)
|
||||
cc_hash = unpad(AES.new(hash_key, AES.MODE_CBC, encrypted_cc_hash[:16]).decrypt(encrypted_cc_hash[16:]))
|
||||
return base64.b64encode(cc_hash).decode("ascii")
|
||||
|
||||
|
||||
|
||||
@@ -36,10 +36,8 @@ from binascii import a2b_hex, b2a_hex
|
||||
|
||||
try:
|
||||
from Cryptodome.Cipher import AES, DES
|
||||
from Cryptodome.Util.Padding import pad, unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES, DES
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
|
||||
# Routines common to Mac and PC
|
||||
|
||||
@@ -116,6 +114,20 @@ STORAGE = "backup.ab"
|
||||
STORAGE1 = "AmazonSecureStorage.xml"
|
||||
STORAGE2 = "map_data_storage.db"
|
||||
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
def pad(data, padding_len=16):
|
||||
padding_data_len = padding_len - (len(data) % padding_len)
|
||||
plaintext = data + chr(padding_data_len) * padding_data_len
|
||||
return plaintext
|
||||
|
||||
class AndroidObfuscation(object):
|
||||
'''AndroidObfuscation
|
||||
For the key, it's written in java, and run in android dalvikvm
|
||||
|
||||
@@ -10,13 +10,19 @@ import os
|
||||
import base64
|
||||
try:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
import hashlib
|
||||
from lxml import etree
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
|
||||
PASS_HASH_SECRET = "9ca588496a1bc4394553d9e018d70b9e"
|
||||
|
||||
@@ -46,10 +52,13 @@ def dump_keys(path_to_adobe_folder):
|
||||
hashes = []
|
||||
|
||||
for pass_hash in activation_xml.findall(".//{http://ns.adobe.com/adept}passHash"):
|
||||
try:
|
||||
encrypted_cc_hash = base64.b64decode(pass_hash.text)
|
||||
cc_hash = unpad(AES.new(hash_key, AES.MODE_CBC, encrypted_cc_hash[:16]).decrypt(encrypted_cc_hash[16:]), 16)
|
||||
cc_hash = unpad(AES.new(hash_key, AES.MODE_CBC, encrypted_cc_hash[:16]).decrypt(encrypted_cc_hash[16:]))
|
||||
hashes.append(base64.b64encode(cc_hash).decode("ascii"))
|
||||
#print("Nook ccHash is %s" % (base64.b64encode(cc_hash).decode("ascii")))
|
||||
except:
|
||||
pass
|
||||
|
||||
return hashes
|
||||
|
||||
|
||||
@@ -16,13 +16,19 @@ import base64
|
||||
import traceback
|
||||
try:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
import hashlib
|
||||
from lxml import etree
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
|
||||
NOOK_DATA_FOLDER = "%LOCALAPPDATA%\\Packages\\BarnesNoble.Nook_ahnzqzva31enc\\LocalState"
|
||||
PASS_HASH_SECRET = "9ca588496a1bc4394553d9e018d70b9e"
|
||||
|
||||
@@ -56,11 +56,18 @@ import hashlib
|
||||
try:
|
||||
from Cryptodome.Cipher import AES, PKCS1_v1_5
|
||||
from Cryptodome.PublicKey import RSA
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES, PKCS1_v1_5
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Util.Padding import unpad
|
||||
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
# Wrap a stream so that output gets flushed immediately
|
||||
# and also make sure that any unicode strings get
|
||||
|
||||
@@ -75,11 +75,19 @@ from uuid import UUID
|
||||
try:
|
||||
from Cryptodome.Cipher import AES, ARC4, PKCS1_v1_5
|
||||
from Cryptodome.PublicKey import RSA
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES, ARC4, PKCS1_v1_5
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Util.Padding import unpad
|
||||
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
|
||||
# Wrap a stream so that output gets flushed immediately
|
||||
# and also make sure that any unicode strings get
|
||||
@@ -1593,7 +1601,12 @@ class PDFDocument(object):
|
||||
|
||||
def initialize_ebx_ignoble(self, keyb64, docid, param):
|
||||
self.is_printable = self.is_modifiable = self.is_extractable = True
|
||||
try:
|
||||
key = keyb64.decode('base64')[:16]
|
||||
# This will probably always error, but I'm not 100% sure, so lets leave the old code in.
|
||||
except AttributeError:
|
||||
key = codecs.decode(keyb64.encode("ascii"), 'base64')[:16]
|
||||
|
||||
length = int_value(param.get('Length', 0)) / 8
|
||||
rights = str_value(param.get('ADEPT_LICENSE')).decode('base64')
|
||||
rights = zlib.decompress(rights, -15)
|
||||
|
||||
@@ -33,10 +33,8 @@ from io import BytesIO
|
||||
try:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome.Util.py3compat import bchr
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
from Crypto.Util.py3compat import bchr
|
||||
|
||||
try:
|
||||
@@ -750,6 +748,26 @@ def addprottable(ion):
|
||||
ion.addtocatalog("ProtectedData", 1, SYM_NAMES)
|
||||
|
||||
|
||||
def pkcs7pad(msg, blocklen):
|
||||
paddinglen = blocklen - len(msg) % blocklen
|
||||
padding = bchr(paddinglen) * paddinglen
|
||||
return msg + padding
|
||||
|
||||
|
||||
def pkcs7unpad(msg, blocklen):
|
||||
_assert(len(msg) % blocklen == 0)
|
||||
|
||||
paddinglen = msg[-1]
|
||||
|
||||
_assert(paddinglen > 0 and paddinglen <= blocklen, "Incorrect padding - Wrong key")
|
||||
_assert(msg[-paddinglen:] == bchr(paddinglen) * paddinglen, "Incorrect padding - Wrong key")
|
||||
|
||||
return msg[:-paddinglen]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# every VoucherEnvelope version has a corresponding "word" and magic number, used in obfuscating the shared secret
|
||||
OBFUSCATION_TABLE = {
|
||||
"V1": (0x00, None),
|
||||
@@ -865,7 +883,7 @@ class DrmIonVoucher(object):
|
||||
key = hmac.new(sharedsecret, b"PIDv3", digestmod=hashlib.sha256).digest()
|
||||
aes = AES.new(key[:32], AES.MODE_CBC, self.cipheriv[:16])
|
||||
b = aes.decrypt(self.ciphertext)
|
||||
b = unpad(b, 16)
|
||||
b = pkcs7unpad(b, 16)
|
||||
|
||||
self.drmkey = BinaryIonParser(BytesIO(b))
|
||||
addprottable(self.drmkey)
|
||||
@@ -1071,7 +1089,7 @@ class DrmIon(object):
|
||||
def processpage(self, ct, civ, outpages, decompress, decrypt):
|
||||
if decrypt:
|
||||
aes = AES.new(self.key[:16], AES.MODE_CBC, civ[:16])
|
||||
msg = unpad(aes.decrypt(ct), 16)
|
||||
msg = pkcs7unpad(aes.decrypt(ct), 16)
|
||||
else:
|
||||
msg = ct
|
||||
|
||||
|
||||
@@ -69,7 +69,11 @@ import getopt
|
||||
import re
|
||||
import traceback
|
||||
import time
|
||||
import html.entities
|
||||
try:
|
||||
import html.entities as htmlentitydefs
|
||||
except:
|
||||
import htmlentitydefs
|
||||
|
||||
import json
|
||||
|
||||
#@@CALIBRE_COMPAT_CODE@@
|
||||
@@ -188,7 +192,7 @@ def unescape(text):
|
||||
else:
|
||||
# named entity
|
||||
try:
|
||||
text = chr(html.entities.name2codepoint[text[1:-1]])
|
||||
text = chr(htmlentitydefs.name2codepoint[text[1:-1]])
|
||||
except KeyError:
|
||||
pass
|
||||
return text # leave as is
|
||||
@@ -215,8 +219,11 @@ def GetDecryptedBook(infile, kDatabases, androidFiles, serials, pids, starttime
|
||||
else:
|
||||
mb = topazextract.TopazBook(infile)
|
||||
|
||||
try:
|
||||
bookname = unescape(mb.getBookTitle())
|
||||
print("Decrypting {1} ebook: {0}".format(bookname, mb.getBookType()))
|
||||
except:
|
||||
print("Decrypting {0} ebook.".format(mb.getBookType()))
|
||||
|
||||
# copy list of pids
|
||||
totalpids = list(pids)
|
||||
|
||||
@@ -77,7 +77,7 @@ def WineGetKeys(scriptpath, extension, wineprefix=""):
|
||||
pyexec = WinePythonCLI(wineprefix)
|
||||
except NoWinePython3Exception:
|
||||
print('{0} v{1}: Unable to find python3 executable in WINEPREFIX="{2}"'.format(PLUGIN_NAME, PLUGIN_VERSION, wineprefix))
|
||||
return []
|
||||
return [], []
|
||||
|
||||
basepath, script = os.path.split(scriptpath)
|
||||
print("{0} v{1}: Running {2} under Wine".format(PLUGIN_NAME, PLUGIN_VERSION, script))
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
from __future__ import print_function
|
||||
|
||||
__version__ = '10.0.1'
|
||||
__about__ = "Obok v{0}\nCopyright © 2012-2020 Physisticated et al.".format(__version__)
|
||||
__about__ = "Obok v{0}\nCopyright © 2012-2022 Physisticated et al.".format(__version__)
|
||||
|
||||
import sys
|
||||
import os
|
||||
@@ -185,10 +185,17 @@ import tempfile
|
||||
|
||||
try:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome.Util.Padding import unpad
|
||||
except ImportError:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
|
||||
def unpad(data, padding=16):
|
||||
if sys.version_info[0] == 2:
|
||||
pad_len = ord(data[-1])
|
||||
else:
|
||||
pad_len = data[-1]
|
||||
|
||||
return data[:-pad_len]
|
||||
|
||||
|
||||
can_parse_xml = True
|
||||
try:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Welcome to the tools!
|
||||
=====================
|
||||
|
||||
This file is to give users a quick overview of what is available and how to get started. This document is part of the DeDRM Tools archive from Apprentice Harper's github repository: https://github.com/apprenticeharper/DeDRM_tools/
|
||||
This file is to give users a quick overview of what is available and how to get started. This document is part of the DeDRM Tools archive from noDRM's github repository: https://github.com/noDRM/DeDRM_tools/
|
||||
|
||||
This archive includes calibre plugins to remove DRM from:
|
||||
|
||||
@@ -12,21 +12,22 @@ This archive includes calibre plugins to remove DRM from:
|
||||
|
||||
These tools do NOT work with Apple's iBooks FairPlay DRM. Use iBook Copy from TunesKit.
|
||||
These tools no longer work well with books from Barnes & Noble.
|
||||
Due to a DMCA request, these tools no longer work with LCP-encrypted books - see https://github.com/noDRM/DeDRM_tools/issues/18 for details.
|
||||
|
||||
For limitations and work-arounds, see the FAQ at https://github.com/apprenticeharper/DeDRM_tools/blob/master/FAQs.md
|
||||
For limitations and work-arounds, see the FAQ at https://github.com/noDRM/DeDRM_tools/blob/master/FAQs.md
|
||||
|
||||
About the tools
|
||||
---------------
|
||||
These tools are updated and maintained by Apprentice Harper and many others. You can find the latest updates at Apprentice Harper's github repository https://github.com/apprenticeharper/DeDRM_tools/ and get support by creating an issue at the repository (github account required) or by posting a comment at Apprentice Alf's blog: http://www.apprenticealf.wordpress.com/
|
||||
These tools are updated and maintained by noDRM and many others. They are based on Apprentice Harper's Calibre plugin. You can find the latest updates at noDRM's github repository https://github.com/noDRM/DeDRM_tools/ and get support by creating an issue at the repository (github account required).
|
||||
|
||||
If you re-post these tools, a link to the repository and/or the blog would be appreciated.
|
||||
If you re-post these tools, a link to the repository would be appreciated.
|
||||
|
||||
The tools are provided in the form of plugins for calibre. Calibre is an open source freeware ebook library manager. It is the best tool around for keeping track of your ebooks.
|
||||
|
||||
|
||||
DeDRM plugin for calibre (Mac OS X, Windows)
|
||||
DeDRM plugin for calibre (Linux, Mac OS X and Windows)
|
||||
-------------------------------------------------------
|
||||
calibe 5.x and later are now written in Python 3, and plugins must also use Python 3. If you have calibre 5, you must use version 7.x or later of the plugins. For calibre 4.x and earlier, use version 6.8.x of the plugins.
|
||||
calibe 5.x and later are now written in Python 3, and plugins must also use Python 3.
|
||||
|
||||
The DeDRM plugin for calibre removes DRM from your Kindle and Adobe DRM ebooks when they are imported to calibre. Just install the DeDRM plugin (DeDRM_plugin.zip), following the instructions and configuration directions provided in the ReadMe file and the help links in the plugin's configuration dialogs.
|
||||
|
||||
@@ -40,18 +41,6 @@ To import ebooks from the Kobo Desktop app or from a Kobo ebook reader, install
|
||||
For instructions, see the obok_plugin_ReadMe.txt file.
|
||||
|
||||
|
||||
DeDRM application for Mac OS X users: (Mac OS X 10.6 and above)
|
||||
---------------------------------------------------------------
|
||||
DeDRM application for Windows users: (Windows XP through Windows 10)
|
||||
------------------------------------------------------------------
|
||||
As of Version 6.7 of the tools, these are no longer provided or supported.
|
||||
|
||||
|
||||
Linux support
|
||||
-------------
|
||||
It may be possible to use the plugins on a Linux system, but no support is given at this time.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
The original inept and ignoble scripts were by i♥cabbages
|
||||
@@ -61,7 +50,8 @@ The original topaz DRM removal script was by CMBDTC
|
||||
The original topaz format conversion scripts were by some_updates, clarknova and Bart Simpson
|
||||
The original KFX format decryption was by lulzkabulz, converted to python by Apprentice Naomi and integrated into the tools by tomthumb1997
|
||||
The alfcrypto library is by some_updates
|
||||
The DeDRM plugin was based on plugins by DiapDealer and is maintained by Apprentice Alf and Apprentice Harper
|
||||
The DeDRM plugin is based on plugins by DiapDealer and is currently maintained by noDRM
|
||||
The DeDRM plugin has been maintained by Apprentice Alf and Apprentice Harper until 2021.
|
||||
|
||||
The original obok script was by Physisticated
|
||||
The plugin conversion was done anonymously.
|
||||
|
||||
Reference in New Issue
Block a user