Exemplo n.º 1
0
def modify_uefi_region(data, command, guid, uefi_file = ''):
    RgLengthChange = 0
    fv = NextFwVolume(data)
    while fv is not None:
        FvLengthChange = 0
        polarity = bit_set(fv.Attributes, EFI_FVB2_ERASE_POLARITY)
        if ((fv.Guid == EFI_FIRMWARE_FILE_SYSTEM2_GUID) or (fv.Guid == EFI_FIRMWARE_FILE_SYSTEM_GUID)):
            fwbin = NextFwFile(fv.Image, fv.Size, fv.HeaderSize, polarity)
            while fwbin is not None:
                next_offset = fwbin.Size + fwbin.Offset
                if (fwbin.Guid == guid):
                    uefi_file_size = (len(uefi_file) + 7) & 0xFFFFFFF8
                    CurFileOffset  = fv.Offset + fwbin.Offset  + FvLengthChange
                    NxtFileOffset  = fv.Offset + next_offset + FvLengthChange
                    if command == CMD_UEFI_FILE_REMOVE:
                        FvLengthChange -= (next_offset - fwbin.Offset)
                        logger().log( "Removing UEFI file with GUID={} at offset={:08X}, size change: {:d} bytes".format(fwbin.Guid, CurFileOffset, FvLengthChange) )
                        data = data[:CurFileOffset] + data[NxtFileOffset:]
                    elif command == CMD_UEFI_FILE_INSERT_BEFORE:
                        FvLengthChange += uefi_file_size
                        logger().log( "Inserting UEFI file before file with GUID={} at offset={:08X}, size change: {:d} bytes".format(fwbin.Guid, CurFileOffset, FvLengthChange) )
                        data = data[:CurFileOffset] + uefi_file.ljust(uefi_file_size, '\xFF') + data[CurFileOffset:]
                    elif command == CMD_UEFI_FILE_INSERT_AFTER:
                        FvLengthChange += uefi_file_size
                        logger().log( "Inserting UEFI file after file with GUID={} at offset={:08X}, size change: {:d} bytes".format(fwbin.Guid, CurFileOffset, FvLengthChange) )
                        data = data[:NxtFileOffset] + uefi_file.ljust(uefi_file_size, '\xFF') + data[NxtFileOffset:]
                    elif command == CMD_UEFI_FILE_REPLACE:
                        FvLengthChange += uefi_file_size - (next_offset - fwbin.Offset)
                        logger().log( "Replacing UEFI file with GUID={} at offset={:08X}, new size: {:d}, old size: {:d}, size change: {:d} bytes".format(fwbin.Guid, CurFileOffset, len(uefi_file), fwbin.Size, FvLengthChange) )
                        data = data[:CurFileOffset] + uefi_file.ljust(uefi_file_size, '\xFF') + data[NxtFileOffset:]
                    else:
                        raise Exception('Invalid command')

                if next_offset - fwbin.Offset >= 24:
                    FvEndOffset = fv.Offset + next_offset + FvLengthChange

                fwbin = NextFwFile(fv.Image, fv.Size, next_offset, polarity)

            if FvLengthChange >= 0:
                data = data[:FvEndOffset] + data[FvEndOffset + FvLengthChange:]
            else:
                data = data[:FvEndOffset] + (abs(FvLengthChange) * '\xFF') + data[FvEndOffset:]

            FvLengthChange = 0

            #if FvLengthChange != 0:
            #    logger().log( "Rebuilding Firmware Volume with GUID={} at offset={:08X}".format(FsGuid, FvOffset) )
            #    FvHeader = data[FvOffset: FvOffset + FvHeaderLength]
            #    FvHeader = FvHeader[:0x20] + struct.pack('<Q', FvLength) + FvHeader[0x28:]
            #    NewChecksum = FvChecksum16(FvHeader[:0x32] + '\x00\x00' + FvHeader[0x34:])
            #    FvHeader = FvHeader[:0x32] + struct.pack('<H', NewChecksum) + FvHeader[0x34:]
            #    data = data[:FvOffset] + FvHeader + data[FvOffset + FvHeaderLength:]

        fv = NextFwVolume(data, fv.Offset + fv.Size)
    return data
Exemplo n.º 2
0
def NextFwFile(FvImage, FvLength, fof, polarity):
    file_header_size = struct.calcsize(EFI_FFS_FILE_HEADER)
    fof = align(fof, 8)
    cur_offset = fof
    res = None
    update_or_deleted = False

    while cur_offset + file_header_size < min(FvLength, len(FvImage)):
        fsize = 0
        #if (fof + file_header_size) <= min(FvLength, len(FvImage)):
        #Check for a blank header
        if polarity:
            blank = b"\xff" * file_header_size
        else:
            blank = b"\x00" * file_header_size

        if (blank == FvImage[cur_offset:cur_offset + file_header_size]):
            #next_offset = fof + 8
            cur_offset += 8
            continue
        Name0, IntegrityCheck, Type, Attributes, Size, State = struct.unpack(
            EFI_FFS_FILE_HEADER,
            FvImage[cur_offset:cur_offset + file_header_size])
        #Get File Header Size
        if Attributes & FFS_ATTRIB_LARGE_FILE:
            header_size = struct.calcsize(EFI_FFS_FILE_HEADER2)
        else:
            header_size = struct.calcsize(EFI_FFS_FILE_HEADER)

        #Get File size
        if Attributes & FFS_ATTRIB_LARGE_FILE and len(
                FvImage) > fof + struct.calcsize(EFI_FFS_FILE_HEADER2):
            fsize = struct.unpack(
                "Q", FvImage[fof + file_header_size:fof + file_header_size +
                             struct.calcsize("Q")])[0]
            fsize &= 0xFFFFFFFF
        if fsize == 0 or fsize > FvLength - cur_offset:
            fsize = get_3b_size(Size)

        #Validate fsize is a legal value
        if fsize == 0 or fsize > FvLength - cur_offset:
            logger().log(
                "Unable to get correct file size for NextFwFile corrupt header information"
            )
            break
        #Get next_offset
        update_or_deleted = (bit_set(State, EFI_FILE_MARKED_FOR_UPDATE,
                                     polarity)) or (bit_set(
                                         State, EFI_FILE_DELETED, polarity))
        if not ((bit_set(State, EFI_FILE_DATA_VALID, polarity))
                or update_or_deleted):
            #else:
            cur_offset = align(cur_offset + 1, 8)
            continue
        Name = UUID(bytes_le=Name0)
        #TODO need to fix up checksum?
        fheader = struct.pack(EFI_FFS_FILE_HEADER, Name0, 0, Type, Attributes,
                              Size, 0)
        hsum = FvChecksum8(fheader)
        if (Attributes & FFS_ATTRIB_CHECKSUM):
            fsum = FvChecksum8(FvImage[cur_offset +
                                       file_header_size:cur_offset + fsize])
        else:
            fsum = FFS_FIXED_CHECKSUM
        CalcSum = (hsum | (fsum << 8))
        res = EFI_FILE(cur_offset, Name, Type, Attributes, State,
                       IntegrityCheck, fsize,
                       FvImage[cur_offset:cur_offset + fsize], header_size,
                       update_or_deleted, CalcSum)
        break
    return res