cleanup old files

This commit is contained in:
platomav 2022-04-01 17:48:20 +03:00
parent 132457afda
commit 7c00479a9e
17 changed files with 0 additions and 3774 deletions

2
.gitattributes vendored
View file

@ -1,2 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto

View file

@ -1,321 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
AMI PFAT Extract
AMI BIOS Guard Extractor
Copyright (C) 2018-2021 Plato Mavropoulos
"""
print('AMI BIOS Guard Extractor v3.2')
import sys
# Detect Python version
sys_ver = sys.version_info
if sys_ver < (3,7) :
sys.stdout.write('\n\nError: Python >= 3.7 required, not %d.%d!\n' % (sys_ver[0], sys_ver[1]))
(raw_input if sys_ver[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
import os
import re
import ctypes
import shutil
import traceback
# https://stackoverflow.com/a/781074 by Torsten Marek
def show_exception_and_exit(exc_type, exc_value, tb) :
if exc_type is KeyboardInterrupt :
print('\n')
else :
print('\nError: ABGE crashed, please report the following:\n')
traceback.print_exception(exc_type, exc_value, tb)
input('\nPress enter to exit')
sys.exit(1)
# Pause after any unexpected python exception
sys.excepthook = show_exception_and_exit
sys.dont_write_bytecode = True
# https://github.com/allowitsme/big-tool by Dmitry Frolov
try :
from big_script_tool import BigScript
is_bgst = True
except :
is_bgst = False
# Set ctypes Structure types
char = ctypes.c_char
uint8_t = ctypes.c_ubyte
uint16_t = ctypes.c_ushort
uint32_t = ctypes.c_uint
uint64_t = ctypes.c_uint64
class PFAT_Header(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('Size', uint32_t), # 0x00
('Checksum', uint32_t), # 0x04 Unknown 16-bits
('Tag', char*8), # 0x04 _AMIPFAT
('Flags', uint8_t), # 0x10
# 0x11
]
def pfat_print(self) :
print('\n PFAT Main Header:\n')
print(' Size : 0x%X' % self.Size)
print(' Checksum : 0x%0.4X' % self.Checksum)
print(' Tag : %s' % self.Tag.decode('utf-8'))
print(' Flags : 0x%0.2X' % self.Flags)
class PFAT_Block_Header(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('PFATVerMajor', uint16_t), # 0x00
('PFATVerMinor', uint16_t), # 0x02
('PlatformID', uint8_t*16), # 0x04
('Attributes', uint32_t), # 0x14
('ScriptVerMajor', uint16_t), # 0x16
('ScriptVerMinor', uint16_t), # 0x18
('ScriptSize', uint32_t), # 0x1C
('DataSize', uint32_t), # 0x20
('BIOSSVN', uint32_t), # 0x24
('ECSVN', uint32_t), # 0x28
('VendorInfo', uint32_t), # 0x2C
# 0x30
]
def __init__(self, count, *args, **kwargs):
super().__init__(*args, **kwargs)
self.count = count
def get_flags(self) :
attr = PFAT_Block_Header_GetAttributes()
attr.asbytes = self.Attributes
return attr.b.SFAM, attr.b.ProtectEC, attr.b.GFXMitDis, attr.b.FTU, attr.b.Reserved
def pfat_print(self) :
no_yes = ['No','Yes']
f1,f2,f3,f4,f5 = self.get_flags()
PlatformID = bytes(self.PlatformID).strip(b'\x00')
if PlatformID.isalpha() : # STRING
PlatformID = PlatformID.decode('utf-8', 'ignore')
else : # GUID
PlatformID = '%0.*X' % (0x10 * 2, int.from_bytes(self.PlatformID, 'big'))
PlatformID = '{%s-%s-%s-%s-%s}' % (PlatformID[:8], PlatformID[8:12], PlatformID[12:16], PlatformID[16:20], PlatformID[20:])
print('\n PFAT Block %s Header:\n' % self.count)
print(' PFAT Version : %d.%d' % (self.PFATVerMajor, self.PFATVerMinor))
print(' Platform ID : %s' % PlatformID)
print(' Signed Flash Address Map : %s' % no_yes[f1])
print(' Protected EC OpCodes : %s' % no_yes[f2])
print(' Graphics Security Disable : %s' % no_yes[f3])
print(' Fault Tolerant Update : %s' % no_yes[f4])
print(' Attributes Reserved : 0x%X' % f5)
print(' Script Version : %d.%d' % (self.ScriptVerMajor, self.ScriptVerMinor))
print(' Script Size : 0x%X' % self.ScriptSize)
print(' Data Size : 0x%X' % self.DataSize)
print(' BIOS SVN : 0x%X' % self.BIOSSVN)
print(' EC SVN : 0x%X' % self.ECSVN)
print(' Vendor Info : 0x%X' % self.VendorInfo)
class PFAT_Block_Header_Attributes(ctypes.LittleEndianStructure):
_fields_ = [
('SFAM', uint32_t, 1), # Signed Flash Address Map
('ProtectEC', uint32_t, 1), # Protected EC OpCodes
('GFXMitDis', uint32_t, 1), # GFX Security Disable
('FTU', uint32_t, 1), # Fault Tolerant Update
('Reserved', uint32_t, 28)
]
class PFAT_Block_Header_GetAttributes(ctypes.Union):
_fields_ = [
('b', PFAT_Block_Header_Attributes),
('asbytes', uint32_t)
]
class PFAT_Block_RSA(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('Unknown0', uint32_t), # 0x00
('Unknown1', uint32_t), # 0x04
('PublicKey', uint32_t*64), # 0x08
('Exponent', uint32_t), # 0x108
('Signature', uint32_t*64), # 0x10C
# 0x20C
]
def __init__(self, count, *args, **kwargs):
super().__init__(*args, **kwargs)
self.count = count
def pfat_print(self) :
PublicKey = '%0.*X' % (0x100 * 2, int.from_bytes(self.PublicKey, 'little'))
Signature = '%0.*X' % (0x100 * 2, int.from_bytes(self.Signature, 'little'))
print('\n PFAT Block %s Signature:\n' % self.count)
print(' Unknown 0 : 0x%X' % self.Unknown0)
print(' Unknown 1 : 0x%X' % self.Unknown1)
print(' Public Key : %s [...]' % PublicKey[:8])
print(' Exponent : 0x%X' % self.Exponent)
print(' Signature : %s [...]' % Signature[:8])
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
def get_struct(buffer, start_offset, class_name, param_list = None) :
if param_list is None : param_list = []
structure = class_name(*param_list) # Unpack parameter list
struct_len = ctypes.sizeof(structure)
struct_data = buffer[start_offset:start_offset + struct_len]
fit_len = min(len(struct_data), struct_len)
if (start_offset >= len(buffer)) or (fit_len < struct_len) :
input('\n Error: Offset 0x%X out of bounds at %s, possibly incomplete image!' % (start_offset, class_name.__name__))
sys.exit(1)
ctypes.memmove(ctypes.addressof(structure), struct_data, fit_len)
return structure
if len(sys.argv) >= 2 :
# Drag & Drop or CLI
ami_pfat = sys.argv[1:]
else :
# Folder path
ami_pfat = []
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, _, files in os.walk(in_path):
for name in files :
ami_pfat.append(os.path.join(root, name))
pfat_index = 1
input_name = ''
input_extension = ''
output_path = ''
block_hdr_size = ctypes.sizeof(PFAT_Block_Header)
block_rsa_size = ctypes.sizeof(PFAT_Block_RSA)
pfat_pat = re.compile(b'_AMIPFAT.AMI_BIOS_GUARD_FLASH_CONFIGURATIONS', re.DOTALL)
for input_file in ami_pfat :
file_data = b''
final_data = b''
block_name = ''
block_count = 0
file_index = 0
blocks = []
with open(input_file, 'rb') as in_file : buffer = in_file.read()
pfat_match = pfat_pat.search(buffer)
if pfat_index == 1 :
input_name,input_extension = os.path.splitext(os.path.basename(input_file))
input_dir = os.path.dirname(os.path.abspath(input_file))
print('\n*** %s%s' % (input_name, input_extension))
if not pfat_match :
print('\n Error: This is not an AMI BIOS Guard (PFAT) image!')
continue
output_path = os.path.join(input_dir, '%s%s' % (input_name, input_extension) + '_extracted') # Set extraction directory
if os.path.isdir(output_path) : shutil.rmtree(output_path) # Delete any existing extraction directory
os.mkdir(output_path) # Create extraction directory
if not pfat_match : continue
buffer = buffer[pfat_match.start() - 0x8:]
pfat_hdr = get_struct(buffer, 0, PFAT_Header)
hdr_size = pfat_hdr.Size
hdr_data = buffer[0x11:hdr_size].decode('utf-8').splitlines()
pfat_hdr.pfat_print()
print(' Title : %s' % hdr_data[0])
file_path = os.path.join(output_path, '%s%s -- %d' % (input_name, input_extension, pfat_index))
for entry in hdr_data[1:] :
entry_data = entry.split(' ')
entry_data = [s for s in entry_data if s != '']
entry_flags = int(entry_data[0])
entry_param = entry_data[1]
entry_blocks = int(entry_data[2])
entry_name = entry_data[3][1:]
for i in range(entry_blocks) : blocks.append([entry_name, entry_param, entry_flags, i + 1, entry_blocks])
block_count += entry_blocks
block_start = hdr_size
for i in range(block_count) :
is_file_start = blocks[i][0] != block_name
if is_file_start : print('\n %s (Parameter: %s, Flags: 0x%X)' % (blocks[i][0], blocks[i][1], blocks[i][2]))
block_hdr = get_struct(buffer, block_start, PFAT_Block_Header, ['%d/%d' % (blocks[i][3], blocks[i][4])])
block_hdr.pfat_print()
block_script_size = block_hdr.ScriptSize
block_script_data = buffer[block_start + block_hdr_size:block_start + block_hdr_size + block_script_size]
block_data_start = block_start + block_hdr_size + block_script_size
block_data_end = block_data_start + block_hdr.DataSize
block_data = buffer[block_data_start:block_data_end]
block_rsa = get_struct(buffer, block_data_end, PFAT_Block_RSA, ['%d/%d' % (blocks[i][3], blocks[i][4])])
block_rsa.pfat_print()
print('\n PFAT Block %d/%d Script:\n' % (blocks[i][3], blocks[i][4]))
is_opcode_div = len(block_script_data) % 8 == 0
is_begin_end = block_script_data[:8] + block_script_data[-8:] == b'\x01' + b'\x00' * 7 + b'\xFF' + b'\x00' * 7
if is_opcode_div and is_begin_end and is_bgst :
block_script_decomp = BigScript(code_bytes=block_script_data)
block_script_lines = block_script_decomp.to_string().replace('\t',' ').split('\n')
for line in block_script_lines :
spacing = ' ' * 16 if line.endswith(('begin','end',':')) else ' ' * 24
operands = [op for op in line.split(' ') if op != '']
print(spacing + ('{:<12s}' + '{:<11s}' * (len(operands) - 1)).format(*operands))
elif not is_opcode_div :
print(' Error: Script not divisible by OpCode length!')
elif not is_begin_end :
print(' Error: Script lacks Begin and/or End OpCodes!')
elif not is_bgst :
print(' Error: BIOS Guard Script Tool dependency missing!')
file_data += block_data
final_data += block_data
if i and is_file_start and file_data :
file_index += 1
with open('%s_%0.2d -- %s' % (file_path, file_index, block_name), 'wb') as o : o.write(file_data)
file_data = b''
block_name = blocks[i][0]
block_start = block_data_end + block_rsa_size
with open('%s_%0.2d -- %s' % (file_path, file_index + 1, block_name), 'wb') as o : o.write(file_data) # Last File
eof_data = buffer[block_start:] # Store any data after the end of PFAT
with open('%s_00 -- AMI_PFAT_%d_DATA_ALL.bin' % (file_path, pfat_index), 'wb') as final : final.write(final_data + eof_data)
if eof_data[:-0x100] != b'\xFF' * (len(eof_data) - 0x100) :
eof_path = '%s_%0.2d -- AMI_PFAT_%d_DATA_END.bin' % (file_path, file_index + 2, pfat_index)
with open(eof_path, 'wb') as final : final.write(eof_data)
if pfat_pat.search(eof_data) :
pfat_index += 1
ami_pfat_index = ami_pfat.index(input_file) + 1
ami_pfat.insert(ami_pfat_index, eof_path)
else :
pfat_index = 1
input('\nDone!')

View file

@ -1,610 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
AMI UCP Extract
AMI UCP BIOS Extractor
Copyright (C) 2021 Plato Mavropoulos
"""
title = 'AMI UCP BIOS Extractor v1.2'
print('\n' + title) # Print script title
import sys
# Detect Python version
sys_ver = sys.version_info
if sys_ver < (3,7) :
sys.stdout.write('\n\nError: Python >= 3.7 required, not %d.%d!\n' % (sys_ver[0], sys_ver[1]))
(raw_input if sys_ver[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
import os
import re
import shutil
import ctypes
import argparse
import traceback
import subprocess
import contextlib
# Pause after any unexpected Python exception
# https://stackoverflow.com/a/781074 by Torsten Marek
def show_exception_and_exit(exc_type, exc_value, tb) :
if exc_type is KeyboardInterrupt :
print('\n')
else :
print('\nError: %s crashed, please report the following:\n' % title)
traceback.print_exception(exc_type, exc_value, tb)
input('\nPress enter to exit')
sys.exit(1)
# Set pause-able Python exception handler
sys.excepthook = show_exception_and_exit
# Set console/shell window title
user_os = sys.platform
if user_os == 'win32' : ctypes.windll.kernel32.SetConsoleTitleW(title)
elif user_os.startswith('linux') or user_os == 'darwin' or user_os.find('bsd') != -1 : sys.stdout.write('\x1b]2;' + title + '\x07')
# Set argparse Arguments
ucp_parser = argparse.ArgumentParser()
ucp_parser.add_argument('executables', type=argparse.FileType('r'), nargs='*')
ucp_parser.add_argument('-p', '--path', help='parse files within given folder', type=str)
ucp_parser.add_argument('-c', '--checksum', help='verify AMI UCP Checksums (slow)', action='store_true')
ucp_params = ucp_parser.parse_args()
verify_chk16 = bool(ucp_params.checksum) # Get Checksum16 Verification optional argument
# Get all files within path
def get_files(path) :
inputs = []
for root, _, files in os.walk(path):
for name in files :
inputs.append(os.path.join(root, name))
return inputs
if len(sys.argv) >= 2 :
if bool(ucp_params.path) :
ucp_exec = get_files(ucp_params.path) # CLI with --path
else :
ucp_exec = []
for executable in ucp_params.executables :
ucp_exec.append(executable.name) # Drag & Drop
else :
in_path = input('\nEnter the full folder path: ')
ucp_exec = get_files(in_path) # Direct Run
# Set ctypes Structure types
char = ctypes.c_char
uint8_t = ctypes.c_ubyte
uint16_t = ctypes.c_ushort
uint32_t = ctypes.c_uint
uint64_t = ctypes.c_uint64
class UAF_HDR(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('ModuleTag', char*4), # 0x00
('ModuleSize', uint32_t), # 0x04
('Checksum', uint16_t), # 0x08
('Unknown0', uint8_t), # 0x0A
('Unknown1', uint8_t), # 0x0A
('Reserved', uint32_t), # 0x0C
# 0x10
]
def __init__(self, padd, *args, **kwargs) :
super().__init__(*args, **kwargs)
self.p = padd
def ucp_print(self, chk16) :
print('\n%s Utility Auxiliary File:\n' % self.p)
print('%s Module Tag : %s' % (self.p, self.ModuleTag.decode('utf-8')))
print('%s Module Size : 0x%X' % (self.p, self.ModuleSize))
print('%s Checksum : 0x%0.4X (%s)' % (self.p, self.Checksum, chk16))
print('%s Unknown 0 : 0x%0.2X' % (self.p, self.Unknown0))
print('%s Unknown 1 : 0x%0.2X' % (self.p, self.Unknown1))
print('%s Reserved : 0x%0.8X' % (self.p, self.Reserved))
class UAF_MOD(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('CompressSize', uint32_t), # 0x00
('OriginalSize', uint32_t), # 0x04
# 0x08
]
def __init__(self, padd, *args, **kwargs) :
super().__init__(*args, **kwargs)
self.p = padd
def ucp_print(self) :
print('%s Compress Size : 0x%X' % (self.p, self.CompressSize))
print('%s Original Size : 0x%X' % (self.p, self.OriginalSize))
class UII_HDR(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('UIISize', uint16_t), # 0x00
('Checksum', uint16_t), # 0x02
('UtilityVersion', uint32_t), # 0x04 i.e. AFU (Unknown Encoding, Signed)
('InfoSize', uint16_t), # 0x08
('SupportBIOS', uint8_t), # 0x0A
('SupportOS', uint8_t), # 0x0B
('DataBusWidth', uint8_t), # 0x0C
('ProgramType', uint8_t), # 0x0D
('ProgramMode', uint8_t), # 0x0E
('SourceSafeRelease', uint8_t), # 0x0F
# 0x10
]
def __init__(self, padd, *args, **kwargs) :
super().__init__(*args, **kwargs)
self.p = padd
def ucp_print(self, chk16) :
sbios = {1: 'ALL', 2: 'AMIBIOS8', 3: 'UEFI', 4: 'AMIBIOS8/UEFI'}
sos = {1: 'DOS', 2: 'EFI', 3: 'Windows', 4: 'Linux', 5: 'FreeBSD', 6: 'MacOS', 128: 'Multi-Platform'}
dbwidth = {1: '16b', 2: '16/32b', 3: '32b', 4: '64b'}
ptype = {1: 'Executable', 2: 'Library', 3: 'Driver'}
pmode = {1: 'API', 2: 'Console', 3: 'GUI', 4: 'Console/GUI'}
SupportBIOS = sbios[self.SupportBIOS] if self.SupportBIOS in sbios else 'Unknown (%d)' % self.SupportBIOS
SupportOS = sos[self.SupportOS] if self.SupportOS in sos else 'Unknown (%d)' % self.SupportOS
DataBusWidth = dbwidth[self.DataBusWidth] if self.DataBusWidth in dbwidth else 'Unknown (%d)' % self.DataBusWidth
ProgramType = ptype[self.ProgramType] if self.ProgramType in ptype else 'Unknown (%d)' % self.ProgramType
ProgramMode = pmode[self.ProgramMode] if self.ProgramMode in pmode else 'Unknown (%d)' % self.ProgramMode
print('\n%s Utility Identification Information:\n' % self.p)
print('%s UII Size : 0x%X' % (self.p, self.UIISize))
print('%s Checksum : 0x%0.4X (%s)' % (self.p, self.Checksum, chk16))
print('%s Tool Version : 0x%0.8X (Unknown)' % (self.p, self.UtilityVersion))
print('%s Info Size : 0x%X' % (self.p, self.InfoSize))
print('%s Supported BIOS : %s' % (self.p, SupportBIOS))
print('%s Supported OS : %s' % (self.p, SupportOS))
print('%s Data Bus Width : %s' % (self.p, DataBusWidth))
print('%s Program Type : %s' % (self.p, ProgramType))
print('%s Program Mode : %s' % (self.p, ProgramMode))
print('%s SourceSafe Tag : %0.2d' % (self.p, self.SourceSafeRelease))
class DIS_HDR(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('PasswordSize', uint16_t), # 0x00
('EntryCount', uint16_t), # 0x02
('Password', char*12), # 0x04
# 0x10
]
def __init__(self, padd, *args, **kwargs) :
super().__init__(*args, **kwargs)
self.p = padd
def ucp_print(self) :
print('\n%s Default Command Status Header:\n' % self.p)
print('%s Password Size : 0x%X' % (self.p, self.PasswordSize))
print('%s Entry Count : %d' % (self.p, self.EntryCount))
print('%s Password : %s' % (self.p, self.Password.decode('utf-8')))
class DIS_MOD(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('EnabledDisabled', uint8_t), # 0x00
('ShownHidden', uint8_t), # 0x01
('Command', char*32), # 0x02
('Description', char*256), # 0x22
# 0x122
]
def __init__(self, padd, *args, **kwargs) :
super().__init__(*args, **kwargs)
self.p = padd
def ucp_print(self) :
enabled = {0: 'Disabled', 1: 'Enabled'}
shown = {0: 'Hidden', 1: 'Shown', 2: 'Shown Only'}
EnabledDisabled = enabled[self.EnabledDisabled] if self.EnabledDisabled in enabled else 'Unknown (%d)' % self.EnabledDisabled
ShownHidden = shown[self.ShownHidden] if self.ShownHidden in shown else 'Unknown (%d)' % self.ShownHidden
print('\n%s Default Command Status Entry:\n' % self.p)
print('%s State : %s' % (self.p, EnabledDisabled))
print('%s Display : %s' % (self.p, ShownHidden))
print('%s Command : %s' % (self.p, self.Command.decode('utf-8').strip()))
print('%s Description : %s' % (self.p, self.Description.decode('utf-8').strip()))
# Process ctypes Structure Classes
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
def get_struct(buffer, start_offset, class_name, param_list = None) :
if param_list is None : param_list = []
structure = class_name(*param_list) # Unpack parameter list
struct_len = ctypes.sizeof(structure)
struct_data = buffer[start_offset:start_offset + struct_len]
fit_len = min(len(struct_data), struct_len)
if (start_offset >= len(buffer)) or (fit_len < struct_len) :
print('\n Error: Offset 0x%X out of bounds at %s, possibly incomplete image!' % (start_offset, class_name.__name__))
input('\n Press enter to exit')
sys.exit(1)
ctypes.memmove(ctypes.addressof(structure), struct_data, fit_len)
return structure
# Get Checksum16 validity result
def checksum16(buffer, check) :
if not check : return 'Skipped'
chk16 = 0
for idx in range(0, len(buffer), 2) :
chk16 += int.from_bytes(buffer[idx:idx + 2], 'little')
chk16 &= 0xFFFF
return 'Good' if chk16 == 0 else 'Bad'
# Get all input file AMI UCP patterns
def get_matches(buffer) :
uaf_len_max = 0 # Length of largest detected @UAF
uaf_hdr_off = 0 # Offset of largest detected @UAF
for uaf in ami_ucp_pat.finditer(buffer) :
uaf_len_cur = int.from_bytes(buffer[uaf.start() + 0x4:uaf.start() + 0x8], 'little')
if uaf_len_cur > uaf_len_max :
uaf_len_max = uaf_len_cur
uaf_hdr_off = uaf.start()
return uaf_hdr_off, uaf_len_max
# Parse & Extract AMI UCP structures
def ucp_extract(buffer, out_dir, level, padd) :
nal_dict = {} # Initialize @NAL Dictionary per UCP
uaf_hdr = get_struct(buffer, 0, UAF_HDR, [padd]) # Parse @UAF Header Structure
uaf_chk = checksum16(buffer, verify_chk16) # Get @UAF Header Checksum16
# Print @UAF Header Info
uaf_hdr.ucp_print(uaf_chk)
print('%s Compress Size : 0x%X' % (padd, len(buffer)))
print('%s Original Size : 0x%X' % (padd, len(buffer)))
print('%s Module Name : %s' % (padd, tag_dict['UAF']))
if uaf_chk == 'Bad' :
input('\n%s Error: Invalid AMI UCP Module UAF Checksum!' % padd)
uaf_off = uaf_hdr_len # Parsed @UAF, next Modules
uaf_all = [] # Initialize list of all UAF Modules
is_pfat = False # Initialize PFAT BIOS detection
is_dual = False # Initialize AMI/Insyde detection
while buffer[uaf_off] == 0x40 : # ASCII of @ is 0x40
uaf_hdr = get_struct(buffer, uaf_off, UAF_HDR, [padd]) # Parse UAF Module Structure
uaf_tag = uaf_hdr.ModuleTag.decode('utf-8')[1:] # Get unique UAF Module Tag
if uaf_tag == 'PFC' : is_pfat = True # Detect if UAF Module has PFAT BIOS
if uaf_tag == 'AMI' : is_dual = True # Detect if UAF Module has dual AMI/Insyde BIOS
uaf_all.append([uaf_tag, uaf_off, uaf_hdr]) # Store UAF Module Info
uaf_off += uaf_hdr.ModuleSize # Adjust to next UAF Module offset
if uaf_off >= len(buffer) : break # Stop parsing at EOF
# Check if UAF Module NAL exists and place it first
# Parsing NAL first allows naming all UAF Modules
for i in range(len(uaf_all)) :
if uaf_all[i][0] == 'NAL' :
uaf_all.insert(1, uaf_all.pop(i)) # After UII for visual purposes
break # NAL found, skip the rest
# Parse all UAF Modules
for uaf in uaf_all :
uaf_tag = uaf[0] # Store UAF Module Tag
uaf_off = uaf[1] # Store UAF Module Offset
uaf_hdr = uaf[2] # Store UAF Module Struct
uaf_data_all = buffer[uaf_off:uaf_off + uaf_hdr.ModuleSize] # UAF Module Entire Data
uaf_data_mod = uaf_data_all[uaf_hdr_len:] # UAF Module EFI Data
uaf_data_raw = uaf_data_mod[uaf_mod_len:] # UAF Module Raw Data
uaf_chk = checksum16(uaf_data_all, verify_chk16) # Get UAF Module Checksum16
uaf_hdr.ucp_print(uaf_chk) # Print UAF Module Info
uaf_mod = get_struct(buffer, uaf_off + uaf_hdr_len, UAF_MOD, [padd]) # Parse UAF Module EFI Structure
uaf_mod.ucp_print() # Print UAF Module EFI Info
is_comp = uaf_mod.CompressSize != uaf_mod.OriginalSize # Detect UAF Module EFI Compression
rom_name = 'PFAT' if is_pfat else 'BIOS' # Set UAF Module BIOS/ROM name based on PFAT state
if uaf_tag in nal_dict : uaf_name = nal_dict[uaf_tag] # Always prefer NAL naming first
elif uaf_tag in tag_dict : uaf_name = tag_dict[uaf_tag] # Otherwise use built-in naming
elif uaf_tag == 'ROM' : uaf_name = '%s.bin' % rom_name # BIOS/PFAT Firmware
elif uaf_tag.startswith('R0') : uaf_name = '%s_0%s.bin' % (rom_name, uaf_tag[2:]) # BIOS/PFAT Firmware
elif uaf_tag.startswith('S0') : uaf_name = '%s_0%s.sig' % (rom_name, uaf_tag[2:]) # BIOS/PFAT Signature
elif uaf_tag.startswith('DR') : uaf_name = 'DROM_0%s.bin' % uaf_tag[2:] # Thunderbolt Retimer Firmware
elif uaf_tag.startswith('DS') : uaf_name = 'DROM_0%s.sig' % uaf_tag[2:] # Thunderbolt Retimer Signature
elif uaf_tag.startswith('EC') : uaf_name = 'EC_0%s.bin' % uaf_tag[2:] # Embedded Controller Firmware
elif uaf_tag.startswith('ME') : uaf_name = 'ME_0%s.bin' % uaf_tag[2:] # Management Engine Firmware
else : uaf_name = uaf_tag # Could not name the UAF Module, use Tag instead
if uaf_name != uaf_tag :
uaf_fext = '' # File extension included in name
print('%s Module Name : %s' % (padd, uaf_name))
elif uaf_tag in ['CMD','PFC','VER','MEC','NAL','CKV'] :
uaf_fext = '.txt' # Known Text files
print('%s Module Name : %s%s (Unknown)' % (padd, uaf_name, uaf_fext))
else :
uaf_fext = '.bin' # Unknown files, assume binary
print('%s Module Name : %s%s (Unknown)' % (padd, uaf_name, uaf_fext))
# Check if unknown UAF Module Tag is present in NAL but not in built-in dictionary
if uaf_tag in nal_dict and uaf_tag not in tag_dict and not uaf_tag.startswith(('ROM','R0','S0','DR','DS')) :
input('\n%s Note: Detected new AMI UCP Module %s (%s) in NAL!' % (padd, uaf_tag, nal_dict[uaf_tag]))
# Generate UAF Module File name, depending on whether decompression will be required
uaf_fname = os.path.join(out_dir, '%s%s' % (uaf_name, '.temp' if is_comp else uaf_fext))
if uaf_chk == 'Bad' :
input('\n%s Error: Invalid AMI UCP Module %s Checksum!' % (padd, uaf_tag))
# Parse Utility Identification Information UAF Module (UII)
if uaf_tag == 'UII' :
info_hdr = get_struct(uaf_data_raw, 0, UII_HDR, [padd]) # Parse UII Module Raw Structure
info_chk = checksum16(uaf_data_raw, verify_chk16) # Get UII Module Checksum16
info_hdr.ucp_print(info_chk) # Print UII Module Info
# Get UII Module Description text field
desc = uaf_data_raw[info_hdr.InfoSize:info_hdr.UIISize].strip(b'\x00').decode('utf-8')
print('%s Description : %s' % (padd, desc)) # Print UII Module Description
if info_chk == 'Bad' :
input('\n%s Error: Invalid AMI UCP Module %s > Info Checksum!' % (padd, uaf_tag))
# Store/Save UII Module Info in file
with open(uaf_fname[:-3] + 'txt', 'a') as uii :
with contextlib.redirect_stdout(uii) :
info_hdr.ucp_print(info_chk) # Store UII Module Info
print('%s Description : %s' % (padd, desc)) # Store UII Module Description
# Adjust UAF Module Raw Data for extraction
if is_comp :
# Some Compressed UAF Module EFI data lack necessary padding in the end
if uaf_mod.CompressSize > len(uaf_data_raw) :
comp_padd = b'\x00' * (uaf_mod.CompressSize - len(uaf_data_raw))
uaf_data_raw = uaf_data_mod[:uaf_mod_len] + uaf_data_raw + comp_padd # Add missing padding for decompression
else :
uaf_data_raw = uaf_data_mod[:uaf_mod_len] + uaf_data_raw # Add the EFI/Tiano Compression info before Raw Data
else :
uaf_data_raw = uaf_data_raw[:uaf_mod.OriginalSize] # No compression, extend to end of Original UAF Module size
# Store/Save UAF Module file
if uaf_tag != 'UII' : # Skip UII binary, already parsed
with open(uaf_fname, 'wb') as out : out.write(uaf_data_raw)
# UAF Module EFI/Tiano Decompression
if is_comp :
try :
dec_fname = uaf_fname[:-5] + uaf_fext # Decompressed UAF Module file path
subprocess.run(['TianoCompress', '-d', uaf_fname, '-o', dec_fname, '--uefi', '-q'], check = True, stdout = subprocess.DEVNULL)
with open(dec_fname, 'rb') as dec : uaf_data_raw = dec.read() # Read back the UAF Module decompressed Raw data
if len(uaf_data_raw) == 0 : raise Exception('DECOMP_OUT_EMPTY') # If decompressed file is empty, something went wrong
os.remove(uaf_fname) # Successful decompression, delete compressed UAF Module file
uaf_fname = dec_fname # Adjust UAF Module file path to the decompressed one
except :
print('\n%s Error: Could not extract AMI UCP Module %s via TianoCompress!' % (padd, uaf_tag))
input('%s Make sure that "TianoCompress" executable exists!' % padd)
# Process and Print known text only UAF Modules (after EFI/Tiano Decompression)
if uaf_tag in ['CMD','PFC','VER','MEC','CKV'] : # Always referenced in tag_desc
text_data = uaf_data_raw.decode('utf-8')
print('\n%s %s:\n\n%s %s' % (padd, tag_desc[uaf_tag], padd, text_data))
# Parse Default Command Status UAF Module (DIS)
if len(uaf_data_raw) and uaf_tag == 'DIS' :
dis_hdr = get_struct(uaf_data_raw, 0, DIS_HDR, [padd]) # Parse DIS Module Raw Header Structure
dis_hdr.ucp_print() # Print DIS Module Raw Header Info
# Store/Save DIS Module Header Info in file
with open(uaf_fname[:-3] + 'txt', 'a') as dis :
with contextlib.redirect_stdout(dis) :
dis_hdr.ucp_print() # Store DIS Module Header Info
dis_data = uaf_data_raw[uaf_hdr_len:] # DIS Module Entries Data
# Parse all DIS Module Entries
for e_idx in range(dis_hdr.EntryCount) :
dis_mod = get_struct(dis_data, e_idx * 0x122, DIS_MOD, [padd]) # Parse DIS Module Raw Entry Structure
dis_mod.ucp_print() # Print DIS Module Raw Entry Info
# Store/Save DIS Module Entry Info in file
with open(uaf_fname[:-3] + 'txt', 'a') as dis :
with contextlib.redirect_stdout(dis) :
dis_mod.ucp_print() # Store DIS Module Entry Info
os.remove(uaf_fname) # Delete DIS Module binary, info exported as text
# Parse Non-AMI List (?) UAF Module (NAL)
if len(uaf_data_raw) >= 5 and (uaf_tag,uaf_data_raw[0],uaf_data_raw[4]) == ('NAL',0x40,0x3A) :
nal_info = uaf_data_raw.decode('utf-8').strip().replace('\r','').split('\n')
print('\n%s UAF List:\n' % padd)
# Parse all NAL Module Entries
for info in nal_info :
print('%s %s : %s' % (padd, info[1:4], info[5:])) # Print NAL Module Tag-Path Info
nal_dict[info[1:4]] = os.path.basename(info[5:]) # Assign a file name (w/o path) to each Tag
# Parse Insyde BIOS UAF Module (INS)
if len(uaf_data_raw) >= 2 and (uaf_tag,is_dual,uaf_data_raw[:2]) == ('INS',True,b'\x4D\x5A') :
ins_dir = os.path.join(out_dir, '%s_extracted (SFX)' % uaf_tag) # Generate extraction directory
print('\n%s Insyde BIOS 7-Zip SFX Archive:\n\n%s 7-Zip will be used for extraction' % (padd, padd))
# INS Module extraction
try :
subprocess.run(['7z', 'x', '-aou', '-bso0', '-bse0', '-bsp0', '-o' + ins_dir, uaf_fname], check = True, stdout = subprocess.DEVNULL)
if not os.path.isdir(ins_dir) : raise Exception('EXTR_DIR_MISSING') # If extraction folder is missing, something went wrong
os.remove(uaf_fname) # Successful extraction, delete archived INS Module file
except :
print('\n%s Error: Could not extract AMI UCP Module %s via 7-Zip!' % (padd, uaf_tag))
input('%s Make sure that "7z" executable exists!' % padd)
# Detect AMI BIOS Guard (PFAT) image and print extraction instructions/utility
if len(uaf_data_raw) >= 16 and (is_pfat,uaf_data_raw[0x8:0x10]) == (True,b'_AMIPFAT') :
print('\n%s AMI BIOS Guard (PFAT) Image:\n' % padd)
print('%s Use "AMI BIOS Guard Extractor" from https://github.com/platomav/BIOSUtilities' % padd)
# Detect Intel Management Engine (ME) image and print parsing instructions/utility
if len(uaf_data_raw) and uaf_name.startswith('ME_0') :
print('\n%s Intel Management Engine (ME) Firmware:\n' % padd)
print('%s Use "ME Analyzer" from https://github.com/platomav/MEAnalyzer' % padd)
# Get best Nested AMI UCP Pattern match based on @UAF Size
uaf_hdr_off,uaf_len_max = get_matches(uaf_data_raw)
# Parse Nested AMI UCP Structure
if uaf_hdr_off :
level += 1 # Increase structure Level to control output padding
uaf_dir = os.path.join(out_dir, '%s_extracted (UCP)' % uaf_tag) # Generate extraction directory
os.mkdir(uaf_dir) # Create extraction directory
ucp_extract(uaf_data_raw[uaf_hdr_off:uaf_hdr_off + uaf_len_max], uaf_dir, level, ' ' * level) # Call recursively
os.remove(uaf_fname) # Delete raw nested AMI UCP Structure after successful recursion/extraction
# Utility Auxiliary File (@UAF) and Utility Identification Information (@UII)
ami_ucp_pat = re.compile(br'\x40\x55\x41\x46.{12}\x40\x55\x49\x49', re.DOTALL)
# Get common ctypes Structure Sizes
uaf_hdr_len = ctypes.sizeof(UAF_HDR)
uaf_mod_len = ctypes.sizeof(UAF_MOD)
# User friendly Tag Descriptions
tag_desc = {
'CMD' : 'AMI AFU Command',
'PFC' : 'AMI BGT Command',
'VER' : 'OEM Version',
'CKV' : 'Check Version',
'MEC' : 'ME FWUpdLcl Command',
}
# AMI UCP Tag-File Dictionary
tag_dict = {
'W32' : 'amifldrv32.sys',
'W64' : 'amifldrv64.sys',
'VXD' : 'amifldrv.vxd',
'DCT' : 'DevCon32.exe',
'DCX' : 'DevCon64.exe',
'CMD' : 'AFU_Command.txt',
'PFC' : 'BGT_Command.txt',
'VER' : 'OEM_Version.txt',
'CKV' : 'Check_Version.txt',
'OKM' : 'OK_Message.txt',
'CPM' : 'AC_Message.txt',
'DIS' : 'Command_Status.bin',
'UAF' : 'UCP_Main.bin',
'UII' : 'UCP_Info.txt',
'NAL' : 'UAF_List.txt',
'MEC' : 'FWUpdLcl.txt',
'MED' : 'FWUpdLcl_DOS.exe',
'MET' : 'FWUpdLcl_WIN.exe',
'AMI' : 'UCP_Nested.bin',
'INS' : 'Insyde_Nested.bin',
'RFI' : 'CryptRSA.efi',
'R3I' : 'CryptRSA32.efi',
'UFI' : 'HpBiosUpdate.efi',
'US9' : 'HpBiosUpdate.s09',
'US2' : 'HpBiosUpdate.s12',
'USG' : 'HpBiosUpdate.sig',
'3FI' : 'HpBiosUpdate32.efi',
'3S9' : 'HpBiosUpdate32.s09',
'3S2' : 'HpBiosUpdate32.s12',
'3SG' : 'HpBiosUpdate32.sig',
'MFI' : 'HpBiosMgmt.efi',
'MS9' : 'HpBiosMgmt.s09',
'MS2' : 'HpBiosMgmt.s12',
'US4' : 'HpBiosUpdate.s14',
'3S4' : 'HpBiosUpdate32.s14',
'MS4' : 'HpBiosMgmt.s14',
'M3I' : 'HpBiosMgmt32.efi',
'M39' : 'HpBiosMgmt32.s09',
'M32' : 'HpBiosMgmt32.s12',
'M34' : 'HpBiosMgmt32.s14',
'BME' : 'BiosMgmt.efi',
'BM9' : 'BiosMgmt.s09',
'B12' : 'BiosMgmt.s12',
'B14' : 'BiosMgmt.s14',
'B3E' : 'BiosMgmt32.efi',
'B39' : 'BiosMgmt32.s09',
'B32' : 'BiosMgmt32.s12',
'B34' : 'BiosMgmt32.s14',
'DFE' : 'HpDevFwUpdate.efi',
'DFS' : 'HpDevFwUpdate.s12',
'ENB' : 'ENBG64.exe',
}
# Process each input AMI UCP BIOS executable
for input_file in ucp_exec :
input_name,input_extension = os.path.splitext(os.path.basename(input_file))
input_dir = os.path.dirname(os.path.abspath(input_file))
print('\n*** %s%s' % (input_name, input_extension))
# Check if input file exists
if not os.path.isfile(input_file) :
print('\n Error: This input file does not exist!')
continue # Next input file
with open(input_file, 'rb') as in_file : input_data = in_file.read()
# Get best AMI UCP Pattern match based on @UAF Size
uaf_hdr_off,uaf_len_max = get_matches(input_data)
# Check if AMI UCP Pattern was found on executable
if not uaf_hdr_off :
print('\n Error: This is not an AMI UCP BIOS executable!')
continue # Next input file
output_path = os.path.join(input_dir, '%s%s' % (input_name, input_extension) + '_extracted') # Set extraction directory
if os.path.isdir(output_path) : shutil.rmtree(output_path) # Delete any existing extraction directory
os.mkdir(output_path) # Create extraction directory
print('\n AMI Utility Configuration Program')
level = 0 # Set initial AMI UCP structure Level to control padding in nested ones
ucp_extract(input_data[uaf_hdr_off:uaf_hdr_off + uaf_len_max], output_path, level, '') # Call the AMI UCP Extractor function
print('\n Extracted AMI UCP BIOS executable!')
input('\nDone!')
sys.exit(0)

View file

@ -1,104 +0,0 @@
#!/usr/bin/env python3
"""
Apple EFI Rename
Apple EFI File Renamer
Copyright (C) 2018-2019 Plato Mavropoulos
https://github.com/tianocore/edk2/blob/master/Vlv2TbltDevicePkg/Include/Library/BiosIdLib.h
"""
print('Apple EFI File Renamer v1.3\n')
import os
import re
import sys
import zlib
import shutil
import subprocess
pattern = re.compile(br'\x24\x49\x42\x49\x4F\x53\x49\x24') # Intel $IBIOSI$
if len(sys.argv) >= 3 and sys.argv[1] == '-skip' :
# Called via Apple_EFI_Package
apple_efi = sys.argv[2:]
skip_pause = True
elif len(sys.argv) >= 2 :
# Drag & Drop or CLI
apple_efi = sys.argv[1:]
skip_pause = False
else :
# Folder path
apple_efi = []
skip_pause = False
in_path = input('\nEnter the full folder path: ')
print('\nWorking...\n')
for root, dirs, files in os.walk(in_path):
for name in files :
apple_efi.append(os.path.join(root, name))
for input_file in apple_efi :
file_path = os.path.abspath(input_file)
file_name = os.path.basename(input_file)
file_dir = os.path.dirname(file_path)
file_ext = os.path.splitext(file_path)[1]
error = False
with open(input_file, 'rb') as in_file : buffer = in_file.read()
is_ibiosi = pattern.search(buffer) # Detect $IBIOSI$ pattern
if not is_ibiosi :
# On some Apple EFI, the $IBIOSI$ pattern is within compressed modules so we need to use UEFIFind and UEFIExtract
try :
uefifind = subprocess.check_output(['UEFIFind', file_path, 'body', 'list', '244942494F534924'], universal_newlines=True)
uefiextr = subprocess.run(['UEFIExtract', file_path, uefifind[0:36], '-o', '_$IBIOSI$_', '-m', 'body'], stdout=subprocess.DEVNULL)
with open(os.path.join('_$IBIOSI$_', 'body.bin'), 'rb') as in_file : buffer = in_file.read()
is_ibiosi = pattern.search(buffer) # Detect decompressed $IBIOSI$ pattern
shutil.rmtree('_$IBIOSI$_') # Remove temporary folder
except :
error = True
if not error :
bios_info = buffer[is_ibiosi.end():is_ibiosi.end() + 0x42].decode('utf-16')
BoardID = bios_info[:7].strip()
BoardRev = bios_info[7]
OEMID = bios_info[9:12] # 88Z
MajorVer = bios_info[13:17]
BuildType = bios_info[18] # B
MinorVer = bios_info[19:21]
Year = bios_info[22:24]
Month = bios_info[24:26]
Day = bios_info[26:28]
Hour = bios_info[28:30]
Minute = bios_info[30:32]
file_chk = zlib.adler32(buffer) # Checksum for EFI with same $IBIOSI$ but different PRD/PRE status
new_name = '%s%s_%s_%s%s_20%s-%s-%s_%s-%s_%0.8X%s' % (BoardID, BoardRev, MajorVer, BuildType, MinorVer, Year, Month, Day, Hour, Minute, file_chk, file_ext)
file_path_new = os.path.join(file_dir, new_name)
if not os.path.isfile(file_path_new) : os.replace(file_path, file_path_new) # Rename input EFI with proper name
print(new_name)
print('\nBoard Identity: %s%s' % (BoardID, BoardRev))
print('Apple Identity: %s' % OEMID)
print('Major Version: %s' % MajorVer)
print('Minor Version: %s' % MinorVer)
print('Build Type: %s' % BuildType)
print('Build Date: 20%s-%s-%s' % (Year, Month, Day))
print('Build Time: %s:%s\n' % (Hour, Minute))
else :
print('\nError: Could not find $IBIOSI$ pattern at %s!' % file_name)
print(' Make sure that "UEFIFind" and "UEFIExtract" executables exist!\n')
if not skip_pause : input('Done!')

View file

@ -1,146 +0,0 @@
#!/usr/bin/env python3
"""
Apple EFI Split
Apple EFI IM4P Splitter
Copyright (C) 2018-2020 Plato Mavropoulos
"""
title = 'Apple EFI IM4P Splitter v2.1'
import os
import re
import sys
im4p = re.compile(br'\x16\x04\x49\x4D\x34\x50\x16\x04') # Apple IM4P
ifd = re.compile(br'\x5A\xA5\xF0\x0F.{172}\xFF{16}', re.DOTALL) # Intel Flash Descriptor (Z¥π. + [0xAC] + 0xFF * 16)
# Flash Descriptor Component Sizes
comp_dict = {
0 : 0x80000, # 512 KB
1 : 0x100000, # 1 MB
2 : 0x200000, # 2 MB
3 : 0x400000, # 4 MB
4 : 0x800000, # 8 MB
5 : 0x1000000, # 16 MB
6 : 0x2000000, # 32 MB
7 : 0x4000000, # 64 MB
8 : 0x8000000, # 128 MB
9 : 0x10000000, # 256 MB
}
# Get input catalog file paths
if len(sys.argv) >= 3 and sys.argv[1] == '-skip' :
# Called via Apple_EFI_Package
apple_im4p = sys.argv[2:]
skip_pause = True
skip_space = ' '
print('\n%s%s' % (skip_space, title)) # Print Title
elif len(sys.argv) >= 2 :
# Drag & Drop or CLI
apple_im4p = sys.argv[1:]
skip_pause = False
skip_space = ''
print('\n%s%s' % (skip_space, title)) # Print Title
else :
# Folder path
apple_im4p = []
skip_pause = False
skip_space = ''
print('\n%s%s' % (skip_space, title)) # Print Title
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, dirs, files in os.walk(in_path):
for name in files :
apple_im4p.append(os.path.join(root, name))
for input_file in apple_im4p :
file_path = os.path.abspath(input_file)
file_name = os.path.basename(input_file)
file_dir = os.path.dirname(file_path)
file_ext = os.path.splitext(file_path)[1]
print('\n%sFile: %s' % (skip_space, file_name)) # Print File Name
# Must be IM4P file because its size is 0x0 dependent
if file_ext not in ('.im4p','.IM4P') :
print('\n%s Error: Could not find IM4P file extension at %s!' % (skip_space, file_name))
continue # Critical error
with open(input_file, 'rb') as in_file : buffer = in_file.read()
is_im4p = im4p.search(buffer) # Detect IM4P pattern
if not is_im4p :
print('\n%s Error: Could not find IM4P pattern at %s!' % (skip_space, file_name))
continue # Critical error
im4p_size = int.from_bytes(buffer[2:is_im4p.start()], 'big') # Variable, from 0x2 - IM4P
im4p_type = buffer[is_im4p.end():is_im4p.end() + 0x4].decode('utf-8') # mefi
if im4p_type != 'mefi' :
print('\n%s Error: Could not find "mefi" IM4P Type at %s!' % (skip_space, file_name))
continue # Critical error
# After IM4P mefi (0x15), multi EFI payloads have _MEFIBIN (0x100) which is difficult to reverse without varying samples.
# However, _MEFIBIN is not required for splitting SPI/EFI images because Intel Flash Descriptor Component Density exists.
mefi_data_start = is_im4p.start() + buffer[is_im4p.start() - 0x1] # IM4P mefi payload start offset
mefi_data_size = int.from_bytes(buffer[is_im4p.end() + 0x9:is_im4p.end() + 0xD], 'big') # IM4P mefi payload size
mefibin_exist = buffer[mefi_data_start:mefi_data_start + 0x8] == b'_MEFIBIN' # Check if mefi is followed by _MEFIBIN
efi_data_start = mefi_data_start + 0x100 if mefibin_exist else mefi_data_start # Actual multi EFI payloads start after _MEFIBIN
efi_data_size = mefi_data_size - 0x100 if mefibin_exist else mefi_data_size # Actual multi EFI payloads size without _MEFIBIN
buffer = buffer[efi_data_start:efi_data_start + efi_data_size] # Adjust input file buffer to actual multi EFI payloads data
fd_matches = list(ifd.finditer(buffer)) # Find Intel Flash Descriptor pattern matches
fd_count = len(fd_matches) # Count found Intel Flash Descriptor pattern matches
fd_final = [] # Initialize final Intel Flash Descriptor info storage
# Parse Intel Flash Descriptor pattern matches
for fd_idx in range(fd_count) :
fd = fd_matches[fd_idx] # Get Intel Flash Descriptor match object
fd_flmap0_fcba = buffer[fd.start() + 0x4] * 0x10 # Component Base Address from FD start (ICH8-ICH10 = 1, IBX = 2, CPT+ = 3)
# I/O Controller Hub (ICH)
if fd_flmap0_fcba == 0x10 :
start_substruct = 0x0 # At ICH, Flash Descriptor starts at 0x0
end_substruct = 0xBC # 0xBC for [0xAC] + 0xFF * 16 sanity check
# Platform Controller Hub (PCH)
else :
start_substruct = 0x10 # At PCH, Flash Descriptor starts at 0x10
end_substruct = 0xBC # 0xBC for [0xAC] + 0xFF * 16 sanity check
fd_match_start = fd.start() - start_substruct # Actual Flash Descriptor Start Offset
fd_match_end = fd.end() - end_substruct # Actual Flash Descriptor End Offset
# Calculate Intel Flash Descriptor Flash Component Total Size
fd_flmap0_nc = ((int.from_bytes(buffer[fd_match_end:fd_match_end + 0x4], 'little') >> 8) & 3) + 1 # Component Count (00 = 1, 01 = 2)
fd_flmap1_isl = buffer[fd_match_end + 0x7] # PCH/ICH Strap Length (ME 2-8 & TXE 0-2 & SPS 1-2 <= 0x12, ME 9+ & TXE 3+ & SPS 3+ >= 0x13)
fd_comp_den = buffer[fd_match_start + fd_flmap0_fcba] # Component Density Byte (ME 2-8 & TXE 0-2 & SPS 1-2 = 0:5, ME 9+ & TXE 3+ & SPS 3+ = 0:7)
fd_comp_1_bitwise = 0xF if fd_flmap1_isl >= 0x13 else 0x7 # Component 1 Density Bits (ME 2-8 & TXE 0-2 & SPS 1-2 = 3, ME 9+ & TXE 3+ & SPS 3+ = 4)
fd_comp_2_bitwise = 0x4 if fd_flmap1_isl >= 0x13 else 0x3 # Component 2 Density Bits (ME 2-8 & TXE 0-2 & SPS 1-2 = 3, ME 9+ & TXE 3+ & SPS 3+ = 4)
fd_comp_all_size = comp_dict[fd_comp_den & fd_comp_1_bitwise] # Component 1 Density (FCBA > C0DEN)
if fd_flmap0_nc == 2 : fd_comp_all_size += comp_dict[fd_comp_den >> fd_comp_2_bitwise] # Component 2 Density (FCBA > C1DEN)
fd_final.append((fd_match_start,fd_comp_all_size)) # Store Intel Flash Descriptor final info
# Split IM4P via the final Intel Flash Descriptor matches
for fd_idx in range(fd_count) :
fd = fd_final[fd_idx] # Get Intel Flash Descriptor final info [FD Start, FD Component(s) Size]
# The Intel Flash Descriptor Flash Component Total Size should be enough to split the IM4P.
# However, for sanity, its Size can be compared to the Size different of Next - Current FD.
fd_diff_size = len(buffer) - fd[0] if fd_idx == fd_count - 1 else fd_final[fd_idx + 1][0] - fd[0] # Last FD ends at mefi payload end
if fd[1] != fd_diff_size : # FD Total Component Size should be equal to Next-Current FD Difference Size
print('\n%s Error: Intel FD %d/%d Component Size 0x%X != Next-Current FD Size Difference 0x%X!'
% (skip_space, fd_idx + 1, fd_count, fd[1], fd_diff_size))
file_data = buffer[fd[0]:fd[0] + max(fd[1], fd_diff_size)] # Split EFI image file data (use largest FD Size just in case)
file_path_new = os.path.join(file_dir, '%s_%d.fd' % (file_name[:-5], fd_idx + 1)) # Split EFI image file path
with open(file_path_new, 'wb') as spi_image : spi_image.write(file_data) # Store split EFI image file
print('\n%s Split IM4P into %d EFI image(s)!' % (skip_space, fd_count))
if not skip_pause : input('\nDone!')

View file

@ -1,101 +0,0 @@
#!/usr/bin/env python3
"""
Apple EFI Package
Apple EFI Package Extractor
Copyright (C) 2019 Plato Mavropoulos
"""
print('Apple EFI Package Extractor v1.1')
import os
import sys
import zlib
import shutil
import subprocess
if len(sys.argv) >= 2 :
pkg = sys.argv[1:]
else :
pkg = []
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, dirs, files in os.walk(in_path):
for name in files :
pkg.append(os.path.join(root, name))
anytoiso_path = 'C:\\Program Files (x86)\\AnyToISO\\anytoiso.exe'
final_path = os.path.join(os.getcwd(), 'AppleEFI')
if os.path.exists(final_path) : shutil.rmtree(final_path)
for input_file in pkg :
file_path = os.path.abspath(input_file)
file_name = os.path.basename(input_file)
file_dir = os.path.dirname(file_path)
file_ext = os.path.splitext(file_path)[1]
print('\nFile: %s\n' % file_name)
with open(input_file, 'rb') as in_buff : file_adler = zlib.adler32(in_buff.read()) & 0xFFFFFFFF
pkg_payload = os.path.join(final_path, '%s_%0.8X' % (file_name, file_adler))
pkg_temp = os.path.join(final_path, '__TEMP_%s_%0.8X' % (file_name, file_adler))
os.makedirs(pkg_temp)
subprocess.run([anytoiso_path, '/extract', file_path, pkg_temp], check = True, stdout=subprocess.DEVNULL)
if os.path.isfile(os.path.join(pkg_temp, 'Scripts')) :
scripts_init = os.path.join(pkg_temp, 'Scripts')
scripts_cpgz = os.path.join(pkg_temp, 'Scripts.cpgz')
scripts_extr = os.path.join(pkg_temp, 'Scripts', '')
efi_path = os.path.join(scripts_extr, 'Tools', 'EFIPayloads', '')
os.replace(scripts_init, scripts_cpgz)
subprocess.run([anytoiso_path, '/extract', scripts_cpgz, scripts_extr], check = True, stdout=subprocess.DEVNULL)
shutil.copytree(efi_path, pkg_payload)
elif os.path.isfile(os.path.join(pkg_temp, 'Payload')) :
payload_init = os.path.join(pkg_temp, 'Payload')
payload_pbzx = os.path.join(pkg_temp, 'Payload.pbzx')
payload_extr = os.path.join(pkg_temp, 'Payload', '')
zip_path = os.path.join(payload_extr, 'usr', 'standalone', 'firmware', 'bridgeOSCustomer.bundle', 'Contents', 'Resources', 'UpdateBundle')
efi_path = os.path.join(zip_path, 'boot', 'Firmware', 'MacEFI', '')
os.replace(payload_init, payload_pbzx)
subprocess.run([anytoiso_path, '/extract', payload_pbzx, payload_extr], check = True, stdout=subprocess.DEVNULL)
subprocess.run([anytoiso_path, '/extract', zip_path + '.zip', zip_path], check = True, stdout=subprocess.DEVNULL)
if os.path.exists(efi_path) : shutil.copytree(efi_path, pkg_payload)
shutil.rmtree(pkg_temp)
im4p_files = []
for root, dirs, files in os.walk(pkg_payload):
for name in files :
if name.endswith('.im4p') :
im4p_files.append(os.path.join(root, name))
if im4p_files : subprocess.run(['python', 'Apple_EFI_Split.py', '-skip', *im4p_files], check = True, stdout=subprocess.DEVNULL)
for im4p in im4p_files : os.remove(im4p)
final_files = []
for root, dirs, files in os.walk(pkg_payload):
for name in files :
final_files.append(os.path.join(root, name))
if final_files : subprocess.run(['python', 'Apple_EFI_Rename.py', '-skip', *final_files], check = True, stdout=subprocess.DEVNULL)
for root, dirs, files in os.walk(pkg_payload):
for name in files :
if not os.path.isfile(os.path.join(final_path, name)) :
shutil.copy2(os.path.join(root, name), os.path.join(final_path, name))
shutil.rmtree(pkg_payload)
else :
input('\nDone!')

View file

@ -1,4 +0,0 @@
2021-01-01 00:00:00

View file

@ -1,129 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Apple EFI Grab
Apple EFI Package Grabber
Copyright (C) 2018-2021 Plato Mavropoulos
"""
title = 'Apple EFI Package Grabber v2.0'
print('\n' + title)
import sys
sys_ver = sys.version_info
if sys_ver < (3,7):
sys.stdout.write('\n\nError: Python >= 3.7 required, not %d.%d!\n' % (sys_ver[0], sys_ver[1]))
(raw_input if sys_ver[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
import traceback
def show_exception_and_exit(exc_type, exc_value, tb):
if exc_type is KeyboardInterrupt:
print('\nNote: Keyboard Interrupt!')
else:
print('\nError: %s crashed, please report the following:\n' % title)
traceback.print_exception(exc_type, exc_value, tb)
input('\nPress enter to exit')
sys.exit(1)
sys.excepthook = show_exception_and_exit
import datetime
import urllib.request
from multiprocessing.pool import ThreadPool
def fetch_cat_info(name):
url = cat_url[:-len('others/')] + name if name in ['index.sucatalog','index-1.sucatalog'] else cat_url + name
with urllib.request.urlopen(urllib.request.Request(url, method='HEAD')) as head : mod = head.headers['last-modified']
return name, url, mod
def fetch_cat_links(cat_file):
cat_links = []
with urllib.request.urlopen(cat_file[1]) as link: fdata = link.readlines()
cat_lines = [l.decode('utf-8').strip('\n') for l in fdata]
for line in cat_lines:
if ('.pkg' in line or '.tar' in line) and ('FirmwareUpd' in line or '/BridgeOSUpdateCustomer' in line or 'EFIUpd' in line) \
and 'Bluetooth' not in line and 'DPVGA' not in line and 'Thunderbolt' not in line and 'PMG5' not in line and 'HardDrive' not in line:
down_link = line[line.find('http'):(line.find('.pkg') if '.pkg' in line else line.find('.tar')) + 4]
down_link = down_link.replace('http:','https:')
cat_links.append(down_link)
return cat_links
dat_db = 'Apple_EFI_Grab.dat'
cat_url = 'https://swscan.apple.com/content/catalogs/others/'
apple_cat = []
down_links = []
svr_date = None
thread_num = 2
with open(dat_db, 'r', encoding='utf-8') as dat: db_lines = dat.readlines()
db_lines = [line.strip('\n') for line in db_lines]
db_date = datetime.datetime.strptime(db_lines[0], '%Y-%m-%d %H:%M:%S')
db_links = set([line for line in db_lines if line.startswith('https')])
db_sucat = [line for line in db_lines if line.startswith('index')]
print('\nGetting Catalog Listing...')
if not db_sucat:
input('\nError: Failed to retrieve Catalogs from DB!\n\nDone!')
sys.exit(1)
apple_mod = ThreadPool(thread_num).imap_unordered(fetch_cat_info, db_sucat)
for name, url, mod in apple_mod:
dt = datetime.datetime.strptime(mod, '%a, %d %b %Y %H:%M:%S %Z')
if not svr_date or dt > svr_date : svr_date = dt
apple_cat.append((name, url, dt))
if not svr_date:
input('\nError: Failed to retrieve Current Catalog Datetime!\n\nDone!')
sys.exit(1)
print('\n Previous Catalog Datetime :', db_date)
print(' Current Catalog Datetime :', svr_date)
if svr_date <= db_date:
input('\nNothing new since %s!\n\nDone!' % db_date)
sys.exit()
print('\nGetting Catalog Links...')
down_links = ThreadPool(thread_num).imap_unordered(fetch_cat_links, apple_cat)
down_links = [item for sublist in down_links for item in sublist]
if not down_links:
input('\nError: Failed to retrieve Catalog Links!\n\nDone!')
sys.exit(1)
new_links = sorted(list(dict.fromkeys([link for link in down_links if link not in db_links])))
if new_links:
print('\nFound %d new link(s) between %s and %s!' % (len(new_links), db_date, svr_date))
cur_date = datetime.datetime.utcnow().isoformat(timespec='seconds').replace('-','').replace('T','').replace(':','') # Local UTC Unix
with open('Apple_%s.txt' % cur_date, 'w', encoding='utf-8') as lout: lout.write('\n'.join(map(str, new_links)))
else:
print('\nThere are no new links between %s and %s!' % (db_date, svr_date))
new_db_sucat = '\n'.join(map(str, db_sucat))
new_db_links = '\n'.join(map(str, sorted(list(dict.fromkeys(down_links)))))
new_db_lines = '%s\n\n%s\n\n%s' % (svr_date, new_db_sucat, new_db_links)
with open(dat_db, 'w', encoding='utf-8') as dbout: dbout.write(new_db_lines)
input('\nDone!')

View file

@ -1,65 +0,0 @@
#!/usr/bin/env python3
"""
Award BIOS Extract
Award BIOS Module Extractor
Copyright (C) 2018-2019 Plato Mavropoulos
http://www.onicos.com/staff/iz/formats/lzh.html
https://ist.uwaterloo.ca/~schepers/formats/LHA.TXT
https://sites.google.com/site/pinczakko/pinczakko-s-guide-to-award-bios-reverse-engineering
"""
print('Award BIOS Module Extractor v1.2\n')
import os
import re
import sys
import subprocess
if len(sys.argv) >= 2 :
# Drag & Drop or CLI
awd_images = sys.argv[1:]
else :
# Folder path
awd_images = []
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, dirs, files in os.walk(in_path):
for name in files :
awd_images.append(os.path.join(root, name))
pat_lzh = re.compile(br'\x2D\x6C((\x68(([\x30-\x37])|(\x64)))|(\x7A([\x34\x73])))\x2D') # All 11 LZH Method IDs (Award probably used LH0 and LH5 only)
# Create output folder
extr_path = os.path.join(os.getcwd(), 'AWD_Extracted')
if not os.path.exists(extr_path) : os.makedirs(extr_path)
for in_file in awd_images :
file_path = os.path.abspath(in_file)
file_name = os.path.basename(in_file)
file_dir = os.path.dirname(file_path)
file_ext = os.path.splitext(file_path)[1]
match_lzh_list = []
print('\nFile: %s%s' % (file_name, file_ext))
with open(in_file, 'rb') as awd_img : buffer = awd_img.read()
match_lzh_list += pat_lzh.finditer(buffer) # Detect LZH patterns
for match_lzh in match_lzh_list :
hdr_size = buffer[match_lzh.start() - 0x2] # From LZH Tag (0x2+)
comp_size = int.from_bytes(buffer[match_lzh.end():match_lzh.end() + 0x4], 'little') # From LZH Header end
mod_data = buffer[match_lzh.start() - 0x2:match_lzh.start() + hdr_size + comp_size]
with open('mod_temp.bin', 'wb') as lzh_img : lzh_img.write(mod_data)
try :
decomp = subprocess.run(['7z', 'x', '-aou', '-bso0', '-bse0', '-bsp0', '-o%s' % os.path.join(extr_path, file_name), 'mod_temp.bin']) # 7-Zip
except :
print('Error: Could not decompress LZH image at %s!' % file_name)
print(' Make sure that "7z" executable exists!\n')
os.remove('mod_temp.bin') # Remove temporary LZH image
input('\nDone!')

File diff suppressed because it is too large Load diff

View file

@ -1,82 +0,0 @@
#!/usr/bin/env python3
"""
Fujitsu SFX Extractor
Fujitsu SFX BIOS Extractor
Copyright (C) 2019-2021 Plato Mavropoulos
"""
print('Fujitsu SFX BIOS Extractor v2.1')
import os
import re
import sys
import subprocess
if len(sys.argv) >= 2 :
# Drag & Drop or CLI
fjsfx_exec = sys.argv[1:]
else :
# Folder path
fjsfx_exec = []
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, dirs, files in os.walk(in_path):
for name in files :
fjsfx_exec.append(os.path.join(root, name))
# "FjSfxBinay" + Microsoft CAB Header XOR 0xFF (Tag[4] + Res[4] + Size[4] + Res[4] + Offset[4] + Res[4] + Ver[2]) pattern
mscf_pattern = re.compile(br'\x46\x6A\x53\x66\x78\x42\x69\x6E\x61\x79\xB2\xAC\xBC\xB9\xFF{4}.{4}\xFF{4}.{4}\xFF{4}\xFC\xFE', re.DOTALL)
for input_file in fjsfx_exec :
file_path = os.path.abspath(input_file)
file_dir = os.path.dirname(file_path)
file_name = os.path.basename(file_path)
print('\nFile: ' + file_name)
# Open Fujitsu SFX Binary Packager executable as mutable bytearray
with open(input_file, 'rb') as in_file : FjSfx = bytearray(in_file.read())
match_mscf = mscf_pattern.search(FjSfx) # Search for Fujitsu Microsoft CAB Header XOR 0xFF pattern
# Check if Microsoft CAB Header XOR 0xFF pattern exists
if match_mscf :
print('\n Detected Obfuscation!')
mscf_start = match_mscf.start() + 0xA # Microsoft CAB Header XOR 0xFF starts after "FjSfxBinay" signature
# Determine the Microsoft CAB image Size
cab_size = int.from_bytes(FjSfx[mscf_start + 0x8:mscf_start + 0xC], 'little') # Get LE XOR-ed CAB Size
xor_size = int.from_bytes(b'\xFF' * 0x4, 'little') # Create CAB Size XOR value
cab_size = cab_size ^ xor_size # Perform XOR 0xFF and get actual CAB Size
print('\n Removing Obfuscation...')
# Determine the Microsoft CAB image Data
cab_data = int.from_bytes(FjSfx[mscf_start:mscf_start + cab_size], 'big') # Get BE XOR-ed CAB Data
xor_data = int.from_bytes(b'\xFF' * cab_size, 'big') # Create CAB Data XOR value
cab_data = (cab_data ^ xor_data).to_bytes(cab_size, 'big') # Perform XOR 0xFF and get actual CAB Data
print('\n Extracting...')
with open('fjsfx_temp.cab', 'wb') as cab_file : cab_file.write(cab_data) # Create temporary CAB image
extr_path = os.path.join(file_dir, file_name[:-4], '') # Create CAB image extraction path
try :
decomp = subprocess.run(['7z', 'x', '-aou', '-bso0', '-bse0', '-bsp0', '-o' + extr_path, 'fjsfx_temp.cab']) # 7-Zip
print('\n Extracted!')
except :
print('\n Error: Could not decompress Microsoft CAB image!')
print(' Make sure that "7z" executable exists!')
os.remove('fjsfx_temp.cab') # Remove temporary CAB image
else :
print('\n Error: This is not a Fujitsu SFX BIOS image!')
continue # Next input file
else :
input('\nDone!')

View file

@ -1,108 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Fujitsu UPC Extract
Fujitsu UPC BIOS Extractor
Copyright (C) 2021 Plato Mavropoulos
"""
title = 'Fujitsu UPC BIOS Extractor v1.0'
print('\n' + title) # Print script title
import sys
# Detect Python version
sys_ver = sys.version_info
if sys_ver < (3,7) :
sys.stdout.write('\n\nError: Python >= 3.7 required, not %d.%d!\n' % (sys_ver[0], sys_ver[1]))
(raw_input if sys_ver[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
import os
import ctypes
import argparse
import traceback
import subprocess
# Pause after any unexpected Python exception
# https://stackoverflow.com/a/781074 by Torsten Marek
def show_exception_and_exit(exc_type, exc_value, tb) :
if exc_type is KeyboardInterrupt :
print('\n')
else :
print('\nError: %s crashed, please report the following:\n' % title)
traceback.print_exception(exc_type, exc_value, tb)
input('\nPress enter to exit')
sys.exit(1)
# Set pause-able Python exception handler
sys.excepthook = show_exception_and_exit
# Set console/shell window title
user_os = sys.platform
if user_os == 'win32' : ctypes.windll.kernel32.SetConsoleTitleW(title)
elif user_os.startswith('linux') or user_os == 'darwin' or user_os.find('bsd') != -1 : sys.stdout.write('\x1b]2;' + title + '\x07')
# Set argparse Arguments
upc_parser = argparse.ArgumentParser()
upc_parser.add_argument('upc', type=argparse.FileType('r'), nargs='*')
upc_parser.add_argument('-p', '--path', help='parse files within given folder', type=str)
upc_params = upc_parser.parse_args()
# Get all files within path
def get_files(path) :
inputs = []
for root, _, files in os.walk(path):
for name in files :
inputs.append(os.path.join(root, name))
return inputs
if len(sys.argv) >= 2 :
if bool(upc_params.path) :
upc_exec = get_files(upc_params.path) # CLI with --path
else :
upc_exec = []
for executable in upc_params.upc :
upc_exec.append(executable.name) # Drag & Drop
else :
in_path = input('\nEnter the full folder path: ')
upc_exec = get_files(in_path) # Direct Run
# Process each input Fujitsu UPC BIOS image
for input_file in upc_exec :
input_name,input_extension = os.path.splitext(os.path.basename(input_file))
print('\n*** %s%s' % (input_name, input_extension))
# Check if input file exists
if not os.path.isfile(input_file) :
print('\n Error: This input file does not exist!')
continue # Next input file
with open(input_file, 'rb') as in_file : upc_data = in_file.read()
if input_extension.upper() != '.UPC' or int.from_bytes(upc_data[0x0:0x4], 'little') + 0x8 != len(upc_data) :
print('\n Error: This is not a Fujitsu UPC BIOS image!')
continue # Next input file
output_file = input_file[:-4] + '.bin' # Decompressed filename
# EFI/Tiano Decompression
try :
subprocess.run(['TianoCompress', '-d', input_file, '-o', output_file, '--uefi', '-q'], check = True, stdout = subprocess.DEVNULL)
if os.path.getsize(output_file) != int.from_bytes(upc_data[0x4:0x8], 'little') : raise Exception('EFI_DECOMP_ERROR')
except :
print('\n Error: Could not extract input file via TianoCompress!')
input(' Make sure that "TianoCompress" executable exists!')
print('\n Extracted Fujitsu UPC BIOS image!')
input('\nDone!')
sys.exit(0)

View file

@ -1,270 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Insyde iFlash Extract
Insyde iFlash Image Extractor
Copyright (C) 2022 Plato Mavropoulos
"""
title = 'Insyde iFlash Image Extractor v1.0'
import sys
# Detect Python version
sys_py = sys.version_info
# Check Python version
if sys_py < (3,7):
sys.stdout.write('%s\n\nError: Python >= 3.7 required, not %d.%d!\n' % (title, sys_py[0], sys_py[1]))
if '--auto-exit' not in sys.argv and '-e' not in sys.argv:
(raw_input if sys_py[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
# Detect OS platform
sys_os = sys.platform
# Check OS platform
if sys_os == 'win32':
sys.stdout.reconfigure(encoding='utf-8') # Fix Windows Unicode console redirection
elif sys_os.startswith('linux') or sys_os == 'darwin' or sys_os.find('bsd') != -1:
pass # Supported/Tested
else:
print('%s\n\nError: Unsupported platform "%s"!\n' % (title, sys_os))
if '--auto-exit' not in sys.argv and '-e' not in sys.argv: input('Press enter to exit')
sys.exit(1)
# Python imports
import os
import re
import ctypes
import inspect
import pathlib
import argparse
import traceback
# Set ctypes Structure types
char = ctypes.c_char
uint32_t = ctypes.c_uint
class IflashHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
('Signature', char*9), # 0x00 $_IFLASH_
('ImageTag', char*7), # 0x08
('TotalSize', uint32_t), # 0x10 from header end
('ImageSize', uint32_t), # 0x14 from header end
# 0x18
]
def ifl_print(self, padd):
p = ' ' * (padd - 1)
print(p, 'Signature : %s' % self.Signature.decode('utf-8','ignore'))
print(p, 'Image Name: %s' % self.ImageTag.decode('utf-8','ignore'))
print(p, 'Total Size: 0x%X' % self.TotalSize)
print(p, 'Image Size: 0x%X' % self.ImageSize)
class InsydeIflash:
def __init__(self, in_data, out_path, in_padd, in_verbose):
self.fw_data = in_data
self.ex_path = out_path
self.padding = in_padd
self.verbose = in_verbose
self.hdr_len = ctypes.sizeof(IflashHeader)
self.mod_names = {
'DRV_IMG':['isflash','efi'],
'INI_IMG':['platform','ini'],
'BIOSIMG':['BIOS','bin'],
'ME_IMG_':['ME','bin'],
'EC_IMG_':['EC','bin'],
'OEM_ID_':['OEM_ID','bin'],
'BIOSCER':['Certificate','bin'],
'BIOSCR2':['Certificate_2','bin'],
}
def iflash_parse(self):
all_ins_ifl = pat_ins_ifl.finditer(self.fw_data)
if not all_ins_ifl: return 1
if not os.path.isdir(self.ex_path): os.mkdir(self.ex_path)
for ins_ifl in all_ins_ifl:
ifl_off = ins_ifl.start()
ifl_hdr = get_struct(self.fw_data, ifl_off, IflashHeader)
if self.verbose:
print('\n%sInsyde iFlash Module @ 0x%0.8X\n' % (' ' * self.padding, ifl_off))
ifl_hdr.ifl_print(self.padding + 4)
mod_bgn = ifl_off + self.hdr_len
mod_end = mod_bgn + ifl_hdr.ImageSize
mod_bin = self.fw_data[mod_bgn:mod_end]
if not mod_bin: continue # Empty/Missing Module
mod_tag = ifl_hdr.ImageTag.decode('utf-8','ignore')
out_tag = self.mod_names[mod_tag][0] if mod_tag in self.mod_names else mod_tag
out_ext = self.mod_names[mod_tag][1] if mod_tag in self.mod_names else 'bin'
out_name = get_safe_name('%s [0x%0.8X-0x%0.8X].%s' % (out_tag, mod_bgn, mod_end, out_ext))
out_path = os.path.join(self.ex_path, out_name)
with open(out_path, 'wb') as out: out.write(mod_bin)
print('\n%sExtracted' % (' ' * (self.padding + 8 if self.verbose else self.padding)), out_name)
return 0
# Process ctypes Structure Classes
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
def get_struct(buffer, start_offset, class_name, param_list=None):
if param_list is None: param_list = []
structure = class_name(*param_list) # Unpack parameter list
struct_len = ctypes.sizeof(structure)
struct_data = buffer[start_offset:start_offset + struct_len]
fit_len = min(len(struct_data), struct_len)
ctypes.memmove(ctypes.addressof(structure), struct_data, fit_len)
return structure
# Get absolute file path (argparse object)
def get_absolute_path(argparse_path):
if not argparse_path:
absolute_path = get_script_dir() # Use input file directory if no user path is specified
else:
# Check if user specified path is absolute, otherwise convert it to input file relative
if pathlib.Path(argparse_path).is_absolute(): absolute_path = argparse_path
else: absolute_path = os.path.join(get_script_dir(), argparse_path)
return absolute_path
# Get list of files from absolute path
def get_path_files(abs_path):
file_list = [] # Initialize list of files
# Traverse input absolute path
for root,_,files in os.walk(abs_path):
file_list = [os.path.join(root, name) for name in files]
return file_list
# Fix illegal/reserved Windows characters
def get_safe_name(file_name):
raw_name = repr(file_name).strip("'")
return re.sub(r'[\\/*?:"<>|]', '_', raw_name)
# Get python script working directory
# https://stackoverflow.com/a/22881871 by jfs
def get_script_dir(follow_symlinks=True):
if getattr(sys, 'frozen', False):
path = os.path.abspath(sys.executable)
else:
path = inspect.getabsfile(get_script_dir)
if follow_symlinks:
path = os.path.realpath(path)
return os.path.dirname(path)
# Pause after any unexpected Python exception
# https://stackoverflow.com/a/781074 by Torsten Marek
def show_exception_and_exit(exc_type, exc_value, tb):
if exc_type is KeyboardInterrupt :
print('\n')
else:
print('\nError: %s crashed, please report the following:\n' % title)
traceback.print_exception(exc_type, exc_value, tb)
if not bool(args.auto_exit): input('\nPress enter to exit')
sys.exit(1) # Crash exceptions are critical
# Insyde iFlash Section Signature
pat_ins_ifl = re.compile(br'\$_IFLASH_')
if __name__ == '__main__':
# Show script title
print('\n' + title)
# Set console/shell window title
user_os = sys.platform
if user_os == 'win32': ctypes.windll.kernel32.SetConsoleTitleW(title)
elif user_os.startswith('linux') or user_os == 'darwin' or user_os.find('bsd') != -1: sys.stdout.write('\x1b]2;' + title + '\x07')
# Set argparse Arguments
parser = argparse.ArgumentParser()
parser.add_argument('images', type=argparse.FileType('r'), nargs='*')
parser.add_argument('-v', '--verbose', help='show iFlash structure information', action='store_true')
parser.add_argument('-e', '--auto-exit', help='skip press enter to exit prompts', action='store_true')
parser.add_argument('-o', '--output-dir', help='extract in given output directory')
parser.add_argument('-i', '--input-dir', help='extract from given input directory')
args = parser.parse_args()
# Set pause-able Python exception handler (must be after args)
sys.excepthook = show_exception_and_exit
# Initialize Dell PFS input file list
iflash_input_images = []
# Process input files
if len(sys.argv) >= 2:
# Drag & Drop or CLI
if args.input_dir:
input_path_user = get_absolute_path(args.input_dir)
iflash_input_images = get_path_files(input_path_user)
else:
iflash_input_images = [image.name for image in args.images]
output_path_user = get_absolute_path(args.output_dir or args.input_dir)
else:
# Script w/o parameters
input_path_user = get_absolute_path(input('\nEnter input directory path: '))
iflash_input_images = get_path_files(input_path_user)
output_path_user = get_absolute_path(input('\nEnter output directory path: '))
# Initialize global variables
exit_code = len(iflash_input_images) # Initialize exit code with input file count
is_verbose = bool(args.verbose) # Set Verbose output mode optional argument
for input_file in iflash_input_images:
input_name = os.path.basename(input_file)
input_padd = 8
print('\n*** %s' % input_name)
# Check if input file exists
if not os.path.isfile(input_file):
print('\n%sError: This input file does not exist!' % (' ' * input_padd))
continue # Next input file
with open(input_file, 'rb') as in_file: input_data = in_file.read()
# Search input image for Insyde iFlash Sections
is_ins_ifl = pat_ins_ifl.search(input_data)
if not is_ins_ifl:
print('\n%sError: This is not an Insyde iFlash image!' % (' ' * input_padd))
continue # Next input file
# Set main extraction path (optional user specified path taken into account)
output_path = os.path.join(output_path_user, input_name + '_extracted')
InsydeIflash(input_data, output_path, input_padd, is_verbose).iflash_parse()
exit_code -= 1 # Adjust exit code to reflect extraction progress
if not bool(args.auto_exit): input('\nDone!')
sys.exit(exit_code)

View file

@ -1,74 +0,0 @@
#!/usr/bin/env python3
"""
Panasonic BIOS Extract
Panasonic BIOS Update Extractor
Copyright (C) 2018 Plato Mavropoulos
"""
print('Panasonic BIOS Update Extractor v1.0')
import os
import sys
import shutil
import pefile
import subprocess
if len(sys.argv) >= 2 :
# Drag & Drop or CLI
panasonic = sys.argv[1:]
else :
# Folder path
panasonic = []
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, dirs, files in os.walk(in_path):
for name in files :
panasonic.append(os.path.join(root, name))
for input_file in panasonic :
file_path = os.path.abspath(input_file)
file_name = os.path.basename(input_file)
file_dir = os.path.dirname(file_path)
file_ext = os.path.splitext(file_path)[1]
# Create output folder
extr_path = os.path.join(os.getcwd(), 'RCDATA')
if os.path.exists(extr_path) : shutil.rmtree(extr_path)
os.makedirs(extr_path)
max_size = 0
max_file = None
pe = pefile.PE(input_file) # Analyze Portable Executable (PE)
for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries :
# Parse Resource Data directories only
if entry.struct.name == 'IMAGE_RESOURCE_DIRECTORY_ENTRY' and entry.struct.Id == 10 : # RCDATA ID = 10
for resource in entry.directory.entries :
offset = resource.directory.entries[0].data.struct.OffsetToData
size = resource.directory.entries[0].data.struct.Size
data = pe.get_data(offset, size)
file = os.path.join(extr_path, '%X_%X.bin' % (offset, size))
with open(file, 'wb') as out_file : out_file.write(data)
# Remember largest resource (SPI/BIOS)
if size > max_size :
max_size = size
max_file = file
if not max_file :
print('\nError: No Panasonic BIOS Update at %s!' % file_name)
shutil.rmtree(extr_path) # Remove temporary folder
continue # Next input file
# Call Rustam Abdullaev's unpack_lznt1 to extract the LZNT1-compressed SPI/BIOS resource at 0x8 onwards
try :
subprocess.run(['unpack_lznt1', max_file, os.path.join(file_dir, file_name[:-4] + '.bin'), '8'], check = True, stdout = subprocess.DEVNULL)
print('\nExtracted %s via unpack_lznt1' % (file_name[:-4] + '.bin'))
except :
print('\nError: Could not extract %s via unpack_lznt1!' % (file_name[:-4] + '.bin'))
print(' Make sure that "unpack_lznt1.exe" executable exists!')
shutil.rmtree(extr_path) # Remove temporary folder
else :
input('\nDone!')

View file

@ -1,213 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Phoenix SCT Extract
Phoenix SCT BIOS Extractor
Copyright (C) 2021 Plato Mavropoulos
"""
title = 'Phoenix SCT BIOS Extractor v1.0'
print('\n' + title) # Print script title
import sys
# Detect Python version
sys_ver = sys.version_info
if sys_ver < (3,7) :
sys.stdout.write('\n\nError: Python >= 3.7 required, not %d.%d!\n' % (sys_ver[0], sys_ver[1]))
(raw_input if sys_ver[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
import os
import re
import lzma
import shutil
import ctypes
import argparse
import traceback
# Pause after any unexpected Python exception
# https://stackoverflow.com/a/781074 by Torsten Marek
def show_exception_and_exit(exc_type, exc_value, tb) :
if exc_type is KeyboardInterrupt :
print('\n')
else :
print('\nError: %s crashed, please report the following:\n' % title)
traceback.print_exception(exc_type, exc_value, tb)
input('\nPress enter to exit')
sys.exit(1)
# Set pause-able Python exception handler
sys.excepthook = show_exception_and_exit
# Set console/shell window title
user_os = sys.platform
if user_os == 'win32' : ctypes.windll.kernel32.SetConsoleTitleW(title)
elif user_os.startswith('linux') or user_os == 'darwin' or user_os.find('bsd') != -1 : sys.stdout.write('\x1b]2;' + title + '\x07')
# Set argparse Arguments
sct_parser = argparse.ArgumentParser()
sct_parser.add_argument('executables', type=argparse.FileType('r'), nargs='*')
sct_parser.add_argument('-p', '--path', help='parse files within given folder', type=str)
sct_params = sct_parser.parse_args()
# Get all files within path
def get_files(path) :
inputs = []
for root, _, files in os.walk(path):
for name in files :
inputs.append(os.path.join(root, name))
return inputs
if len(sys.argv) >= 2 :
if bool(sct_params.path) :
sct_exec = get_files(sct_params.path) # CLI with --path
else :
sct_exec = []
for executable in sct_params.executables :
sct_exec.append(executable.name) # Drag & Drop
else :
in_path = input('\nEnter the full folder path: ')
sct_exec = get_files(in_path) # Direct Run
# Set ctypes Structure types
char = ctypes.c_char
uint8_t = ctypes.c_ubyte
uint16_t = ctypes.c_ushort
uint32_t = ctypes.c_uint
uint64_t = ctypes.c_uint64
class SCT_HDR(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('Tag', char*8), # 0x00
('Size', uint32_t), # 0x08
('Count', uint32_t), # 0x0C
# 0x10
]
def sct_print(self) :
print('\n Phoenix SCT Header:\n')
print(' Tag : %s' % self.Tag.decode('utf-8','replace').strip())
print(' Size : 0x%X' % self.Size)
print(' Count : %d' % self.Count)
class SCT_MOD(ctypes.LittleEndianStructure) :
_pack_ = 1
_fields_ = [
('Name', char*256), # 0x000
('Offset', uint32_t), # 0x100
('Size', uint32_t), # 0x104
('Compressed', uint32_t), # 0x108
('Reserved', uint32_t), # 0x10C
# 0x110
]
def sct_print(self) :
print('\n Phoenix SCT Entry:\n')
print(' Name : %s' % self.Name.decode('utf-8','replace').strip())
print(' Offset : 0x%X' % self.Offset)
print(' Size : 0x%X' % self.Size)
print(' Compressed : %s' % ['No','Yes'][self.Compressed])
print(' Reserved : 0x%X' % self.Reserved)
# Process ctypes Structure Classes
# https://github.com/skochinsky/me-tools/blob/master/me_unpack.py by Igor Skochinsky
def get_struct(buffer, start_offset, class_name, param_list = None) :
if param_list is None : param_list = []
structure = class_name(*param_list) # Unpack parameter list
struct_len = ctypes.sizeof(structure)
struct_data = buffer[start_offset:start_offset + struct_len]
fit_len = min(len(struct_data), struct_len)
if (start_offset >= len(buffer)) or (fit_len < struct_len) :
print('\n Error: Offset 0x%X out of bounds at %s, possibly incomplete image!' % (start_offset, class_name.__name__))
input('\n Press enter to exit')
sys.exit(1)
ctypes.memmove(ctypes.addressof(structure), struct_data, fit_len)
return structure
# Phoenix SCT BIOS Package Pattern ($PACK + Size + Count)
sct_pat = re.compile(br'\x24\x50\x41\x43\x4B\x00{3}..\x00{2}.\x00{3}', re.DOTALL)
# Get common ctypes Structure Sizes
sct_hdr_len = ctypes.sizeof(SCT_HDR)
sct_mod_len = ctypes.sizeof(SCT_MOD)
# Size of dummy/placeholder SCT Entries
sct_dummy_len = 0x200 # Top 2, Names only
# Process each input Phoenix SCT BIOS executable
for input_file in sct_exec :
input_name,input_extension = os.path.splitext(os.path.basename(input_file))
input_dir = os.path.dirname(os.path.abspath(input_file))
print('\n*** %s%s' % (input_name, input_extension))
# Check if input file exists
if not os.path.isfile(input_file) :
print('\n Error: This input file does not exist!')
continue # Next input file
with open(input_file, 'rb') as in_file : input_data = in_file.read()
sct_match = sct_pat.search(input_data) # Search for Phoenix SCT BIOS Pattern
# Check if Phoenix SCT BIOS Pattern was found on executable
if not sct_match :
print('\n Error: This is not a Phoenix SCT BIOS executable!')
continue # Next input file
output_path = os.path.join(input_dir, '%s%s' % (input_name, input_extension) + '_extracted') # Set extraction directory
if os.path.isdir(output_path) : shutil.rmtree(output_path) # Delete any existing extraction directory
os.mkdir(output_path) # Create extraction directory
print('\n Phoenix SecureCore Technology')
sct_hdr = get_struct(input_data, sct_match.start(), SCT_HDR) # Parse SCT Header Structure
sct_hdr.sct_print() # Print SCT Header Info
# Check if reported SCT Header Size matches manual SCT Entry Count calculation
if sct_hdr.Size != sct_hdr_len + sct_dummy_len + sct_hdr.Count * sct_mod_len :
input('\n Error: This Phoenix SCT BIOS image is corrupted!')
continue # Next input file
# Store all SCT $PACK Data w/o initial dummy/placeholder Entries
pack_data = input_data[sct_match.end() + sct_dummy_len:sct_match.start() + sct_hdr.Size]
# Parse each SCT Entry
for e_idx in range(sct_hdr.Count) :
mod_hdr = get_struct(pack_data, e_idx * sct_mod_len, SCT_MOD) # Parse SCT Entry Structure
mod_hdr.sct_print() # Print SCT Entry Info
mod_data = input_data[mod_hdr.Offset:mod_hdr.Offset + mod_hdr.Size] # Store SCT Entry Raw Data
# Check if SCT Entry Raw Data is complete
if len(mod_data) != mod_hdr.Size :
input('\n Error: This Phoenix SCT BIOS image is incomplete!')
# Store SCT Entry LZMA Decompressed Data, when applicable
if mod_hdr.Compressed : mod_data = lzma.LZMADecompressor().decompress(mod_data)
# Replace common Windows reserved/illegal filename characters
mod_fname = re.sub(r'[\\/*?:"<>|]', '_', mod_hdr.Name.decode('utf-8','replace').strip())
with open(os.path.join(output_path, mod_fname), 'wb') as out : out.write(mod_data) # Store SCT Entry Data/File
print('\n Extracted Phoenix SCT BIOS executable!')
input('\nDone!')
sys.exit(0)

View file

@ -1,174 +0,0 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Portwell EFI Extract
Portwell EFI BIOS Extractor
Copyright (C) 2021 Plato Mavropoulos
"""
title = 'Portwell EFI BIOS Extractor v1.0'
print('\n' + title) # Print script title
import sys
# Detect Python version
sys_ver = sys.version_info
if sys_ver < (3,7) :
sys.stdout.write('\n\nError: Python >= 3.7 required, not %d.%d!\n' % (sys_ver[0], sys_ver[1]))
(raw_input if sys_ver[0] <= 2 else input)('\nPress enter to exit') # pylint: disable=E0602
sys.exit(1)
import os
import pefile
import shutil
import ctypes
import argparse
import traceback
import subprocess
# Pause after any unexpected Python exception
# https://stackoverflow.com/a/781074 by Torsten Marek
def show_exception_and_exit(exc_type, exc_value, tb) :
if exc_type is KeyboardInterrupt :
print('\n')
else :
print('\nError: %s crashed, please report the following:\n' % title)
traceback.print_exception(exc_type, exc_value, tb)
input('\nPress enter to exit')
sys.exit(1)
# Set pause-able Python exception handler
sys.excepthook = show_exception_and_exit
# Set console/shell window title
user_os = sys.platform
if user_os == 'win32' : ctypes.windll.kernel32.SetConsoleTitleW(title)
elif user_os.startswith('linux') or user_os == 'darwin' or user_os.find('bsd') != -1 : sys.stdout.write('\x1b]2;' + title + '\x07')
# Set argparse Arguments
efi_parser = argparse.ArgumentParser()
efi_parser.add_argument('efi', type=argparse.FileType('r'), nargs='*')
efi_parser.add_argument('-p', '--path', help='parse files within given folder', type=str)
efi_params = efi_parser.parse_args()
# Get all files within path
def get_files(path) :
inputs = []
for root, _, files in os.walk(path):
for name in files :
inputs.append(os.path.join(root, name))
return inputs
if len(sys.argv) >= 2 :
if bool(efi_params.path) :
efi_exec = get_files(efi_params.path) # CLI with --path
else :
efi_exec = []
for executable in efi_params.efi :
efi_exec.append(executable.name) # Drag & Drop
else :
in_path = input('\nEnter the full folder path: ')
efi_exec = get_files(in_path) # Direct Run
# Portwell UEFI Unpacker File Names (v1.1 - v1.2)
file_names = {0 : 'Flash.efi', 1 : 'Fparts.txt', 2 : 'Update.nsh', 3 : 'Temp.bin', 4 : 'SaveDmiData.efi'}
# Process each input Portwell EFI Update Package
for input_file in efi_exec :
input_name,input_extension = os.path.splitext(os.path.basename(input_file))
input_dir = os.path.dirname(os.path.abspath(input_file))
print('\n*** %s%s' % (input_name, input_extension))
# Check if input file exists
if not os.path.isfile(input_file) :
print('\n Error: This input file does not exist!')
continue # Next input file
with open(input_file, 'rb') as in_file : input_data = in_file.read()
try :
assert input_data[0x0:0x2] == b'\x4D\x5A' # EFI images start with DOS Header MZ
pe = pefile.PE(input_file, fast_load=True) # Analyze EFI Portable Executable (PE)
payload_data = input_data[pe.OPTIONAL_HEADER.SizeOfImage:] # Skip EFI executable (pylint: disable=E1101)
assert payload_data[0x0:0x4] == b'\x3C\x55\x55\x3E' # Portwell EFI files start with <UU>
except :
print('\n Error: This is not a Portwell EFI Update Package!')
continue # Next input file
output_path = os.path.join(input_dir, '%s%s' % (input_name, input_extension) + '_extracted') # Set extraction directory
if os.path.isdir(output_path) : shutil.rmtree(output_path) # Delete any existing extraction directory
os.mkdir(output_path) # Create extraction directory
pack_tag = 'UEFI Unpacker' # Initialize Portwell UEFI Unpacker tag
# Get Portwell UEFI Unpacker tag
for s in pe.sections :
if s.Name.startswith(b'.data') : # Unpacker Tag, Version, Strings etc are found in .data PE section
# Decode any valid UTF-16 .data PE section info to a parsable text buffer
info = input_data[s.PointerToRawData:s.PointerToRawData + s.SizeOfRawData].decode('utf-16','ignore')
# Search .data for UEFI Unpacker tag
pack_tag_off = info.find('UEFI Unpacker')
if pack_tag_off != -1 :
pack_tag_len = info[pack_tag_off:].find('=')
if pack_tag_len != -1 :
# Found full UEFI Unpacker tag, store and slightly beautify the resulting text
pack_tag = info[pack_tag_off:pack_tag_off + pack_tag_len].strip().replace(' ',' ').replace('<',' <')
break # Found PE .data section, skip the rest
print('\n Portwell %s' % pack_tag) # Print Portwell UEFI Unpacker tag
efi_files = payload_data.split(b'\x3C\x55\x55\x3E')[1:] # Split EFI Payload into <UU> file chunks
# Parse each EFI Payload File
for i in range(len(efi_files)) :
file_data = efi_files[i] # Store EFI File data
if len(file_data) == 0 or file_data == b'NULL' : continue # Skip empty/unused files
is_known = i in file_names # Check if EFI file is known & Store result
file_name = file_names[i] if is_known else 'Unknown_%d.bin' % i # Assign Name to EFI file
print('\n %s' % file_name) # Print EFI file name, indicate progress
if not is_known : input('\n Note: Detected unknown Portwell EFI file with ID %d!' % i) # Report new EFI files
file_path = os.path.join(output_path, file_name) # Store EFI file output path
with open(file_path, 'wb') as o : o.write(file_data) # Store EFI file data to drive
# Attempt to detect EFI/Tiano Compression & Decompress when applicable
if int.from_bytes(file_data[0x0:0x4], 'little') + 0x8 == len(file_data) :
try :
comp_fname = file_path + '.temp' # Store temporary compressed file name
os.replace(file_path, comp_fname) # Rename initial/compressed file
subprocess.run(['TianoCompress', '-d', comp_fname, '-o', file_path, '--uefi', '-q'], check = True, stdout = subprocess.DEVNULL)
if os.path.getsize(file_path) != int.from_bytes(file_data[0x4:0x8], 'little') : raise Exception('EFI_DECOMP_ERROR')
os.remove(comp_fname) # Successful decompression, delete initial/compressed file
except :
print('\n Error: Could not extract file %s via TianoCompress!' % file_name)
input(' Make sure that "TianoCompress" executable exists!')
print('\n Extracted Portwell EFI Update Package!')
input('\nDone!')
sys.exit(0)

View file

@ -1,126 +0,0 @@
#!/usr/bin/env python3
"""
VAIO Package Extractor
VAIO Packaging Manager Extractor
Copyright (C) 2019-2020 Plato Mavropoulos
"""
print('VAIO Packaging Manager Extractor v2.0')
import os
import re
import sys
import subprocess
if len(sys.argv) >= 2 :
# Drag & Drop or CLI
vaio_exec = sys.argv[1:]
else :
# Folder path
vaio_exec = []
in_path = input('\nEnter the full folder path: ')
print('\nWorking...')
for root, dirs, files in os.walk(in_path):
for name in files :
vaio_exec.append(os.path.join(root, name))
# Microsoft CAB Header XOR 0xFF (Tag[4] + Res[4] + Size[4] + Res[4] + Offset[4] + Res[4] + Ver[2]) pattern
mscf_pattern = re.compile(br'\xB2\xAC\xBC\xB9\xFF{4}.{4}\xFF{4}.{4}\xFF{4}\xFC\xFE', re.DOTALL)
# VAIO Packaging Manager Configuration file ("[Setting]" + Windows_new_line) pattern
vaio_pattern = re.compile(br'\x5B\x53\x65\x74\x74\x69\x6E\x67\x5D\x0D\x0A')
# VAIO Packaging Manager Configuration file entry "UseVAIOCheck" pattern
check_pattern = re.compile(br'\x0A\x55\x73\x65\x56\x41\x49\x4F\x43\x68\x65\x63\x6B\x3D')
# VAIO Packaging Manager Configuration file entry "ExtractPathByUser" pattern
path_pattern = re.compile(br'\x0A\x45\x78\x74\x72\x61\x63\x74\x50\x61\x74\x68\x42\x79\x55\x73\x65\x72\x3D')
for input_file in vaio_exec :
file_path = os.path.abspath(input_file)
file_dir = os.path.dirname(file_path)
file_name = os.path.basename(file_path)
print('\nFile: ' + file_name)
# Open Locked VAIO Packaging Manager executable as mutable bytearray
with open(input_file, 'rb') as in_file : vaio_data = bytearray(in_file.read())
match_mscf = mscf_pattern.search(vaio_data) # Search for Microsoft CAB Header XOR 0xFF pattern
match_vaio = vaio_pattern.search(vaio_data) if not match_mscf else None # Search for VAIO Packaging Manager Configuration file
# Check if Microsoft CAB Header XOR 0xFF pattern exists
if match_mscf :
print('\n Detected Obfuscation!')
# Determine the Microsoft CAB image Size
cab_size = int.from_bytes(vaio_data[match_mscf.start() + 0x8:match_mscf.start() + 0xC], 'little') # Get LE XOR-ed CAB Size
xor_size = int.from_bytes(b'\xFF' * 0x4, 'little') # Create CAB Size XOR value
cab_size = cab_size ^ xor_size # Perform XOR 0xFF and get actual CAB Size
print('\n Removing Obfuscation...')
# Determine the Microsoft CAB image Data
cab_data = int.from_bytes(vaio_data[match_mscf.start():match_mscf.start() + cab_size], 'big') # Get BE XOR-ed CAB Data
xor_data = int.from_bytes(b'\xFF' * cab_size, 'big') # Create CAB Data XOR value
cab_data = (cab_data ^ xor_data).to_bytes(cab_size, 'big') # Perform XOR 0xFF and get actual CAB Data
print('\n Extracting...')
with open('vaio_temp.cab', 'wb') as cab_file : cab_file.write(cab_data) # Create temporary CAB image
extr_path = os.path.join(file_dir, file_name[:-4], '') # Create CAB image extraction path
try :
decomp = subprocess.run(['7z', 'x', '-aou', '-bso0', '-bse0', '-bsp0', '-o' + extr_path, 'vaio_temp.cab']) # 7-Zip
print('\n Extracted!')
except :
print('\n Error: Could not decompress Microsoft CAB image!')
print(' Make sure that "7z" executable exists!')
os.remove('vaio_temp.cab') # Remove temporary CAB image
# Check if VAIO Packaging Manager Configuration file pattern exists
elif match_vaio :
print('\n Error: Failed to Extract, attempting to Unlock instead...')
# Initialize VAIO Package Configuration file variables (assume overkill size of 0x500)
info_start, info_end, val_false, val_true = [match_vaio.start(), match_vaio.start() + 0x500, b'', b'']
# Get VAIO Package Configuration file info, split at new_line and stop at payload DOS header (EOF)
vaio_info = vaio_data[info_start:info_end].split(b'\x0D\x0A\x4D\x5A')[0].replace(b'\x0D',b'').split(b'\x0A')
# Determine VAIO Package Configuration file True & False values
for info in vaio_info :
if info.startswith(b'ExtractPathByUser=') : val_false = bytearray(b'0' if info[18:] in (b'0',b'1') else info[18:]) # Should be 0/No/False
if info.startswith(b'UseCompression=') : val_true = bytearray(b'1' if info[15:] in (b'0',b'1') else info[15:]) # Should be 1/Yes/True
else :
if val_false == val_true or not val_false or not val_true :
print('\n Error: Could not determine True/False values!')
print(' Please report this VAIO Packaging Manager!')
continue # Next input file
# Find and replace UseVAIOCheck entry from 1/Yes/True to 0/No/False
UseVAIOCheck = check_pattern.search(vaio_data[info_start:])
if UseVAIOCheck : vaio_data[info_start + UseVAIOCheck.end():info_start + UseVAIOCheck.end() + len(val_false)] = val_false
else : print('\n Error: Could not find UseVAIOCheck entry!')
# Find and replace ExtractPathByUser entry from 0/No/False to 1/Yes/True
ExtractPathByUser = path_pattern.search(vaio_data[info_start:])
if ExtractPathByUser : vaio_data[info_start + ExtractPathByUser.end():info_start + ExtractPathByUser.end() + len(val_false)] = val_true
else : print('\n Error: Could not find ExtractPathByUser entry!')
# Store Unlocked VAIO Packaging Manager executable
if UseVAIOCheck and ExtractPathByUser :
with open(os.path.join(file_dir, file_name + '_Unlocked.exe'), 'wb') as unl_file : unl_file.write(vaio_data)
print('\n Unlocked!')
else :
print('\n Error: No VAIO Packaging Manager found!')
continue # Next input file
else :
input('\nDone!')