예제 #1
0
        internal string GetFirmwareVersion()
        {
            string Result = null;

            Partition Plat = GPT.GetPartition("PLAT");

            if (Plat != null)
            {
                byte[] Data   = GetPartition("PLAT");
                uint?  Offset = ByteOperations.FindAscii(Data, "SWVERSION=");
                if (Offset != null)
                {
                    uint Start    = (uint)Offset + 10;
                    uint Length   = (uint)ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x00 }, null, null) - Start;
                    uint?Offset0D = ByteOperations.FindPattern(Data, Start, 0x100, new byte[] { 0x0D }, null, null);
                    if ((Offset0D != null) && (Offset0D < (Start + Length)))
                    {
                        Length = (uint)Offset0D - Start;
                    }

                    Result = ByteOperations.ReadAsciiString(Data, Start, Length);
                }
            }

            return(Result);
        }
예제 #2
0
        // Magic!
        internal byte[] Patch()
        {
            byte[] SecurityDxe = GetFile("SecurityDxe");
            ClearEfiChecksum(SecurityDxe);

            UInt32?PatchOffset = ByteOperations.FindPattern(SecurityDxe,
                                                            new byte[] { 0xF0, 0x41, 0x2D, 0xE9, 0xFF, 0xFF, 0xB0, 0xE1, 0x28, 0xD0, 0x4D, 0xE2, 0xFF, 0xFF, 0xA0, 0xE1, 0x00, 0x00, 0xFF, 0x13, 0x20, 0xFF, 0xA0, 0xE3 },
                                                            new byte[] { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00 },
                                                            null);

            if (PatchOffset == null)
            {
                throw new BadImageFormatException();
            }

            Buffer.BlockCopy(new byte[] { 0x00, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1 }, 0, SecurityDxe, (int)PatchOffset, 8);

            ReplaceFile("SecurityDxe", SecurityDxe);

            byte[] SecurityServicesDxe = GetFile("SecurityServicesDxe");
            ClearEfiChecksum(SecurityServicesDxe);

            PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe,
                                                     new byte[] { 0x10, 0xFF, 0xFF, 0xE5, 0x80, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A },
                                                     new byte[] { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00 },
                                                     null);

            if (PatchOffset == null)
            {
                throw new BadImageFormatException();
            }

            ByteOperations.WriteUInt8(SecurityServicesDxe, (UInt32)PatchOffset + 0x0B, 0xEA);

            PatchOffset = ByteOperations.FindPattern(SecurityServicesDxe,
                                                     new byte[] { 0x11, 0xFF, 0xFF, 0xE5, 0x40, 0xFF, 0x10, 0xE3, 0xFF, 0xFF, 0xFF, 0x0A },
                                                     new byte[] { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00 },
                                                     null);

            if (PatchOffset == null)
            {
                throw new BadImageFormatException();
            }

            ByteOperations.WriteUInt8(SecurityServicesDxe, (UInt32)PatchOffset + 0x0B, 0xEA);

            ReplaceFile("SecurityServicesDxe", SecurityServicesDxe);

            return(Rebuild());
        }
예제 #3
0
        // Magic!
        internal byte[] Patch()
        {
            UInt32?PatchOffset = ByteOperations.FindPattern(Binary,
                                                            new byte[] { 0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1 },
                                                            null, null);

            if (PatchOffset == null)
            {
                throw new BadImageFormatException();
            }

            Buffer.BlockCopy(new byte[] { 0x00, 0x00, 0xA0, 0xE3 }, 0, Binary, (int)PatchOffset + 4, 4);

            return(Binary);
        }
