mirror of
https://github.com/platomav/BIOSUtilities.git
synced 2025-05-12 22:26:13 -04:00
Added AMI BIOS Guard Extractor
Parses AMI BIOS Guard (a.k.a. PFAT) images and extracts a proper SPI/BIOS image.
This commit is contained in:
parent
09c02caa9a
commit
d702d7f8a8
2 changed files with 227 additions and 2 deletions
185
AMI BIOS Guard Extractor/AMI_PFAT_Extract.py
Normal file
185
AMI BIOS Guard Extractor/AMI_PFAT_Extract.py
Normal file
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
AMI PFAT Extract
|
||||
AMI BIOS Guard Extractor
|
||||
Copyright (C) 2018 Plato Mavropoulos
|
||||
"""
|
||||
|
||||
print('AMI BIOS Guard Extractor v1.0')
|
||||
|
||||
import os
|
||||
import sys
|
||||
import ctypes
|
||||
import struct
|
||||
|
||||
# Set ctypes Structure types
|
||||
char = ctypes.c_char
|
||||
uint8_t = ctypes.c_ubyte
|
||||
uint16_t = ctypes.c_ushort
|
||||
uint32_t = ctypes.c_uint
|
||||
uint64_t = ctypes.c_uint64
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
class PFAT_Header(ctypes.LittleEndianStructure) :
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('Size', uint32_t), # 0x00
|
||||
('Validation', uint32_t), # 0x04 Unknown 16-bit Checksum ?
|
||||
('Tag', char*8), # 0x04 _AMIPFAT
|
||||
('Control', uint8_t), # 0x10 0x4
|
||||
# 0x11
|
||||
]
|
||||
|
||||
def pfat_print(self) :
|
||||
print('\nPFAT Main Header:\n')
|
||||
print(' Size : 0x%X' % self.Size)
|
||||
print(' Validation : 0x%X' % self.Validation)
|
||||
print(' Tag : %s' % self.Tag.decode('utf-8'))
|
||||
print(' Control : 0x%X' % self.Control)
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
class PFAT_Block_Header(ctypes.LittleEndianStructure) :
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('Revision', uint32_t), # 0x00 PFAT
|
||||
('Platform', char*16), # 0x04
|
||||
('Unknown0', uint32_t), # 0x14
|
||||
('Unknown1', uint32_t), # 0x18
|
||||
('FlagsSize', uint32_t), # 0x1C From Block Header end
|
||||
('DataSize', uint32_t), # 0x20 From Block Flags end
|
||||
('Unknown2', uint32_t), # 0x24
|
||||
('Unknown3', uint32_t), # 0x28
|
||||
('Unknown4', uint32_t), # 0x2C
|
||||
# 0x30
|
||||
]
|
||||
|
||||
def __init__(self, count, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.count = count
|
||||
|
||||
def pfat_print(self) :
|
||||
print('\n PFAT Block %s Header:\n' % self.count)
|
||||
print(' Revision : %d' % self.Revision)
|
||||
print(' Platform : %s' % self.Platform.decode('utf-8'))
|
||||
print(' Unknown 0 : 0x%X' % self.Unknown0)
|
||||
print(' Unknown 1 : 0x%X' % self.Unknown1)
|
||||
print(' Flags Size : 0x%X' % self.FlagsSize)
|
||||
print(' Data Size : 0x%X' % self.DataSize)
|
||||
print(' Unknown 2 : 0x%X' % self.Unknown2)
|
||||
print(' Unknown 3 : 0x%X' % self.Unknown3)
|
||||
print(' Unknown 4 : 0x%X' % self.Unknown4)
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
class PFAT_Block_RSA(ctypes.LittleEndianStructure) :
|
||||
_pack_ = 1
|
||||
_fields_ = [
|
||||
('Unknown0', uint32_t), # 0x00
|
||||
('Unknown1', uint32_t), # 0x04
|
||||
('PublicKey', uint32_t*64), # 0x08
|
||||
('Exponent', uint32_t), # 0x108
|
||||
('Signature', uint32_t*64), # 0x10C
|
||||
# 0x20C
|
||||
]
|
||||
|
||||
def __init__(self, count, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.count = count
|
||||
|
||||
def pfat_print(self) :
|
||||
RSAPublicKey = ''.join('%0.8X' % int.from_bytes(struct.pack('<I', val), 'little') for val in reversed(self.PublicKey))
|
||||
RSASignature = ''.join('%0.8X' % int.from_bytes(struct.pack('<I', val), 'little') for val in reversed(self.Signature))
|
||||
|
||||
print('\n PFAT Block %s Signature:\n' % self.count)
|
||||
print(' Unknown 0 : 0x%X' % self.Unknown0)
|
||||
print(' Unknown 1 : 0x%X' % self.Unknown1)
|
||||
print(' Public Key : %s [...]' % RSAPublicKey[:8])
|
||||
print(' Exponent : 0x%X' % self.Exponent)
|
||||
print(' Signature : %s [...]' % RSASignature[:8])
|
||||
|
||||
# Process ctypes Structure Classes
|
||||
def get_struct(buffer, start_offset, class_name, param_list = None) :
|
||||
if param_list is None : param_list = []
|
||||
|
||||
structure = class_name(*param_list) # Unpack parameter list
|
||||
struct_len = ctypes.sizeof(structure)
|
||||
struct_data = buffer[start_offset:start_offset + struct_len]
|
||||
fit_len = min(len(struct_data), struct_len)
|
||||
|
||||
if (start_offset >= len(buffer)) or (fit_len < struct_len) :
|
||||
print('Error: Offset 0x%X out of bounds at %s, possibly incomplete image!' % (start_offset, class_name))
|
||||
sys.exit(1)
|
||||
|
||||
ctypes.memmove(ctypes.addressof(structure), struct_data, fit_len)
|
||||
|
||||
return structure
|
||||
|
||||
if len(sys.argv) >= 2 :
|
||||
# Drag & Drop or CLI
|
||||
pfat = sys.argv[1:]
|
||||
else :
|
||||
# Folder path
|
||||
pfat = []
|
||||
in_path = input('\nEnter the full folder path: ')
|
||||
print('\nWorking...')
|
||||
for root, dirs, files in os.walk(in_path):
|
||||
for name in files :
|
||||
pfat.append(os.path.join(root, name))
|
||||
|
||||
for input_file in pfat :
|
||||
with open(input_file, 'rb') as in_file : buffer = in_file.read()
|
||||
final_image = b''
|
||||
block_name = ''
|
||||
block_count = 0
|
||||
blocks = []
|
||||
|
||||
pfat_hdr = get_struct(buffer, 0, PFAT_Header)
|
||||
|
||||
if pfat_hdr.Tag.decode('utf-8', 'ignore') != '_AMIPFAT' : continue
|
||||
|
||||
hdr_size = pfat_hdr.Size
|
||||
hdr_data = buffer[0x11:hdr_size].decode('utf-8').splitlines()
|
||||
|
||||
pfat_hdr.pfat_print()
|
||||
print(' Title : %s' % hdr_data[0])
|
||||
|
||||
for entry in hdr_data[1:] :
|
||||
entry_data = entry.split(' ')
|
||||
entry_data = [s for s in entry_data if s != '']
|
||||
entry_flash = int(entry_data[0])
|
||||
entry_param = entry_data[1]
|
||||
entry_blocks = int(entry_data[2])
|
||||
entry_name = entry_data[3][1:]
|
||||
|
||||
for i in range(entry_blocks) : blocks.append([entry_name, entry_param, entry_flash, i + 1, entry_blocks])
|
||||
|
||||
block_count += entry_blocks
|
||||
|
||||
block_start = hdr_size
|
||||
for i in range(block_count) :
|
||||
if blocks[i][0] != block_name : print('\n%s (Parameter: %s, Update: %s)' % (blocks[i][0], blocks[i][1], ['No','Yes'][blocks[i][2]]))
|
||||
block_hdr = get_struct(buffer, block_start, PFAT_Block_Header, ['%d/%d' % (blocks[i][3], blocks[i][4])])
|
||||
block_hdr_size = ctypes.sizeof(PFAT_Block_Header)
|
||||
block_flag_size = block_hdr.FlagsSize
|
||||
flag_data = buffer[block_start + block_hdr_size:block_start + block_hdr_size + block_flag_size] # Flags not parsed
|
||||
block_data_start = block_start + block_hdr_size + block_flag_size
|
||||
block_data_end = block_data_start + block_hdr.DataSize
|
||||
block_hdr.pfat_print()
|
||||
|
||||
block_rsa = get_struct(buffer, block_data_end, PFAT_Block_RSA, ['%d/%d' % (blocks[i][3], blocks[i][4])])
|
||||
block_rsa_size = ctypes.sizeof(PFAT_Block_RSA)
|
||||
#block_rsa_exp = block_rsa.Exponent
|
||||
#block_rsa_pkey = int((''.join('%0.8X' % int.from_bytes(struct.pack('<I', val), 'little') for val in reversed(block_rsa.PublicKey))), 16)
|
||||
#block_rsa_sign = int((''.join('%0.8X' % int.from_bytes(struct.pack('<I', val), 'little') for val in reversed(block_rsa.Signature))), 16)
|
||||
#block_rsa_sign_dec = '%X' % pow(block_rsa_sign, block_rsa_exp, block_rsa_pkey) # Decrypted signature is 4096 bits
|
||||
block_rsa.pfat_print()
|
||||
|
||||
final_image += buffer[block_data_start:block_data_end]
|
||||
|
||||
block_name = blocks[i][0]
|
||||
block_start = block_data_end + block_rsa_size
|
||||
|
||||
with open('%s_unpacked.bin' % os.path.basename(input_file), 'wb') as final : final.write(final_image)
|
||||
|
||||
else :
|
||||
input('\nDone!')
|
44
README.md
44
README.md
|
@ -5,7 +5,7 @@ Various BIOS Utilities for Modding/Research
|
|||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DJDZD3PRGCSCL)
|
||||
|
||||

|
||||

|
||||
|
||||
## **Dell HDR Module Extractor**
|
||||
|
||||
|
@ -49,6 +49,46 @@ PyInstaller can build/freeze/compile the utility at all three supported platform
|
|||
|
||||
At dist folder you should find the final utility executable
|
||||
|
||||
## **AMI BIOS Guard Extractor**
|
||||
|
||||
#### **Description**
|
||||
|
||||
Parses AMI BIOS Guard (a.k.a. PFAT) images and extracts a proper SPI/BIOS image.
|
||||
|
||||
#### **Usage**
|
||||
|
||||
You can either Drag & Drop or manually enter the full path of a folder containing AMI PFAT images.
|
||||
|
||||
#### **Download**
|
||||
|
||||
An already built/frozen/compiled binary is provided by me for Windows only. Thus, **you don't need to manually build/freeze/compile it under Windows**. Instead, download the latest version from the [Releases](https://github.com/platomav/BIOSUtilities/releases) tab. To extract the already built/frozen/compiled archive, you need to use programs which support RAR5 compression. Note that you need to manually apply any prerequisites.
|
||||
|
||||
#### **Compatibility**
|
||||
|
||||
Should work at all Windows, Linux or macOS operating systems which have Python 3.6 support. Windows users who plan to use the already built/frozen/compiled binary must make sure that they have the latest Windows Updates installed which include all required "Universal C Runtime (CRT)" libraries.
|
||||
|
||||
#### **Prerequisites**
|
||||
|
||||
To run the utility, you do not need any 3rd party tool.
|
||||
|
||||
#### **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.6.0 or newer is installed:
|
||||
|
||||
> python --version
|
||||
|
||||
2. Use pip to install PyInstaller:
|
||||
|
||||
> pip3 install pyinstaller
|
||||
|
||||
3. Build/Freeze/Compile:
|
||||
|
||||
> pyinstaller --noupx --onefile AMI_PFAT_Extract.py
|
||||
|
||||
At dist folder you should find the final utility executable
|
||||
|
||||
## **Apple EFI Sucatalog Link Grabber**
|
||||
|
||||
#### **Description**
|
||||
|
@ -93,7 +133,7 @@ At dist folder you should find the final utility executable
|
|||
|
||||
#### **Description**
|
||||
|
||||
Parses Apple EFI files and renames them based on Apple's official $IBIOSI$ tag as follows: Model_Version_Build_Year_Month_Day_Hour_Minute_Checksum. The checksum is calculated and added by the utility in order to differentiate any EFI files with the same $IBIOSI$ tag. In rare cases in which the $IBIOSI$ tag is compressed, the utility automatically first uses [LongSoft's UEFIFind and UEFIExtract](https://github.com/LongSoft/UEFITool) tools.
|
||||
Parses Apple EFI files and renames them based on Intel's official $IBIOSI$ tag as follows: Model_Version_Build_Year_Month_Day_Hour_Minute_Checksum. The checksum is calculated and added by the utility in order to differentiate any EFI files with the same $IBIOSI$ tag. In rare cases in which the $IBIOSI$ tag is compressed, the utility automatically first uses [LongSoft's UEFIFind and UEFIExtract](https://github.com/LongSoft/UEFITool) tools.
|
||||
|
||||
#### **Usage**
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue