Added Fujitsu SFX BIOS Extractor v3.0_a2

Fixed deletion of folders with read-only files

Fixed missing README > Requirement for VAIO Packaging Manager Extractor
This commit is contained in:
platomav 2022-07-14 01:32:25 +03:00
parent df47293d01
commit 48562b0f68
4 changed files with 194 additions and 4 deletions

118
Fujitsu_SFX_Extract.py Normal file
View file

@ -0,0 +1,118 @@
#!/usr/bin/env python3
#coding=utf-8
"""
Fujitsu SFX Extractor
Fujitsu SFX BIOS Extractor
Copyright (C) 2019-2022 Plato Mavropoulos
"""
TITLE = 'Fujitsu SFX BIOS Extractor v3.0_a2'
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_FUJITSU_SFX
from common.system import argparse_init, printer, script_init
from common.text_ops import file_to_bytes
# Check if input is Fujitsu SFX image
def is_fujitsu_sfx(in_file):
buffer = file_to_bytes(in_file)
return bool(PAT_FUJITSU_SFX.search(buffer))
# Extract Fujitsu SFX image
def fujitsu_cabinet(in_file, extract_path, padding=0):
buffer = file_to_bytes(in_file)
match_cab = PAT_FUJITSU_SFX.search(buffer) # Microsoft CAB Header XOR 0xFF
if not match_cab:
return 1
printer('Detected obfuscated CAB archive!', padding)
# Microsoft CAB Header XOR 0xFF starts after "FjSfxBinay" signature
cab_start = match_cab.start() + 0xA
# Determine the Microsoft CAB image size
cab_size = int.from_bytes(buffer[cab_start + 0x8: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[cab_start: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, 'FjSfxBinay.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 + 8, check=True):
if szip_decompress(cab_path, extract_path, 'CAB', padding + 8, check=True) == 0:
os.remove(cab_path) # Successful extraction, delete temporary CAB archive
else:
return 3
else:
return 2
return 0
# Parse & Extract Fujitsu SFX image
def fujitsu_sfx_extract(in_file, output_path, padding=0):
buffer = file_to_bytes(in_file)
extract_path = os.path.join(f'{output_path}_extracted')
make_dirs(extract_path, delete=True)
if fujitsu_cabinet(buffer, extract_path, padding) == 0:
printer('Successfully Extracted!', padding)
else:
printer('Error: Failed to Extract image!', 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 Fujitsu SFX pattern was found on image
if not is_fujitsu_sfx(input_buffer):
printer('Error: This is not a Fujitsu SFX image!', padding)
continue # Next input file
extract_path = os.path.join(output_path, input_name)
if fujitsu_sfx_extract(input_buffer, extract_path, padding) == 0:
exit_code -= 1
printer('Done!', pause=True)
sys.exit(exit_code)

View file

@ -7,6 +7,7 @@
* [**AMI UCP Update Extractor**](#ami-ucp-update-extractor) * [**AMI UCP Update Extractor**](#ami-ucp-update-extractor)
* [**Award BIOS Module Extractor**](#award-bios-module-extractor) * [**Award BIOS Module Extractor**](#award-bios-module-extractor)
* [**Dell PFS/PKG Update Extractor**](#dell-pfspkg-update-extractor) * [**Dell PFS/PKG Update Extractor**](#dell-pfspkg-update-extractor)
* [**Fujitsu SFX BIOS Extractor**](#fujitsu-sfx-bios-extractor)
* [**Fujitsu UPC BIOS Extractor**](#fujitsu-upc-bios-extractor) * [**Fujitsu UPC BIOS Extractor**](#fujitsu-upc-bios-extractor)
* [**Insyde iFlash/iFdPacker Extractor**](#insyde-iflashifdpacker-extractor) * [**Insyde iFlash/iFdPacker Extractor**](#insyde-iflashifdpacker-extractor)
* [**Panasonic BIOS Package Extractor**](#panasonic-bios-package-extractor) * [**Panasonic BIOS Package Extractor**](#panasonic-bios-package-extractor)
@ -259,6 +260,64 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con
![]() ![]()
## **Fujitsu SFX BIOS Extractor**
![]()
#### **Description**
Parses Fujitsu SFX BIOS images and extracts their obfuscated Microsoft CAB archived firmware (e.g. SPI, BIOS/UEFI, EC, ME etc) and utilities (e.g. WinPhlash, PHLASH.INI etc) components. The output comprises only final firmware components which are directly usable by end users.
#### **Usage**
You can either Drag & Drop or manually enter Fujitsu SFX BIOS 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
#### **Compatibility**
Should work at all Windows, Linux or macOS operating systems which have Python 3.10 support.
#### **Prerequisites**
To run the utility, you must have the following 3rd party tool at the "external" project directory:
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux)
#### **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.10.0 or newer is installed:
> python --version
2. Use pip to install PyInstaller:
> pip3 install pyinstaller
3. Place prerequisite at the "external" project directory:
> 7-Zip Console
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Fujitsu_SFX_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**
![]()
## **Fujitsu UPC BIOS Extractor** ## **Fujitsu UPC BIOS Extractor**
![]() ![]()
@ -644,7 +703,9 @@ Should work at all Windows, Linux or macOS operating systems which have Python 3
#### **Prerequisites** #### **Prerequisites**
To run the utility, you do not need any prerequisites. To run the utility, you must have the following 3rd party tool at the "external" project directory:
* [7-Zip Console](https://www.7-zip.org/) (i.e. 7z.exe for Windows or 7zzs for Linux)
#### **Build/Freeze/Compile with PyInstaller** #### **Build/Freeze/Compile with PyInstaller**
@ -658,9 +719,13 @@ PyInstaller can build/freeze/compile the utility at all three supported platform
> pip3 install pyinstaller > pip3 install pyinstaller
3. Build/Freeze/Compile: 3. Place prerequisite at the "external" project directory:
> pyinstaller --noupx --onefile \<path-to-project\>\/VAIO_Package_Extract.py > 7-Zip Console
4. Build/Freeze/Compile:
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/VAIO_Package_Extract.py
At dist folder you should find the final utility executable At dist folder you should find the final utility executable

View file

@ -8,6 +8,7 @@ Copyright (C) 2022 Plato Mavropoulos
import os import os
import re import re
import sys import sys
import stat
import shutil import shutil
from pathlib import Path, PurePath from pathlib import Path, PurePath
@ -92,7 +93,12 @@ def make_dirs(in_path, parents=True, exist_ok=False, delete=False):
# Delete folder(s), if present # Delete folder(s), if present
def del_dirs(in_path): def del_dirs(in_path):
if Path(in_path).is_dir(): if Path(in_path).is_dir():
shutil.rmtree(in_path) shutil.rmtree(in_path, onerror=clear_readonly)
# Clear read-only file attribute (on shutil.rmtree error)
def clear_readonly(in_func, in_path, _):
os.chmod(in_path, stat.S_IWRITE)
in_func(in_path)
# Walk path to get all files # Walk path to get all files
def get_path_files(in_path): def get_path_files(in_path):

View file

@ -13,6 +13,7 @@ PAT_AWARD_LZH = re.compile(br'-lh[04567]-')
PAT_DELL_FTR = re.compile(br'\xEE\xAA\xEE\x8F\x49\x1B\xE8\xAE\x14\x37\x90') 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_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_DELL_PKG = re.compile(br'\x72\x13\x55\x00.{45}7zXZ', re.DOTALL)
PAT_FUJITSU_SFX = re.compile(br'FjSfxBinay\xB2\xAC\xBC\xB9\xFF{4}.{4}\xFF{4}.{4}\xFF{4}\xFC\xFE', re.DOTALL)
PAT_INSYDE_IFL = re.compile(br'\$_IFLASH') PAT_INSYDE_IFL = re.compile(br'\$_IFLASH')
PAT_INSYDE_SFX = re.compile(br'\x0D\x0A;!@InstallEnd@!\x0D\x0A(7z\xBC\xAF\x27|\x6E\xF4\x79\x5F\x4E)') PAT_INSYDE_SFX = re.compile(br'\x0D\x0A;!@InstallEnd@!\x0D\x0A(7z\xBC\xAF\x27|\x6E\xF4\x79\x5F\x4E)')
PAT_INTEL_ENG = re.compile(br'\x04\x00{3}[\xA1\xE1]\x00{3}.{8}\x86\x80.{9}\x00\$((MN2)|(MAN))', re.DOTALL) PAT_INTEL_ENG = re.compile(br'\x04\x00{3}[\xA1\xE1]\x00{3}.{8}\x86\x80.{9}\x00\$((MN2)|(MAN))', re.DOTALL)