mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-18 21:30:15 +10:00
Initial commit - WPinternals 2.6
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace WPinternals
|
||||
{
|
||||
internal enum QualcommPartitionHeaderType
|
||||
{
|
||||
Long,
|
||||
Short
|
||||
};
|
||||
|
||||
internal class QualcommPartition
|
||||
{
|
||||
internal byte[] Binary;
|
||||
internal uint HeaderOffset;
|
||||
internal QualcommPartitionHeaderType HeaderType;
|
||||
internal uint ImageOffset;
|
||||
internal uint ImageAddress;
|
||||
internal uint ImageSize;
|
||||
internal uint CodeSize;
|
||||
internal uint SignatureAddress;
|
||||
internal uint SignatureSize;
|
||||
internal uint SignatureOffset;
|
||||
internal uint CertificatesAddress;
|
||||
internal uint CertificatesSize;
|
||||
internal uint CertificatesOffset;
|
||||
internal byte[] RootKeyHash = null;
|
||||
|
||||
internal QualcommPartition(string Path): this(File.ReadAllBytes(Path)) { }
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user