예제 #4
0
        internal QualcommPartition(byte[] Binary, uint Offset = 0)
        {
#if DEBUG
            System.Diagnostics.Debug.Print("Loader: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, 0, Binary.Length), ""));
#endif

            this.Binary = Binary;

            byte[] LongHeaderPattern = new byte[] { 0xD1, 0xDC, 0x4B, 0x84, 0x34, 0x10, 0xD7, 0x73, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
            byte[] LongHeaderMask    = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

            if (ByteOperations.FindPattern(Binary, Offset, 4, new byte[] { 0x7F, 0x45, 0x4C, 0x46 }, new byte[] { 0x00, 0x00, 0x00, 0x00 }, null) == 0)
            {
                // This is an ELF image
                // First program header is a reference to the elf-header
                // Second program header is a reference to the signed hash-table
                HeaderType = QualcommPartitionHeaderType.Short;
                UInt32 ProgramHeaderOffset;
                UInt16 ProgramHeaderEntrySize;
                UInt32 HashTableProgramHeaderOffset;
                if (Binary[Offset + 0x04] == 1)
                {
                    // 32-bit elf image
                    ProgramHeaderOffset          = Offset + ByteOperations.ReadUInt32(Binary, Offset + 0x1c);
                    ProgramHeaderEntrySize       = ByteOperations.ReadUInt16(Binary, Offset + 0x2a);
                    HashTableProgramHeaderOffset = ProgramHeaderOffset + ProgramHeaderEntrySize;
                    ImageOffset  = Offset + ByteOperations.ReadUInt32(Binary, HashTableProgramHeaderOffset + 0x04);
                    HeaderOffset = ImageOffset + 8;
                }
                else if (Binary[Offset + 0x04] == 2)
                {
                    // 64-bit elf image
                    ProgramHeaderOffset          = Offset + ByteOperations.ReadUInt32(Binary, Offset + 0x20);
                    ProgramHeaderEntrySize       = ByteOperations.ReadUInt16(Binary, Offset + 0x36);
                    HashTableProgramHeaderOffset = ProgramHeaderOffset + ProgramHeaderEntrySize;
                    ImageOffset  = Offset + (UInt32)ByteOperations.ReadUInt64(Binary, HashTableProgramHeaderOffset + 0x08);
                    HeaderOffset = ImageOffset + 8;
                }
                else
                {
                    throw new WPinternalsException("Invalid programmer");
                }
            }
            else if (ByteOperations.FindPattern(Binary, Offset, (uint)LongHeaderPattern.Length, LongHeaderPattern, LongHeaderMask, null) == null)
            {
                HeaderType   = QualcommPartitionHeaderType.Short;
                ImageOffset  = Offset;
                HeaderOffset = ImageOffset + 8;
            }
            else
            {
                HeaderType   = QualcommPartitionHeaderType.Long;
                ImageOffset  = Offset;
                HeaderOffset = ImageOffset + (uint)LongHeaderPattern.Length;
            }

            if (ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00) != 0)
            {
                ImageOffset = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X00);
            }
            else if (HeaderType == QualcommPartitionHeaderType.Short)
            {
                ImageOffset += 0x28;
            }
            else
            {
                ImageOffset += 0x50;
            }

            ImageAddress        = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X04);
            ImageSize           = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X08);
            CodeSize            = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X0C);
            SignatureAddress    = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X10);
            SignatureSize       = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X14);
            SignatureOffset     = SignatureAddress - ImageAddress + ImageOffset;
            CertificatesAddress = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X18);
            CertificatesSize    = ByteOperations.ReadUInt32(Binary, HeaderOffset + 0X1C);
            CertificatesOffset  = CertificatesAddress - ImageAddress + ImageOffset;

            uint CurrentCertificateOffset = CertificatesOffset;
            uint CertificateSize          = 0;
            while (CurrentCertificateOffset < (CertificatesOffset + CertificatesSize))
            {
                if ((Binary[CurrentCertificateOffset] == 0x30) && (Binary[CurrentCertificateOffset + 1] == 0x82))
                {
                    CertificateSize = (uint)(Binary[CurrentCertificateOffset + 2] * 0x100) + Binary[CurrentCertificateOffset + 3] + 4; // Big endian!

                    if ((CurrentCertificateOffset + CertificateSize) == (CertificatesOffset + CertificatesSize))
                    {
                        // This is the last certificate. So this is the root key.
                        RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize);

#if DEBUG
                        System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif
                    }
#if DEBUG
                    else
                    {
                        System.Diagnostics.Debug.Print("Cert: " + Converter.ConvertHexToString(new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize), ""));
                    }
#endif
                    CurrentCertificateOffset += CertificateSize;
                }
                else
                {
                    if ((RootKeyHash == null) && (CurrentCertificateOffset > CertificatesOffset))
                    {
                        CurrentCertificateOffset -= CertificateSize;

                        // This is the last certificate. So this is the root key.
                        RootKeyHash = new SHA256Managed().ComputeHash(Binary, (int)CurrentCertificateOffset, (int)CertificateSize);

#if DEBUG
                        System.Diagnostics.Debug.Print("RKH: " + Converter.ConvertHexToString(RootKeyHash, ""));
#endif
                    }
                    break;
                }
            }
        }
