diff options
author | Jean-Marc Lenoir | 2019-09-27 22:59:52 +0200 |
---|---|---|
committer | Jean-Marc Lenoir | 2019-09-27 22:59:52 +0200 |
commit | 6a1c8801d17f403088bd538eed381af4afb4a640 (patch) | |
tree | 7f7777a4c3a8c0662554adf6996a9ea852cc8443 | |
parent | d6ac9daad7deef56440d9fd020c795e98e4a0944 (diff) | |
download | aur-6a1c8801d17f403088bd538eed381af4afb4a640.tar.gz |
Remove the check for server versions in EFI firmwares
-rw-r--r-- | .SRCINFO | 9 | ||||
-rw-r--r-- | PKGBUILD | 21 | ||||
-rw-r--r-- | unlocker.patch | 60 | ||||
-rw-r--r-- | unlocker.py | 400 |
4 files changed, 86 insertions, 404 deletions
@@ -9,6 +9,7 @@ pkgbase = vmware-workstation makedepends = sqlite makedepends = python2 makedepends = unzip + makedepends = uefitool-git depends = dkms depends = ncurses5-compat-libs depends = fuse2 @@ -62,7 +63,9 @@ pkgbase = vmware-workstation source = vmmon.patch source = vmnet.patch source = VMware-Fusion-11.5.0-14634996.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/11.5.0/14634996/core/com.vmware.fusion.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 = b557b4dcebefb51466da5b33dc51549537b0d381864b6155c3a48a66801a8597 sha256sums = 12e7b16abf8d7e858532edabb8868919c678063c566a6535855b194aac72d55e sha256sums = da1698bf4e73ae466c1c7fc93891eba4b9c4581856649635e6532275dbfea141 @@ -86,7 +89,9 @@ pkgbase = vmware-workstation sha256sums = 1060b5d45caeda5119b220fab4e1ece398af34d75131139a5dc6f74ee06672c3 sha256sums = 7c3b6a7871b19e31fafdcc2631751dd9569196740d8e7c2026653d155c0c8da0 sha256sums = ed819604cb9c0f204e377f16b8678103467d2cf4a50129932e2b1a9a000ad8cf - sha256sums = ecf6d9186f109ec420287bd327e1f1f407de8e4b9e3faa23828bcf903f6246c6 + sha256sums = 29e0b0db9c0296ab81eee543803c4bd430e2c69c76e33492910e17280da1c05c + sha256sums = d0b16c21246468869ae26cc33d64eb2790c2e9446702a40916770c9d634ef03d + sha256sums = 392c1effcdec516000e9f8ffc97f2586524d8953d3e7d6f2c5f93f2acd809d91 pkgname = vmware-workstation @@ -146,18 +146,26 @@ if [ -n "$_enable_macOS_guests" ]; then _vmware_fusion_ver=11.5.0_14634996 # 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+=( "VMware-Fusion-${_vmware_fusion_ver/_/-}.zip.tar::https://softwareupdate.vmware.com/cds/vmw-desktop/fusion/${_vmware_fusion_ver/_//}/core/com.vmware.fusion.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+=( 'ed819604cb9c0f204e377f16b8678103467d2cf4a50129932e2b1a9a000ad8cf' - 'ecf6d9186f109ec420287bd327e1f1f407de8e4b9e3faa23828bcf903f6246c6' + '29e0b0db9c0296ab81eee543803c4bd430e2c69c76e33492910e17280da1c05c' + 'd0b16c21246468869ae26cc33d64eb2790c2e9446702a40916770c9d634ef03d' + '392c1effcdec516000e9f8ffc97f2586524d8953d3e7d6f2c5f93f2acd809d91' ) _fusion_isoimages=(darwin darwinPre15) @@ -203,6 +211,8 @@ if [ -n "$_enable_macOS_guests" ]; then done rm -rf __MACOSX payload manifest.plist preflight postflight + 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 } @@ -458,6 +468,13 @@ if [ -n "$_enable_macOS_guests" ]; then do install -Dm 644 "$srcdir/fusion-isoimages/$isoimage.iso" "$pkgdir/usr/lib/vmware/isoimages/$isoimage.iso" 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 000000000000..9d4456622935 --- /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 0f9d3f66eeba..000000000000 --- 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() |