Fix Wine extraction script for python 2/3

This commit is contained in:
melvyn2 2022-06-20 22:03:54 -07:00 committed by Florian Bach
parent 53cbe88c8b
commit 61a03fe988

View File

@ -162,20 +162,20 @@ def GetMasterKey(path_to_wine_prefix):
serial = 0 serial = 0
if (verbose_logging): if (verbose_logging):
print("Serial: " + str(serial)) print("Serial: {}".format(serial))
cpu = cpuid.CPUID() cpu = cpuid.CPUID()
_, b, c, d = cpu(0) _, b, c, d = cpu(0)
vendor = struct.pack("III", b, d, c) vendor = struct.pack("III", b, d, c)
if (verbose_logging): if (verbose_logging):
print("Vendor: " + vendor.decode("utf-8")) print("Vendor: {}".format(vendor))
signature, _, _, _ = cpu(1) signature, _, _, _ = cpu(1)
signature = struct.pack('>I', signature)[1:] signature = struct.pack('>I', signature)[1:]
if (verbose_logging): if (verbose_logging):
print("Signature: " + str(binascii.hexlify(signature))) print("Signature: {}".format(binascii.hexlify(signature)))
# Search for the username in the registry: # Search for the username in the registry:
user = None user = None
@ -216,8 +216,14 @@ def GetMasterKey(path_to_wine_prefix):
print("Error while determining username ...") print("Error while determining username ...")
exit() exit()
# Comes as bytearray
if sys.version_info[0] == 3:
user = bytes(user)
else:
user = str(user)
if verbose_logging: if verbose_logging:
print("Username: " + str(user)) print("Username: {}".format(user))
# Find the value we want to decrypt from the registry. loop through the Wine registry file to find the "key" attribute # Find the value we want to decrypt from the registry. loop through the Wine registry file to find the "key" attribute
try: try:
@ -261,20 +267,17 @@ def GetMasterKey(path_to_wine_prefix):
return None return None
if verbose_logging: if verbose_logging:
print("Encrypted key: " + binascii.hexlify(key_line)) print("Encrypted key: {}".format(binascii.hexlify(key_line)))
# These should all be "bytes" (Py3) or "str" (Py2) # These should all be "bytes" (Py3) or "str" (Py2)
#print(type(vendor)) # print(type(vendor))
#print(type(signature)) # print(type(signature))
#print(type(user)) # print(type(user))
if sys.version_info[0] == 2:
user = bytes(user)
entropy = struct.pack('>I12s3s13s', serial, vendor, signature, user) entropy = struct.pack('>I12s3s13s', serial, vendor, signature, user)
if verbose_logging: if verbose_logging:
print("Entropy: " + str(entropy)) print("Entropy: {}".format(binascii.hexlify(entropy)))
# We would now call CryptUnprotectData to decrypt the stuff, # We would now call CryptUnprotectData to decrypt the stuff,
# but unfortunately there's no working Linux implementation # but unfortunately there's no working Linux implementation
@ -292,12 +295,11 @@ def GetMasterKey(path_to_wine_prefix):
if (success): if (success):
keykey = data keykey = data
if verbose_logging: if verbose_logging:
print("Key key: ") print("Key: {}".format(binascii.hexlify(keykey)))
print(binascii.hexlify(keykey))
return keykey return keykey
else: else:
print("Error number: " + str(data)) print("Error number: {}".format(data))
if data == 13: # WINError ERROR_INVALID_DATA if data == 13: # WINError ERROR_INVALID_DATA
print("Could not decrypt data with the given key. Did the entropy change?") print("Could not decrypt data with the given key. Did the entropy change?")
return None return None
@ -350,8 +352,8 @@ def CryptUnprotectDataExecuteWine(wineprefix, data, entropy):
env_dict["WINEDEBUG"] = "+err,+fixme" env_dict["WINEDEBUG"] = "+err,+fixme"
# Use environment variables to get the input data to the application. # Use environment variables to get the input data to the application.
env_dict["X_DECRYPT_DATA"] = binascii.hexlify(data) env_dict["X_DECRYPT_DATA"] = binascii.hexlify(data).decode("utf-8")
env_dict["X_DECRYPT_ENTROPY"] = binascii.hexlify(entropy) env_dict["X_DECRYPT_ENTROPY"] = binascii.hexlify(entropy).decode("utf-8")
try: try:
from calibre.utils.config import config_dir from calibre.utils.config import config_dir
@ -362,17 +364,16 @@ def CryptUnprotectDataExecuteWine(wineprefix, data, entropy):
import os import os
moddir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "keyextract") moddir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "keyextract")
proc = subprocess.Popen(["wine", "decrypt_" + winearch + ".exe" ], shell=False, cwd=moddir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
prog_output, prog_stderr = proc.communicate()
# calls decrypt_win32.exe or decrypt_win64.exe # calls decrypt_win32.exe or decrypt_win64.exe
proc = subprocess.Popen(["wine", "decrypt_" + winearch + ".exe"], shell=False, cwd=moddir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
prog_output, prog_stderr = proc.communicate()
stdout = prog_output.decode("utf-8")
stderr = prog_stderr.decode("utf-8")
if stdout.startswith("PROGOUTPUT:0:"):
if prog_output.decode("utf-8").startswith("PROGOUTPUT:0:"): key_string = stdout.split(':')[2]
key_string = prog_output.decode("utf-8").split(':')[2]
if verbose_logging: if verbose_logging:
print("Successfully got encryption key from WINE: " + key_string) print("Successfully got encryption key from WINE: {}".format(key_string))
#print("Debug log:")
#print(prog_stderr.decode("utf-8"))
else: else:
print("Successfully got encryption key from WINE.") print("Successfully got encryption key from WINE.")
master_key = binascii.unhexlify(key_string) master_key = binascii.unhexlify(key_string)
@ -382,19 +383,18 @@ def CryptUnprotectDataExecuteWine(wineprefix, data, entropy):
else: else:
print("Huh. That didn't work. ") print("Huh. That didn't work. ")
try: try:
err = int(prog_output.decode("utf-8").split(':')[1]) err = int(stdout.split(':')[1])
if err == -4: if err == -4:
err = int(prog_output.decode("utf-8").split(':')[2]) err = int(stdout.split(':')[2])
new_serial = int(prog_output.decode("utf-8").split(':')[3]) new_serial = int(stdout.split(':')[3])
if verbose_logging: if verbose_logging:
print("New serial: " + str(new_serial)) print("New serial: {}".format(new_serial))
except: except:
pass err = None
if verbose_logging: if verbose_logging:
print("Program reported: " + prog_output.decode("utf-8")) # print("Stderr log:\n{}".format(stderr))
print("Debug log: ") print("Program output: {}".format(stdout))
print(prog_stderr.decode("utf-8"))
return False, err return False, err