Implement Qualcomm Sahara VIP and fix a few bugs

* Qualcomm Sahara VIP
* Project Cleanup
* Allow unlocking an already unlocked phone
This commit is contained in:
Gustave Monce
2021-08-11 14:33:49 +02:00
parent 9f4c92f437
commit c5fcb1ec8d
72 changed files with 987 additions and 861 deletions
+11 -16
View File
@@ -48,7 +48,7 @@ namespace WPinternals
Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
}
byte[] TextBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(Text);
byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(Text);
int WriteLength = TextBytes.Length;
if (WriteLength > MaxBufferLength)
{
@@ -65,7 +65,7 @@ namespace WPinternals
Array.Clear(ByteArray, (int)Offset, (int)MaxBufferLength);
}
byte[] TextBytes = System.Text.UnicodeEncoding.Unicode.GetBytes(Text);
byte[] TextBytes = System.Text.Encoding.Unicode.GetBytes(Text);
int WriteLength = TextBytes.Length;
if (WriteLength > MaxBufferLength)
{
@@ -82,7 +82,7 @@ namespace WPinternals
internal static void WriteUInt32(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
}
internal static Int32 ReadInt32(byte[] ByteArray, UInt32 Offset)
@@ -92,7 +92,7 @@ namespace WPinternals
internal static void WriteInt32(byte[] ByteArray, UInt32 Offset, Int32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 4);
}
internal static UInt16 ReadUInt16(byte[] ByteArray, UInt32 Offset)
@@ -102,7 +102,7 @@ namespace WPinternals
internal static void WriteUInt16(byte[] ByteArray, UInt32 Offset, UInt16 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
}
internal static Int16 ReadInt16(byte[] ByteArray, UInt32 Offset)
@@ -112,7 +112,7 @@ namespace WPinternals
internal static void WriteInt16(byte[] ByteArray, UInt32 Offset, Int16 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 2);
}
internal static byte ReadUInt8(byte[] ByteArray, UInt32 Offset)
@@ -132,7 +132,7 @@ namespace WPinternals
internal static void WriteUInt24(byte[] ByteArray, UInt32 Offset, UInt32 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 3);
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 3);
}
internal static UInt64 ReadUInt64(byte[] ByteArray, UInt32 Offset)
@@ -142,7 +142,7 @@ namespace WPinternals
internal static void WriteUInt64(byte[] ByteArray, UInt32 Offset, UInt64 Value)
{
System.Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8);
Buffer.BlockCopy(BitConverter.GetBytes(Value), 0, ByteArray, (int)Offset, 8);
}
internal static Guid ReadGuid(byte[] ByteArray, UInt32 Offset)
@@ -241,12 +241,12 @@ namespace WPinternals
internal static UInt32? FindAscii(byte[] SourceBuffer, string Pattern)
{
return FindPattern(SourceBuffer, System.Text.ASCIIEncoding.ASCII.GetBytes(Pattern), null, null);
return FindPattern(SourceBuffer, System.Text.Encoding.ASCII.GetBytes(Pattern), null, null);
}
internal static UInt32? FindUnicode(byte[] SourceBuffer, string Pattern)
{
return FindPattern(SourceBuffer, System.Text.UnicodeEncoding.Unicode.GetBytes(Pattern), null, null);
return FindPattern(SourceBuffer, System.Text.Encoding.Unicode.GetBytes(Pattern), null, null);
}
internal static UInt32? FindUint(byte[] SourceBuffer, UInt32 Pattern)
@@ -296,7 +296,7 @@ namespace WPinternals
if (OutPattern != null)
{
System.Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length);
Buffer.BlockCopy(SourceBuffer, (int)SearchPosition, OutPattern, 0, Pattern.Length);
}
break;
@@ -394,11 +394,6 @@ namespace WPinternals
}
crc = (uint)(crc ^ (-1));
if (crc < 0)
{
crc += (uint)4294967296;
}
return crc;
}
}
+8 -14
View File
@@ -110,12 +110,9 @@ namespace WPinternals
DiskAccessMethod = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x08 + (j * 0x08)));
ChunkIndex = ByteOperations.ReadInt32(StoreHeader, (UInt32)(WriteDescriptorEntryOffset + 0x0C + (j * 0x08)));
if (DiskAccessMethod == 0) // 0 = From begin, 2 = From end. We ignore chunks at end of disk. These contain secondairy GPT.
if (DiskAccessMethod == 0 && (ChunkIndex + ChunkCount - 1) > HighestChunkIndex) // 0 = From begin, 2 = From end. We ignore chunks at end of disk. These contain secondairy GPT.
{
if ((ChunkIndex + ChunkCount - 1) > HighestChunkIndex)
{
HighestChunkIndex = ChunkIndex + ChunkCount - 1;
}
HighestChunkIndex = ChunkIndex + ChunkCount - 1;
}
}
WriteDescriptorEntryOffset += 8 + (LocationCount * 0x08);
@@ -183,7 +180,7 @@ namespace WPinternals
byte[] Signature = new byte[0x10];
FFUFile.Read(Signature, 0, 0x10);
Result = (ByteOperations.ReadAsciiString(Signature, 0x04, 0x0C) == "SignedImage ");
Result = ByteOperations.ReadAsciiString(Signature, 0x04, 0x0C) == "SignedImage ";
FFUFile.Close();
@@ -214,12 +211,9 @@ namespace WPinternals
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/2e67ca57-3556-4275-accd-58b7df30d424/unnecessary-filestreamseek-and-setting-filestreamposition-has-huge-effect-on-performance?forum=csharpgeneral
if (FFUFile != null)
if (FFUFile != null && FFUFile.Position != Position)
{
if (FFUFile.Position != Position)
{
FFUFile.Seek(Position, SeekOrigin.Begin);
}
FFUFile.Seek(Position, SeekOrigin.Begin);
}
}
@@ -239,7 +233,7 @@ namespace WPinternals
{
if ((Size % ChunkSize) > 0)
{
return (UInt32)((Size / ChunkSize) * ChunkSize);
return (UInt32)(Size / ChunkSize * ChunkSize);
}
else
{
@@ -292,7 +286,7 @@ namespace WPinternals
internal byte[] GetPartition(string Name)
{
Partition Target = GPT.Partitions.Find(p => (string.Compare(p.Name, Name, true) == 0));
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null)
{
throw new ArgumentOutOfRangeException();
@@ -318,7 +312,7 @@ namespace WPinternals
private void WritePartition(string Name, string FilePath, Action<int, TimeSpan?> ProgressUpdateCallback, ProgressUpdater UpdaterPerSector, bool Compress = false)
{
Partition Target = GPT.Partitions.Find(p => (string.Compare(p.Name, Name, true) == 0));
Partition Target = GPT.Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
if (Target == null)
{
throw new ArgumentOutOfRangeException();
+15 -18
View File
@@ -96,16 +96,16 @@ namespace WPinternals
internal Partition GetPartition(string Name)
{
return Partitions.Find(p => (string.Compare(p.Name, Name, true) == 0));
return Partitions.Find(p => string.Equals(p.Name, Name, StringComparison.CurrentCultureIgnoreCase));
}
// Magic!
// SecureBoot hack for Bootloader Spec A starts here
internal byte[] InsertHack()
{
Partition HackPartition = Partitions.Find(p => (p.Name == "HACK"));
Partition SBL1 = Partitions.Find(p => (p.Name == "SBL1"));
Partition SBL2 = Partitions.Find(p => (p.Name == "SBL2"));
Partition HackPartition = Partitions.Find(p => p.Name == "HACK");
Partition SBL1 = Partitions.Find(p => p.Name == "SBL1");
Partition SBL2 = Partitions.Find(p => p.Name == "SBL2");
if ((SBL1 == null) || (SBL2 == null))
{
@@ -140,9 +140,9 @@ namespace WPinternals
internal byte[] RemoveHack()
{
Partition HackPartition = Partitions.Find(p => (p.Name == "HACK"));
Partition SBL1 = Partitions.Find(p => (p.Name == "SBL1"));
Partition SBL2 = Partitions.Find(p => (p.Name == "SBL2"));
Partition HackPartition = Partitions.Find(p => p.Name == "HACK");
Partition SBL1 = Partitions.Find(p => p.Name == "SBL1");
Partition SBL2 = Partitions.Find(p => p.Name == "SBL2");
if ((SBL1 == null) || (SBL2 == null))
{
@@ -227,7 +227,7 @@ namespace WPinternals
{
foreach (Partition NewPartition in GptToMerge.Partitions)
{
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => ((string.Compare(e.Name, NewPartition.Name, true) == 0) || (e.Name.StartsWith(NewPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")))));
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => string.Equals(e.Name, NewPartition.Name, StringComparison.CurrentCultureIgnoreCase) || e.Name.StartsWith(NewPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")));
if (Entry == null)
{
// There is a partition entry in the xml, but this partition is not present in the archive.
@@ -342,7 +342,7 @@ namespace WPinternals
Partition OldPartition = SortedPartitions.ElementAt(i);
// Present in archive?
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => ((string.Compare(e.Name, OldPartition.Name, true) == 0) || (e.Name.StartsWith(OldPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")))));
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => string.Equals(e.Name, OldPartition.Name, StringComparison.CurrentCultureIgnoreCase) || e.Name.StartsWith(OldPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")));
if (Entry != null)
{
// Not present in new GPT or present in GPT without FirstSector?
@@ -378,7 +378,7 @@ namespace WPinternals
foreach (Partition NewPartition in GptToMerge.Partitions)
{
// If the new partition is a dynamic partition, then skip it here. It will be added later.
if (DynamicPartitions.Select(p => p.Name).Any(n => string.Compare(n, NewPartition.Name, true) == 0))
if (DynamicPartitions.Select(p => p.Name).Any(n => string.Equals(n, NewPartition.Name, StringComparison.CurrentCultureIgnoreCase)))
{
continue;
}
@@ -448,13 +448,10 @@ namespace WPinternals
for (int i = this.Partitions.Count - 1; i >= 0; i--)
{
if (this.Partitions[i] != CurrentPartition)
if (this.Partitions[i] != CurrentPartition && (CurrentPartition.FirstSector <= this.Partitions[i].LastSector) && (CurrentPartition.LastSector >= this.Partitions[i].FirstSector))
{
if ((CurrentPartition.FirstSector <= this.Partitions[i].LastSector) && (CurrentPartition.LastSector >= this.Partitions[i].FirstSector))
{
this.Partitions.RemoveAt(i);
HasChanged = true;
}
this.Partitions.RemoveAt(i);
HasChanged = true;
}
}
}
@@ -465,7 +462,7 @@ namespace WPinternals
// Check if the sizes of the partitions in the archive do not exceed the size of the partition, as listed in the GPT.
foreach (Partition OldPartition in this.Partitions)
{
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => ((string.Compare(e.Name, OldPartition.Name, true) == 0) || (e.Name.StartsWith(OldPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")))));
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => string.Equals(e.Name, OldPartition.Name, StringComparison.CurrentCultureIgnoreCase) || e.Name.StartsWith(OldPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")));
if (Entry != null)
{
DecompressedStream DecompressedStream = new(Entry.Open());
@@ -517,7 +514,7 @@ namespace WPinternals
NewPartition.FirstSector = FirstFreeSector;
HasChanged = true;
}
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => ((string.Compare(e.Name, NewPartition.Name, true) == 0) || (e.Name.StartsWith(NewPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")))));
ZipArchiveEntry Entry = Archive.Entries.FirstOrDefault(e => string.Equals(e.Name, NewPartition.Name, StringComparison.CurrentCultureIgnoreCase) || e.Name.StartsWith(NewPartition.Name + ".", true, System.Globalization.CultureInfo.GetCultureInfo("en-US")));
DecompressedStream DecompressedStream = new(Entry.Open());
ulong StreamLengthInSectors = (ulong)Entry.Length / 0x200;
try
+3 -3
View File
@@ -246,15 +246,15 @@ namespace WPinternals
BufferSize -= b.Length;
Monitor.Pulse(BufferQueue);
BytesRead += (b.Length - BufferOffset);
BytesRead += b.Length - BufferOffset;
BufferOffset = 0;
}
else
{
Array.Copy(b, BufferOffset, buffer, offset + BytesRead, count - BytesRead);
BufferOffset += (count - BytesRead);
BytesRead += (count - BytesRead);
BufferOffset += count - BytesRead;
BytesRead += count - BytesRead;
}
}
else
+7 -7
View File
@@ -51,23 +51,23 @@ namespace WPinternals
{
foreach (ManagementObject drive in partition.GetRelated("Win32_DiskDrive"))
{
if ((drive["PNPDeviceID"].ToString().Contains("VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.CurrentCulture)) ||
(drive["PNPDeviceID"].ToString().Contains("VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.CurrentCulture)))
if (drive["PNPDeviceID"].ToString().Contains("VEN_QUALCOMM&PROD_MMC_STORAGE", StringComparison.CurrentCulture) ||
drive["PNPDeviceID"].ToString().Contains("VEN_MSFT&PROD_PHONE_MMC_STOR", StringComparison.CurrentCulture))
{
Label = (logical["VolumeName"] == null ? "" : logical["VolumeName"].ToString());
if ((Drive == null) || (string.Compare(Label, "MainOS", true) == 0)) // Always prefer the MainOS drive-mapping
Label = logical["VolumeName"] == null ? "" : logical["VolumeName"].ToString();
if ((Drive == null) || string.Equals(Label, "MainOS", StringComparison.CurrentCultureIgnoreCase)) // Always prefer the MainOS drive-mapping
{
Drive = logical["Name"].ToString();
PhysicalDrive = drive["DeviceID"].ToString();
VolumeLabel = Label;
}
if (string.Compare(Label, "MainOS", true) == 0)
if (string.Equals(Label, "MainOS", StringComparison.CurrentCultureIgnoreCase))
{
break;
}
}
}
if (string.Compare(Label, "MainOS", true) == 0)
if (string.Equals(Label, "MainOS", StringComparison.CurrentCultureIgnoreCase))
{
break;
}
@@ -188,7 +188,7 @@ namespace WPinternals
internal bool IsVolumeOpen()
{
return (int)(hVolume) != -1;
return (int)hVolume != -1;
}
internal void CloseVolume()
+3 -3
View File
@@ -212,12 +212,12 @@ namespace WPinternals
internal const uint FILE_SHARE_DELETE = 0x00000004;
internal const uint OPEN_EXISTING = 3;
internal const uint GENERIC_READ = (0x80000000);
internal const uint GENERIC_WRITE = (0x40000000);
internal const uint GENERIC_READ = 0x80000000;
internal const uint GENERIC_WRITE = 0x40000000;
internal const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
internal const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
internal const uint FILE_READ_ATTRIBUTES = (0x0080);
internal const uint FILE_READ_ATTRIBUTES = 0x0080;
internal const uint FILE_WRITE_ATTRIBUTES = 0x0100;
internal const uint ERROR_INSUFFICIENT_BUFFER = 122;
internal const uint FILE_BEGIN = 0;
+68 -67
View File
@@ -33,6 +33,7 @@ namespace WPinternals
ProtocolAsyncV3 = 16
}
[Flags]
internal enum FlashOptions : byte
{
SkipWrite = 1,
@@ -57,8 +58,8 @@ namespace WPinternals
byte[] Request = new byte[0x0B];
const string Header = "NOKXFR";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Param), 0, Request, 7, Param.Length);
byte[] Response = ExecuteRawMethod(Request);
if ((Response == null) || (Response.Length < 0x10))
@@ -67,7 +68,7 @@ namespace WPinternals
}
byte[] Result = new byte[Response[0x10]];
System.Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
Buffer.BlockCopy(Response, 0x11, Result, 0, Response[0x10]);
return Result;
}
@@ -79,7 +80,7 @@ namespace WPinternals
return null;
}
return System.Text.ASCIIEncoding.ASCII.GetString(Bytes).Trim(new char[] { '\0' });
return System.Text.Encoding.ASCII.GetString(Bytes).Trim(new char[] { '\0' });
}
[Flags]
@@ -195,12 +196,12 @@ namespace WPinternals
byte[] AsskMask = new byte[0x10] { 1, 0, 16, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64 };
byte[] Request = new byte[0xAC];
const string Header = "NOKXFT";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Request[7] = 1;
System.Buffer.BlockCopy(BigEndian.GetBytes(0x18, 4), 0, Request, 0x08, 4); // Subblocktype = 0x18
System.Buffer.BlockCopy(BigEndian.GetBytes(0x9C, 4), 0, Request, 0x0C, 4); // Subblocklength = 0x9C
System.Buffer.BlockCopy(BigEndian.GetBytes(0x00, 4), 0, Request, 0x10, 4); // AsicIndex = 0x00
System.Buffer.BlockCopy(AsskMask, 0, Request, 0x14, 0x10);
Buffer.BlockCopy(BigEndian.GetBytes(0x18, 4), 0, Request, 0x08, 4); // Subblocktype = 0x18
Buffer.BlockCopy(BigEndian.GetBytes(0x9C, 4), 0, Request, 0x0C, 4); // Subblocklength = 0x9C
Buffer.BlockCopy(BigEndian.GetBytes(0x00, 4), 0, Request, 0x10, 4); // AsicIndex = 0x00
Buffer.BlockCopy(AsskMask, 0, Request, 0x14, 0x10);
byte[] TerminalResponse = ExecuteRawMethod(Request);
if ((TerminalResponse?.Length > 0x20) && (BigEndian.ToUInt32(TerminalResponse, 0x14) == (TerminalResponse.Length - 0x18)) && (BitConverter.ToUInt32(TerminalResponse, 0x1C) == (TerminalResponse.Length - 0x20)))
{
@@ -219,14 +220,14 @@ namespace WPinternals
byte[] Request = new byte[FfuHeader.Length + 0x20];
const string Header = "NOKXFS";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
System.Buffer.BlockCopy(BigEndian.GetBytes(0x0001, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes(0x0001, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Request[0x08] = 0; // Progress = 0%
Request[0x0B] = 1; // Subblock count = 1
System.Buffer.BlockCopy(BigEndian.GetBytes(0x0000000B, 4), 0, Request, 0x0C, 4); // Subblock type for header = 0x0B
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length + 0x0C, 4), 0, Request, 0x10, 4); // Subblock length = length of header + 0x0C
System.Buffer.BlockCopy(BigEndian.GetBytes(0x00000000, 4), 0, Request, 0x14, 4); // Header type = 0
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length, 4), 0, Request, 0x18, 4); // Payload length = length of header
Buffer.BlockCopy(BigEndian.GetBytes(0x0000000B, 4), 0, Request, 0x0C, 4); // Subblock type for header = 0x0B
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length + 0x0C, 4), 0, Request, 0x10, 4); // Subblock length = length of header + 0x0C
Buffer.BlockCopy(BigEndian.GetBytes(0x00000000, 4), 0, Request, 0x14, 4); // Header type = 0
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length, 4), 0, Request, 0x18, 4); // Payload length = length of header
Request[0x1C] = Options; // Header options = 0
Buffer.BlockCopy(FfuHeader, 0, Request, 0x20, FfuHeader.Length);
@@ -249,20 +250,20 @@ namespace WPinternals
byte[] Request = new byte[FfuHeader.Length + 0x3C];
const string Header = "NOKXFS";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
System.Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV2, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV2, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Request[0x08] = 0; // Progress = 0%
Request[0x0B] = 1; // Subblock count = 1
System.Buffer.BlockCopy(BigEndian.GetBytes(0x00000021, 4), 0, Request, 0x0C, 4); // Subblock type for header v2 = 0x21
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length + 0x28, 4), 0, Request, 0x10, 4); // Subblock starts at 0x14, payload starts at 0x3C.
Buffer.BlockCopy(BigEndian.GetBytes(0x00000021, 4), 0, Request, 0x0C, 4); // Subblock type for header v2 = 0x21
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length + 0x28, 4), 0, Request, 0x10, 4); // Subblock starts at 0x14, payload starts at 0x3C.
System.Buffer.BlockCopy(BigEndian.GetBytes(0x00000000, 4), 0, Request, 0x14, 4); // Header type = 0
System.Buffer.BlockCopy(BigEndian.GetBytes(TotalHeaderLength, 4), 0, Request, 0x18, 4); // Payload length = length of header
Buffer.BlockCopy(BigEndian.GetBytes(0x00000000, 4), 0, Request, 0x14, 4); // Header type = 0
Buffer.BlockCopy(BigEndian.GetBytes(TotalHeaderLength, 4), 0, Request, 0x18, 4); // Payload length = length of header
Request[0x1C] = Options; // Header options = 0
System.Buffer.BlockCopy(BigEndian.GetBytes(OffsetForThisPart, 4), 0, Request, 0x1D, 4);
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length, 4), 0, Request, 0x21, 4);
Buffer.BlockCopy(BigEndian.GetBytes(OffsetForThisPart, 4), 0, Request, 0x1D, 4);
Buffer.BlockCopy(BigEndian.GetBytes(FfuHeader.Length, 4), 0, Request, 0x21, 4);
Request[0x25] = 0; // No Erase
Buffer.BlockCopy(FfuHeader, 0, Request, 0x3C, FfuHeader.Length);
@@ -290,15 +291,15 @@ namespace WPinternals
byte[] Request = new byte[FfuChunk.Length + 0x1C];
const string Header = "NOKXFS";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
System.Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV1, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV1, 2), 0, Request, 0x06, 2); // Protocol version = 0x0001
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
System.Buffer.BlockCopy(BigEndian.GetBytes(0x0000000C, 4), 0, Request, 0x0C, 4); // Subblock type for ChunkData = 0x0C
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x08, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
Buffer.BlockCopy(BigEndian.GetBytes(0x0000000C, 4), 0, Request, 0x0C, 4); // Subblock type for ChunkData = 0x0C
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x08, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
Request[0x18] = Options; // Data options = 0 (1 = verify)
Buffer.BlockCopy(FfuChunk, 0, Request, 0x1C, FfuChunk.Length);
@@ -321,15 +322,15 @@ namespace WPinternals
byte[] Request = new byte[FfuChunk.Length + 0x20];
const string Header = "NOKXFS";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
System.Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV2, 2), 0, Request, 0x06, 2); // Protocol
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolSyncV2, 2), 0, Request, 0x06, 2); // Protocol
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
System.Buffer.BlockCopy(BigEndian.GetBytes(0x0000001B, 4), 0, Request, 0x0C, 4); // Subblock type for Payload v2 = 0x1B
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x0C, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
Buffer.BlockCopy(BigEndian.GetBytes(0x0000001B, 4), 0, Request, 0x0C, 4); // Subblock type for Payload v2 = 0x1B
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x0C, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
Request[0x18] = Options; // Data options = 0 (1 = verify)
Buffer.BlockCopy(FfuChunk, 0, Request, 0x20, FfuChunk.Length);
@@ -352,18 +353,18 @@ namespace WPinternals
byte[] Request = new byte[FfuChunk.Length + 0x20];
const string Header = "NOKXFS";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
System.Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolAsyncV3, 2), 0, Request, 0x06, 2); // Protocol
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(BigEndian.GetBytes((int)FfuProtocol.ProtocolAsyncV3, 2), 0, Request, 0x06, 2); // Protocol
Request[0x08] = (byte)Progress; // Progress = 0% (0 - 100)
Request[0x0B] = 1; // Subblock count = 1
System.Buffer.BlockCopy(BigEndian.GetBytes(0x0000001D, 4), 0, Request, 0x0C, 4); // Subblock type for Payload v2 = 0x1B
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x2C, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
Buffer.BlockCopy(BigEndian.GetBytes(0x0000001D, 4), 0, Request, 0x0C, 4); // Subblock type for Payload v2 = 0x1B
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length + 0x2C, 4), 0, Request, 0x10, 4); // Subblock length = length of chunk + 0x08
System.Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
Buffer.BlockCopy(BigEndian.GetBytes(FfuChunk.Length, 4), 0, Request, 0x14, 4); // Payload length = length of chunk
Request[0x18] = Options; // Data options = 0 (1 = verify)
System.Buffer.BlockCopy(BigEndian.GetBytes(WriteDescriptorIndex, 4), 0, Request, 0x19, 4); // Payload length = length of chunk
System.Buffer.BlockCopy(BigEndian.GetBytes(CRC, 4), 0, Request, 0x1D, 4); // Payload length = length of chunk
Buffer.BlockCopy(BigEndian.GetBytes(WriteDescriptorIndex, 4), 0, Request, 0x19, 4); // Payload length = length of chunk
Buffer.BlockCopy(BigEndian.GetBytes(CRC, 4), 0, Request, 0x1D, 4); // Payload length = length of chunk
Buffer.BlockCopy(FfuChunk, 0, Request, 0x40, FfuChunk.Length);
@@ -387,11 +388,11 @@ namespace WPinternals
{
byte[] Request = new byte[84];
const string Header = "NOKXFB";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Request[0x07] = 1; // Subblock count = 1
Request[0x08] = 6; // Subblock ID = 6 = Create Partition Backup to RAM
System.Buffer.BlockCopy(BigEndian.GetBytes(73, 2), 0, Request, 0x09, 2); // Subblock length = Length of data in subblock including fillers (subblock-ID-field and subblock-length-field are not counted for the subblock-length)
System.Text.UnicodeEncoding.Unicode.GetBytes(PartitionName);
Buffer.BlockCopy(BigEndian.GetBytes(73, 2), 0, Request, 0x09, 2); // Subblock length = Length of data in subblock including fillers (subblock-ID-field and subblock-length-field are not counted for the subblock-length)
System.Text.Encoding.Unicode.GetBytes(PartitionName);
byte[] PartitionBytes = System.Text.Encoding.Unicode.GetBytes(PartitionName);
Buffer.BlockCopy(PartitionBytes, 0, Request, 0x0C, PartitionBytes.Length);
@@ -415,18 +416,18 @@ namespace WPinternals
{
byte[] Request = new byte[MmosPart.Length + 0x20];
const string Header = "NOKXFL";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Request[0x07] = 1; // Subblock count = 1
System.Buffer.BlockCopy(BigEndian.GetBytes(0x0000001E, 4), 0, Request, 0x08, 4); // Subblock ID = Load MMOS Binary = 0x1E
System.Buffer.BlockCopy(BigEndian.GetBytes(MmosPart.Length + 0x10, 4), 0, Request, 0x0C, 4); // Subblock length = Payload-length + 0x10
System.Buffer.BlockCopy(BigEndian.GetBytes(TotalLength, 4), 0, Request, 0x10, 4);
System.Buffer.BlockCopy(BigEndian.GetBytes(Offset, 4), 0, Request, 0x14, 4);
Buffer.BlockCopy(BigEndian.GetBytes(0x0000001E, 4), 0, Request, 0x08, 4); // Subblock ID = Load MMOS Binary = 0x1E
Buffer.BlockCopy(BigEndian.GetBytes(MmosPart.Length + 0x10, 4), 0, Request, 0x0C, 4); // Subblock length = Payload-length + 0x10
Buffer.BlockCopy(BigEndian.GetBytes(TotalLength, 4), 0, Request, 0x10, 4);
Buffer.BlockCopy(BigEndian.GetBytes(Offset, 4), 0, Request, 0x14, 4);
if (SkipMmosSupportCheck)
{
Request[0x18] = 1;
}
System.Buffer.BlockCopy(BigEndian.GetBytes(MmosPart.Length, 4), 0, Request, 0x1C, 4);
Buffer.BlockCopy(BigEndian.GetBytes(MmosPart.Length, 4), 0, Request, 0x1C, 4);
Buffer.BlockCopy(MmosPart, 0, Request, 0x20, MmosPart.Length);
byte[] Response = ExecuteRawMethod(Request);
@@ -521,7 +522,7 @@ namespace WPinternals
UInt64 CombinedFFUHeaderSize = FFU.HeaderSize;
byte[] FfuHeader = new byte[CombinedFFUHeaderSize];
using (FileStream FfuFile = new(FFU.Path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (FileStream FfuFile = new(FFU.Path, FileMode.Open, FileAccess.Read))
{
FfuFile.Read(FfuHeader, 0, (int)CombinedFFUHeaderSize);
SendFfuHeaderV1(FfuHeader, Options);
@@ -597,7 +598,7 @@ namespace WPinternals
uint totalcounts = (uint)Math.Truncate((decimal)length / maximumbuffersize);
using (FileStream MMOSFile = new(MMOSPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (FileStream MMOSFile = new(MMOSPath, FileMode.Open, FileAccess.Read))
{
for (int i = 1; i <= (uint)Math.Truncate((decimal)length / maximumbuffersize); i++)
{
@@ -633,10 +634,10 @@ namespace WPinternals
byte[] Request = new byte[Data.Length + 0x40];
const string Header = "NOKF";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Request[0x05] = 0; // Device type = 0
System.Buffer.BlockCopy(BigEndian.GetBytes(StartSector, 4), 0, Request, 0x0B, 4); // Start sector
System.Buffer.BlockCopy(BigEndian.GetBytes(Data.Length / 0x200, 4), 0, Request, 0x0F, 4); // Sector count
Buffer.BlockCopy(BigEndian.GetBytes(StartSector, 4), 0, Request, 0x0B, 4); // Start sector
Buffer.BlockCopy(BigEndian.GetBytes(Data.Length / 0x200, 4), 0, Request, 0x0F, 4); // Sector count
Request[0x13] = (byte)Progress; // Progress (0 - 100)
Request[0x18] = 0; // Do Verify
Request[0x19] = 0; // Is Test
@@ -650,7 +651,7 @@ namespace WPinternals
{
byte[] Request = new byte[4];
const string Header = "NOKD";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
ExecuteRawMethod(Request);
}
@@ -658,7 +659,7 @@ namespace WPinternals
{
byte[] Request = new byte[4];
const string Header = "NOKZ";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
ExecuteRawMethod(Request);
}
@@ -690,7 +691,7 @@ namespace WPinternals
PhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
FlashAppType OriginalAppType = Info.App;
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure);
bool Switch = (Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure;
if (Switch)
{
SwitchToBootManagerContext();
@@ -871,7 +872,7 @@ namespace WPinternals
byte[] Request = new byte[0x50];
const string Header = "NOKXFP";
System.Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Buffer.BlockCopy(System.Text.Encoding.ASCII.GetBytes(Header), 0, Request, 0, Header.Length);
Request[0x06] = 1; // Protocol version must be 1
Request[0x07] = 0; // Device type = 0
@@ -950,7 +951,7 @@ namespace WPinternals
Result.TransferSize = BigEndian.ToUInt32(Response, SubblockPayloadOffset);
break;
case 0x1F:
Result.MmosOverUsbSupported = (Response[SubblockPayloadOffset] == 1);
Result.MmosOverUsbSupported = Response[SubblockPayloadOffset] == 1;
break;
case 0x04:
if (Result.App == FlashAppType.BootManager)
@@ -975,17 +976,17 @@ namespace WPinternals
Result.PlatformID = ByteOperations.ReadAsciiString(Response, (uint)SubblockPayloadOffset, SubblockLength).Trim(new char[] { ' ', '\0' });
break;
case 0x0D:
Result.AsyncSupport = (Response[SubblockPayloadOffset + 1] == 1);
Result.AsyncSupport = Response[SubblockPayloadOffset + 1] == 1;
break;
case 0x0F:
SubblockVersion = Response[SubblockPayloadOffset]; // 0x03
Result.PlatformSecureBootEnabled = (Response[SubblockPayloadOffset + 0x01] == 0x01);
Result.SecureFfuEnabled = (Response[SubblockPayloadOffset + 0x02] == 0x01);
Result.JtagDisabled = (Response[SubblockPayloadOffset + 0x03] == 0x01);
Result.RdcPresent = (Response[SubblockPayloadOffset + 0x04] == 0x01);
Result.Authenticated = ((Response[SubblockPayloadOffset + 0x05] == 0x01) || (Response[SubblockPayloadOffset + 0x05] == 0x02));
Result.UefiSecureBootEnabled = (Response[SubblockPayloadOffset + 0x06] == 0x01);
Result.SecondaryHardwareKeyPresent = (Response[SubblockPayloadOffset + 0x07] == 0x01);
Result.PlatformSecureBootEnabled = Response[SubblockPayloadOffset + 0x01] == 0x01;
Result.SecureFfuEnabled = Response[SubblockPayloadOffset + 0x02] == 0x01;
Result.JtagDisabled = Response[SubblockPayloadOffset + 0x03] == 0x01;
Result.RdcPresent = Response[SubblockPayloadOffset + 0x04] == 0x01;
Result.Authenticated = (Response[SubblockPayloadOffset + 0x05] == 0x01) || (Response[SubblockPayloadOffset + 0x05] == 0x02);
Result.UefiSecureBootEnabled = Response[SubblockPayloadOffset + 0x06] == 0x01;
Result.SecondaryHardwareKeyPresent = Response[SubblockPayloadOffset + 0x07] == 0x01;
break;
case 0x10:
SubblockVersion = Response[SubblockPayloadOffset]; // 0x01
+2 -2
View File
@@ -76,7 +76,7 @@ namespace WPinternals
Length = Device.InputPipe.Read(Buffer);
}
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.ASCIIEncoding.ASCII.GetString(Buffer, 0, Length));
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
try
{
@@ -298,7 +298,7 @@ namespace WPinternals
{
Length = Device.InputPipe.EndRead(AsyncResultRead);
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.ASCIIEncoding.ASCII.GetString(Buffer, 0, Length));
JsonDocument ResultMessage = JsonDocument.Parse(System.Text.Encoding.ASCII.GetString(Buffer, 0, Length));
JsonElement? ResultToken = ResultMessage.RootElement.GetProperty("result");
if ((ResultToken == null) || (ResultElement == null))
+6 -6
View File
@@ -120,7 +120,7 @@ namespace WPinternals
LogFile.Log("Attempt patch: " + PatchDefinition);
// Find a matching TargetVersion
PatchDefinition Definition = PatchDefinitions.Single(d => string.Compare(d.Name, PatchDefinition, true) == 0);
PatchDefinition Definition = PatchDefinitions.Single(d => string.Equals(d.Name, PatchDefinition, StringComparison.CurrentCultureIgnoreCase));
TargetVersion MatchedVersion = null;
int VersionIndex = 0;
foreach (TargetVersion CurrentVersion in Definition.TargetVersions)
@@ -146,7 +146,7 @@ namespace WPinternals
}
// Lookup file
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Compare(f.FilePath, TargetPath, true) == 0);
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Equals(f.FilePath, TargetPath, StringComparison.CurrentCultureIgnoreCase));
if (CurrentFile == null)
{
CurrentFile = (TargetImage != null) && (!TargetPath.Contains(':'))
@@ -196,7 +196,7 @@ namespace WPinternals
foreach (TargetFile CurrentTargetFile in MatchedVersion.TargetFiles)
{
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Compare(f.FilePath, Path.Combine(TargetPath + "\\", CurrentTargetFile.Path), true) == 0);
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Equals(f.FilePath, Path.Combine(TargetPath + "\\", CurrentTargetFile.Path), StringComparison.CurrentCultureIgnoreCase));
if (!StructuralComparisons.StructuralEqualityComparer.Equals(CurrentFile.Hash, CurrentTargetFile.HashPatched))
{
@@ -242,7 +242,7 @@ namespace WPinternals
try
{
// Find a matching TargetVersion
PatchDefinition Definition = PatchDefinitions.Single(d => string.Compare(d.Name, PatchDefinition, true) == 0);
PatchDefinition Definition = PatchDefinitions.Single(d => string.Equals(d.Name, PatchDefinition, StringComparison.CurrentCultureIgnoreCase));
TargetVersion MatchedVersion = null;
foreach (TargetVersion CurrentVersion in Definition.TargetVersions)
{
@@ -266,7 +266,7 @@ namespace WPinternals
}
// Lookup file
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Compare(f.FilePath, TargetPath, true) == 0);
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Equals(f.FilePath, TargetPath, StringComparison.CurrentCultureIgnoreCase));
if (CurrentFile == null)
{
CurrentFile = new FilePatcher(TargetPath);
@@ -306,7 +306,7 @@ namespace WPinternals
{
foreach (TargetFile CurrentTargetFile in MatchedVersion.TargetFiles)
{
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Compare(f.FilePath, Path.Combine(TargetPath, CurrentTargetFile.Path), true) == 0);
FilePatcher CurrentFile = LoadedFiles.SingleOrDefault(f => string.Equals(f.FilePath, Path.Combine(TargetPath, CurrentTargetFile.Path), StringComparison.CurrentCultureIgnoreCase));
if (!StructuralComparisons.StructuralEqualityComparer.Equals(CurrentFile.Hash, CurrentTargetFile.HashOriginal))
{
+14 -23
View File
@@ -186,16 +186,13 @@ namespace WPinternals
{
lock (syncRoot)
{
if (processHandle.IsInvalid)
{
if (!NativeMethods.OpenProcessToken(
if (processHandle.IsInvalid && !NativeMethods.OpenProcessToken(
NativeMethods.GetCurrentProcess(),
TokenAccessLevels.Duplicate,
ref processHandle))
{
cachingError = Marshal.GetLastWin32Error();
success = false;
}
{
cachingError = Marshal.GetLastWin32Error();
success = false;
}
}
}
@@ -237,15 +234,12 @@ namespace WPinternals
}
}
if (success)
{
if (!NativeMethods.SetThreadToken(
if (success && !NativeMethods.SetThreadToken(
IntPtr.Zero,
this.threadHandle))
{
error = Marshal.GetLastWin32Error();
success = false;
}
{
error = Marshal.GetLastWin32Error();
success = false;
}
if (success)
@@ -424,7 +418,7 @@ namespace WPinternals
NativeMethods.TOKEN_PRIVILEGE newState = new();
newState.PrivilegeCount = 1;
newState.Privilege.Luid = this.luid;
newState.Privilege.Attributes = (this.initialState ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED);
newState.Privilege.Attributes = this.initialState ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED;
NativeMethods.TOKEN_PRIVILEGE previousState = new();
uint previousSize = 0;
@@ -578,11 +572,11 @@ namespace WPinternals
{
// This is the initial state that revert will have to go back to
this.initialState = ((previousState.Privilege.Attributes & NativeMethods.SE_PRIVILEGE_ENABLED) != 0);
this.initialState = (previousState.Privilege.Attributes & NativeMethods.SE_PRIVILEGE_ENABLED) != 0;
// Remember whether state has changed at all
this.stateWasChanged = (this.initialState != enable);
this.stateWasChanged = this.initialState != enable;
// If we had to impersonate, or if the privilege state changed we'll need to revert
@@ -630,13 +624,10 @@ namespace WPinternals
this.initialState = false;
this.needToRevert = false;
if (this.tlsContents != null)
if (this.tlsContents?.DecrementReferenceCount() == 0)
{
if (this.tlsContents.DecrementReferenceCount() == 0)
{
this.tlsContents = null;
Thread.SetData(tlsSlot, null);
}
this.tlsContents = null;
Thread.SetData(tlsSlot, null);
}
}
}
+1 -1
View File
@@ -60,7 +60,7 @@ namespace WPinternals
CurrentLength = Remaining >= 0x100 ? 0x100 : (UInt32)Remaining;
CurrentLength = (UInt32)(Data.Read(Buffer, 7, (int)CurrentLength));
CurrentLength = (UInt32)Data.Read(Buffer, 7, (int)CurrentLength);
Serial.SendCommand(Buffer, new byte[] { 0x02 });
CurrentAddress += CurrentLength;
+1 -1
View File
@@ -55,7 +55,7 @@ namespace WPinternals
// We expect the user to know what he is doing in such case and we will ignore checks
if (!StructuralComparisons.StructuralEqualityComparer.Equals(RootKeyHash, new byte[RootKeyHash.Length]))
{
if ((StructuralComparisons.StructuralEqualityComparer.Equals(Loader.RootKeyHash, RootKeyHash))
if (StructuralComparisons.StructuralEqualityComparer.Equals(Loader.RootKeyHash, RootKeyHash)
&& (ByteOperations.FindUnicode(Loader.Binary, "QHSUSB_ARMPRG") != null)) // To detect that this is a loader, and not SBL1 or something. V1 loaders are QHSUSB_ARMPRG. V2 loaders are QHSUSB__BULK. Only V1 supported for now, because V2 only accepts signed payload.
{
Result.Add(Loader);
+269 -16
View File
@@ -19,6 +19,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WPinternals
@@ -90,7 +95,7 @@ namespace WPinternals
Serial.SendData(HelloResponse);
Step = 3;
using System.IO.FileStream FileStream = new(Path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
using FileStream FileStream = new(Path, FileMode.Open, FileAccess.Read);
while (true)
{
Step = 4;
@@ -116,7 +121,7 @@ namespace WPinternals
if (FileStream.Position != Offset)
{
FileStream.Seek(Offset, System.IO.SeekOrigin.Begin);
FileStream.Seek(Offset, SeekOrigin.Begin);
}
Step = 6;
@@ -182,7 +187,7 @@ namespace WPinternals
Serial.SendCommand(new byte[] { 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, new byte[] { 0x08, 0x00, 0x00, 0x00 });
}
public bool ConnectToProgrammerInTestMode()
public bool ConnectToProgrammer(byte[] PacketFromPcToProgrammer)
{
// Behaviour of old firehose:
// Takes about 20 ms to be started.
@@ -198,12 +203,6 @@ namespace WPinternals
// When sending succeeds, an answer should be incoming immediately to complete the handshake.
// When an incoming Hello was received, the phone still expects to receive another Hello.
byte[] HelloPacketFromPcToProgrammer = new byte[0x20C];
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0, 0x57503730);
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x28, 0x57503730);
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x208, 0x57503730);
ByteOperations.WriteUInt16(HelloPacketFromPcToProgrammer, 0x48, 0x4445);
int HelloSendCount = 0;
bool HandshakeCompleted = false;
string Incoming;
@@ -214,7 +213,7 @@ namespace WPinternals
try
{
LogFile.Log("Send Hello to programmer (" + HelloSendCount.ToString() + ")", LogType.FileOnly);
Serial.SendData(HelloPacketFromPcToProgrammer);
Serial.SendData(PacketFromPcToProgrammer);
LogFile.Log("Hello packet accepted", LogType.FileOnly);
}
catch
@@ -225,29 +224,50 @@ namespace WPinternals
try
{
Serial.SetTimeOut(500);
Incoming = System.Text.Encoding.ASCII.GetString(Serial.GetResponse(null));
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("In: " + Incoming, LogType.FileOnly);
Serial.SetTimeOut(200);
if (Incoming.Contains("Chip serial num"))
{
Incoming = System.Text.Encoding.ASCII.GetString(Serial.GetResponse(null));
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("In: " + Incoming, LogType.FileOnly);
LogFile.Log("Incoming Hello-packets received", LogType.FileOnly);
}
while (Incoming.IndexOf("response value") < 0)
{
Incoming = System.Text.Encoding.ASCII.GetString(Serial.GetResponse(null));
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("In: " + Incoming, LogType.FileOnly);
}
LogFile.Log("Incoming Hello-response received", LogType.FileOnly);
HandshakeCompleted = true;
if (!Incoming.Contains("Failed to authenticate Digital Signature."))
{
HandshakeCompleted = true;
}
else
{
LogFile.Log("Programmer failed to authenticate Digital Signature", LogType.FileOnly);
}
}
catch { }
}
while (!HandshakeCompleted && (HelloSendCount < 6));
return HandshakeCompleted;
}
public bool ConnectToProgrammerInTestMode()
{
byte[] HelloPacketFromPcToProgrammer = new byte[0x20C];
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0, 0x57503730);
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x28, 0x57503730);
ByteOperations.WriteUInt32(HelloPacketFromPcToProgrammer, 0x208, 0x57503730);
ByteOperations.WriteUInt16(HelloPacketFromPcToProgrammer, 0x48, 0x4445);
bool HandshakeCompleted = ConnectToProgrammer(HelloPacketFromPcToProgrammer);
if (HandshakeCompleted)
{
LogFile.Log("Handshake completed with programmer in testmode", LogType.FileOnly);
@@ -279,12 +299,12 @@ namespace WPinternals
LogFile.Log("Rebooting phone", LogType.FileAndConsole);
const string Command03 = "<?xml version=\"1.0\" ?><data><power value=\"reset\"/></data>";
LogFile.Log("Out: " + Command03, LogType.FileOnly);
Serial.SendData(System.Text.Encoding.ASCII.GetBytes(Command03));
Serial.SendData(Encoding.ASCII.GetBytes(Command03));
string Incoming;
do
{
Incoming = System.Text.Encoding.ASCII.GetString(Serial.GetResponse(null));
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
LogFile.Log("In: " + Incoming, LogType.FileOnly);
}
while (Incoming.IndexOf("response value") < 0);
@@ -343,5 +363,238 @@ namespace WPinternals
}
LogFile.Log("Programmer being launched on phone", LogType.FileOnly);
}
public async Task<bool> SendEdPayload(string ProgrammerPath, string PayloadPath)
{
// First, let's read the Emergency Download payload header and verify its validity
FileStream PayloadStream = File.OpenRead(PayloadPath);
byte[] ValidReferencePayloadHeader = new byte[] { 0x45, 0x6D, 0x65, 0x72, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x20, 0x50, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64 };
byte[] PayloadHeader = new byte[17];
PayloadStream.Read(PayloadHeader, 0, 17);
bool IsValidEdPayloadImage = StructuralComparisons.StructuralEqualityComparer.Equals(PayloadHeader, ValidReferencePayloadHeader);
if (!IsValidEdPayloadImage)
{
return false;
}
// Now let's read the information block
PayloadStream.Seek(0x64, SeekOrigin.Begin);
byte[] PayloadInformationBlock = new byte[0x64];
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
string buildtime = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
string builddate = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
PayloadStream.Read(PayloadInformationBlock, 0, 0x64);
string version = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
PayloadInformationBlock = new byte[0x670];
PayloadStream.Read(PayloadInformationBlock, 0, 0x670);
string Info = Encoding.ASCII.GetString(PayloadInformationBlock).Trim('\0');
// Print some information about the payload
LogFile.Log("Emerency flasher version 0.1", LogType.FileAndConsole);
LogFile.Log("Programmer information:", LogType.FileAndConsole);
LogFile.Log("Build time: " + buildtime, LogType.FileAndConsole);
LogFile.Log("Build date: " + builddate, LogType.FileAndConsole);
LogFile.Log("Version: " + version, LogType.FileAndConsole);
LogFile.Log("Info: " + Info, LogType.FileAndConsole);
// Send the emergency programmer to the phone
bool SendImageResult = await Task.Run(() => SendImage(ProgrammerPath));
if (!SendImageResult)
{
return false;
}
// Start the emergency programmer on the phone
await Task.Run(() => StartProgrammer());
// Wait a few seconds before sending commands
LogFile.Log("Waiting...", LogType.FileAndConsole);
Thread.Sleep(2000);
LogFile.Log("Waiting...OK", LogType.FileAndConsole);
bool Terminated = false;
bool Connected = false;
bool ProgrammerRawMode = false;
string Incoming;
while (!Terminated)
{
PayloadInformationBlock = new byte[0x200];
PayloadStream.Read(PayloadInformationBlock, 0, 0x200);
string ProgrammerCommand = Encoding.ASCII.GetString(PayloadInformationBlock.Skip(0xC).ToArray()).Trim('\0');
LogFile.Log(ProgrammerCommand, LogType.FileAndConsole);
byte[] PacketFromPcToProgrammer = Array.Empty<byte>();
byte[] temp = new byte[0x200];
while (true)
{
if (PayloadStream.Position == PayloadStream.Length)
{
Terminated = true;
break;
}
PayloadStream.Read(temp, 0, 0x200);
if (temp[12] == 77 && temp[13] == 83 && temp[14] == 71 && temp[15] == 95)
{
PayloadStream.Seek(-0x200, SeekOrigin.Current);
break;
}
PacketFromPcToProgrammer = PacketFromPcToProgrammer.Concat(temp).ToArray();
}
bool ExpectingReplyFromProgrammer = false;
if (ProgrammerCommand.Contains("XML"))
{
string Outgoing = Encoding.ASCII.GetString(PacketFromPcToProgrammer).Trim('\0');
PacketFromPcToProgrammer = Encoding.ASCII.GetBytes(Outgoing);
LogFile.Log("Out: " + Outgoing, LogType.FileAndConsole);
}
if (!ProgrammerCommand.Contains("RAW_DATA") && !ProgrammerRawMode)
{
ExpectingReplyFromProgrammer = true;
}
if (ProgrammerCommand.Contains("LAST") && ProgrammerRawMode)
{
ExpectingReplyFromProgrammer = true;
}
if (ProgrammerCommand.Contains("DATA_ALL") && ProgrammerRawMode)
{
ExpectingReplyFromProgrammer = true;
}
if (ProgrammerCommand.Contains("RAW_DATA") && !ProgrammerRawMode)
{
LogFile.Log("Phone is not in raw mode ON, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
if (!ProgrammerCommand.Contains("RAW_DATA") && ProgrammerRawMode)
{
LogFile.Log("Phone is not in raw mode ON, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
if (Connected)
{
Serial.SendData(PacketFromPcToProgrammer);
}
if (ExpectingReplyFromProgrammer)
{
if (!Connected)
{
Connected = ConnectToProgrammer(PacketFromPcToProgrammer);
if (Connected)
{
LogFile.Log("Handshake completed with programmer in validated image programming (VIP) mode", LogType.FileAndConsole);
}
else
{
LogFile.Log("Handshake with programmer failed", LogType.FileAndConsole);
}
if (!Connected)
{
LogFile.Log("Phone programmer is now ignoring us, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
}
else
{
do
{
Serial.SetTimeOut(500);
Incoming = Encoding.ASCII.GetString(Serial.GetResponse(null));
Serial.SetTimeOut(200);
LogFile.Log("In: " + Incoming, LogType.FileAndConsole);
}
while (Incoming.IndexOf("response value") < 0);
if (Incoming.Contains("rawmode=\"false\""))
{
ProgrammerRawMode = false;
LogFile.Log("Raw mode: OFF", LogType.FileAndConsole);
}
if (Incoming.Contains("rawmode=\"true\""))
{
ProgrammerRawMode = true;
LogFile.Log("Raw mode: ON", LogType.FileAndConsole);
}
if (!Incoming.Contains("ACK"))
{
LogFile.Log("Phone programmer is now ignoring us, leaving...", LogType.FileAndConsole);
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed unsuccessfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return false;
}
}
}
}
// Workaround for problem
// SerialPort is sometimes not disposed correctly when the device is already removed.
// So explicitly dispose here
Serial.Close();
LogFile.Log("Phone has been emergency flashed successfully!", LogType.FileAndConsole);
PayloadStream.Dispose();
return true;
}
}
}
+4 -4
View File
@@ -39,7 +39,7 @@ namespace WPinternals
CRC16 = new CRC16(0x1189, 0xFFFF, 0xFFFF);
string[] DevicePathElements = DevicePath.Split(new char[] { '#' });
if (string.Compare(DevicePathElements[3], "{86E0D1E0-8089-11D0-9CE4-08003E301F73}", true) == 0)
if (string.Equals(DevicePathElements[3], "{86E0D1E0-8089-11D0-9CE4-08003E301F73}", StringComparison.CurrentCultureIgnoreCase))
{
string PortName = (string)Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\" + DevicePathElements[1] + @"\" + DevicePathElements[2] + @"\Device Parameters", "PortName", null);
if (PortName != null)
@@ -316,9 +316,9 @@ namespace WPinternals
}
}
public class IncompleteMessageException : Exception { };
public class BadMessageException : Exception { };
public class BadConnectionException : Exception { };
public class IncompleteMessageException : Exception { public IncompleteMessageException() { } public IncompleteMessageException(string message) : base(message) { } public IncompleteMessageException(string message, Exception innerException) : base(message, innerException) { } }
public class BadMessageException : Exception { public BadMessageException() { } public BadMessageException(string message) : base(message) { } public BadMessageException(string message, Exception innerException) : base(message, innerException) { } }
public class BadConnectionException : Exception { public BadConnectionException() { } public BadConnectionException(string message) : base(message) { } public BadConnectionException(string message, Exception innerException) : base(message, innerException) { } }
public class CRC16
{
+6 -6
View File
@@ -237,7 +237,7 @@ namespace WPinternals
Type = ByteOperations.ReadUInt8(DecompressedImage, DecompressedFileHeaderOffset + 0x12)
};
byte[] FileGuidBytes = new byte[0x10];
System.Buffer.BlockCopy(DecompressedImage, (int)DecompressedFileHeaderOffset + 0x00, FileGuidBytes, 0, 0x10);
Buffer.BlockCopy(DecompressedImage, (int)DecompressedFileHeaderOffset + 0x00, FileGuidBytes, 0, 0x10);
CurrentEFI.Guid = new Guid(FileGuidBytes);
// Parse sections of the EFI
@@ -286,7 +286,7 @@ namespace WPinternals
internal byte[] GetFile(string Name)
{
EFI File = EFIs.Find(f => (string.Compare(Name, f.Name, true) == 0) || (string.Compare(Name, f.Guid.ToString(), true) == 0));
EFI File = EFIs.Find(f => string.Equals(Name, f.Name, StringComparison.CurrentCultureIgnoreCase) || string.Equals(Name, f.Guid.ToString(), StringComparison.CurrentCultureIgnoreCase));
if (File == null)
{
return null;
@@ -300,7 +300,7 @@ namespace WPinternals
internal byte[] GetFile(Guid Guid)
{
EFI File = EFIs.Find(f => (Guid == f.Guid));
EFI File = EFIs.Find(f => Guid == f.Guid);
if (File == null)
{
return null;
@@ -314,7 +314,7 @@ namespace WPinternals
internal void ReplaceFile(string Name, byte[] Binary)
{
EFI File = EFIs.Find(f => (string.Compare(Name, f.Name, true) == 0) || (string.Compare(Name, f.Guid.ToString(), true) == 0));
EFI File = EFIs.Find(f => string.Equals(Name, f.Name, StringComparison.CurrentCultureIgnoreCase) || string.Equals(Name, f.Guid.ToString(), StringComparison.CurrentCultureIgnoreCase));
if (File == null)
{
throw new ArgumentOutOfRangeException();
@@ -515,7 +515,7 @@ namespace WPinternals
{
UInt16 VolumeHeaderSize = ByteOperations.ReadUInt16(Image, Offset + 0x30);
byte[] Header = new byte[VolumeHeaderSize];
System.Buffer.BlockCopy(Image, (int)Offset, Header, 0, VolumeHeaderSize);
Buffer.BlockCopy(Image, (int)Offset, Header, 0, VolumeHeaderSize);
ByteOperations.WriteUInt16(Header, 0x32, 0); // Clear checksum
UInt16 CurrentChecksum = ByteOperations.ReadUInt16(Image, Offset + 0x32);
UInt16 NewChecksum = ByteOperations.CalculateChecksum16(Header, 0, VolumeHeaderSize);
@@ -553,7 +553,7 @@ namespace WPinternals
UInt32 FileSize = ByteOperations.ReadUInt24(Image, Offset + 0x14);
byte[] Header = new byte[FileHeaderSize - 1];
System.Buffer.BlockCopy(Image, (int)Offset, Header, 0, FileHeaderSize - 1);
Buffer.BlockCopy(Image, (int)Offset, Header, 0, FileHeaderSize - 1);
ByteOperations.WriteUInt16(Header, 0x10, 0); // Clear checksum
byte CurrentHeaderChecksum = ByteOperations.ReadUInt8(Image, Offset + 0x10);
byte CalculatedHeaderChecksum = ByteOperations.CalculateChecksum8(Header, 0, (UInt32)FileHeaderSize - 1);