summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO9
-rw-r--r--PKGBUILD21
-rw-r--r--unlocker.patch60
-rw-r--r--unlocker.py400
4 files changed, 86 insertions, 404 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 24feba01907..7e2e38c1cff 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -9,6 +9,7 @@ pkgbase = vmware-workstation14
makedepends = sqlite
makedepends = python2
makedepends = unzip
+ makedepends = uefitool-git
depends = dkms
depends = ncurses5-compat-libs
depends = fuse2
@@ -64,7 +65,9 @@ pkgbase = vmware-workstation14
source = vmnet.patch
source = darwinPre15-tools-10.1.6_12989998.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/10.1.6/12989998/packages/com.vmware.fusion.tools.darwinPre15.zip.tar
source = darwin-tools-10.1.6_12989998.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/10.1.6/12989998/packages/com.vmware.fusion.tools.darwin.zip.tar
- source = unlocker.py
+ source = unlocker-3.0.2.py::https://raw.githubusercontent.com/DrDonk/unlocker/3.0.2/unlocker.py
+ source = unlocker.patch
+ source = efi-unlocker-patch-1.0.0.txt::https://raw.githubusercontent.com/DrDonk/efi-unlocker/1.0.0/patches.txt
sha256sums = a9b5ff8adb885a064f582f700c2ad42aa6c2a3b1b8964f3f8cab35cc084c89c4
sha256sums = 12e7b16abf8d7e858532edabb8868919c678063c566a6535855b194aac72d55e
sha256sums = da1698bf4e73ae466c1c7fc93891eba4b9c4581856649635e6532275dbfea141
@@ -89,7 +92,9 @@ pkgbase = vmware-workstation14
sha256sums = 9503ab7064fe7b63f18dfbc061e6246e0af26f01812e39f6d778a169dd93dd13
sha256sums = 195313791f2c2cf880b0ba6c9d130e40ab6729335c0980fcc40df4209c1ed52b
sha256sums = e36fb99a56a65d2c4d82168c8adb1ed19a9a7aaf75807c667c79a79f4968740a
- sha256sums = ecf6d9186f109ec420287bd327e1f1f407de8e4b9e3faa23828bcf903f6246c6
+ sha256sums = 29e0b0db9c0296ab81eee543803c4bd430e2c69c76e33492910e17280da1c05c
+ sha256sums = d0b16c21246468869ae26cc33d64eb2790c2e9446702a40916770c9d634ef03d
+ sha256sums = 392c1effcdec516000e9f8ffc97f2586524d8953d3e7d6f2c5f93f2acd809d91
pkgname = vmware-workstation14
diff --git a/PKGBUILD b/PKGBUILD
index a9f25e60e55..ffbc77a5fc7 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -143,20 +143,28 @@ if [ -n "$_enable_macOS_guests" ]; then
_vmware_fusion_ver=10.1.6_12989998
# List of VMware Fusion versions: https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/
+_unlocker_ver=3.0.2
+_efi_unlocker_ver=1.0.0
+
makedepends+=(
python2
unzip
+ uefitool-git
)
source+=(
"darwinPre15-tools-${_vmware_fusion_ver}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver/_//}/packages/com.vmware.fusion.tools.darwinPre15.zip.tar"
"darwin-tools-${_vmware_fusion_ver}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver/_//}/packages/com.vmware.fusion.tools.darwin.zip.tar"
- 'unlocker.py'
+ "unlocker-${_unlocker_ver}.py::https://raw.githubusercontent.com/DrDonk/unlocker/${_unlocker_ver}/unlocker.py"
+ 'unlocker.patch'
+ "efi-unlocker-patch-${_efi_unlocker_ver}.txt::https://raw.githubusercontent.com/DrDonk/efi-unlocker/${_efi_unlocker_ver}/patches.txt"
)
sha256sums+=(
'195313791f2c2cf880b0ba6c9d130e40ab6729335c0980fcc40df4209c1ed52b'
'e36fb99a56a65d2c4d82168c8adb1ed19a9a7aaf75807c667c79a79f4968740a'
- 'ecf6d9186f109ec420287bd327e1f1f407de8e4b9e3faa23828bcf903f6246c6'
+ '29e0b0db9c0296ab81eee543803c4bd430e2c69c76e33492910e17280da1c05c'
+ 'd0b16c21246468869ae26cc33d64eb2790c2e9446702a40916770c9d634ef03d'
+ '392c1effcdec516000e9f8ffc97f2586524d8953d3e7d6f2c5f93f2acd809d91'
)
_fusion_isoimages=(darwin darwinPre15)
@@ -203,6 +211,8 @@ if [ -n "$_enable_macOS_guests" ]; then
rm -rf payload manifest.plist
done
+ cp "$srcdir/unlocker-${_unlocker_ver}.py" "$srcdir/unlocker.py"
+ patch -Np1 < unlocker.patch
sed -i -e "s|/usr/lib/vmware/|${pkgdir}/usr/lib/vmware/|" "$srcdir/unlocker.py"
fi
}
@@ -449,6 +459,13 @@ if [ -n "$_enable_macOS_guests" ]; then
install -Dm 644 "$srcdir/fusion-isoimages/$isoimage.iso" "$pkgdir/usr/lib/vmware/isoimages/$isoimage.iso"
install -Dm 644 "$srcdir/fusion-isoimages/$isoimage.iso.sig" "$pkgdir/usr/lib/vmware/isoimages/$isoimage.iso.sig"
done
+
+ msg "Patching EFI firmwares to remove the check for server versions"
+ _efi_arch=(32 64)
+ for arch in ${_efi_arch[@]}
+ do
+ uefipatch "$pkgdir/usr/lib/vmware/roms/EFI${arch}.ROM" "$srcdir/efi-unlocker-patch-${_efi_unlocker_ver}.txt" -o "$pkgdir/usr/lib/vmware/roms/EFI${arch}.ROM" > /dev/null
+ done
fi
_create_database_file
diff --git a/unlocker.patch b/unlocker.patch
new file mode 100644
index 00000000000..9d445662293
--- /dev/null
+++ b/unlocker.patch
@@ -0,0 +1,60 @@
+diff --git a/unlocker.py b/unlocker.py
+index decbc51..0f9d3f6 100755
+--- a/unlocker.py
++++ b/unlocker.py
+@@ -44,6 +44,7 @@ Offset Length Struct Type Description
+ from __future__ import print_function
+ import codecs
+ import os
++import re
+ import struct
+ import sys
+
+@@ -55,7 +56,10 @@ if sys.version_info < (2, 7):
+ if sys.platform == 'win32' \
+ or sys.platform == 'cli':
+ # noinspection PyUnresolvedReferences
+- from _winreg import *
++ if sys.version_info > (3, 0):
++ from winreg import *
++ else:
++ from _winreg import *
+
+
+ def bytetohex(data):
+@@ -301,9 +305,10 @@ def patchbase(name):
+ f = open(name, 'r+b')
+
+ # Entry to search for in GOS table
+- # Should work for 12 & 14 of Workstation...
+- darwin = b'\x10\x00\x00\x00\x10\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00' \
+- '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
++ # Should work for Workstation 12-15...
++ darwin = re.compile(
++ b'\x10\x00\x00\x00[\x10|\x20]\x00\x00\x00[\x01|\x02]\x00\x00\x00\x00\x00\x00\x00'
++ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+
+ # Read file into string variable
+ base = f.read()
+@@ -311,11 +316,8 @@ def patchbase(name):
+ # Loop through each entry and set top bit
+ # 0xBE --> 0xBF (WKS 12)
+ # 0x3E --> 0x3F (WKS 14)
+- offset = 0
+- while offset < len(base):
+- offset = base.find(darwin, offset)
+- if offset == -1:
+- break
++ for m in darwin.finditer(base):
++ offset = m.start()
+ f.seek(offset + 32)
+ flag = ord(f.read(1))
+ flag = set_bit(flag, 0)
+@@ -323,7 +325,6 @@ def patchbase(name):
+ f.seek(offset + 32)
+ f.write(flag)
+ print('GOS Patched flag @: ' + hex(offset))
+- offset += 40
+
+ # Tidy up
+ f.flush()
diff --git a/unlocker.py b/unlocker.py
deleted file mode 100644
index 0f9d3f66eeb..00000000000
--- a/unlocker.py
+++ /dev/null
@@ -1,400 +0,0 @@
-#!/usr/bin/env python
-"""
-The MIT License (MIT)
-
-Copyright (c) 2014-2018 Dave Parsons & Sam Bingner
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the 'Software'), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-vSMC Header Structure
-Offset Length Struct Type Description
-----------------------------------------
-0x00/00 0x08/08 Q ptr Offset to key table
-0x08/08 0x04/4 I int Number of private keys
-0x0C/12 0x04/4 I int Number of public keys
-
-vSMC Key Data Structure
-Offset Length Struct Type Description
-----------------------------------------
-0x00/00 0x04/04 4s int Key name (byte reversed e.g. #KEY is YEK#)
-0x04/04 0x01/01 B byte Length of returned data
-0x05/05 0x04/04 4s int Data type (byte reversed e.g. ui32 is 23iu)
-0x09/09 0x01/01 B byte Flag R/W
-0x0A/10 0x06/06 6x byte Padding
-0x10/16 0x08/08 Q ptr Internal VMware routine
-0x18/24 0x30/48 48B byte Data
-"""
-
-from __future__ import print_function
-import codecs
-import os
-import re
-import struct
-import sys
-
-if sys.version_info < (2, 7):
- sys.stderr.write('You need Python 2.7 or later\n')
- sys.exit(1)
-
-# Setup imports depending on whether IronPython or CPython
-if sys.platform == 'win32' \
- or sys.platform == 'cli':
- # noinspection PyUnresolvedReferences
- if sys.version_info > (3, 0):
- from winreg import *
- else:
- from _winreg import *
-
-
-def bytetohex(data):
- if sys.version_info > (3, 0):
- # Python 3 code in this block
- return "".join("{:02X} ".format(c) for c in data)
- else:
- # Python 2 code in this block
- return "".join("{:02X} ".format(ord(c)) for c in data)
-
-
-def joinpath(folder, filename):
- return os.path.join(folder, filename)
-
-
-def printkey(i, offset, smc_key, smc_data):
- print(str(i + 1).zfill(3)
- + ' ' + hex(offset)
- + ' ' + smc_key[0][::-1].decode('UTF-8')
- + ' ' + str(smc_key[1]).zfill(2)
- + ' ' + smc_key[2][::-1].replace(b'\x00', b' ').decode('UTF-8')
- + ' ' + '{0:#0{1}x}'.format(smc_key[3], 4)
- + ' ' + hex(smc_key[4])
- + ' ' + bytetohex(smc_data))
-
-
-def set_bit(value, bit):
- return value | (1 << bit)
-
-
-def clear_bit(value, bit):
- return value & ~(1 << bit)
-
-
-def test_bit(value, bit):
- return value & bit
-
-
-E_CLASS64 = 2
-E_SHT_RELA = 4
-
-
-def patchelf(f, oldoffset, newoffset):
- f.seek(0)
- magic = f.read(4)
- if not magic == b'\x7fELF':
- raise Exception('Magic number does not match')
-
- ei_class = struct.unpack('=B', f.read(1))[0]
- if ei_class != E_CLASS64:
- raise Exception('Not 64bit elf header: ' + ei_class)
-
- f.seek(40)
- e_shoff = struct.unpack('=Q', f.read(8))[0]
- f.seek(58)
- e_shentsize = struct.unpack('=H', f.read(2))[0]
- e_shnum = struct.unpack('=H', f.read(2))[0]
- e_shstrndx = struct.unpack('=H', f.read(2))[0]
-
- print('e_shoff: 0x{:x} e_shentsize: 0x{:x} e_shnum:0x{:x} e_shstrndx:0x{:x}'.format(e_shoff, e_shentsize,
- e_shnum, e_shstrndx))
-
- for i in range(0, e_shnum):
- f.seek(e_shoff + i * e_shentsize)
- e_sh = struct.unpack('=LLQQQQLLQQ', f.read(e_shentsize))
- # e_sh_name = e_sh[0]
- e_sh_type = e_sh[1]
- e_sh_offset = e_sh[4]
- e_sh_size = e_sh[5]
- e_sh_entsize = e_sh[9]
- if e_sh_type == E_SHT_RELA:
- e_sh_nument = int(e_sh_size / e_sh_entsize)
- # print 'RELA at 0x{:x} with {:d} entries'.format(e_sh_offset, e_sh_nument)
- for j in range(0, e_sh_nument):
- f.seek(e_sh_offset + e_sh_entsize * j)
- rela = struct.unpack('=QQq', f.read(e_sh_entsize))
- r_offset = rela[0]
- r_info = rela[1]
- r_addend = rela[2]
- if r_addend == oldoffset:
- r_addend = newoffset
- f.seek(e_sh_offset + e_sh_entsize * j)
- f.write(struct.pack('=QQq', r_offset, r_info, r_addend))
- print('Relocation modified at: ' + hex(e_sh_offset + e_sh_entsize * j))
-
-
-def patchkeys(f, key):
- # Setup struct pack string
- key_pack = '=4sB4sB6xQ'
- # smc_old_memptr = 0
- smc_new_memptr = 0
-
- # Do Until OSK1 read
- i = 0
- while True:
-
- # Read key into struct str and data byte str
- offset = key + (i * 72)
- f.seek(offset)
- smc_key = struct.unpack(key_pack, f.read(24))
- smc_data = f.read(smc_key[1])
-
- # Reset pointer to beginning of key entry
- f.seek(offset)
-
- if smc_key[0] == b'SKL+':
- # Use the +LKS data routine for OSK0/1
- smc_new_memptr = smc_key[4]
- print('+LKS Key: ')
- printkey(i, offset, smc_key, smc_data)
-
- elif smc_key[0] == b'0KSO':
- # Write new data routine pointer from +LKS
- print('OSK0 Key Before:')
- printkey(i, offset, smc_key, smc_data)
- # smc_old_memptr = smc_key[4]
- f.seek(offset)
- f.write(struct.pack(key_pack, smc_key[0], smc_key[1], smc_key[2], smc_key[3], smc_new_memptr))
- f.flush()
-
- # Write new data for key
- f.seek(offset + 24)
- smc_new_data = codecs.encode('bheuneqjbexolgurfrjbeqfthneqrqcy', 'rot_13')
- f.write(smc_new_data.encode('UTF-8'))
- f.flush()
-
- # Re-read and print key
- f.seek(offset)
- smc_key = struct.unpack(key_pack, f.read(24))
- smc_data = f.read(smc_key[1])
- print('OSK0 Key After:')
- printkey(i, offset, smc_key, smc_data)
-
- elif smc_key[0] == b'1KSO':
- # Write new data routine pointer from +LKS
- print('OSK1 Key Before:')
- printkey(i, offset, smc_key, smc_data)
- smc_old_memptr = smc_key[4]
- f.seek(offset)
- f.write(struct.pack(key_pack, smc_key[0], smc_key[1], smc_key[2], smc_key[3], smc_new_memptr))
- f.flush()
-
- # Write new data for key
- f.seek(offset + 24)
- smc_new_data = codecs.encode('rnfrqbagfgrny(p)NccyrPbzchgreVap', 'rot_13')
- f.write(smc_new_data.encode('UTF-8'))
- f.flush()
-
- # Re-read and print key
- f.seek(offset)
- smc_key = struct.unpack(key_pack, f.read(24))
- smc_data = f.read(smc_key[1])
- print('OSK1 Key After:')
- printkey(i, offset, smc_key, smc_data)
-
- # Finished so get out of loop
- break
-
- else:
- pass
-
- i += 1
- return smc_old_memptr, smc_new_memptr
-
-
-def patchsmc(name, sharedobj):
- with open(name, 'r+b') as f:
-
- smc_old_memptr = 0
- smc_new_memptr = 0
-
- # Read file into string variable
- vmx = f.read()
-
- print('File: ' + name + '\n')
-
- # Setup hex string for vSMC headers
- # These are the private and public key counts
- smc_header_v0 = b'\xF2\x00\x00\x00\xF0\x00\x00\x00'
- smc_header_v1 = b'\xB4\x01\x00\x00\xB0\x01\x00\x00'
-
- # Setup hex string for #KEY key
- key_key = b'\x59\x45\x4B\x23\x04\x32\x33\x69\x75'
-
- # Setup hex string for $Adr key
- adr_key = b'\x72\x64\x41\x24\x04\x32\x33\x69\x75'
-
- # Find the vSMC headers
- smc_header_v0_offset = vmx.find(smc_header_v0) - 8
- smc_header_v1_offset = vmx.find(smc_header_v1) - 8
-
- # Find '#KEY' keys
- smc_key0 = vmx.find(key_key)
- smc_key1 = vmx.rfind(key_key)
-
- # Find '$Adr' key only V1 table
- smc_adr = vmx.find(adr_key)
-
- # Print vSMC0 tables and keys
- print('appleSMCTableV0 (smc.version = "0")')
- print('appleSMCTableV0 Address : ' + hex(smc_header_v0_offset))
- print('appleSMCTableV0 Private Key #: 0xF2/242')
- print('appleSMCTableV0 Public Key #: 0xF0/240')
-
- if (smc_adr - smc_key0) != 72:
- print('appleSMCTableV0 Table : ' + hex(smc_key0))
- smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key0)
- elif (smc_adr - smc_key1) != 72:
- print('appleSMCTableV0 Table : ' + hex(smc_key1))
- smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1)
-
- print()
-
- # Print vSMC1 tables and keys
- print('appleSMCTableV1 (smc.version = "1")')
- print('appleSMCTableV1 Address : ' + hex(smc_header_v1_offset))
- print('appleSMCTableV1 Private Key #: 0x01B4/436')
- print('appleSMCTableV1 Public Key #: 0x01B0/432')
-
- if (smc_adr - smc_key0) == 72:
- print('appleSMCTableV1 Table : ' + hex(smc_key0))
- smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key0)
- elif (smc_adr - smc_key1) == 72:
- print('appleSMCTableV1 Table : ' + hex(smc_key1))
- smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1)
-
- print()
-
- # Find matching RELA record in .rela.dyn in ESXi ELF files
- # This is temporary code until proper ELF parsing written
- if sharedobj:
- print('Modifying RELA records from: ' + hex(smc_old_memptr) + ' to ' + hex(smc_new_memptr))
- patchelf(f, smc_old_memptr, smc_new_memptr)
-
- # Tidy up
- f.flush()
- f.close()
-
-
-def patchbase(name):
- # Patch file
- print('GOS Patching: ' + name)
- f = open(name, 'r+b')
-
- # Entry to search for in GOS table
- # Should work for Workstation 12-15...
- darwin = re.compile(
- b'\x10\x00\x00\x00[\x10|\x20]\x00\x00\x00[\x01|\x02]\x00\x00\x00\x00\x00\x00\x00'
- b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-
- # Read file into string variable
- base = f.read()
-
- # Loop through each entry and set top bit
- # 0xBE --> 0xBF (WKS 12)
- # 0x3E --> 0x3F (WKS 14)
- for m in darwin.finditer(base):
- offset = m.start()
- f.seek(offset + 32)
- flag = ord(f.read(1))
- flag = set_bit(flag, 0)
- flag = chr(flag)
- f.seek(offset + 32)
- f.write(flag)
- print('GOS Patched flag @: ' + hex(offset))
-
- # Tidy up
- f.flush()
- f.close()
- print('GOS Patched: ' + name)
-
-
-def patchvmkctl(name):
- # Patch file
- print('smcPresent Patching: ' + name)
- f = open(name, 'r+b')
-
- # Read file into string variable
- vmkctl = f.read()
- applesmc = vmkctl.find(b'applesmc')
- f.seek(applesmc)
- f.write(b'vmkernel')
-
- # Tidy up
- f.flush()
- f.close()
- print('smcPresent Patched: ' + name)
-
-
-# noinspection PyUnresolvedReferences
-def main():
- # Work around absent Platform module on VMkernel
- if os.name == 'nt' or os.name == 'cli':
- osname = 'windows'
- else:
- osname = os.uname()[0].lower()
-
- # vmwarebase = ''
- vmx_so = False
-
- # Setup default paths
- if osname == 'linux':
- vmx_path = '/usr/lib/vmware/bin/'
- vmx = joinpath(vmx_path, 'vmware-vmx')
- vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug')
- vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats')
- if os.path.isfile('/usr/lib/vmware/lib/libvmwarebase.so/libvmwarebase.so'):
- vmx_so = True
- vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so/libvmwarebase.so'
- else:
- vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so.0/libvmwarebase.so.0'
-
- elif osname == 'windows':
- reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
- key = OpenKey(reg, r'SOFTWARE\Wow6432Node\VMware, Inc.\VMware Workstation')
- vmwarebase_path = QueryValueEx(key, 'InstallPath')[0]
- vmx_path = QueryValueEx(key, 'InstallPath64')[0]
- vmx = joinpath(vmx_path, 'vmware-vmx.exe')
- vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug.exe')
- vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats.exe')
- vmwarebase = joinpath(vmwarebase_path, 'vmwarebase.dll')
-
- else:
- print('Unknown Operating System: ' + osname)
- return
-
- # Patch the vmx executables skipping stats version for Player
- patchsmc(vmx, vmx_so)
- patchsmc(vmx_debug, vmx_so)
- if os.path.isfile(vmx_stats):
- patchsmc(vmx_stats, vmx_so)
-
- # Patch vmwarebase for Workstation and Player
- patchbase(vmwarebase)
-
-
-if __name__ == '__main__':
- main()