diff --git a/dumpsmc.py b/dumpsmc.py index 58f3540..65fff8a 100755 --- a/dumpsmc.py +++ b/dumpsmc.py @@ -40,6 +40,7 @@ Offset Length struct Type Description 0x18/24 0x30/48 48B byte Data """ +from __future__ import print_function import struct import sys @@ -48,18 +49,24 @@ if sys.version_info < (2, 7): sys.exit(1) -def bytetohex(bytestr): - return ''.join(['%02X ' % ord(x) for x in bytestr]).strip() +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 printkey(i, smc_key, smc_data): - print str(i+1).zfill(3) \ - + ' ' + smc_key[0][::-1] \ - + ' ' + str(smc_key[1]).zfill(2) \ - + ' ' + smc_key[2][::-1].replace('\x00', ' ') \ - + ' ' + '{0:#0{1}x}'.format(smc_key[3], 4) \ - + ' ' + hex(smc_key[4]) \ - + ' ' + bytetohex(smc_data) +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 dumpkeys(f, key): @@ -77,10 +84,10 @@ def dumpkeys(f, key): smc_data = f.read(smc_key[1]) # Dump entry - printkey(i, smc_key, smc_data) + printkey(i, offset, smc_key, smc_data) # Exit when OSK1 has been read - if smc_key[0] == '1KSO': + if smc_key[0] == b'1KSO': break else: i += 1 @@ -88,23 +95,23 @@ def dumpkeys(f, key): def dumpsmc(name): - with open(name, 'r+b') as f: + with open(name, 'rb') as f: - # Read file into string variable + # Read file into variable vmx = f.read() - print 'File: ' + name + print('File: ' + name) # Setup hex string for vSMC headers # These are the private and public key counts - smc_header_v0 = '\xF2\x00\x00\x00\xF0\x00\x00\x00' - smc_header_v1 = '\xB4\x01\x00\x00\xB0\x01\x00\x00' + 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 = '\x59\x45\x4B\x23\x04\x32\x33\x69\x75' + key_key = b'\x59\x45\x4B\x23\x04\x32\x33\x69\x75' # Setup hex string for $Adr key - adr_key = '\x72\x64\x41\x24\x04\x32\x33\x69\x75' + 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 @@ -118,31 +125,31 @@ def dumpsmc(name): 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' + 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) + print('appleSMCTableV0 Table : ' + hex(smc_key0)) dumpkeys(f, smc_key0) elif (smc_adr - smc_key1) != 72: - print 'appleSMCTableV0 Table : ' + hex(smc_key1) + print('appleSMCTableV0 Table : ' + hex(smc_key1)) dumpkeys(f, smc_key1) - print + print('xxxx') # 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' + 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) + print('appleSMCTableV1 Table : ' + hex(smc_key0)) dumpkeys(f, smc_key0) elif (smc_adr - smc_key1) == 72: - print 'appleSMCTableV1 Table : ' + hex(smc_key1) + print('appleSMCTableV1 Table : ' + hex(smc_key1)) dumpkeys(f, smc_key1) # Tidy up @@ -150,19 +157,19 @@ def dumpsmc(name): def main(): - print 'dumpsmc' - print '-------' + print('dumpsmc') + print('-------') if len(sys.argv) >= 2: vmx_path = sys.argv[1] else: - print 'Please pass file name!' + print('Please pass file name!') return try: dumpsmc(vmx_path) except IOError: - print 'Cannot find file ' + vmx_path + print('Cannot find file ' + vmx_path) if __name__ == '__main__': diff --git a/esxi-install.sh b/esxi-install.sh index babe344..399168a 100755 --- a/esxi-install.sh +++ b/esxi-install.sh @@ -1,5 +1,6 @@ #!/bin/sh set -e +set -x echo VMware Unlocker 2.0.9 echo =============================== @@ -8,12 +9,42 @@ echo Copyright: Dave Parsons 2011-16 # Ensure we only use unmodified commands export PATH=/bin:/sbin:/usr/bin:/usr/sbin -# Copy patch to local.sh -echo Installing local.sh -cp local-template.sh local.sh -cat unlocker.py >> local.sh -echo END >> local.sh -echo /etc/init.d/hostd restart >> local.sh -chmod +x local.sh +echo Creating unlocker vmtar disk + +# Create tmp folder for patching the files +mkdir -p tmp/bin +mkdir -p tmp/lib + +cp -v /bin/vmx tmp/bin +cp -v /bin/vmx-debug tmp/bin +cp -v /bin/vmx-stats tmp/bin +cp -v /lib/libvmkctl.so tmp/lib + +if [ -f /lib64/libvmkctl.so ]; then + mkdir -p tmp/lib64 + cp -v /lib64/libvmkctl.so tmp/lib64 +fi + +# Patch the files +python unlocker.py + +# Create the vmtar file for ESXi kernel +if [ -f /lib64/libvmkctl.so ]; then + tar cvf tmp/unlocker.tar -C tmp bin lib lib64 +else + tar cvf tmp/unlocker.tar -C tmp bin lib +fi + +vmtar -c tmp/unlocker.tar -v -o tmp/unlocker.vmtar +gzip tmp/unlocker.vmtar +mv tmp/unlocker.vmtar.gz tmp/unlocker.vgz + +# Copy to bootbank and setup local.sh +echo Copying unlocker.vgz to bootbank... +cp tmp/unlocker.vgz /bootbank cp local.sh /etc/rc.local.d/local.sh + +# Clean up +#rm -rfv tmp + echo Success - please now restart the server! diff --git a/esxi-uninstall.sh b/esxi-uninstall.sh index ceeca6d..3a45bd8 100755 --- a/esxi-uninstall.sh +++ b/esxi-uninstall.sh @@ -1,5 +1,6 @@ #!/bin/sh set -e +set -x echo VMware Unlocker 2.0.9 echo =============================== @@ -8,6 +9,9 @@ echo Copyright: Dave Parsons 2011-16 # Ensure we only use unmodified commands export PATH=/bin:/sbin:/usr/bin:/usr/sbin -echo Uninstalling local.sh -cp /etc/rc.local.d/.#local.sh /etc/rc.local.d/local.sh -echo Success - please now restart the server! +# Remove entry from the boot configuration file +echo Deleting unlocker.vgz from bootbank... +rm /bootbank/unlocker.vgz +rm /etc/rc.local.d/local.sh + +echo Please now reboot the host system! diff --git a/local-template.sh b/local-template.sh deleted file mode 100755 index 1229028..0000000 --- a/local-template.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh -set -e -set -x - -echo VMware ESXi 6.x Unlocker 2.0.9 -echo =============================== -echo Copyright: Dave Parsons 2011-16 - -# Ensure we only use unmodified commands -export PATH=/bin:/sbin:/usr/bin:/usr/sbin - -# Make sure working files are removed -if [ -d /unlocker ]; then - logger -t unlocker Removing current patches - rm -rfv /unlocker -fi - -# Create new RAM disk and map to /unlocker -logger -t unlocker Creating RAM disk -mkdir /unlocker -localcli system visorfs ramdisk add -m 200 -M 200 -n unlocker -p 0755 -t /unlocker - -# Copy the vmx files -logger -t unlocker Copying vmx files -cp /bin/vmx /unlocker/ -cp /bin/vmx-debug /unlocker/ -cp /bin/vmx-stats /unlocker/ - -# Setup symlink from /bin -logger -t unlocker Setup sym links -rm -fv /bin/vmx -ln -s /unlocker/vmx /bin/vmx -rm -fv /bin/vmx-debug -ln -s /unlocker/vmx-debug /bin/vmx-debug -rm -fv /bin/vmx-stats -ln -s /unlocker/vmx-stats /bin/vmx-stats - -# Copy the libvmkctl.so file -mkdir /unlocker/lib -cp /lib/libvmkctl.so /unlocker/lib/libvmkctl.so -rm -fv /lib/libvmkctl.so -ln -s /unlocker/lib/libvmkctl.so /lib/libvmkctl.so - -if [ -f "/lib64/libvmkctl.so" ] ; then - mkdir /unlocker/lib64 - cp /lib64/libvmkctl.so /unlocker/lib64/libvmkctl.so - rm -fv /lib64/libvmkctl.so - ln -s /unlocker/lib64/libvmkctl.so /lib64/libvmkctl.so -fi - -# Patch the vmx files -logger -t unlocker Patching vmx files -python < -1 else c + return ''.join(rot_char(c) for c in s) + + +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, file): + return os.path.join(folder, file) def printkey(i, offset, smc_key, smc_data): - print str(i + 1).zfill(3) \ - + ' ' + hex(offset) \ - + ' ' + smc_key[0][::-1] \ - + ' ' + str(smc_key[1]).zfill(2) \ - + ' ' + smc_key[2][::-1].replace('\x00', ' ') \ - + ' ' + '{0:#0{1}x}'.format(smc_key[3], 4) \ - + ' ' + hex(smc_key[4]) \ - + ' ' + bytetohex(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)) + + +E_CLASS64 = 2 +E_SHT_RELA = 4 def patchelf(f, oldoffset, newoffset): - E_CLASS64 = 2 - E_SHT_RELA = 4 f.seek(0) magic = f.read(4) if not magic == b'\x7fELF': @@ -90,20 +108,20 @@ def patchelf(f, oldoffset, newoffset): 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) + 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_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 = e_sh_size / e_sh_entsize - print 'RELA at 0x{:x} with {:d} entries'.format(e_sh_offset, e_sh_nument) + 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)) @@ -114,7 +132,7 @@ def patchelf(f, oldoffset, newoffset): 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) + print('Relocation modified at: ' + hex(e_sh_offset + e_sh_entsize * j)) def patchkeys(f, key): @@ -136,15 +154,15 @@ def patchkeys(f, key): # Reset pointer to beginning of key entry f.seek(offset) - if smc_key[0] == 'SKL+': + if smc_key[0] == b'SKL+': # Use the +LKS data routine for OSK0/1 smc_new_memptr = smc_key[4] - print '+LKS Key: ' + print('+LKS Key: ') printkey(i, offset, smc_key, smc_data) - elif smc_key[0] == '0KSO': + elif smc_key[0] == b'0KSO': # Write new data routine pointer from +LKS - print 'OSK0 Key Before:' + print('OSK0 Key Before:') printkey(i, offset, smc_key, smc_data) smc_old_memptr = smc_key[4] f.seek(offset) @@ -153,20 +171,20 @@ def patchkeys(f, key): # Write new data for key f.seek(offset + 24) - smc_new_data = codecs.decode('bheuneqjbexolgurfrjbeqfthneqrqcy', 'rot_13') - f.write(smc_new_data) + smc_new_data = rot13('bheuneqjbexolgurfrjbeqfthneqrqcy') + 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:' + print('OSK0 Key After:') printkey(i, offset, smc_key, smc_data) - elif smc_key[0] == '1KSO': + elif smc_key[0] == b'1KSO': # Write new data routine pointer from +LKS - print 'OSK1 Key Before:' + print('OSK1 Key Before:') printkey(i, offset, smc_key, smc_data) smc_old_memptr = smc_key[4] f.seek(offset) @@ -175,15 +193,15 @@ def patchkeys(f, key): # Write new data for key f.seek(offset + 24) - smc_new_data = codecs.decode('rnfrqbagfgrny(p)NccyrPbzchgreVap', 'rot_13') - f.write(smc_new_data) + smc_new_data = rot13('rnfrqbagfgrny(p)NccyrPbzchgreVap') + 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:' + print('OSK1 Key After:') printkey(i, offset, smc_key, smc_data) # Finished so get out of loop @@ -205,18 +223,18 @@ def patchsmc(name, sharedobj): # Read file into string variable vmx = f.read() - print 'File: ' + name + print('File: ' + name) # Setup hex string for vSMC headers # These are the private and public key counts - smc_header_v0 = '\xF2\x00\x00\x00\xF0\x00\x00\x00' - smc_header_v1 = '\xB4\x01\x00\x00\xB0\x01\x00\x00' + 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 = '\x59\x45\x4B\x23\x04\x32\x33\x69\x75' + key_key = b'\x59\x45\x4B\x23\x04\x32\x33\x69\x75' # Setup hex string for $Adr key - adr_key = '\x72\x64\x41\x24\x04\x32\x33\x69\x75' + 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 @@ -230,39 +248,39 @@ def patchsmc(name, sharedobj): 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' + 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) + 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) + print('appleSMCTableV0 Table : ' + hex(smc_key1)) smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1) - print + 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' + 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) + 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) + print('appleSMCTableV1 Table : ' + hex(smc_key1)) smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1) - print + 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) + print('Modifying RELA records from: ' + hex(smc_old_memptr) + ' to ' + hex(smc_new_memptr)) patchelf(f, smc_old_memptr, smc_new_memptr) # Tidy up @@ -272,7 +290,7 @@ def patchsmc(name, sharedobj): def patchbase(name): # Patch file - print 'GOS Patching: ' + name + print('GOS Patching: ' + name) f = open(name, 'r+b') # Entry to search for in GOS table @@ -299,33 +317,33 @@ def patchbase(name): if flag == '\xBE': f.seek(offset + 32) f.write('\xBF') - print 'GOS Patched flag @: ' + hex(offset) + print('GOS Patched flag @: ' + hex(offset)) else: - print 'GOS Unknown flag @: ' + hex(offset) + '/' + hex(int(flag)) + print('GOS Unknown flag @: ' + hex(offset) + '/' + hex(int(flag))) offset += 33 # Tidy up f.flush() f.close() - print 'GOS Patched: ' + name + print('GOS Patched: ' + name) def patchvmkctl(name): # Patch file - print 'smcPresent Patching: ' + name + print('smcPresent Patching: ' + name) f = open(name, 'r+b') # Read file into string variable vmkctl = f.read() - applesmc = vmkctl.find('applesmc') + applesmc = vmkctl.find(b'applesmc') f.seek(applesmc) - f.write('vmkernel') + f.write(b'vmkernel') # Tidy up f.flush() f.close() - print 'smcPresent Patched: ' + name + print('smcPresent Patched: ' + name) def main(): @@ -335,20 +353,23 @@ def main(): else: osname = os.uname()[0].lower() + vmwarebase = '' + libvmkctl32 = '' + libvmkctl64 = '' vmx_so = False # Setup default paths if osname == 'darwin': vmx_path = '/Applications/VMware Fusion.app/Contents/Library/' - vmx = vmx_path + 'vmware-vmx' - vmx_debug = vmx_path + 'vmware-vmx-debug' - vmx_stats = vmx_path + 'vmware-vmx-stats' + vmx = joinpath(vmx_path, 'vmware-vmx') + vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug') + vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats') elif osname == 'linux': vmx_path = '/usr/lib/vmware/bin/' - vmx = vmx_path + 'vmware-vmx' - vmx_debug = vmx_path + 'vmware-vmx-debug' - vmx_stats = vmx_path + 'vmware-vmx-stats' + vmx = joinpath(vmx_path, 'vmware-vmx') + vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug') + vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats') vmx_version = subprocess.check_output(["vmplayer", "-v"]) if vmx_version.startswith('VMware Player 12'): vmx_so = True @@ -357,23 +378,23 @@ def main(): vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so.0/libvmwarebase.so.0' elif osname == 'vmkernel': - vmx_path = '/unlocker/' - vmx = vmx_path + 'vmx' - vmx_debug = vmx_path + 'vmx-debug' - vmx_stats = vmx_path + 'vmx-stats' + vmx_path = os.path.dirname(os.path.abspath(__file__)) + vmx = joinpath(vmx_path, 'tmp/bin/vmx') + vmx_debug = joinpath(vmx_path, 'tmp/bin/vmx-debug') + vmx_stats = joinpath(vmx_path, 'tmp/bin/vmx-stats') vmx_so = True - libvmkctl32 = vmx_path + 'lib/libvmkctl.so' - libvmkctl64 = vmx_path + 'lib64/libvmkctl.so' + libvmkctl32 = joinpath(vmx_path, 'tmp/lib/libvmkctl.so') + libvmkctl64 = joinpath(vmx_path, 'tmp/lib64/libvmkctl.so') 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 = vmx_path + 'vmware-vmx.exe' - vmx_debug = vmx_path + 'vmware-vmx-debug.exe' - vmx_stats = vmx_path + 'vmware-vmx-stats.exe' - vmwarebase = vmwarebase_path + 'vmwarebase.dll' + 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) @@ -382,27 +403,23 @@ def main(): # Patch the vmx executables skipping stats version for Player patchsmc(vmx, vmx_so) patchsmc(vmx_debug, vmx_so) - try: + if os.path.isfile(vmx_stats): patchsmc(vmx_stats, vmx_so) - except IOError: - pass # Patch vmwarebase for Workstation and Player # Not required on Fusion or ESXi as table already has correct flags if vmwarebase != '': patchbase(vmwarebase) else: - print 'Patching vmwarebase is not required on this system' + print('Patching vmwarebase is not required on this system') if osname == 'vmkernel': # Patch ESXi 6.0 and 6.5 32 bit .so patchvmkctl(libvmkctl32) - # Try and patch ESXi 6.5 64 bit .so - try: + # Patch ESXi 6.5 64 bit .so + if os.path.isfile(libvmkctl64): patchvmkctl(libvmkctl64) - except IOError: - pass if __name__ == '__main__': diff --git a/wip/test.py b/wip/test.py deleted file mode 100755 index f5cc971..0000000 --- a/wip/test.py +++ /dev/null @@ -1,469 +0,0 @@ -""" -The MIT License (MIT) - -Copyright (c) 2014-2016 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 -""" - -import argparse -import codecs -import os -import sys -import struct - -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': - from _winreg import * - - -def bytetohex(bytestr): - return ''.join(['%02X ' % ord(x) for x in bytestr]).strip() - - -def printkey(i, offset, smc_key, smc_data): - print str(i + 1).zfill(3) \ - + ' ' + hex(offset) \ - + ' ' + smc_key[0][::-1] \ - + ' ' + str(smc_key[1]).zfill(2) \ - + ' ' + smc_key[2][::-1].replace('\x00', ' ') \ - + ' ' + '{0:#0{1}x}'.format(smc_key[3], 4) \ - + ' ' + hex(smc_key[4]) \ - + ' ' + bytetohex(smc_data) - - -def patchelf(f, oldoffset, newoffset): - E_CLASS64 = 2 - E_SHT_RELA = 4 - 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 = 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) - print - - -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] == '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] == '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.decode('bheuneqjbexolgurfrjbeqfthneqrqcy', 'rot_13') - f.write(smc_new_data) - 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] == '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.decode('rnfrqbagfgrny(p)NccyrPbzchgreVap', 'rot_13') - f.write(smc_new_data) - 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 - - # Setup hex string for vSMC headers - # These are the private and public key counts - smc_header_v0 = '\xF2\x00\x00\x00\xF0\x00\x00\x00' - smc_header_v1 = '\xB4\x01\x00\x00\xB0\x01\x00\x00' - - # Setup hex string for #KEY key - key_key = '\x59\x45\x4B\x23\x04\x32\x33\x69\x75' - - # Setup hex string for $Adr key - adr_key = '\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 patchgos(name): - # Patch vmwarebase for Workstation and Player - # Not required on Fusion or ESXi as table already has correct flags - print 'GOS Patching: ' + name - f = open(name, 'r+b') - - # Entry to search for in GOS table - darwin = ( - '\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' - '\xBE' - ) - - # Read file into string variable - base = f.read() - - # Loop thorugh each entry and set top bit - # 0xBE --> 0xBF - offset = 0 - while offset < len(base): - offset = base.find(darwin, offset) - if offset == -1: - break - f.seek(offset + 32) - flag = f.read(1) - if flag == '\xBE': - f.seek(offset + 32) - f.write('\xBF') - print 'GOS Patched flag @: ' + hex(offset) - else: - print 'GOS Unknown flag @: ' + hex(offset) + '/' + hex(int(flag)) - - offset += 33 - - # 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('applesmc') - f.seek(applesmc) - f.write('vmkernel') - - # Tidy up - f.flush() - f.close() - print 'smcPresent Patched: ' + name - - -def main(): - - # Parse input arguments - parser = argparse.ArgumentParser() - osnames = ['darwin', 'linux', 'vmkernel', 'windows'] - parser.add_argument('-v', '--vmx', help='vmx file', dest='vmx', action='store', type=str) - parser.add_argument('-d', '--vmx-debug', help='vmx-debug file', dest='vmx_debug', action='store', type=str) - parser.add_argument('-s', '--vmx-stats', help='vmx-stats file', dest='vmx_stats', action='store', type=str) - parser.add_argument('-b', '--vmbase', help='vmwarebase file', dest='vmwarebase', action='store', type=str) - parser.add_argument('-k', '--vmkctl', help='vmkctl file', dest='vmkctl', action='store', type=str) - parser.add_argument('-o', '--osname', help='OS type', dest='ostype', action='store', choices=osnames) - args = parser.parse_args() - - # Work around absent Platform module on VMkernel - if os.name == 'nt' or os.name == 'cli': - osname = 'windows' - else: - osname = os.uname()[0].lower() - - # Setup default paths - if len(sys.argv) > 1: - - # Need to patch SO if vmkernel - if args.ostype == 'vmkernel': - elf = True - else: - elf = False - - # Patch the vSMC tables - try: - if args.vmx != None: - patchsmc(args.vmx, elf) - except IOError: - pass - try: - if args.vmx_debug != None: - patchsmc(args.vmx_debug, elf) - except IOError: - pass - try: - if args.vmx_stats != None: - patchsmc(args.vmx_stats, elf) - except IOError: - pass - - # Patch GOS tables - try: - if args.vmwarebase != None: - patchgos(args.vmwarebase, elf) - except IOError: - pass - - # Patch vmkctl - try: - if args.vmkctl != None: - patchvmkctl(args.vmkctl) - except IOError: - pass - - elif osname == 'darwin': - # Assumes default folder on macOS - vmx_path = '/Applications/VMware Fusion.app/Contents/Library/' - - # Patch virtual SMC tables - patchsmc(vmx_path + 'vmware-vmx', False) - patchsmc(vmx_path + 'vmware-vmx-debug', False) - patchsmc(vmx_path + 'vmware-vmx-stats', False) - - elif osname == 'linux': - # Assumes default folder on Linux - vmx_path = '/usr/lib/vmware/bin/' - - # Patch virtual SMC tables - patchsmc(vmx_path + 'vmware-vmx', False) - patchsmc(vmx_path + 'vmware-vmx-debug', False) - try: - patchsmc(vmx_path + 'vmware-vmx-stats', False) - except IOError: - pass - - # Patch the GOS tables - # Try V11 patch path for vmwarebase - try: - patchgos('/usr/lib/vmware/lib/libvmwarebase.so.0/libvmwarebase.so.0', False) - except IOError: - pass - - # Try V12 patch path for vmwarebase - try: - patchgos('/usr/lib/vmware/lib/libvmwarebase.so/libvmwarebase.so', False) - except IOError: - pass - - elif osname == 'vmkernel': - # Patch the copied files in the unlocker directory - vmx_path = '/unlocker/' - - # Patch virtual SMC tables - patchsmc(vmx_path + 'vmware-vmx', True) - patchsmc(vmx_path + 'vmware-vmx-debug', True) - patchsmc(vmx_path + 'vmware-vmx-stats', True) - - # Patch smcPresent flag - # ESXi 6.0 and 6.5 32 bit .so - patchvmkctl(vmx_path + 'lib/libvmkctl.so') - - # Patch ESXi 6.5 64 bit .so - try: - patchvmkctl(vmx_path + 'lib64/libvmkctl.so') - except IOError: - pass - - elif osname == 'windows': - # Find the path for VMware on Windows - # Find using Player reg settings as present for Player & Workstation - reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE) - key = OpenKey(reg, r'SOFTWARE\Wow6432Node\VMware, Inc.\VMware Player') - vmwarebase_path = QueryValueEx(key, 'InstallPath')[0] - vmx_path = QueryValueEx(key, 'InstallPath64')[0] - - # Patch virtual SMC tables - patchsmc(vmx_path + 'vmware-vmx.exe', False) - patchsmc(vmx_path + 'vmware-vmx-debug.exe', False) - try: - patchsmc(vmx_path + 'vmware-vmx-stats.exe', False) - except IOError: - pass - - # Patch the GOS tables - patchgos(vmwarebase_path + 'vmwarebase.dll') - - else: - print('Unknown Operating System: ' + osname) - return - - -if __name__ == '__main__': - main()