mirror of
https://github.com/paolo-projects/unlocker.git
synced 2025-07-28 16:34:29 +02:00
Release candidate for 2.0.9
This commit is contained in:
parent
a95a7511fb
commit
f1c216c753
79
dumpsmc.py
79
dumpsmc.py
@ -40,6 +40,7 @@ Offset Length struct Type Description
|
|||||||
0x18/24 0x30/48 48B byte Data
|
0x18/24 0x30/48 48B byte Data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -48,18 +49,24 @@ if sys.version_info < (2, 7):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def bytetohex(bytestr):
|
def bytetohex(data):
|
||||||
return ''.join(['%02X ' % ord(x) for x in bytestr]).strip()
|
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):
|
def printkey(i, offset, smc_key, smc_data):
|
||||||
print str(i+1).zfill(3) \
|
print(str(i + 1).zfill(3)
|
||||||
+ ' ' + smc_key[0][::-1] \
|
+ ' ' + hex(offset)
|
||||||
+ ' ' + str(smc_key[1]).zfill(2) \
|
+ ' ' + smc_key[0][::-1].decode('UTF-8')
|
||||||
+ ' ' + smc_key[2][::-1].replace('\x00', ' ') \
|
+ ' ' + str(smc_key[1]).zfill(2)
|
||||||
+ ' ' + '{0:#0{1}x}'.format(smc_key[3], 4) \
|
+ ' ' + smc_key[2][::-1].replace(b'\x00', b' ').decode('UTF-8')
|
||||||
+ ' ' + hex(smc_key[4]) \
|
+ ' ' + '{0:#0{1}x}'.format(smc_key[3], 4)
|
||||||
+ ' ' + bytetohex(smc_data)
|
+ ' ' + hex(smc_key[4])
|
||||||
|
+ ' ' + bytetohex(smc_data))
|
||||||
|
|
||||||
|
|
||||||
def dumpkeys(f, key):
|
def dumpkeys(f, key):
|
||||||
@ -77,10 +84,10 @@ def dumpkeys(f, key):
|
|||||||
smc_data = f.read(smc_key[1])
|
smc_data = f.read(smc_key[1])
|
||||||
|
|
||||||
# Dump entry
|
# Dump entry
|
||||||
printkey(i, smc_key, smc_data)
|
printkey(i, offset, smc_key, smc_data)
|
||||||
|
|
||||||
# Exit when OSK1 has been read
|
# Exit when OSK1 has been read
|
||||||
if smc_key[0] == '1KSO':
|
if smc_key[0] == b'1KSO':
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
i += 1
|
i += 1
|
||||||
@ -88,23 +95,23 @@ def dumpkeys(f, key):
|
|||||||
|
|
||||||
def dumpsmc(name):
|
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()
|
vmx = f.read()
|
||||||
|
|
||||||
print 'File: ' + name
|
print('File: ' + name)
|
||||||
|
|
||||||
# Setup hex string for vSMC headers
|
# Setup hex string for vSMC headers
|
||||||
# These are the private and public key counts
|
# These are the private and public key counts
|
||||||
smc_header_v0 = '\xF2\x00\x00\x00\xF0\x00\x00\x00'
|
smc_header_v0 = b'\xF2\x00\x00\x00\xF0\x00\x00\x00'
|
||||||
smc_header_v1 = '\xB4\x01\x00\x00\xB0\x01\x00\x00'
|
smc_header_v1 = b'\xB4\x01\x00\x00\xB0\x01\x00\x00'
|
||||||
|
|
||||||
# Setup hex string for #KEY key
|
# 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
|
# 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
|
# Find the vSMC headers
|
||||||
smc_header_v0_offset = vmx.find(smc_header_v0) - 8
|
smc_header_v0_offset = vmx.find(smc_header_v0) - 8
|
||||||
@ -118,31 +125,31 @@ def dumpsmc(name):
|
|||||||
smc_adr = vmx.find(adr_key)
|
smc_adr = vmx.find(adr_key)
|
||||||
|
|
||||||
# Print vSMC0 tables and keys
|
# Print vSMC0 tables and keys
|
||||||
print 'appleSMCTableV0 (smc.version = "0")'
|
print('appleSMCTableV0 (smc.version = "0")')
|
||||||
print 'appleSMCTableV0 Address : ' + hex(smc_header_v0_offset)
|
print('appleSMCTableV0 Address : ' + hex(smc_header_v0_offset))
|
||||||
print 'appleSMCTableV0 Private Key #: 0xF2/242'
|
print('appleSMCTableV0 Private Key #: 0xF2/242')
|
||||||
print 'appleSMCTableV0 Public Key #: 0xF0/240'
|
print('appleSMCTableV0 Public Key #: 0xF0/240')
|
||||||
|
|
||||||
if (smc_adr - smc_key0) != 72:
|
if (smc_adr - smc_key0) != 72:
|
||||||
print 'appleSMCTableV0 Table : ' + hex(smc_key0)
|
print('appleSMCTableV0 Table : ' + hex(smc_key0))
|
||||||
dumpkeys(f, smc_key0)
|
dumpkeys(f, smc_key0)
|
||||||
elif (smc_adr - smc_key1) != 72:
|
elif (smc_adr - smc_key1) != 72:
|
||||||
print 'appleSMCTableV0 Table : ' + hex(smc_key1)
|
print('appleSMCTableV0 Table : ' + hex(smc_key1))
|
||||||
dumpkeys(f, smc_key1)
|
dumpkeys(f, smc_key1)
|
||||||
|
|
||||||
print
|
print('xxxx')
|
||||||
|
|
||||||
# Print vSMC1 tables and keys
|
# Print vSMC1 tables and keys
|
||||||
print 'appleSMCTableV1 (smc.version = "1")'
|
print('appleSMCTableV1 (smc.version = "1")')
|
||||||
print 'appleSMCTableV1 Address : ' + hex(smc_header_v1_offset)
|
print('appleSMCTableV1 Address : ' + hex(smc_header_v1_offset))
|
||||||
print 'appleSMCTableV1 Private Key #: 0x01B4/436'
|
print('appleSMCTableV1 Private Key #: 0x01B4/436')
|
||||||
print 'appleSMCTableV1 Public Key #: 0x01B0/432'
|
print('appleSMCTableV1 Public Key #: 0x01B0/432')
|
||||||
|
|
||||||
if (smc_adr - smc_key0) == 72:
|
if (smc_adr - smc_key0) == 72:
|
||||||
print 'appleSMCTableV1 Table : ' + hex(smc_key0)
|
print('appleSMCTableV1 Table : ' + hex(smc_key0))
|
||||||
dumpkeys(f, smc_key0)
|
dumpkeys(f, smc_key0)
|
||||||
elif (smc_adr - smc_key1) == 72:
|
elif (smc_adr - smc_key1) == 72:
|
||||||
print 'appleSMCTableV1 Table : ' + hex(smc_key1)
|
print('appleSMCTableV1 Table : ' + hex(smc_key1))
|
||||||
dumpkeys(f, smc_key1)
|
dumpkeys(f, smc_key1)
|
||||||
|
|
||||||
# Tidy up
|
# Tidy up
|
||||||
@ -150,19 +157,19 @@ def dumpsmc(name):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print 'dumpsmc'
|
print('dumpsmc')
|
||||||
print '-------'
|
print('-------')
|
||||||
|
|
||||||
if len(sys.argv) >= 2:
|
if len(sys.argv) >= 2:
|
||||||
vmx_path = sys.argv[1]
|
vmx_path = sys.argv[1]
|
||||||
else:
|
else:
|
||||||
print 'Please pass file name!'
|
print('Please pass file name!')
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dumpsmc(vmx_path)
|
dumpsmc(vmx_path)
|
||||||
except IOError:
|
except IOError:
|
||||||
print 'Cannot find file ' + vmx_path
|
print('Cannot find file ' + vmx_path)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
echo VMware Unlocker 2.0.9
|
echo VMware Unlocker 2.0.9
|
||||||
echo ===============================
|
echo ===============================
|
||||||
@ -8,12 +9,42 @@ echo Copyright: Dave Parsons 2011-16
|
|||||||
# Ensure we only use unmodified commands
|
# Ensure we only use unmodified commands
|
||||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
||||||
|
|
||||||
# Copy patch to local.sh
|
echo Creating unlocker vmtar disk
|
||||||
echo Installing local.sh
|
|
||||||
cp local-template.sh local.sh
|
# Create tmp folder for patching the files
|
||||||
cat unlocker.py >> local.sh
|
mkdir -p tmp/bin
|
||||||
echo END >> local.sh
|
mkdir -p tmp/lib
|
||||||
echo /etc/init.d/hostd restart >> local.sh
|
|
||||||
chmod +x local.sh
|
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
|
cp local.sh /etc/rc.local.d/local.sh
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
#rm -rfv tmp
|
||||||
|
|
||||||
echo Success - please now restart the server!
|
echo Success - please now restart the server!
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
echo VMware Unlocker 2.0.9
|
echo VMware Unlocker 2.0.9
|
||||||
echo ===============================
|
echo ===============================
|
||||||
@ -8,6 +9,9 @@ echo Copyright: Dave Parsons 2011-16
|
|||||||
# Ensure we only use unmodified commands
|
# Ensure we only use unmodified commands
|
||||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
||||||
|
|
||||||
echo Uninstalling local.sh
|
# Remove entry from the boot configuration file
|
||||||
cp /etc/rc.local.d/.#local.sh /etc/rc.local.d/local.sh
|
echo Deleting unlocker.vgz from bootbank...
|
||||||
echo Success - please now restart the server!
|
rm /bootbank/unlocker.vgz
|
||||||
|
rm /etc/rc.local.d/local.sh
|
||||||
|
|
||||||
|
echo Please now reboot the host system!
|
||||||
|
@ -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 <<END
|
|
183
unlocker.py
183
unlocker.py
@ -40,7 +40,7 @@ Offset Length struct Type Description
|
|||||||
0x18/24 0x30/48 48B byte Data
|
0x18/24 0x30/48 48B byte Data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import codecs
|
from __future__ import print_function
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import struct
|
import struct
|
||||||
@ -56,24 +56,42 @@ if sys.platform == 'win32' \
|
|||||||
from _winreg import *
|
from _winreg import *
|
||||||
|
|
||||||
|
|
||||||
def bytetohex(bytestr):
|
def rot13(s):
|
||||||
return ''.join(['%02X ' % ord(x) for x in bytestr]).strip()
|
chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
|
||||||
|
trans = chars[26:] + chars[:26]
|
||||||
|
rot_char = lambda c: trans[chars.find(c)] if chars.find(c) > -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):
|
def printkey(i, offset, smc_key, smc_data):
|
||||||
print str(i + 1).zfill(3) \
|
print(str(i + 1).zfill(3)
|
||||||
+ ' ' + hex(offset) \
|
+ ' ' + hex(offset)
|
||||||
+ ' ' + smc_key[0][::-1] \
|
+ ' ' + smc_key[0][::-1].decode('UTF-8')
|
||||||
+ ' ' + str(smc_key[1]).zfill(2) \
|
+ ' ' + str(smc_key[1]).zfill(2)
|
||||||
+ ' ' + smc_key[2][::-1].replace('\x00', ' ') \
|
+ ' ' + smc_key[2][::-1].replace(b'\x00', b' ').decode('UTF-8')
|
||||||
+ ' ' + '{0:#0{1}x}'.format(smc_key[3], 4) \
|
+ ' ' + '{0:#0{1}x}'.format(smc_key[3], 4)
|
||||||
+ ' ' + hex(smc_key[4]) \
|
+ ' ' + hex(smc_key[4])
|
||||||
+ ' ' + bytetohex(smc_data)
|
+ ' ' + bytetohex(smc_data))
|
||||||
|
|
||||||
|
|
||||||
|
E_CLASS64 = 2
|
||||||
|
E_SHT_RELA = 4
|
||||||
|
|
||||||
|
|
||||||
def patchelf(f, oldoffset, newoffset):
|
def patchelf(f, oldoffset, newoffset):
|
||||||
E_CLASS64 = 2
|
|
||||||
E_SHT_RELA = 4
|
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
magic = f.read(4)
|
magic = f.read(4)
|
||||||
if not magic == b'\x7fELF':
|
if not magic == b'\x7fELF':
|
||||||
@ -90,20 +108,20 @@ def patchelf(f, oldoffset, newoffset):
|
|||||||
e_shnum = 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]
|
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,
|
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)
|
e_shnum, e_shstrndx))
|
||||||
|
|
||||||
for i in range(0, e_shnum):
|
for i in range(0, e_shnum):
|
||||||
f.seek(e_shoff + i * e_shentsize)
|
f.seek(e_shoff + i * e_shentsize)
|
||||||
e_sh = struct.unpack('=LLQQQQLLQQ', f.read(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_type = e_sh[1]
|
||||||
e_sh_offset = e_sh[4]
|
e_sh_offset = e_sh[4]
|
||||||
e_sh_size = e_sh[5]
|
e_sh_size = e_sh[5]
|
||||||
e_sh_entsize = e_sh[9]
|
e_sh_entsize = e_sh[9]
|
||||||
if e_sh_type == E_SHT_RELA:
|
if e_sh_type == E_SHT_RELA:
|
||||||
e_sh_nument = e_sh_size / e_sh_entsize
|
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)
|
# print 'RELA at 0x{:x} with {:d} entries'.format(e_sh_offset, e_sh_nument)
|
||||||
for j in range(0, e_sh_nument):
|
for j in range(0, e_sh_nument):
|
||||||
f.seek(e_sh_offset + e_sh_entsize * j)
|
f.seek(e_sh_offset + e_sh_entsize * j)
|
||||||
rela = struct.unpack('=QQq', f.read(e_sh_entsize))
|
rela = struct.unpack('=QQq', f.read(e_sh_entsize))
|
||||||
@ -114,7 +132,7 @@ def patchelf(f, oldoffset, newoffset):
|
|||||||
r_addend = newoffset
|
r_addend = newoffset
|
||||||
f.seek(e_sh_offset + e_sh_entsize * j)
|
f.seek(e_sh_offset + e_sh_entsize * j)
|
||||||
f.write(struct.pack('=QQq', r_offset, r_info, r_addend))
|
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):
|
def patchkeys(f, key):
|
||||||
@ -136,15 +154,15 @@ def patchkeys(f, key):
|
|||||||
# Reset pointer to beginning of key entry
|
# Reset pointer to beginning of key entry
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
|
|
||||||
if smc_key[0] == 'SKL+':
|
if smc_key[0] == b'SKL+':
|
||||||
# Use the +LKS data routine for OSK0/1
|
# Use the +LKS data routine for OSK0/1
|
||||||
smc_new_memptr = smc_key[4]
|
smc_new_memptr = smc_key[4]
|
||||||
print '+LKS Key: '
|
print('+LKS Key: ')
|
||||||
printkey(i, offset, smc_key, smc_data)
|
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
|
# Write new data routine pointer from +LKS
|
||||||
print 'OSK0 Key Before:'
|
print('OSK0 Key Before:')
|
||||||
printkey(i, offset, smc_key, smc_data)
|
printkey(i, offset, smc_key, smc_data)
|
||||||
smc_old_memptr = smc_key[4]
|
smc_old_memptr = smc_key[4]
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
@ -153,20 +171,20 @@ def patchkeys(f, key):
|
|||||||
|
|
||||||
# Write new data for key
|
# Write new data for key
|
||||||
f.seek(offset + 24)
|
f.seek(offset + 24)
|
||||||
smc_new_data = codecs.decode('bheuneqjbexolgurfrjbeqfthneqrqcy', 'rot_13')
|
smc_new_data = rot13('bheuneqjbexolgurfrjbeqfthneqrqcy')
|
||||||
f.write(smc_new_data)
|
f.write(smc_new_data.encode('UTF-8'))
|
||||||
f.flush()
|
f.flush()
|
||||||
|
|
||||||
# Re-read and print key
|
# Re-read and print key
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
smc_key = struct.unpack(key_pack, f.read(24))
|
smc_key = struct.unpack(key_pack, f.read(24))
|
||||||
smc_data = f.read(smc_key[1])
|
smc_data = f.read(smc_key[1])
|
||||||
print 'OSK0 Key After:'
|
print('OSK0 Key After:')
|
||||||
printkey(i, offset, smc_key, smc_data)
|
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
|
# Write new data routine pointer from +LKS
|
||||||
print 'OSK1 Key Before:'
|
print('OSK1 Key Before:')
|
||||||
printkey(i, offset, smc_key, smc_data)
|
printkey(i, offset, smc_key, smc_data)
|
||||||
smc_old_memptr = smc_key[4]
|
smc_old_memptr = smc_key[4]
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
@ -175,15 +193,15 @@ def patchkeys(f, key):
|
|||||||
|
|
||||||
# Write new data for key
|
# Write new data for key
|
||||||
f.seek(offset + 24)
|
f.seek(offset + 24)
|
||||||
smc_new_data = codecs.decode('rnfrqbagfgrny(p)NccyrPbzchgreVap', 'rot_13')
|
smc_new_data = rot13('rnfrqbagfgrny(p)NccyrPbzchgreVap')
|
||||||
f.write(smc_new_data)
|
f.write(smc_new_data.encode('UTF-8'))
|
||||||
f.flush()
|
f.flush()
|
||||||
|
|
||||||
# Re-read and print key
|
# Re-read and print key
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
smc_key = struct.unpack(key_pack, f.read(24))
|
smc_key = struct.unpack(key_pack, f.read(24))
|
||||||
smc_data = f.read(smc_key[1])
|
smc_data = f.read(smc_key[1])
|
||||||
print 'OSK1 Key After:'
|
print('OSK1 Key After:')
|
||||||
printkey(i, offset, smc_key, smc_data)
|
printkey(i, offset, smc_key, smc_data)
|
||||||
|
|
||||||
# Finished so get out of loop
|
# Finished so get out of loop
|
||||||
@ -205,18 +223,18 @@ def patchsmc(name, sharedobj):
|
|||||||
# Read file into string variable
|
# Read file into string variable
|
||||||
vmx = f.read()
|
vmx = f.read()
|
||||||
|
|
||||||
print 'File: ' + name
|
print('File: ' + name)
|
||||||
|
|
||||||
# Setup hex string for vSMC headers
|
# Setup hex string for vSMC headers
|
||||||
# These are the private and public key counts
|
# These are the private and public key counts
|
||||||
smc_header_v0 = '\xF2\x00\x00\x00\xF0\x00\x00\x00'
|
smc_header_v0 = b'\xF2\x00\x00\x00\xF0\x00\x00\x00'
|
||||||
smc_header_v1 = '\xB4\x01\x00\x00\xB0\x01\x00\x00'
|
smc_header_v1 = b'\xB4\x01\x00\x00\xB0\x01\x00\x00'
|
||||||
|
|
||||||
# Setup hex string for #KEY key
|
# 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
|
# 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
|
# Find the vSMC headers
|
||||||
smc_header_v0_offset = vmx.find(smc_header_v0) - 8
|
smc_header_v0_offset = vmx.find(smc_header_v0) - 8
|
||||||
@ -230,39 +248,39 @@ def patchsmc(name, sharedobj):
|
|||||||
smc_adr = vmx.find(adr_key)
|
smc_adr = vmx.find(adr_key)
|
||||||
|
|
||||||
# Print vSMC0 tables and keys
|
# Print vSMC0 tables and keys
|
||||||
print 'appleSMCTableV0 (smc.version = "0")'
|
print('appleSMCTableV0 (smc.version = "0")')
|
||||||
print 'appleSMCTableV0 Address : ' + hex(smc_header_v0_offset)
|
print('appleSMCTableV0 Address : ' + hex(smc_header_v0_offset))
|
||||||
print 'appleSMCTableV0 Private Key #: 0xF2/242'
|
print('appleSMCTableV0 Private Key #: 0xF2/242')
|
||||||
print 'appleSMCTableV0 Public Key #: 0xF0/240'
|
print('appleSMCTableV0 Public Key #: 0xF0/240')
|
||||||
|
|
||||||
if (smc_adr - smc_key0) != 72:
|
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)
|
smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key0)
|
||||||
elif (smc_adr - smc_key1) != 72:
|
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)
|
smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1)
|
||||||
|
|
||||||
print
|
print()
|
||||||
|
|
||||||
# Print vSMC1 tables and keys
|
# Print vSMC1 tables and keys
|
||||||
print 'appleSMCTableV1 (smc.version = "1")'
|
print('appleSMCTableV1 (smc.version = "1")')
|
||||||
print 'appleSMCTableV1 Address : ' + hex(smc_header_v1_offset)
|
print('appleSMCTableV1 Address : ' + hex(smc_header_v1_offset))
|
||||||
print 'appleSMCTableV1 Private Key #: 0x01B4/436'
|
print('appleSMCTableV1 Private Key #: 0x01B4/436')
|
||||||
print 'appleSMCTableV1 Public Key #: 0x01B0/432'
|
print('appleSMCTableV1 Public Key #: 0x01B0/432')
|
||||||
|
|
||||||
if (smc_adr - smc_key0) == 72:
|
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)
|
smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key0)
|
||||||
elif (smc_adr - smc_key1) == 72:
|
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)
|
smc_old_memptr, smc_new_memptr = patchkeys(f, smc_key1)
|
||||||
|
|
||||||
print
|
print()
|
||||||
|
|
||||||
# Find matching RELA record in .rela.dyn in ESXi ELF files
|
# Find matching RELA record in .rela.dyn in ESXi ELF files
|
||||||
# This is temporary code until proper ELF parsing written
|
# This is temporary code until proper ELF parsing written
|
||||||
if sharedobj:
|
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)
|
patchelf(f, smc_old_memptr, smc_new_memptr)
|
||||||
|
|
||||||
# Tidy up
|
# Tidy up
|
||||||
@ -272,7 +290,7 @@ def patchsmc(name, sharedobj):
|
|||||||
|
|
||||||
def patchbase(name):
|
def patchbase(name):
|
||||||
# Patch file
|
# Patch file
|
||||||
print 'GOS Patching: ' + name
|
print('GOS Patching: ' + name)
|
||||||
f = open(name, 'r+b')
|
f = open(name, 'r+b')
|
||||||
|
|
||||||
# Entry to search for in GOS table
|
# Entry to search for in GOS table
|
||||||
@ -299,33 +317,33 @@ def patchbase(name):
|
|||||||
if flag == '\xBE':
|
if flag == '\xBE':
|
||||||
f.seek(offset + 32)
|
f.seek(offset + 32)
|
||||||
f.write('\xBF')
|
f.write('\xBF')
|
||||||
print 'GOS Patched flag @: ' + hex(offset)
|
print('GOS Patched flag @: ' + hex(offset))
|
||||||
else:
|
else:
|
||||||
print 'GOS Unknown flag @: ' + hex(offset) + '/' + hex(int(flag))
|
print('GOS Unknown flag @: ' + hex(offset) + '/' + hex(int(flag)))
|
||||||
|
|
||||||
offset += 33
|
offset += 33
|
||||||
|
|
||||||
# Tidy up
|
# Tidy up
|
||||||
f.flush()
|
f.flush()
|
||||||
f.close()
|
f.close()
|
||||||
print 'GOS Patched: ' + name
|
print('GOS Patched: ' + name)
|
||||||
|
|
||||||
|
|
||||||
def patchvmkctl(name):
|
def patchvmkctl(name):
|
||||||
# Patch file
|
# Patch file
|
||||||
print 'smcPresent Patching: ' + name
|
print('smcPresent Patching: ' + name)
|
||||||
f = open(name, 'r+b')
|
f = open(name, 'r+b')
|
||||||
|
|
||||||
# Read file into string variable
|
# Read file into string variable
|
||||||
vmkctl = f.read()
|
vmkctl = f.read()
|
||||||
applesmc = vmkctl.find('applesmc')
|
applesmc = vmkctl.find(b'applesmc')
|
||||||
f.seek(applesmc)
|
f.seek(applesmc)
|
||||||
f.write('vmkernel')
|
f.write(b'vmkernel')
|
||||||
|
|
||||||
# Tidy up
|
# Tidy up
|
||||||
f.flush()
|
f.flush()
|
||||||
f.close()
|
f.close()
|
||||||
print 'smcPresent Patched: ' + name
|
print('smcPresent Patched: ' + name)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -335,20 +353,23 @@ def main():
|
|||||||
else:
|
else:
|
||||||
osname = os.uname()[0].lower()
|
osname = os.uname()[0].lower()
|
||||||
|
|
||||||
|
vmwarebase = ''
|
||||||
|
libvmkctl32 = ''
|
||||||
|
libvmkctl64 = ''
|
||||||
vmx_so = False
|
vmx_so = False
|
||||||
|
|
||||||
# Setup default paths
|
# Setup default paths
|
||||||
if osname == 'darwin':
|
if osname == 'darwin':
|
||||||
vmx_path = '/Applications/VMware Fusion.app/Contents/Library/'
|
vmx_path = '/Applications/VMware Fusion.app/Contents/Library/'
|
||||||
vmx = vmx_path + 'vmware-vmx'
|
vmx = joinpath(vmx_path, 'vmware-vmx')
|
||||||
vmx_debug = vmx_path + 'vmware-vmx-debug'
|
vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug')
|
||||||
vmx_stats = vmx_path + 'vmware-vmx-stats'
|
vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats')
|
||||||
|
|
||||||
elif osname == 'linux':
|
elif osname == 'linux':
|
||||||
vmx_path = '/usr/lib/vmware/bin/'
|
vmx_path = '/usr/lib/vmware/bin/'
|
||||||
vmx = vmx_path + 'vmware-vmx'
|
vmx = joinpath(vmx_path, 'vmware-vmx')
|
||||||
vmx_debug = vmx_path + 'vmware-vmx-debug'
|
vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug')
|
||||||
vmx_stats = vmx_path + 'vmware-vmx-stats'
|
vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats')
|
||||||
vmx_version = subprocess.check_output(["vmplayer", "-v"])
|
vmx_version = subprocess.check_output(["vmplayer", "-v"])
|
||||||
if vmx_version.startswith('VMware Player 12'):
|
if vmx_version.startswith('VMware Player 12'):
|
||||||
vmx_so = True
|
vmx_so = True
|
||||||
@ -357,23 +378,23 @@ def main():
|
|||||||
vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so.0/libvmwarebase.so.0'
|
vmwarebase = '/usr/lib/vmware/lib/libvmwarebase.so.0/libvmwarebase.so.0'
|
||||||
|
|
||||||
elif osname == 'vmkernel':
|
elif osname == 'vmkernel':
|
||||||
vmx_path = '/unlocker/'
|
vmx_path = os.path.dirname(os.path.abspath(__file__))
|
||||||
vmx = vmx_path + 'vmx'
|
vmx = joinpath(vmx_path, 'tmp/bin/vmx')
|
||||||
vmx_debug = vmx_path + 'vmx-debug'
|
vmx_debug = joinpath(vmx_path, 'tmp/bin/vmx-debug')
|
||||||
vmx_stats = vmx_path + 'vmx-stats'
|
vmx_stats = joinpath(vmx_path, 'tmp/bin/vmx-stats')
|
||||||
vmx_so = True
|
vmx_so = True
|
||||||
libvmkctl32 = vmx_path + 'lib/libvmkctl.so'
|
libvmkctl32 = joinpath(vmx_path, 'tmp/lib/libvmkctl.so')
|
||||||
libvmkctl64 = vmx_path + 'lib64/libvmkctl.so'
|
libvmkctl64 = joinpath(vmx_path, 'tmp/lib64/libvmkctl.so')
|
||||||
|
|
||||||
elif osname == 'windows':
|
elif osname == 'windows':
|
||||||
reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
|
reg = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
|
||||||
key = OpenKey(reg, r'SOFTWARE\Wow6432Node\VMware, Inc.\VMware Workstation')
|
key = OpenKey(reg, r'SOFTWARE\Wow6432Node\VMware, Inc.\VMware Workstation')
|
||||||
vmwarebase_path = QueryValueEx(key, 'InstallPath')[0]
|
vmwarebase_path = QueryValueEx(key, 'InstallPath')[0]
|
||||||
vmx_path = QueryValueEx(key, 'InstallPath64')[0]
|
vmx_path = QueryValueEx(key, 'InstallPath64')[0]
|
||||||
vmx = vmx_path + 'vmware-vmx.exe'
|
vmx = joinpath(vmx_path, 'vmware-vmx.exe')
|
||||||
vmx_debug = vmx_path + 'vmware-vmx-debug.exe'
|
vmx_debug = joinpath(vmx_path, 'vmware-vmx-debug.exe')
|
||||||
vmx_stats = vmx_path + 'vmware-vmx-stats.exe'
|
vmx_stats = joinpath(vmx_path, 'vmware-vmx-stats.exe')
|
||||||
vmwarebase = vmwarebase_path + 'vmwarebase.dll'
|
vmwarebase = joinpath(vmwarebase_path, 'vmwarebase.dll')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print('Unknown Operating System: ' + osname)
|
print('Unknown Operating System: ' + osname)
|
||||||
@ -382,27 +403,23 @@ def main():
|
|||||||
# Patch the vmx executables skipping stats version for Player
|
# Patch the vmx executables skipping stats version for Player
|
||||||
patchsmc(vmx, vmx_so)
|
patchsmc(vmx, vmx_so)
|
||||||
patchsmc(vmx_debug, vmx_so)
|
patchsmc(vmx_debug, vmx_so)
|
||||||
try:
|
if os.path.isfile(vmx_stats):
|
||||||
patchsmc(vmx_stats, vmx_so)
|
patchsmc(vmx_stats, vmx_so)
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Patch vmwarebase for Workstation and Player
|
# Patch vmwarebase for Workstation and Player
|
||||||
# Not required on Fusion or ESXi as table already has correct flags
|
# Not required on Fusion or ESXi as table already has correct flags
|
||||||
if vmwarebase != '':
|
if vmwarebase != '':
|
||||||
patchbase(vmwarebase)
|
patchbase(vmwarebase)
|
||||||
else:
|
else:
|
||||||
print 'Patching vmwarebase is not required on this system'
|
print('Patching vmwarebase is not required on this system')
|
||||||
|
|
||||||
if osname == 'vmkernel':
|
if osname == 'vmkernel':
|
||||||
# Patch ESXi 6.0 and 6.5 32 bit .so
|
# Patch ESXi 6.0 and 6.5 32 bit .so
|
||||||
patchvmkctl(libvmkctl32)
|
patchvmkctl(libvmkctl32)
|
||||||
|
|
||||||
# Try and patch ESXi 6.5 64 bit .so
|
# Patch ESXi 6.5 64 bit .so
|
||||||
try:
|
if os.path.isfile(libvmkctl64):
|
||||||
patchvmkctl(libvmkctl64)
|
patchvmkctl(libvmkctl64)
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
469
wip/test.py
469
wip/test.py
@ -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()
|
|
Loading…
x
Reference in New Issue
Block a user