From fddd33aafdaf17432c3ac1daf6505d9aa777b557 Mon Sep 17 00:00:00 2001 From: platomav Date: Thu, 2 Jun 2022 02:14:39 +0300 Subject: [PATCH] Added VAIO Packaging Manager Extractor v3.0_a4 Sort README utilities based on name --- README.md | 85 ++++++++++++++++---- VAIO_Package_Extract.py | 167 ++++++++++++++++++++++++++++++++++++++++ common/patterns.py | 2 +- 3 files changed, 237 insertions(+), 17 deletions(-) create mode 100644 VAIO_Package_Extract.py diff --git a/README.md b/README.md index 0f6aa71..14ea101 100644 --- a/README.md +++ b/README.md @@ -5,31 +5,32 @@ BIOS Utilities Donation via Paypal or Debit/Credit Card -* [**Dell PFS Update Extractor**](#dell-pfs-update-extractor) -* [**AMI UCP Update Extractor**](#ami-ucp-update-extractor) * [**AMI BIOS Guard Extractor**](#ami-bios-guard-extractor) +* [**AMI UCP Update Extractor**](#ami-ucp-update-extractor) +* [**Dell PFS Update Extractor**](#dell-pfs-update-extractor) * [**Phoenix TDK Packer Extractor**](#phoenix-tdk-packer-extractor) * [**Portwell EFI Update Extractor**](#portwell-efi-update-extractor) +* [**VAIO Packaging Manager Extractor**](#vaio-packaging-manager-extractor) -## **Dell PFS Update Extractor** +## **AMI BIOS Guard Extractor** ![]() #### **Description** -Parses Dell PFS Update images and extracts their Firmware (e.g. SPI, BIOS/UEFI, EC, ME etc) and Utilities (e.g. Flasher etc) component sections. It supports all Dell PFS revisions and formats, including those which are originally LZMA compressed in ThinOS packages, ZLIB compressed or Intel BIOS Guard (PFAT) protected. The output comprises only final firmware components which are directly usable by end users. +Parses AMI BIOS Guard (a.k.a. PFAT, Platform Firmware Armoring Technology) images, extracts their SPI/BIOS/UEFI firmware components and decompiles the Intel BIOS Guard Scripts. It supports all AMI PFAT revisions and formats, including those with Index Information tables or nested AMI PFAT structures. The output comprises only final firmware components which are directly usable by end users. + +Note that the AMI PFAT structure may not have an explicit component order. AMI's BIOS Guard Firmware Update Tool (AFUBGT) updates components based on the user/OEM provided Parameters and Options or Index Information table, when applicable. That means that merging all the components together does not usually yield a proper SPI/BIOS/UEFI image. The utility does generate such a merged file with the name "00 -- \\_ALL.bin" but it is up to the end user to determine its usefulness. Moreover, any custom OEM data after the AMI PFAT structure are additionally stored in the last file with the name "\ -- \_OOB.bin" and it is once again up to the end user to determine its usefulness. In cases where the trailing custom OEM data include a nested AMI PFAT structure, the utility will process and extract it automatically as well. #### **Usage** -You can either Drag & Drop or manually enter Dell PFS Update images(s). Optional arguments: +You can either Drag & Drop or manually enter AMI BIOS Guard (PFAT) image file(s). Optional arguments: * -h or --help : show help message and exit * -v or --version : show utility name and version * -i or --input-dir : extract from given input directory * -o or --output-dir : extract in given output directory * -e or --auto-exit : skip press enter to exit prompts -* -a or --advanced : extract signatures and metadata -* -s or --structure : show PFS structure information #### **Compatibility** @@ -37,7 +38,7 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -Optionally, to decompile the Intel BIOS Guard (PFAT) Scripts, you must have the following 3rd party utility at the "external" project directory: +Optionally, to decompile the AMI PFAT \> Intel BIOS Guard Scripts, you must have the following 3rd party utility at the "external" project directory: * [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py) @@ -59,7 +60,7 @@ PyInstaller can build/freeze/compile the utility at all three supported platform 4. Build/Freeze/Compile: -> pyinstaller --add-data="external/*;external/" --noupx --onefile \\/Dell_PFS_Extract.py +> pyinstaller --add-data="external/*;external/" --noupx --onefile \\/AMI_PFAT_Extract.py You should find the final utility executable at "dist" folder @@ -137,25 +138,25 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con ![]() -## **AMI BIOS Guard Extractor** +## **Dell PFS Update Extractor** ![]() #### **Description** -Parses AMI BIOS Guard (a.k.a. PFAT, Platform Firmware Armoring Technology) images, extracts their SPI/BIOS/UEFI firmware components and decompiles the Intel BIOS Guard Scripts. It supports all AMI PFAT revisions and formats, including those with Index Information tables or nested AMI PFAT structures. The output comprises only final firmware components which are directly usable by end users. - -Note that the AMI PFAT structure may not have an explicit component order. AMI's BIOS Guard Firmware Update Tool (AFUBGT) updates components based on the user/OEM provided Parameters and Options or Index Information table, when applicable. That means that merging all the components together does not usually yield a proper SPI/BIOS/UEFI image. The utility does generate such a merged file with the name "00 -- \\_ALL.bin" but it is up to the end user to determine its usefulness. Moreover, any custom OEM data after the AMI PFAT structure are additionally stored in the last file with the name "\ -- \_OOB.bin" and it is once again up to the end user to determine its usefulness. In cases where the trailing custom OEM data include a nested AMI PFAT structure, the utility will process and extract it automatically as well. +Parses Dell PFS Update images and extracts their Firmware (e.g. SPI, BIOS/UEFI, EC, ME etc) and Utilities (e.g. Flasher etc) component sections. It supports all Dell PFS revisions and formats, including those which are originally LZMA compressed in ThinOS packages, ZLIB compressed or Intel BIOS Guard (PFAT) protected. The output comprises only final firmware components which are directly usable by end users. #### **Usage** -You can either Drag & Drop or manually enter AMI BIOS Guard (PFAT) image file(s). Optional arguments: +You can either Drag & Drop or manually enter Dell PFS Update images(s). Optional arguments: * -h or --help : show help message and exit * -v or --version : show utility name and version * -i or --input-dir : extract from given input directory * -o or --output-dir : extract in given output directory * -e or --auto-exit : skip press enter to exit prompts +* -a or --advanced : extract signatures and metadata +* -s or --structure : show PFS structure information #### **Compatibility** @@ -163,7 +164,7 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3 #### **Prerequisites** -Optionally, to decompile the AMI PFAT \> Intel BIOS Guard Scripts, you must have the following 3rd party utility at the "external" project directory: +Optionally, to decompile the Intel BIOS Guard (PFAT) Scripts, you must have the following 3rd party utility at the "external" project directory: * [BIOS Guard Script Tool](https://github.com/platomav/BGScriptTool) (i.e. big_script_tool.py) @@ -185,7 +186,7 @@ PyInstaller can build/freeze/compile the utility at all three supported platform 4. Build/Freeze/Compile: -> pyinstaller --add-data="external/*;external/" --noupx --onefile \\/AMI_PFAT_Extract.py +> pyinstaller --add-data="external/*;external/" --noupx --onefile \\/Dell_PFS_Extract.py You should find the final utility executable at "dist" folder @@ -323,5 +324,57 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con ![]() +## **VAIO Packaging Manager Extractor** + +![]() + +#### **Description** + +Parses VAIO Packaging Manager executables and extracts their firmware (e.g. SPI, BIOS/UEFI, EC, ME etc), utilities (e.g. WBFLASH etc) and driver (audio, video etc) components. If direct extraction fails, it attempts to unlock the executable in order to run at all non-VAIO systems and allow the user to choose the extraction location. It supports all VAIO Packaging Manager revisions and formats, including those which contain obfuscated Microsoft CAB archives or obfuscated unlock values. The output comprises only final firmware components which are directly usable by end users. + +#### **Usage** + +You can either Drag & Drop or manually enter VAIO Packaging Manager executable file(s). Optional arguments: + +* -h or --help : show help message and exit +* -v or --version : show utility name and version +* -i or --input-dir : extract from given input directory +* -o or --output-dir : extract in given output directory +* -e or --auto-exit : skip press enter to exit prompts + +#### **Compatibility** + +Should work at all Windows, Linux or macOS operating systems which have Python 3.8 support. + +#### **Prerequisites** + +To run the utility, you do not need any prerequisites. + +#### **Build/Freeze/Compile with PyInstaller** + +PyInstaller can build/freeze/compile the utility at all three supported platforms, it is simple to run and gets updated often. + +1. Make sure Python 3.8.0 or newer is installed: + +> python --version + +2. Use pip to install PyInstaller: + +> pip3 install pyinstaller + +3. Build/Freeze/Compile: + +> pyinstaller --noupx --onefile \\/Phoenix_TDK_Extract.py + +At dist folder you should find the final utility executable + +#### **Anti-Virus False Positives** + +Some Anti-Virus software may claim that the built/frozen/compiled executable contains viruses. Any such detections are false positives, usually of PyInstaller. You can switch to a better Anti-Virus software, report the false positive to their support, add the executable to the exclusions, build/freeze/compile yourself or use the Python script directly. + +#### **Pictures** + +![]() + ###### _Donate Button Card Image: [Credit and Loan Pack](https://flaticon.com/free-icon/credit-card_3898076) by **Freepik** under Flaticon license_ ###### _Donate Button Paypal Image: [Credit Cards Pack](https://flaticon.com/free-icon/paypal_349278) by **Freepik** under Flaticon license_ \ No newline at end of file diff --git a/VAIO_Package_Extract.py b/VAIO_Package_Extract.py new file mode 100644 index 0000000..d788634 --- /dev/null +++ b/VAIO_Package_Extract.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +#coding=utf-8 + +""" +VAIO Package Extractor +VAIO Packaging Manager Extractor +Copyright (C) 2019-2022 Plato Mavropoulos +""" + +TITLE = 'VAIO Packaging Manager Extractor v3.0_a4' + +import os +import sys + +# Stop __pycache__ generation +sys.dont_write_bytecode = True + +from common.comp_szip import is_szip_supported, szip_decompress +from common.path_ops import make_dirs +from common.patterns import PAT_VAIO_CFG, PAT_VAIO_CHK, PAT_VAIO_EXT, PAT_VAIO_CAB +from common.system import script_init, argparse_init, printer +from common.text_ops import file_to_bytes + +# Check if input is VAIO Packaging Manager +def is_vaio_pkg(in_file): + buffer = file_to_bytes(in_file) + + return bool(PAT_VAIO_CFG.search(buffer)) + +# Extract VAIO Packaging Manager executable +def vaio_cabinet(name, buffer, extract_path, padding=0): + match_cab = PAT_VAIO_CAB.search(buffer) # Microsoft CAB Header XOR 0xFF + + if not match_cab: return 1 + + printer('Detected obfuscated CAB archive!', padding) + + # Determine the Microsoft CAB image size + cab_size = int.from_bytes(buffer[match_cab.start() + 0x8:match_cab.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 ^= xor_size # Perform XOR 0xFF and get actual CAB size + + printer('Removing obfuscation...', padding + 4) + + # Determine the Microsoft CAB image Data + cab_data = int.from_bytes(buffer[match_cab.start():match_cab.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 + + printer('Extracting archive...', padding + 4) + + cab_path = os.path.join(extract_path, f'{name}_Temporary.cab') + + with open(cab_path, 'wb') as cab_file: cab_file.write(cab_data) # Create temporary CAB archive + + if is_szip_supported(cab_path, padding + 4): + if szip_decompress(cab_path, extract_path, 'CAB', padding + 8) == 0: + os.remove(cab_path) # Successful extraction, delete temporary CAB archive + else: + return 3 + else: + return 2 + + return 0 + +# Unlock VAIO Packaging Manager executable +def vaio_unlock(name, buffer, extract_path, padding=0): + match_cfg = PAT_VAIO_CFG.search(buffer) + + if not match_cfg: return 1 + + printer('Attempting to Unlock executable!', padding) + + # Initialize VAIO Package Configuration file variables (assume overkill size of 0x500) + cfg_bgn,cfg_end,cfg_false,cfg_true = [match_cfg.start(), match_cfg.start() + 0x500, b'', b''] + + # Get VAIO Package Configuration file info, split at new_line and stop at payload DOS header (EOF) + cfg_info = buffer[cfg_bgn:cfg_end].split(b'\x0D\x0A\x4D\x5A')[0].replace(b'\x0D',b'').split(b'\x0A') + + printer('Retrieving True/False values...', padding + 4) + + # Determine VAIO Package Configuration file True & False values + for info in cfg_info: + if info.startswith(b'ExtractPathByUser='): + cfg_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='): + cfg_true = bytearray(b'1' if info[15:] in (b'0',b'1') else info[15:]) # Should be 1/Yes/True + + # Check if valid True/False values have been retrieved + if cfg_false == cfg_true or not cfg_false or not cfg_true: + printer('Error: Could not retrieve True/False values!', padding + 8) + return 2 + + printer('Adjusting UseVAIOCheck entry...', padding + 4) + + # Find and replace UseVAIOCheck entry from 1/Yes/True to 0/No/False + vaio_check = PAT_VAIO_CHK.search(buffer[cfg_bgn:]) + if vaio_check: + buffer[cfg_bgn + vaio_check.end():cfg_bgn + vaio_check.end() + len(cfg_true)] = cfg_false + else: + printer('Error: Could not find entry UseVAIOCheck!', padding + 8) + return 3 + + printer('Adjusting ExtractPathByUser entry...', padding + 4) + + # Find and replace ExtractPathByUser entry from 0/No/False to 1/Yes/True + user_path = PAT_VAIO_EXT.search(buffer[cfg_bgn:]) + if user_path: + buffer[cfg_bgn + user_path.end():cfg_bgn + user_path.end() + len(cfg_false)] = cfg_true + else: + printer('Error: Could not find entry ExtractPathByUser!', padding + 8) + return 4 + + printer('Storing unlocked executable...', padding + 4) + + # Store Unlocked VAIO Packaging Manager executable + if vaio_check and user_path: + unlock_path = os.path.join(extract_path, f'{name}_Unlocked.exe') + with open(unlock_path, 'wb') as unl_file: unl_file.write(buffer) + + return 0 + +# Parse & Extract or Unlock VAIO Packaging Manager +def vaio_pkg_extract(name, buffer, output_path, padding=0): + extract_path = os.path.join(f'{output_path}_extracted') + + make_dirs(extract_path, delete=True) + + if vaio_cabinet(name, buffer, extract_path, padding) == 0: + printer('Successfully Extracted!', padding) + elif vaio_unlock(name, bytearray(buffer), extract_path, padding) == 0: + printer('Successfully Unlocked!', padding) + else: + printer('Error: Failed to Extract or Unlock executable!', padding) + return 1 + + return 0 + +if __name__ == '__main__': + # Set argparse Arguments + argparser = argparse_init() + arguments = argparser.parse_args() + + # Initialize script (must be after argparse) + exit_code,input_files,output_path,padding = script_init(TITLE, arguments, 4) + + for input_file in input_files: + input_name = os.path.basename(input_file) + + printer(['***', input_name], padding - 4) + + with open(input_file, 'rb') as in_file: input_buffer = in_file.read() + + # Check if VAIO Packaging Manager pattern was found on executable + if not is_vaio_pkg(input_buffer): + printer('Error: This is not a VAIO Packaging Manager executable!', padding) + + continue # Next input file + + extract_path = os.path.join(output_path, input_name) + + if vaio_pkg_extract(input_name, input_buffer, extract_path, padding) == 0: + exit_code -= 1 + + printer('Done!', pause=True) + + sys.exit(exit_code) diff --git a/common/patterns.py b/common/patterns.py index b3ab80a..2ec78c8 100644 --- a/common/patterns.py +++ b/common/patterns.py @@ -13,11 +13,11 @@ PAT_DELL_FTR = re.compile(br'\xEE\xAA\xEE\x8F\x49\x1B\xE8\xAE\x14\x37\x90') PAT_DELL_HDR = re.compile(br'\xEE\xAA\x76\x1B\xEC\xBB\x20\xF1\xE6\x51.\x78\x9C', re.DOTALL) PAT_DELL_PKG = re.compile(br'\x72\x13\x55\x00.{45}7zXZ', re.DOTALL) PAT_INTEL_ENG = re.compile(br'\x04\x00{3}[\xA1\xE1]\x00{3}.{8}\x86\x80.{9}\x00\$((MN2)|(MAN))', re.DOTALL) -PAT_MICROSOFT_CAB_FF = re.compile(br'\xB2\xAC\xBC\xB9\xFF{4}.{4}\xFF{4}.{4}\xFF{4}\xFC\xFE', re.DOTALL) PAT_MICROSOFT_MZ = re.compile(br'MZ') PAT_MICROSOFT_PE = re.compile(br'PE\x00{2}') PAT_PHOENIX_TDK = re.compile(br'\$PACK\x00{3}..\x00{2}.\x00{3}', re.DOTALL) PAT_PORTWELL_EFI = re.compile(br'') +PAT_VAIO_CAB = re.compile(br'\xB2\xAC\xBC\xB9\xFF{4}.{4}\xFF{4}.{4}\xFF{4}\xFC\xFE', re.DOTALL) PAT_VAIO_CFG = re.compile(br'\[Setting]\x0D\x0A') PAT_VAIO_CHK = re.compile(br'\x0AUseVAIOCheck=') PAT_VAIO_EXT = re.compile(br'\x0AExtractPathByUser=')