Improved Intel BIOS Guard Signature parsing

AMI BIOS Guard Extractor can now attempt to detect Intel BG Signature via a pattern, when the Signature header is unknown or obfuscated (Panasonic).
This commit is contained in:
Plato Mavropoulos 2024-05-16 01:03:15 +03:00
parent c5e8638f92
commit fdfdab011d
4 changed files with 50 additions and 20 deletions

View file

@ -10,6 +10,7 @@ Copyright (C) 2018-2024 Plato Mavropoulos
import ctypes
import os
import re
import struct
from common.externals import get_bgs_tool
from common.num_ops import get_ordinal
@ -20,7 +21,7 @@ from common.system import printer
from common.templates import BIOSUtility
from common.text_ops import bytes_to_hex, file_to_bytes
TITLE = 'AMI BIOS Guard Extractor v5.0'
TITLE = 'AMI BIOS Guard Extractor v6.0'
class AmiBiosGuardHeader(ctypes.LittleEndianStructure):
@ -79,6 +80,11 @@ class IntelBiosGuardHeader(ctypes.LittleEndianStructure):
return f'{id_text} {id_guid}'
def get_hdr_marker(self) -> bytes:
""" Get Intel BIOS Guard Header Marker """
return struct.pack('<HH16B', self.BGVerMajor, self.BGVerMinor, *self.PlatformID)
def get_flags(self) -> tuple:
""" Get Intel BIOS Guard Header Attributes """
@ -261,19 +267,30 @@ def parse_bg_script(script_data: bytes, padding: int = 0) -> int:
return 0
def parse_bg_sign(input_data: bytes, sign_offset: int, print_info: bool = False, padding: int = 0) -> int:
def parse_bg_sign(input_data: bytes, sign_offset: int, sign_length: int = 0,
print_info: bool = False, padding: int = 0) -> int:
""" Process Intel BIOS Guard Signature """
bg_sig_hdr = get_struct(input_data, sign_offset, IntelBiosGuardSignatureHeader)
if bg_sig_hdr.Unknown0 == 1:
# Unknown0 = 1, Unknown1 = 1
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa2k # Unknown0 = 1, Unknown1 = 1
elif bg_sig_hdr.Unknown0 == 2:
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa3k # Unknown0 = 2, Unknown1 = 3
elif sign_length == PFAT_INT_SIG_HDR_LEN + PFAT_INT_SIG_R2K_LEN:
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa2k
else:
# Unknown0 = 2, Unknown1 = 3
printer('Warning: Detected Intel BIOS Guard Signature 2K length via pattern!\n', padding, False)
elif sign_length == PFAT_INT_SIG_HDR_LEN + PFAT_INT_SIG_R3K_LEN:
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa3k
bg_sig_rsa = get_struct(input_data, sign_offset + PFAT_BLK_SIG_LEN, bg_sig_rsa_struct)
printer('Warning: Detected Intel BIOS Guard Signature 3K length via pattern!\n', padding, False)
else:
bg_sig_rsa_struct = IntelBiosGuardSignatureRsa3k
printer('Error: Could not detect Intel BIOS Guard Signature length, assuming 3K!\n', padding, False, pause=True)
bg_sig_rsa = get_struct(input_data, sign_offset + PFAT_INT_SIG_HDR_LEN, bg_sig_rsa_struct)
if print_info:
bg_sig_hdr.struct_print(padding)
@ -281,7 +298,7 @@ def parse_bg_sign(input_data: bytes, sign_offset: int, print_info: bool = False,
bg_sig_rsa.struct_print(padding)
# Total size of Signature Header and RSA Structure
return PFAT_BLK_SIG_LEN + ctypes.sizeof(bg_sig_rsa_struct)
return PFAT_INT_SIG_HDR_LEN + ctypes.sizeof(bg_sig_rsa_struct)
def parse_pfat_hdr(buffer: bytes | bytearray, padding: int = 0) -> tuple:
@ -347,6 +364,8 @@ def parse_pfat_file(input_object: str | bytes | bytearray, extract_path: str, pa
all_blocks_dict: dict = {}
bg_sign_len: int = 0
extract_name: str = path_name(extract_path).removesuffix(extract_suffix())
make_dirs(extract_path, delete=True)
@ -371,7 +390,7 @@ def parse_pfat_file(input_object: str | bytes | bytearray, extract_path: str, pa
bg_hdr.struct_print(padding + 12)
bg_script_bgn: int = block_off + PFAT_BLK_HDR_LEN
bg_script_bgn: int = block_off + PFAT_INT_HDR_LEN
bg_script_end: int = bg_script_bgn + bg_hdr.ScriptSize
bg_data_bgn: int = bg_script_end
@ -379,15 +398,19 @@ def parse_pfat_file(input_object: str | bytes | bytearray, extract_path: str, pa
bg_data_bin: bytes = pfat_buffer[bg_data_bgn:bg_data_end]
block_off: int = bg_data_end # Assume next block starts at data end
block_off = bg_data_end # Assume next block starts at data end
is_sfam, _, _, _, _ = bg_hdr.get_flags() # SFAM, ProtectEC, GFXMitDis, FTU, Reserved
if is_sfam:
printer(f'Intel BIOS Guard {block_status} Signature:\n', padding + 8)
if bg_sign_len == 0:
bg_sign_len = pfat_buffer.find(bg_hdr.get_hdr_marker(), bg_data_end,
bg_data_end + PFAT_INT_SIG_MAX_LEN) - bg_data_end
# Adjust next block to start after current block Data + Signature
block_off += parse_bg_sign(pfat_buffer, bg_data_end, True, padding + 12)
block_off += parse_bg_sign(pfat_buffer, bg_data_end, bg_sign_len, True, padding + 12)
printer(f'Intel BIOS Guard {block_status} Script:\n', padding + 8)
@ -427,8 +450,11 @@ def parse_pfat_file(input_object: str | bytes | bytearray, extract_path: str, pa
PFAT_AMI_HDR_LEN: int = ctypes.sizeof(AmiBiosGuardHeader)
PFAT_BLK_HDR_LEN: int = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_BLK_SIG_LEN: int = ctypes.sizeof(IntelBiosGuardSignatureHeader)
PFAT_INT_HDR_LEN: int = ctypes.sizeof(IntelBiosGuardHeader)
PFAT_INT_SIG_HDR_LEN: int = ctypes.sizeof(IntelBiosGuardSignatureHeader)
PFAT_INT_SIG_R2K_LEN: int = ctypes.sizeof(IntelBiosGuardSignatureRsa2k)
PFAT_INT_SIG_R3K_LEN: int = ctypes.sizeof(IntelBiosGuardSignatureRsa3k)
PFAT_INT_SIG_MAX_LEN: int = PFAT_INT_SIG_HDR_LEN + PFAT_INT_SIG_R3K_LEN
if __name__ == '__main__':
BIOSUtility(title=TITLE, check=is_ami_pfat, main=parse_pfat_file).run_utility()