From aea54aeaad200194d58b599579acf0c0127e9917 Mon Sep 17 00:00:00 2001 From: platomav Date: Tue, 24 May 2022 14:36:46 +0300 Subject: [PATCH] Phoenix TDK Packer Extractor v2.0_a6 Dramatically increase TDK Packer base offset detection speed Applied regex pattern improvements --- Phoenix_TDK_Extract.py | 21 ++++++++++++++------- Portwell_EFI_Extract.py | 17 ++++++++++++----- common/patterns.py | 6 +++--- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Phoenix_TDK_Extract.py b/Phoenix_TDK_Extract.py index 8133047..2d93793 100644 --- a/Phoenix_TDK_Extract.py +++ b/Phoenix_TDK_Extract.py @@ -7,7 +7,7 @@ Phoenix TDK Packer Extractor Copyright (C) 2021-2022 Plato Mavropoulos """ -TITLE = 'Phoenix TDK Packer Extractor v2.0_a5' +TITLE = 'Phoenix TDK Packer Extractor v2.0_a6' import os import sys @@ -92,29 +92,36 @@ def get_tdk_base(in_buffer, pack_off): for mz in mz_ord: mz_off = mz.start() - # MZ (DOS) > PE (NT) image offset is found at offset 0x3C-0x40 relative to MZ base + # MZ (DOS) > PE (NT) image Offset is found at offset 0x3C-0x40 relative to MZ base pe_off = mz_off + int.from_bytes(in_buffer[mz_off + 0x3C:mz_off + 0x40], 'little') + # Skip MZ (DOS) with bad PE (NT) image Offset + if pe_off == mz_off or pe_off >= pack_off: + continue + # 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 - pe_file = pefile.PE(data=in_buffer[mz_off:]) + # Analyze detected MZ > PE image buffer quickly (fast_load) + pe_file = pefile.PE(data=in_buffer[mz_off:], fast_load=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']]) # Attempt to retrieve the PE > "Product Name" version string value - pe_name = pe_file.FileInfo[0][0].StringTable[0].entries[b'ProductName'] + pe_name = pe_file.FileInfo[0][0].StringTable[0].entries[b'ProductName'].upper() except: # Any error means no PE > "Product Name" retrieved pe_name = b'' # Check for valid Phoenix TDK Packer PE > "Product Name" # Expected value is "TDK Packer (Extractor for Windows)" - if pe_name.upper().startswith(b'TDK PACKER'): + if pe_name.startswith(b'TDK PACKER'): # Set TDK Base Offset to valid TDK Packer MZ offset tdk_base_off = mz_off # Stop parsing detected MZ once TDK Base Offset is found - if tdk_base_off: + if tdk_base_off is not None: break else: # No TDK Base Offset could be found, assume 0x0 diff --git a/Portwell_EFI_Extract.py b/Portwell_EFI_Extract.py index c0abac9..edccf27 100644 --- a/Portwell_EFI_Extract.py +++ b/Portwell_EFI_Extract.py @@ -7,7 +7,7 @@ Portwell EFI Update Extractor Copyright (C) 2021-2022 Plato Mavropoulos """ -TITLE = 'Portwell EFI Update Extractor v2.0_a6' +TITLE = 'Portwell EFI Update Extractor v2.0_a7' import os import sys @@ -37,8 +37,8 @@ def is_portwell_efi(in_file): try: pe_buffer = get_portwell_pe(in_buffer)[1] except: pe_buffer = b'' - is_mz = in_buffer.startswith(PAT_MICROSOFT_MZ.pattern) # EFI images start with PE Header MZ - is_uu = pe_buffer.startswith(PAT_PORTWELL_EFI.pattern) # Portwell EFI files start with + is_mz = PAT_MICROSOFT_MZ.search(in_buffer[:0x2]) # EFI images start with PE Header MZ + is_uu = PAT_PORTWELL_EFI.search(pe_buffer[:0x4]) # Portwell EFI files start with return is_mz and is_uu @@ -52,6 +52,8 @@ def get_portwell_pe(in_buffer): # Parse & Extract Portwell UEFI Unpacker def portwell_efi_extract(input_buffer, output_path, padding=0): + efi_files = [] # Initialize EFI Payload file chunks + extract_path = os.path.join(f'{output_path}_extracted') make_dirs(extract_path, delete=True) @@ -62,9 +64,14 @@ def portwell_efi_extract(input_buffer, output_path, padding=0): printer(efi_title, padding) - efi_files = pe_data.split(PAT_PORTWELL_EFI.pattern) # Split EFI Payload into file chunks + # Split EFI Payload into 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() + efi_files.append(pe_data[efi_bgn:efi_end]) - parse_efi_files(extract_path, efi_files[1:], padding) + parse_efi_files(extract_path, efi_files, padding) # Get Portwell UEFI Unpacker tag def get_unpacker_tag(input_buffer, pe_file): diff --git a/common/patterns.py b/common/patterns.py index c26f02b..a94208a 100644 --- a/common/patterns.py +++ b/common/patterns.py @@ -7,13 +7,13 @@ Copyright (C) 2022 Plato Mavropoulos import re -PAT_AMI_PFAT = re.compile(b'_AMIPFAT.AMI_BIOS_GUARD_FLASH_CONFIGURATIONS', re.DOTALL) +PAT_AMI_PFAT = re.compile(br'_AMIPFAT.AMI_BIOS_GUARD_FLASH_CONFIGURATIONS', re.DOTALL) PAT_AMI_UCP = re.compile(br'@(UAF|HPU).{12}@', re.DOTALL) 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_MZ = re.compile(br'MZ') -PAT_MICROSOFT_PE = re.compile(br'PE\x00\x00') +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_PORTWELL_EFI = re.compile(br'')