mirror of
https://github.com/platomav/BIOSUtilities.git
synced 2025-05-13 06:34:42 -04:00
Added Panasonic BIOS Package Extractor v2.0_a7
New processes to better handle PE files Various common package fixes and improvements
This commit is contained in:
parent
f5905ec662
commit
fc73921967
12 changed files with 400 additions and 35 deletions
|
@ -7,7 +7,7 @@ AMI UCP Update Extractor
|
|||
Copyright (C) 2021-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'AMI UCP Update Extractor v2.0_a15'
|
||||
TITLE = 'AMI UCP Update Extractor v2.0_a16'
|
||||
|
||||
import os
|
||||
import re
|
||||
|
@ -163,7 +163,7 @@ def chk16_validate(data, tag, padd=0):
|
|||
def is_ami_ucp(in_file):
|
||||
buffer = file_to_bytes(in_file)
|
||||
|
||||
return bool(get_ami_ucp(buffer)[0] != None)
|
||||
return bool(get_ami_ucp(buffer)[0] is not None)
|
||||
|
||||
# Get all input file AMI UCP patterns
|
||||
def get_ami_ucp(buffer):
|
||||
|
@ -419,7 +419,7 @@ def uaf_extract(buffer, extract_path, mod_info, padding=0, is_checksum=False, na
|
|||
nested_uaf_off,nested_uaf_bin,nested_uaf_tag = get_ami_ucp(uaf_data_raw)
|
||||
|
||||
# Parse Nested AMI UCP Structure
|
||||
if nested_uaf_off != None:
|
||||
if nested_uaf_off is not None:
|
||||
uaf_dir = os.path.join(extract_path, safe_name(f'{uaf_tag}_nested-UCP')) # Generate extraction directory
|
||||
|
||||
ucp_extract(nested_uaf_bin, uaf_dir, nested_uaf_tag, padding + 4, is_checksum) # Call recursively
|
||||
|
@ -512,7 +512,7 @@ if __name__ == '__main__':
|
|||
# Get best AMI UCP Pattern match based on @UAF|@HPU Size
|
||||
main_uaf_off,main_uaf_bin,main_uaf_tag = get_ami_ucp(input_buffer)
|
||||
|
||||
if main_uaf_off == None:
|
||||
if main_uaf_off is None:
|
||||
printer('Error: This is not an AMI UCP Update executable!', padding)
|
||||
|
||||
continue # Next input file
|
||||
|
|
237
Panasonic_BIOS_Extract.py
Normal file
237
Panasonic_BIOS_Extract.py
Normal file
|
@ -0,0 +1,237 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Panasonic BIOS Extract
|
||||
Panasonic BIOS Package Extractor
|
||||
Copyright (C) 2018-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Panasonic BIOS Package Extractor v2.0_a7'
|
||||
|
||||
import os
|
||||
import io
|
||||
import sys
|
||||
import lznt1
|
||||
import pefile
|
||||
|
||||
# Stop __pycache__ generation
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from common.comp_szip import is_szip_supported, szip_decompress
|
||||
from common.path_ops import get_path_files, make_dirs, path_stem, safe_name
|
||||
from common.pe_ops import get_pe_file, get_pe_info, is_pe_file, show_pe_info
|
||||
from common.patterns import PAT_MICROSOFT_CAB
|
||||
from common.system import script_init, argparse_init, printer
|
||||
from common.text_ops import file_to_bytes
|
||||
|
||||
from AMI_PFAT_Extract import get_ami_pfat, parse_pfat_file
|
||||
|
||||
# Check if input is Panasonic BIOS Package PE
|
||||
def is_panasonic_pkg(in_file):
|
||||
in_buffer = file_to_bytes(in_file)
|
||||
|
||||
pe_file = get_pe_file(in_buffer, fast=True)
|
||||
|
||||
if not pe_file:
|
||||
return False
|
||||
|
||||
pe_info = get_pe_info(pe_file)
|
||||
|
||||
if not pe_info:
|
||||
return False
|
||||
|
||||
if pe_info.get(b'FileDescription',b'').upper() != b'UNPACK UTILITY':
|
||||
return False
|
||||
|
||||
if not PAT_MICROSOFT_CAB.search(in_buffer):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
# Search and Extract Panasonic BIOS Package PE CAB archive
|
||||
def panasonic_cab_extract(buffer, extract_path, padding=0):
|
||||
pe_path,pe_file,pe_info = [None] * 3
|
||||
|
||||
cab_bgn = PAT_MICROSOFT_CAB.search(buffer).start()
|
||||
cab_len = int.from_bytes(buffer[cab_bgn + 0x8:cab_bgn + 0xC], 'little')
|
||||
cab_end = cab_bgn + cab_len
|
||||
cab_bin = buffer[cab_bgn:cab_end]
|
||||
cab_tag = f'[0x{cab_bgn:06X}-0x{cab_end:06X}]'
|
||||
|
||||
cab_path = os.path.join(extract_path, f'CAB_{cab_tag}.cab')
|
||||
|
||||
with open(cab_path, 'wb') as cab_file:
|
||||
cab_file.write(cab_bin) # Store CAB archive
|
||||
|
||||
if is_szip_supported(cab_path, padding):
|
||||
printer(f'Panasonic BIOS Package > PE > CAB {cab_tag}', padding)
|
||||
|
||||
if szip_decompress(cab_path, extract_path, 'CAB', padding + 4) == 0:
|
||||
os.remove(cab_path) # Successful extraction, delete CAB archive
|
||||
else:
|
||||
return pe_path, pe_file, pe_info
|
||||
else:
|
||||
return pe_path, pe_file, pe_info
|
||||
|
||||
for file_path in get_path_files(extract_path):
|
||||
pe_file = get_pe_file(file_path, fast=True)
|
||||
if pe_file:
|
||||
pe_info = get_pe_info(pe_file)
|
||||
if pe_info.get(b'FileDescription',b'').upper() == b'BIOS UPDATE':
|
||||
pe_path = file_path
|
||||
break
|
||||
else:
|
||||
return pe_path, pe_file, pe_info
|
||||
|
||||
return pe_path, pe_file, pe_info
|
||||
|
||||
# Extract & Decompress Panasonic BIOS Update PE RCDATA (LZNT1)
|
||||
def panasonic_res_extract(pe_name, pe_file, extract_path, padding=0):
|
||||
is_rcdata = False
|
||||
|
||||
# When fast_load is used, IMAGE_DIRECTORY_ENTRY_RESOURCE must be parsed prior to RCDATA Directories
|
||||
pe_file.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE']])
|
||||
|
||||
# Parse all Resource Data Directories > RCDATA (ID = 10)
|
||||
for entry in pe_file.DIRECTORY_ENTRY_RESOURCE.entries:
|
||||
if entry.struct.name == 'IMAGE_RESOURCE_DIRECTORY_ENTRY' and entry.struct.Id == 0xA:
|
||||
is_rcdata = True
|
||||
for resource in entry.directory.entries:
|
||||
res_bgn = resource.directory.entries[0].data.struct.OffsetToData
|
||||
res_len = resource.directory.entries[0].data.struct.Size
|
||||
res_end = res_bgn + res_len
|
||||
res_bin = pe_file.get_data(res_bgn, res_len)
|
||||
res_tag = f'{pe_name} [0x{res_bgn:06X}-0x{res_end:06X}]'
|
||||
res_out = os.path.join(extract_path, f'{res_tag}')
|
||||
|
||||
printer(res_tag, padding + 4)
|
||||
|
||||
try:
|
||||
res_raw = lznt1.decompress(res_bin[0x8:])
|
||||
|
||||
printer('Succesfull LZNT1 decompression via lznt1!', padding + 8)
|
||||
except:
|
||||
res_raw = res_bin
|
||||
|
||||
printer('Succesfull PE Resource extraction!', padding + 8)
|
||||
|
||||
# Detect & Unpack AMI BIOS Guard (PFAT) BIOS image
|
||||
pfat_match,pfat_buffer = get_ami_pfat(res_raw)
|
||||
|
||||
if pfat_match:
|
||||
pfat_dir = os.path.join(extract_path, res_tag)
|
||||
|
||||
parse_pfat_file(pfat_buffer, pfat_dir, padding + 12)
|
||||
else:
|
||||
if is_pe_file(res_raw):
|
||||
res_ext = 'exe'
|
||||
elif res_raw.startswith(b'[') and res_raw.endswith((b'\x0D\x0A',b'\x0A')):
|
||||
res_ext = 'txt'
|
||||
else:
|
||||
res_ext = 'bin'
|
||||
|
||||
if res_ext == 'txt':
|
||||
printer(new_line=False)
|
||||
for line in io.BytesIO(res_raw).readlines():
|
||||
line_text = line.decode('utf-8','ignore').rstrip()
|
||||
printer(line_text, padding + 12, new_line=False)
|
||||
|
||||
with open(f'{res_out}.{res_ext}', 'wb') as out_file:
|
||||
out_file.write(res_raw)
|
||||
|
||||
return is_rcdata
|
||||
|
||||
# Extract Panasonic BIOS Update PE Data when RCDATA is not available
|
||||
def panasonic_img_extract(pe_name, pe_path, pe_file, extract_path, padding=0):
|
||||
pe_data = file_to_bytes(pe_path)
|
||||
|
||||
sec_bgn = pe_file.OPTIONAL_HEADER.DATA_DIRECTORY[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_SECURITY']].VirtualAddress
|
||||
img_bgn = pe_file.OPTIONAL_HEADER.BaseOfData + pe_file.OPTIONAL_HEADER.SizeOfInitializedData
|
||||
img_end = sec_bgn or len(pe_data)
|
||||
img_bin = pe_data[img_bgn:img_end]
|
||||
img_tag = f'{pe_name} [0x{img_bgn:X}-0x{img_end:X}]'
|
||||
img_out = os.path.join(extract_path, f'{img_tag}.bin')
|
||||
|
||||
printer(img_tag, padding + 4)
|
||||
|
||||
with open(img_out, 'wb') as out_img:
|
||||
out_img.write(img_bin)
|
||||
|
||||
printer('Succesfull PE Data extraction!', padding + 8)
|
||||
|
||||
return bool(img_bin)
|
||||
|
||||
# Parse & Extract Panasonic BIOS Package PE
|
||||
def panasonic_pkg_extract(input_path, input_buffer, output_path, padding=0):
|
||||
is_upd_res,is_upd_img = [False] * 2
|
||||
|
||||
extract_path = os.path.join(f'{output_path}_extracted')
|
||||
|
||||
make_dirs(extract_path, delete=True)
|
||||
|
||||
pkg_pe_file = get_pe_file(input_buffer, fast=True)
|
||||
|
||||
if not pkg_pe_file:
|
||||
return 2
|
||||
|
||||
pkg_pe_info = get_pe_info(pkg_pe_file)
|
||||
|
||||
if not pkg_pe_info:
|
||||
return 3
|
||||
|
||||
pkg_pe_name = path_stem(input_path)
|
||||
|
||||
printer(f'Panasonic BIOS Package > PE ({pkg_pe_name})\n', padding)
|
||||
|
||||
show_pe_info(pkg_pe_info, padding + 4)
|
||||
|
||||
upd_pe_path,upd_pe_file,upd_pe_info = panasonic_cab_extract(input_buffer, extract_path, padding + 4)
|
||||
|
||||
if not (upd_pe_path and upd_pe_file and upd_pe_info):
|
||||
return 4
|
||||
|
||||
upd_pe_name = safe_name(path_stem(upd_pe_path))
|
||||
|
||||
printer(f'Panasonic BIOS Update > PE ({upd_pe_name})\n', padding + 12)
|
||||
|
||||
show_pe_info(upd_pe_info, padding + 16)
|
||||
|
||||
is_upd_res = panasonic_res_extract(upd_pe_name, upd_pe_file, extract_path, padding + 16)
|
||||
|
||||
if not is_upd_res:
|
||||
is_upd_img = panasonic_img_extract(upd_pe_name, upd_pe_path, upd_pe_file, extract_path, padding + 16)
|
||||
|
||||
os.remove(upd_pe_path)
|
||||
|
||||
return 0 if is_upd_res or is_upd_img else 1
|
||||
|
||||
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 Panasonic BIOS Package pattern was found on executable
|
||||
if not is_panasonic_pkg(input_buffer):
|
||||
printer('Error: This is not a Panasonic BIOS Package executable!', padding)
|
||||
|
||||
continue # Next input file
|
||||
|
||||
extract_path = os.path.join(output_path, input_name)
|
||||
|
||||
if panasonic_pkg_extract(input_file, input_buffer, extract_path, padding) == 0:
|
||||
exit_code -= 1
|
||||
|
||||
printer('Done!', pause=True)
|
||||
|
||||
sys.exit(exit_code)
|
|
@ -7,18 +7,18 @@ Phoenix TDK Packer Extractor
|
|||
Copyright (C) 2021-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Phoenix TDK Packer Extractor v2.0_a7'
|
||||
TITLE = 'Phoenix TDK Packer Extractor v2.0_a8'
|
||||
|
||||
import os
|
||||
import sys
|
||||
import lzma
|
||||
import pefile
|
||||
import ctypes
|
||||
|
||||
# Stop __pycache__ generation
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from common.path_ops import safe_name, make_dirs
|
||||
from common.pe_ops import get_pe_file, get_pe_info
|
||||
from common.patterns import PAT_PHOENIX_TDK, PAT_MICROSOFT_MZ, PAT_MICROSOFT_PE
|
||||
from common.struct_ops import get_struct, char, uint32_t
|
||||
from common.system import script_init, argparse_init, printer
|
||||
|
@ -102,21 +102,21 @@ def get_tdk_base(in_buffer, pack_off):
|
|||
# Check if potential MZ > PE image magic value is valid
|
||||
if PAT_MICROSOFT_PE.search(in_buffer[pe_off:pe_off + 0x4]):
|
||||
try:
|
||||
# Analyze detected MZ > PE image buffer quickly (fast_load)
|
||||
pe_file = pefile.PE(data=in_buffer[mz_off:], fast_load=True)
|
||||
# Parse detected MZ > PE > Image, quickly (fast_load)
|
||||
pe_file = get_pe_file(in_buffer[mz_off:], fast=True)
|
||||
|
||||
# Since fast_load is used, IMAGE_DIRECTORY_ENTRY_RESOURCE must be parsed for FileInfo > StringTable
|
||||
pe_file.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE']])
|
||||
# Parse detected MZ > PE > Info
|
||||
pe_info = get_pe_info(pe_file)
|
||||
|
||||
# Attempt to retrieve the PE > "Product Name" version string value
|
||||
pe_name = pe_file.FileInfo[0][0].StringTable[0].entries[b'ProductName'].upper()
|
||||
# Parse detected MZ > PE > Info > Product Name
|
||||
pe_name = pe_info.get(b'ProductName',b'')
|
||||
except:
|
||||
# Any error means no PE > "Product Name" retrieved
|
||||
# Any error means no MZ > PE > Info > Product Name
|
||||
pe_name = b''
|
||||
|
||||
# Check for valid Phoenix TDK Packer PE > "Product Name"
|
||||
# Check for valid Phoenix TDK Packer PE > Product Name
|
||||
# Expected value is "TDK Packer (Extractor for Windows)"
|
||||
if pe_name.startswith(b'TDK PACKER'):
|
||||
if pe_name.upper().startswith(b'TDK PACKER'):
|
||||
# Set TDK Base Offset to valid TDK Packer MZ offset
|
||||
tdk_base_off = mz_off
|
||||
|
||||
|
@ -149,7 +149,7 @@ def get_phoenix_tdk(in_buffer):
|
|||
def is_phoenix_tdk(in_file):
|
||||
buffer = file_to_bytes(in_file)
|
||||
|
||||
return bool(get_phoenix_tdk(buffer)[1] != None)
|
||||
return bool(get_phoenix_tdk(buffer)[1] is not None)
|
||||
|
||||
# Parse & Extract Phoenix Tools Development Kit (TDK) Packer
|
||||
def phoenix_tdk_extract(input_buffer, output_path, pack_off, base_off=0, padding=0):
|
||||
|
@ -253,7 +253,7 @@ if __name__ == '__main__':
|
|||
tdk_base_off,tdk_pack_off = get_phoenix_tdk(input_buffer)
|
||||
|
||||
# Check if Phoenix TDK Packer pattern was found on executable
|
||||
if tdk_pack_off == None:
|
||||
if tdk_pack_off is None:
|
||||
printer('Error: This is not a Phoenix TDK Packer executable!', padding)
|
||||
|
||||
continue # Next input file
|
||||
|
|
|
@ -7,17 +7,17 @@ Portwell EFI Update Extractor
|
|||
Copyright (C) 2021-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'Portwell EFI Update Extractor v2.0_a9'
|
||||
TITLE = 'Portwell EFI Update Extractor v2.0_a10'
|
||||
|
||||
import os
|
||||
import sys
|
||||
import pefile
|
||||
|
||||
# Stop __pycache__ generation
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from common.comp_efi import efi_decompress, is_efi_compressed
|
||||
from common.path_ops import safe_name, make_dirs
|
||||
from common.pe_ops import get_pe_file
|
||||
from common.patterns import PAT_PORTWELL_EFI, PAT_MICROSOFT_MZ
|
||||
from common.system import script_init, argparse_init, printer
|
||||
from common.text_ops import file_to_bytes
|
||||
|
@ -44,7 +44,7 @@ def is_portwell_efi(in_file):
|
|||
|
||||
# Get PE of Portwell EFI executable
|
||||
def get_portwell_pe(in_buffer):
|
||||
pe_file = pefile.PE(data=in_buffer, fast_load=True) # Analyze EFI Portable Executable (PE)
|
||||
pe_file = get_pe_file(in_buffer, fast=True) # Analyze EFI Portable Executable (PE)
|
||||
|
||||
pe_data = in_buffer[pe_file.OPTIONAL_HEADER.SizeOfImage:] # Skip EFI executable (pylint: disable=E1101)
|
||||
|
||||
|
@ -66,9 +66,9 @@ def portwell_efi_extract(input_buffer, output_path, padding=0):
|
|||
|
||||
# Split EFI Payload into <UU> file chunks
|
||||
efi_list = list(PAT_PORTWELL_EFI.finditer(pe_data))
|
||||
for i,_ in enumerate(efi_list):
|
||||
efi_bgn = efi_list[i].end()
|
||||
efi_end = len(pe_data) if i == len(efi_list) - 1 else efi_list[i + 1].start()
|
||||
for idx,val in enumerate(efi_list):
|
||||
efi_bgn = val.end()
|
||||
efi_end = len(pe_data) if idx == len(efi_list) - 1 else efi_list[idx + 1].start()
|
||||
efi_files.append(pe_data[efi_bgn:efi_end])
|
||||
|
||||
parse_efi_files(extract_path, efi_files, padding)
|
||||
|
@ -108,7 +108,7 @@ def parse_efi_files(extract_path, efi_files, padding):
|
|||
|
||||
file_name = FILE_NAMES.get(file_index, f'Unknown_{file_index}.bin') # Assign Name to EFI file
|
||||
|
||||
printer(file_name, padding + 4) # Print EFI file name, indicate progress
|
||||
printer(f'[{file_index}] {file_name}', padding + 4) # Print EFI file name, indicate progress
|
||||
|
||||
if file_name.startswith('Unknown_'):
|
||||
printer(f'Note: Detected new Portwell EFI file ID {file_index}!', padding + 8, pause=True) # Report new EFI files
|
||||
|
|
68
README.md
68
README.md
|
@ -6,6 +6,7 @@
|
|||
* [**AMI BIOS Guard Extractor**](#ami-bios-guard-extractor)
|
||||
* [**AMI UCP Update Extractor**](#ami-ucp-update-extractor)
|
||||
* [**Dell PFS Update Extractor**](#dell-pfs-update-extractor)
|
||||
* [**Panasonic BIOS Package Extractor**](#panasonic-bios-package-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)
|
||||
|
@ -196,6 +197,73 @@ Some Anti-Virus software may claim that the built/frozen/compiled executable con
|
|||
|
||||
![]()
|
||||
|
||||
## **Panasonic BIOS Package Extractor**
|
||||
|
||||
![]()
|
||||
|
||||
#### **Description**
|
||||
|
||||
Parses Panasonic BIOS Package executables and extracts their firmware (e.g. SPI, BIOS/UEFI, EC etc) and utilities (e.g. winprom, configuration etc) components. It supports all Panasonic BIOS Package revisions and formats, including those which contain LZNT1 compressed files. The output comprises only final firmware components which are directly usable by end users.
|
||||
|
||||
#### **Usage**
|
||||
|
||||
You can either Drag & Drop or manually enter Panasonic BIOS Package 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 must have the following 3rd party Python modules installed:
|
||||
|
||||
* [pefile](https://pypi.org/project/pefile/)
|
||||
* [lznt1](https://pypi.org/project/lznt1/)
|
||||
|
||||
Moreover, 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.8.0 or newer is installed:
|
||||
|
||||
> python --version
|
||||
|
||||
2. Use pip to install PyInstaller:
|
||||
|
||||
> pip3 install pyinstaller
|
||||
|
||||
3. Use pip to install pefile and lznt1:
|
||||
|
||||
> pip3 install pefile lznt1
|
||||
|
||||
4. Place prerequisite at the "external" project directory:
|
||||
|
||||
> 7-Zip Console
|
||||
|
||||
5. Build/Freeze/Compile:
|
||||
|
||||
> pyinstaller --add-data="external/*;external/" --noupx --onefile \<path-to-project\>\/Panasonic_BIOS_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**
|
||||
|
||||
![]()
|
||||
|
||||
## **Phoenix TDK Packer Extractor**
|
||||
|
||||
![]()
|
||||
|
|
|
@ -7,7 +7,7 @@ VAIO Packaging Manager Extractor
|
|||
Copyright (C) 2019-2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
TITLE = 'VAIO Packaging Manager Extractor v3.0_a4'
|
||||
TITLE = 'VAIO Packaging Manager Extractor v3.0_a5'
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -53,7 +53,7 @@ def vaio_cabinet(name, buffer, extract_path, padding=0):
|
|||
|
||||
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 is_szip_supported(cab_path, padding + 8):
|
||||
if szip_decompress(cab_path, extract_path, 'CAB', padding + 8) == 0:
|
||||
os.remove(cab_path) # Successful extraction, delete temporary CAB archive
|
||||
else:
|
||||
|
|
|
@ -35,7 +35,7 @@ def get_tiano_path():
|
|||
return safe_path(project_root(), ['external',exec_name])
|
||||
|
||||
# EFI/Tiano Decompression via TianoCompress
|
||||
def efi_decompress(in_path, out_path, padding=0, comp_type='--uefi'):
|
||||
def efi_decompress(in_path, out_path, padding=0, silent=False, comp_type='--uefi'):
|
||||
try:
|
||||
subprocess.run([get_tiano_path(), '-d', in_path, '-o', out_path, '-q', comp_type], check=True, stdout=subprocess.DEVNULL)
|
||||
|
||||
|
@ -43,10 +43,12 @@ def efi_decompress(in_path, out_path, padding=0, comp_type='--uefi'):
|
|||
|
||||
if os.path.getsize(out_path) != size_orig: raise Exception('EFI_DECOMPRESS_ERROR')
|
||||
except:
|
||||
if not silent:
|
||||
printer(f'Error: TianoCompress could not extract file {in_path}!', padding)
|
||||
|
||||
return 1
|
||||
|
||||
if not silent:
|
||||
printer('Succesfull EFI decompression via TianoCompress!', padding)
|
||||
|
||||
return 0
|
||||
|
|
|
@ -19,10 +19,11 @@ def get_szip_path():
|
|||
return safe_path(project_root(), ['external',exec_name])
|
||||
|
||||
# Check if file is 7-Zip supported
|
||||
def is_szip_supported(in_path, padding=0):
|
||||
def is_szip_supported(in_path, padding=0, silent=False):
|
||||
try:
|
||||
subprocess.run([get_szip_path(), 't', in_path, '-bso0', '-bse0', '-bsp0'], check=True)
|
||||
except:
|
||||
if not silent:
|
||||
printer(f'Error: 7-Zip could not check support for file {in_path}!', padding)
|
||||
|
||||
return False
|
||||
|
@ -30,7 +31,7 @@ def is_szip_supported(in_path, padding=0):
|
|||
return True
|
||||
|
||||
# Archive decompression via 7-Zip
|
||||
def szip_decompress(in_path, out_path, in_name, padding=0):
|
||||
def szip_decompress(in_path, out_path, in_name, padding=0, silent=False):
|
||||
if not in_name: in_name = 'archive'
|
||||
|
||||
try:
|
||||
|
@ -38,10 +39,12 @@ def szip_decompress(in_path, out_path, in_name, padding=0):
|
|||
|
||||
if not os.path.isdir(out_path): raise Exception('EXTRACT_DIR_MISSING')
|
||||
except:
|
||||
if not silent:
|
||||
printer(f'Error: 7-Zip could not extract {in_name} file {in_path}!', padding)
|
||||
|
||||
return 1
|
||||
|
||||
if not silent:
|
||||
printer(f'Succesfull {in_name} decompression via 7-Zip!', padding)
|
||||
|
||||
return 0
|
||||
|
|
|
@ -70,6 +70,10 @@ def agnostic_path(in_path):
|
|||
def path_parent(in_path):
|
||||
return Path(in_path).parent.absolute()
|
||||
|
||||
# Get final path component, w/o suffix
|
||||
def path_stem(in_path):
|
||||
return PurePath(in_path).stem
|
||||
|
||||
# Check if path is absolute
|
||||
def is_path_absolute(in_path):
|
||||
return Path(in_path).is_absolute()
|
||||
|
|
|
@ -13,6 +13,7 @@ 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 = re.compile(br'MSCF\x00{4}')
|
||||
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)
|
||||
|
|
49
common/pe_ops.py
Normal file
49
common/pe_ops.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python3
|
||||
#coding=utf-8
|
||||
|
||||
"""
|
||||
Copyright (C) 2022 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
import pefile
|
||||
|
||||
from common.system import printer
|
||||
from common.text_ops import file_to_bytes
|
||||
|
||||
# Check if input is a PE file
|
||||
def is_pe_file(in_file):
|
||||
return bool(get_pe_file(in_file))
|
||||
|
||||
# Get pefile object from PE file
|
||||
def get_pe_file(in_file, fast=True):
|
||||
in_buffer = file_to_bytes(in_file)
|
||||
|
||||
try:
|
||||
# Analyze detected MZ > PE image buffer
|
||||
pe_file = pefile.PE(data=in_buffer, fast_load=fast)
|
||||
except:
|
||||
pe_file = None
|
||||
|
||||
return pe_file
|
||||
|
||||
# Get PE info from pefile object
|
||||
def get_pe_info(pe_file):
|
||||
try:
|
||||
# When fast_load is used, IMAGE_DIRECTORY_ENTRY_RESOURCE must be parsed prior to FileInfo > StringTable
|
||||
pe_file.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_RESOURCE']])
|
||||
|
||||
# Retrieve MZ > PE > FileInfo > StringTable information
|
||||
pe_info = pe_file.FileInfo[0][0].StringTable[0].entries
|
||||
except:
|
||||
pe_info = {}
|
||||
|
||||
return pe_info
|
||||
|
||||
# Print PE info from pefile StringTable
|
||||
def show_pe_info(pe_info, padding=0):
|
||||
if type(pe_info).__name__ == 'dict':
|
||||
for title,value in pe_info.items():
|
||||
info_title = title.decode('utf-8','ignore').strip()
|
||||
info_value = value.decode('utf-8','ignore').strip()
|
||||
if info_title and info_value:
|
||||
printer(f'{info_title}: {info_value}', padding, new_line=False)
|
1
external/requirements.txt
vendored
1
external/requirements.txt
vendored
|
@ -1 +1,2 @@
|
|||
lznt1==0.2
|
||||
pefile==2021.9.3
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue