Guest User

Untitled

a guest
Aug 10th, 2011
7,618
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.09 KB | None | 0 0
  1. #! /usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. # ineptkey.pyw, version 5
  5. # Copyright © 2009-2010 i♥cabbages
  6.  
  7. # Released under the terms of the GNU General Public Licence, version 3 or
  8. # later.  <http://www.gnu.org/licenses/>
  9.  
  10. # Windows users: Before running this program, you must first install Python 2.6
  11. #   from <http://www.python.org/download/> and PyCrypto from
  12. #   <http://www.voidspace.org.uk/python/modules.shtml#pycrypto> (make certain
  13. #   to install the version for Python 2.6).  Then save this script file as
  14. #   ineptkey.pyw and double-click on it to run it.  It will create a file named
  15. #   adeptkey.der in the same directory.  This is your ADEPT user key.
  16. #
  17. # Mac OS X users: Save this script file as ineptkey.pyw.  You can run this
  18. #   program from the command line (pythonw ineptkey.pyw) or by double-clicking
  19. #   it when it has been associated with PythonLauncher.  It will create a file
  20. #   named adeptkey.der in the same directory.  This is your ADEPT user key.
  21.  
  22. # Revision history:
  23. #   1 - Initial release, for Adobe Digital Editions 1.7
  24. #   2 - Better algorithm for finding pLK; improved error handling
  25. #   3 - Rename to INEPT
  26. #   4 - Series of changes by joblack (and others?) --
  27. #   4.1 - quick beta fix for ADE 1.7.2 (anon)
  28. #   4.2 - added old 1.7.1 processing
  29. #   4.3 - better key search
  30. #   4.4 - Make it working on 64-bit Python
  31. #   5 - Clean up and improve 4.x changes;
  32. #       Clean up and merge OS X support by unknown
  33.  
  34. """
  35. Retrieve Adobe ADEPT user key.
  36. """
  37.  
  38. from __future__ import with_statement
  39.  
  40. __license__ = 'GPL v3'
  41.  
  42. import sys
  43. import os
  44. import struct
  45. import Tkinter
  46. import Tkconstants
  47. import tkMessageBox
  48. import traceback
  49.  
  50. class ADEPTError(Exception):
  51.     pass
  52.  
  53. if sys.platform.startswith('win'):
  54.     from ctypes import windll, c_char_p, c_wchar_p, c_uint, POINTER, byref, \
  55.         create_unicode_buffer, create_string_buffer, CFUNCTYPE, addressof, \
  56.         string_at, Structure, c_void_p, cast, c_size_t, memmove
  57.     from ctypes.wintypes import LPVOID, DWORD, BOOL
  58.     import _winreg as winreg
  59.  
  60.     try:
  61.         from Crypto.Cipher import AES
  62.     except ImportError:
  63.         AES = None
  64.  
  65.     DEVICE_KEY_PATH = r'Software\Adobe\Adept\Device'
  66.     PRIVATE_LICENCE_KEY_PATH = r'Software\Adobe\Adept\Activation'
  67.  
  68.     MAX_PATH = 255
  69.  
  70.     kernel32 = windll.kernel32
  71.     advapi32 = windll.advapi32
  72.     crypt32 = windll.crypt32
  73.  
  74.     def GetSystemDirectory():
  75.         GetSystemDirectoryW = kernel32.GetSystemDirectoryW
  76.         GetSystemDirectoryW.argtypes = [c_wchar_p, c_uint]
  77.         GetSystemDirectoryW.restype = c_uint
  78.         def GetSystemDirectory():
  79.             buffer = create_unicode_buffer(MAX_PATH + 1)
  80.             GetSystemDirectoryW(buffer, len(buffer))
  81.             return buffer.value
  82.         return GetSystemDirectory
  83.     GetSystemDirectory = GetSystemDirectory()
  84.  
  85.     def GetVolumeSerialNumber():
  86.         GetVolumeInformationW = kernel32.GetVolumeInformationW
  87.         GetVolumeInformationW.argtypes = [c_wchar_p, c_wchar_p, c_uint,
  88.                                           POINTER(c_uint), POINTER(c_uint),
  89.                                           POINTER(c_uint), c_wchar_p, c_uint]
  90.         GetVolumeInformationW.restype = c_uint
  91.         def GetVolumeSerialNumber(path):
  92.             vsn = c_uint(0)
  93.             GetVolumeInformationW(
  94.                 path, None, 0, byref(vsn), None, None, None, 0)
  95.             return vsn.value
  96.         return GetVolumeSerialNumber
  97.     GetVolumeSerialNumber = GetVolumeSerialNumber()
  98.  
  99.     def GetUserName():
  100.         GetUserNameW = advapi32.GetUserNameW
  101.         GetUserNameW.argtypes = [c_wchar_p, POINTER(c_uint)]
  102.         GetUserNameW.restype = c_uint
  103.         def GetUserName():
  104.             buffer = create_unicode_buffer(32)
  105.             size = c_uint(len(buffer))
  106.             while not GetUserNameW(buffer, byref(size)):
  107.                 buffer = create_unicode_buffer(len(buffer) * 2)
  108.                 size.value = len(buffer)
  109.             return buffer.value.encode('utf-16-le')[::2]
  110.         return GetUserName
  111.     GetUserName = GetUserName()
  112.  
  113.     PAGE_EXECUTE_READWRITE = 0x40
  114.     MEM_COMMIT  = 0x1000
  115.     MEM_RESERVE = 0x2000
  116.  
  117.     def VirtualAlloc():
  118.         _VirtualAlloc = kernel32.VirtualAlloc
  119.         _VirtualAlloc.argtypes = [LPVOID, c_size_t, DWORD, DWORD]
  120.         _VirtualAlloc.restype = LPVOID
  121.         def VirtualAlloc(addr, size, alloctype=(MEM_COMMIT | MEM_RESERVE),
  122.                          protect=PAGE_EXECUTE_READWRITE):
  123.             return _VirtualAlloc(addr, size, alloctype, protect)
  124.         return VirtualAlloc
  125.     VirtualAlloc = VirtualAlloc()
  126.  
  127.     MEM_RELEASE = 0x8000
  128.  
  129.     def VirtualFree():
  130.         _VirtualFree = kernel32.VirtualFree
  131.         _VirtualFree.argtypes = [LPVOID, c_size_t, DWORD]
  132.         _VirtualFree.restype = BOOL
  133.         def VirtualFree(addr, size=0, freetype=MEM_RELEASE):
  134.             return _VirtualFree(addr, size, freetype)
  135.         return VirtualFree
  136.     VirtualFree = VirtualFree()
  137.  
  138.     class NativeFunction(object):
  139.         def __init__(self, restype, argtypes, insns):
  140.             self._buf = buf = VirtualAlloc(None, len(insns))
  141.             memmove(buf, insns, len(insns))
  142.             ftype = CFUNCTYPE(restype, *argtypes)
  143.             self._native = ftype(buf)
  144.  
  145.         def __call__(self, *args):
  146.             return self._native(*args)
  147.  
  148.         def __del__(self):
  149.             if self._buf is not None:
  150.                 VirtualFree(self._buf)
  151.                 self._buf = None
  152.  
  153.     if struct.calcsize("P") == 4:
  154.         CPUID0_INSNS = (
  155.             "\x53"             # push   %ebx
  156.             "\x31\xc0"         # xor    %eax,%eax
  157.             "\x0f\xa2"         # cpuid
  158.             "\x8b\x44\x24\x08" # mov    0x8(%esp),%eax
  159.             "\x89\x18"         # mov    %ebx,0x0(%eax)
  160.             "\x89\x50\x04"     # mov    %edx,0x4(%eax)
  161.             "\x89\x48\x08"     # mov    %ecx,0x8(%eax)
  162.             "\x5b"             # pop    %ebx
  163.             "\xc3"             # ret
  164.         )
  165.         CPUID1_INSNS = (
  166.             "\x53"             # push   %ebx
  167.             "\x31\xc0"         # xor    %eax,%eax
  168.             "\x40"             # inc    %eax
  169.             "\x0f\xa2"         # cpuid
  170.             "\x5b"             # pop    %ebx
  171.             "\xc3"             # ret
  172.         )
  173.     else:
  174.         CPUID0_INSNS = (
  175.             "\x49\x89\xd8"     # mov    %rbx,%r8
  176.             "\x49\x89\xc9"     # mov    %rcx,%r9
  177.             "\x48\x31\xc0"     # xor    %rax,%rax
  178.             "\x0f\xa2"         # cpuid
  179.             "\x4c\x89\xc8"     # mov    %r9,%rax
  180.             "\x89\x18"         # mov    %ebx,0x0(%rax)
  181.             "\x89\x50\x04"     # mov    %edx,0x4(%rax)
  182.             "\x89\x48\x08"     # mov    %ecx,0x8(%rax)
  183.             "\x4c\x89\xc3"     # mov    %r8,%rbx
  184.             "\xc3"             # retq
  185.         )
  186.         CPUID1_INSNS = (
  187.             "\x53"             # push   %rbx
  188.             "\x48\x31\xc0"     # xor    %rax,%rax
  189.             "\x48\xff\xc0"     # inc    %rax
  190.             "\x0f\xa2"         # cpuid
  191.             "\x5b"             # pop    %rbx
  192.             "\xc3"             # retq
  193.         )
  194.  
  195.     def cpuid0():
  196.         _cpuid0 = NativeFunction(None, [c_char_p], CPUID0_INSNS)
  197.         buf = create_string_buffer(12)
  198.         def cpuid0():
  199.             _cpuid0(buf)
  200.             return buf.raw
  201.         return cpuid0
  202.     cpuid0 = cpuid0()
  203.  
  204.     cpuid1 = NativeFunction(c_uint, [], CPUID1_INSNS)
  205.  
  206.     class DataBlob(Structure):
  207.         _fields_ = [('cbData', c_uint),
  208.                     ('pbData', c_void_p)]
  209.     DataBlob_p = POINTER(DataBlob)
  210.  
  211.     def CryptUnprotectData():
  212.         _CryptUnprotectData = crypt32.CryptUnprotectData
  213.         _CryptUnprotectData.argtypes = [DataBlob_p, c_wchar_p, DataBlob_p,
  214.                                        c_void_p, c_void_p, c_uint, DataBlob_p]
  215.         _CryptUnprotectData.restype = c_uint
  216.         def CryptUnprotectData(indata, entropy):
  217.             indatab = create_string_buffer(indata)
  218.             indata = DataBlob(len(indata), cast(indatab, c_void_p))
  219.             entropyb = create_string_buffer(entropy)
  220.             entropy = DataBlob(len(entropy), cast(entropyb, c_void_p))
  221.             outdata = DataBlob()
  222.             if not _CryptUnprotectData(byref(indata), None, byref(entropy),
  223.                                        None, None, 0, byref(outdata)):
  224.                 raise ADEPTError("Failed to decrypt user key key (sic)")
  225.             return string_at(outdata.pbData, outdata.cbData)
  226.         return CryptUnprotectData
  227.     CryptUnprotectData = CryptUnprotectData()
  228.  
  229.     def retrieve_key(keypath):
  230.         if AES is None:
  231.             tkMessageBox.showerror(
  232.                 "ADEPT Key",
  233.                 "This script requires PyCrypto, which must be installed "
  234.                 "separately.  Read the top-of-script comment for details.")
  235.             return False
  236.         root = GetSystemDirectory().split('\\')[0] + '\\'
  237.         serial = GetVolumeSerialNumber(root)
  238.         vendor = cpuid0()
  239.         signature = struct.pack('>I', cpuid1())[1:]
  240.         user = GetUserName()
  241.         entropy = struct.pack('>I12s3s13s', serial, vendor, signature, user)
  242.         cuser = winreg.HKEY_CURRENT_USER
  243.         try:
  244.             regkey = winreg.OpenKey(cuser, DEVICE_KEY_PATH)
  245.         except WindowsError:
  246.             raise ADEPTError("Adobe Digital Editions not activated")
  247.         device = winreg.QueryValueEx(regkey, 'key')[0]
  248.         keykey = CryptUnprotectData(device, entropy)
  249.         userkey = None
  250.         try:
  251.             plkroot = winreg.OpenKey(cuser, PRIVATE_LICENCE_KEY_PATH)
  252.         except WindowsError:
  253.             raise ADEPTError("Could not locate ADE activation")
  254.         for i in xrange(0, 16):
  255.             try:
  256.                 plkparent = winreg.OpenKey(plkroot, "%04d" % (i,))
  257.             except WindowsError:
  258.                 break
  259.             ktype = winreg.QueryValueEx(plkparent, None)[0]
  260.             if ktype != 'credentials':
  261.                 continue
  262.             for j in xrange(0, 16):
  263.                 try:
  264.                     plkkey = winreg.OpenKey(plkparent, "%04d" % (j,))
  265.                 except WindowsError:
  266.                     break
  267.                 ktype = winreg.QueryValueEx(plkkey, None)[0]
  268.                 if ktype != 'privateLicenseKey':
  269.                     continue
  270.                 userkey = winreg.QueryValueEx(plkkey, 'value')[0]
  271.                 break
  272.             if userkey is not None:
  273.                 break
  274.         if userkey is None:
  275.             raise ADEPTError('Could not locate privateLicenseKey')
  276.         userkey = userkey.decode('base64')
  277.         userkey = AES.new(keykey, AES.MODE_CBC).decrypt(userkey)
  278.         userkey = userkey[26:-ord(userkey[-1])]
  279.         with open(keypath, 'wb') as f:
  280.             f.write(userkey)
  281.         return True
  282.  
  283. elif sys.platform.startswith('darwin'):
  284.     import xml.etree.ElementTree as etree
  285.     import Carbon.File
  286.     import Carbon.Folder
  287.     import Carbon.Folders
  288.     import MacOS
  289.  
  290.     ACTIVATION_PATH = 'Adobe/Digital Editions/activation.dat'
  291.     NSMAP = {'adept': 'http://ns.adobe.com/adept',
  292.              'enc': 'http://www.w3.org/2001/04/xmlenc#'}
  293.  
  294.     def find_folder(domain, dtype):
  295.         try:
  296.             fsref = Carbon.Folder.FSFindFolder(domain, dtype, False)
  297.             return Carbon.File.pathname(fsref)
  298.         except MacOS.Error:
  299.             return None
  300.  
  301.     def find_app_support_file(subpath):
  302.         dtype = Carbon.Folders.kApplicationSupportFolderType
  303.         for domain in Carbon.Folders.kUserDomain, Carbon.Folders.kLocalDomain:
  304.             path = find_folder(domain, dtype)
  305.             if path is None:
  306.                 continue
  307.             path = os.path.join(path, subpath)
  308.             if os.path.isfile(path):
  309.                 return path
  310.         return None
  311.  
  312.     def retrieve_key(keypath):
  313.         actpath = find_app_support_file(ACTIVATION_PATH)
  314.         if actpath is None:
  315.             raise ADEPTError("Could not locate ADE activation")
  316.         tree = etree.parse(actpath)
  317.         adept = lambda tag: '{%s}%s' % (NSMAP['adept'], tag)
  318.         expr = '//%s/%s' % (adept('credentials'), adept('privateLicenseKey'))
  319.         userkey = tree.findtext(expr)
  320.         userkey = userkey.decode('base64')
  321.         userkey = userkey[26:]
  322.         with open(keypath, 'wb') as f:
  323.             f.write(userkey)
  324.         return True
  325.  
  326. elif sys.platform.startswith('cygwin'):
  327.     def retrieve_key(keypath):
  328.         tkMessageBox.showerror(
  329.             "ADEPT Key",
  330.             "This script requires a Windows-native Python, and cannot be run "
  331.             "under Cygwin.  Please install a Windows-native Python and/or "
  332.             "check your file associations.")
  333.         return False
  334.  
  335. else:
  336.     def retrieve_key(keypath):
  337.         tkMessageBox.showerror(
  338.             "ADEPT Key",
  339.             "This script only supports Windows and Mac OS X.  For Linux "
  340.             "you should be able to run ADE and this script under Wine (with "
  341.             "an appropriate version of Windows Python installed).")
  342.         return False
  343.  
  344. class ExceptionDialog(Tkinter.Frame):
  345.     def __init__(self, root, text):
  346.         Tkinter.Frame.__init__(self, root, border=5)
  347.         label = Tkinter.Label(self, text="Unexpected error:",
  348.                               anchor=Tkconstants.W, justify=Tkconstants.LEFT)
  349.         label.pack(fill=Tkconstants.X, expand=0)
  350.         self.text = Tkinter.Text(self)
  351.         self.text.pack(fill=Tkconstants.BOTH, expand=1)
  352.         self.text.insert(Tkconstants.END, text)
  353.  
  354. def main(argv=sys.argv):
  355.     root = Tkinter.Tk()
  356.     root.withdraw()
  357.     progname = os.path.basename(argv[0])
  358.     keypath = 'adeptkey.der'
  359.     success = False
  360.     try:
  361.         success = retrieve_key(keypath)
  362.     except ADEPTError, e:
  363.         tkMessageBox.showerror("ADEPT Key", "Error: " + str(e))
  364.     except Exception:
  365.         root.wm_state('normal')
  366.         root.title('ADEPT Key')
  367.         text = traceback.format_exc()
  368.         ExceptionDialog(root, text).pack(fill=Tkconstants.BOTH, expand=1)
  369.         root.mainloop()
  370.     if not success:
  371.         return 1
  372.     tkMessageBox.showinfo(
  373.         "ADEPT Key", "Key successfully retrieved to %s" % (keypath))
  374.     return 0
  375.  
  376. if __name__ == '__main__':
  377.     sys.exit(main())
Add Comment
Please, Sign In to add comment