예제 #5
0
        internal byte[] GenerateExtraSector(byte[] PartitionHeader)
        {
            UInt32?Offset = ByteOperations.FindPattern(Binary,
                                                       new byte[] {
                0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            }, null, null);

            if (Offset == null)
            {
                throw new BadImageFormatException();
            }

            UInt32 PartitionLoaderTableOffset = (UInt32)Offset;

            byte[] FoundPattern = new byte[0x10];
            Offset = ByteOperations.FindPattern(Binary,
                                                new byte[] {
                0x04, 0x00, 0x9F, 0xE5, 0x28, 0x00, 0xD0, 0xE5, 0x1E, 0xFF, 0x2F, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF
            },
                                                new byte[] {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
            },
                                                FoundPattern);
            if (Offset == null)
            {
                throw new BadImageFormatException();
            }

            UInt32 SharedMemoryAddress            = ByteOperations.ReadUInt32(FoundPattern, 0x0C);
            UInt32 GlobalIsSecurityEnabledAddress = SharedMemoryAddress + 0x28;

            Offset = ByteOperations.FindPattern(Binary,
                                                new byte[] {
                0x01, 0xFF, 0xA0, 0xE3, 0xFF, 0xFF, 0xA0, 0xE1, 0x1C, 0xD0, 0x8D, 0xE2, 0xF0, 0x4F, 0xBD, 0xE8,
                0x1E, 0xFF, 0x2F, 0xE1
            },
                                                new byte[] {
                0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00
            },
                                                null);
            if (Offset == null)
            {
                throw new BadImageFormatException();
            }

            UInt32 ReturnAddress = (UInt32)Offset - ImageOffset + ImageAddress;

            byte[] Sector = new byte[0x200];
            Array.Clear(Sector, 0, 0x200);

            byte[] Content = new byte[] {
                0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0xBD, 0x02, 0x00,
                0xD8, 0x01, 0x00, 0x00, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0xE3, 0x3C, 0x10, 0x9F, 0xE5,
                0x00, 0x00, 0xC1, 0xE5, 0x38, 0x00, 0x9F, 0xE5, 0x38, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x81, 0xE5,
                0x34, 0x10, 0x9F, 0xE5, 0x00, 0x00, 0x81, 0xE5, 0x30, 0x00, 0x9F, 0xE5, 0x20, 0x10, 0x9F, 0xE5,
                0x2C, 0x30, 0x9F, 0xE5, 0x00, 0x20, 0x90, 0xE5, 0x00, 0x20, 0x81, 0xE5, 0x04, 0x00, 0x80, 0xE2,
                0x04, 0x10, 0x81, 0xE2, 0x03, 0x00, 0x50, 0xE1, 0xF9, 0xFF, 0xFF, 0xBA, 0x14, 0xF0, 0x9F, 0xE5,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x90, 0xBF, 0x02, 0x00, 0xD0, 0xBF, 0x02, 0x00,
                0xA0, 0xBD, 0x02, 0x00, 0xA0, 0xBE, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
            };

            byte[] PartitionTypeGuid = new byte[] {
                0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74
            };

            Buffer.BlockCopy(Content, 0, Sector, 0, Content.Length);

            // Overwrite first part of partition-header with model-specific header
            Buffer.BlockCopy(PartitionHeader, 0, Sector, 0, PartitionHeader.Length);

            ByteOperations.WriteUInt32(Sector, 0x70, GlobalIsSecurityEnabledAddress);
            ByteOperations.WriteUInt32(Sector, 0x88, ReturnAddress);

            Buffer.BlockCopy(Binary, (int)PartitionLoaderTableOffset, Sector, 0xA0, 0x50);
            ByteOperations.WriteUInt32(Sector, 0xA0 + 0x30, 0);

            Buffer.BlockCopy(Binary, (int)PartitionLoaderTableOffset, Sector, 0xF0, 0x50);
            ByteOperations.WriteUInt32(Sector, 0xF0 + 0x2C, 0);
            ByteOperations.WriteUInt32(Sector, 0xF0 + 0x38, 0x210F0);

            Buffer.BlockCopy(PartitionTypeGuid, 0, Sector, 0x190, 0x10);

            ByteOperations.WriteUInt32(Sector, 0x1FC, 0x0002BD28);

            return(Sector);
        }