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); }
// 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()); }
// 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); }
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; } } }
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); }