Implemented the new flashing hack

This new flashing hack exploits a bug in flash app where it will not properly check the integrity of catalog files used in FFU files
This commit is contained in:
Gustave Monce
2020-01-12 15:43:56 +01:00
parent a3f323259a
commit 774ff9956f
14 changed files with 1170 additions and 300 deletions
+22 -1
View File
@@ -670,7 +670,7 @@ namespace WPinternals
Info = FlashModel.ReadPhoneInfo();
Info.Log(LogType.ConsoleOnly);
LogFile.Log("Flashing FFU...", LogType.FileAndConsole);
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)((Info.RdcPresent || !Info.SecureFfuEnabled || Info.Authenticated) ? FlashOptions.SkipSignatureCheck : 0)));
await Task.Run(() => FlashModel.FlashFFU(new FFU(FFUPath), true, (byte)(!Info.IsBootloaderSecure ? FlashOptions.SkipSignatureCheck : 0)));
LogFile.Log("FFU flashed successfully", LogType.FileAndConsole);
Notifier.Stop();
}
@@ -1608,6 +1608,24 @@ namespace WPinternals
throw new WPinternalsException("Unable to find compatible FFU", "No donor-FFU has been found in the repository with a supported OS version. You can add a donor-FFU within the download section of the tool or by using the command line. A donor-FFU can be for a different device and a different CPU than your device. It is only used to gather Operating System specific binaries to be patched and used as part of the unlock process.");
}
break;
case "rewritepartitionsfrommassstorage":
if (args.Length < 2)
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RewritePartitionsFromMassStorage <Path to folder containing img partitions> \n The name of the imgs must be the partition names. For example, DPP.img will get written to the DPP partition.");
await TestCode.RewriteParts(args[2]);
break;
case "restoregptusingedl":
if (args.Length < 3)
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingEDL <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)> <Loaders path>");
await TestCode.RecoverBadGPT(args[2], args[3]);
break;
case "restoregptusingmassstorage":
if (args.Length < 2)
throw new ArgumentException("Wrong number of arguments. Usage: WPinternals.exe -RestoreGPTUsingMassStorage <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)>");
await TestCode.RewriteGPT(args[2]);
break;
default:
LogFile.Log("", LogType.ConsoleOnly);
LogFile.Log("WPinternals commandline usage:", LogType.ConsoleOnly);
@@ -1671,6 +1689,9 @@ namespace WPinternals
LogFile.Log(" <Optional: Destination folder>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -DumpUEFI <UEFI binary or FFU file> <Destination folder>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -TestProgrammer <EDE file>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -RewritePartitionsFromMassStorage <Path to folder containing img partitions>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -RestoreGPTUsingEDL <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)> <Loaders path>", LogType.ConsoleOnly);
LogFile.Log("WPinternals -RestoreGPTUsingMassStorage <Path to GPT.bin to be flashed at sector 1 (minus the MBR at sector 0)>", LogType.ConsoleOnly);
break;
}
}
+8 -4
View File
@@ -620,7 +620,7 @@ namespace WPinternals
PhoneInfo Info = ReadPhoneInfo(ExtendedInfo: false);
FlashAppType OriginalAppType = Info.App;
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent);
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure);
if (Switch)
SwitchToBootManagerContext();
@@ -943,6 +943,8 @@ namespace WPinternals
Result.State = PhoneInfoState.Extended;
}
Result.IsBootloaderSecure = !(Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
if (!PhoneInfoLogged)
Result.Log(LogType.FileOnly);
@@ -1193,6 +1195,8 @@ namespace WPinternals
public bool UefiSecureBootEnabled;
public bool SecondaryHardwareKeyPresent;
public bool IsBootloaderSecure;
internal void Log(LogType Type)
{
if (State == PhoneInfoState.Extended)
@@ -1227,12 +1231,12 @@ namespace WPinternals
break;
}
LogFile.Log("SecureBoot: " + ((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled"), Type);
LogFile.Log("SecureBoot: " + ((!PlatformSecureBootEnabled || !UefiSecureBootEnabled) ? "Disabled" : "Enabled") + " (Platform Secure Boot: " + (PlatformSecureBootEnabled ? "Enabled" : "Disabled") + ", UEFI Secure Boot: " + (PlatformSecureBootEnabled ? "Enabled" : "Disabled") + ")", Type);
if ((Type == LogType.ConsoleOnly) || (Type == LogType.FileAndConsole))
LogFile.Log("Flash app security: " + ((!SecureFfuEnabled || RdcPresent || Authenticated) ? "Disabled" : "Enabled"), LogType.ConsoleOnly);
LogFile.Log("Flash app security: " + (!IsBootloaderSecure ? "Disabled" : "Enabled"), LogType.ConsoleOnly);
if ((Type == LogType.FileOnly) || (Type == LogType.FileAndConsole))
LogFile.Log("Flash app security: " + ((!SecureFfuEnabled || RdcPresent || Authenticated) ? "Disabled" : "Enabled") + " (FFU security: " + (SecureFfuEnabled ? "Enabled" : "Disabled") + ", RDC: " + (RdcPresent ? "Present" : "Not found") + ", Authenticated: " + (Authenticated ? "True" : "False") + ")", LogType.FileOnly);
LogFile.Log("Flash app security: " + (!IsBootloaderSecure ? "Disabled" : "Enabled") + " (FFU security: " + (SecureFfuEnabled ? "Enabled" : "Disabled") + ", RDC: " + (RdcPresent ? "Present" : "Not found") + ", Authenticated: " + (Authenticated ? "True" : "False") + ")", LogType.FileOnly);
LogFile.Log("JTAG: " + (JtagDisabled ? "Disabled" : "Enabled"), Type);
}
+201
View File
@@ -19,6 +19,9 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace WPinternals
@@ -36,6 +39,204 @@ namespace WPinternals
// MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
}
internal static async Task RecoverBadGPT(string GPTPath, string LoadersPath)
{
byte[] GPT = File.ReadAllBytes(GPTPath);
PhoneNotifierViewModel PhoneNotifier = new PhoneNotifierViewModel();
PhoneNotifier.Start();
await SwitchModeViewModel.SwitchTo(PhoneNotifier, PhoneInterfaces.Qualcomm_Download);
byte[] RootKeyHash = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{
QualcommDownload Download2 = new QualcommDownload((QualcommSerial)PhoneNotifier.CurrentModel);
RootKeyHash = Download2.GetRKH();
}
List<QualcommPartition> PossibleLoaders = null;
if (PhoneNotifier.CurrentInterface == PhoneInterfaces.Qualcomm_Download)
{
try
{
PossibleLoaders = QualcommLoaders.GetPossibleLoadersForRootKeyHash(LoadersPath, RootKeyHash);
if (PossibleLoaders.Count == 0)
{
throw new Exception("Error: No matching loaders found for RootKeyHash.");
}
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
throw new Exception("Error: Unexpected error during scanning for loaders.");
}
}
QualcommSerial Serial = (QualcommSerial)PhoneNotifier.CurrentModel;
QualcommDownload Download = new QualcommDownload(Serial);
if (Download.IsAlive())
{
int Attempt = 1;
bool Result = false;
foreach (QualcommPartition Loader in PossibleLoaders)
{
LogFile.Log("Attempt " + Attempt.ToString(), LogType.ConsoleOnly);
try
{
Download.SendToPhoneMemory(0x2A000000, Loader.Binary);
Download.StartBootloader(0x2A000000);
Result = true;
LogFile.Log("Loader sent successfully", LogType.ConsoleOnly);
}
catch { }
if (Result)
break;
Attempt++;
}
Serial.Close();
if (!Result)
LogFile.Log("Loader failed", LogType.ConsoleOnly);
}
else
{
LogFile.Log("Failed to communicate to Qualcomm Emergency Download mode", LogType.ConsoleOnly);
throw new BadConnectionException();
}
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
await PhoneNotifier.WaitForArrival();
if (PhoneNotifier.CurrentInterface != PhoneInterfaces.Qualcomm_Flash)
throw new WPinternalsException("Phone failed to switch to emergency flash mode.");
// Flash bootloader
QualcommSerial Serial2 = (QualcommSerial)PhoneNotifier.CurrentModel;
Serial2.EncodeCommands = false;
QualcommFlasher Flasher = new QualcommFlasher(Serial2);
Flasher.Hello();
Flasher.SetSecurityMode(0);
Flasher.OpenPartition(0x21);
LogFile.Log("Partition opened.", LogType.ConsoleOnly);
LogFile.Log("Flash GPT at 0x" + ((UInt32)0x200).ToString("X8"), LogType.ConsoleOnly);
Flasher.Flash(0x200, GPT, 0, 0x41FF); // Bad bounds-check in the flash-loader prohibits to write the last byte.
Flasher.ClosePartition();
LogFile.Log("Partition closed. Flashing ready. Rebooting.");
Flasher.Reboot();
Flasher.CloseSerial();
}
internal static async Task RewriteGPT(string GPTPath)
{
PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(1, GPTPath);
}
internal static async Task RewriteMBRGPT()
{
FFU FFU = new FFU(@"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\RX100_9825.ffu");
string GPTPath = @"E:\Device Backups\Alpha\9200_1230.0025.9200.9825\CorrectGPT.bin";
PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
byte[] MBR = FFU.GetSectors(0, 1);
LogFile.Log("Writing MBR to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(0, MBR);
LogFile.Log("Writing GPT to the device.", LogType.ConsoleOnly);
MassStorage.WriteSectors(1, GPTPath);
}
internal static async Task RewriteParts(string PartPath)
{
PhoneNotifierViewModel Notifier = new PhoneNotifierViewModel();
Notifier.Start();
await SwitchModeViewModel.SwitchTo(Notifier, PhoneInterfaces.Lumia_MassStorage);
MassStorage MassStorage = (MassStorage)Notifier.CurrentModel;
foreach (var part in Directory.EnumerateFiles(PartPath))
{
var partname = part.Split('\\').Last().Replace(".img", "");
try
{
LogFile.Log($"Writing {partname} to the device.", LogType.ConsoleOnly);
LogFile.Log("", LogType.ConsoleOnly);
MassStorage.RestorePartition(part, partname, (v, t) =>
{
LogFile.Log("Progress: " + v + "%", LogType.ConsoleOnly);
});
LogFile.Log("", LogType.ConsoleOnly);
}
catch
{
LogFile.Log("", LogType.ConsoleOnly);
LogFile.Log($"Failed writing {partname} to the device.", LogType.ConsoleOnly);
};
}
}
internal static void PatchImg(string dump)
{
using (var fil = File.Open(dump, FileMode.Open))
{
byte[] gptbuffer = new byte[0x4200];
fil.Seek(0x200, SeekOrigin.Begin);
fil.Read(gptbuffer, 0, 0x4200);
uint BackupLBA = ByteOperations.ReadUInt32(gptbuffer, 0x20);
uint LastUsableLBA = ByteOperations.ReadUInt32(gptbuffer, 0x30);
LogFile.Log("Previous BackupLBA: " + BackupLBA, LogType.ConsoleOnly);
LogFile.Log("Previous LastUsableLBA: " + LastUsableLBA, LogType.ConsoleOnly);
uint NewBackupLBA = 62078975u;
uint NewLastUsableLBA = 62078942u;
ByteOperations.WriteUInt32(gptbuffer, 0x20, NewBackupLBA);
ByteOperations.WriteUInt32(gptbuffer, 0x30, NewLastUsableLBA);
uint HeaderSize = ByteOperations.ReadUInt32(gptbuffer, 0x0C);
uint PrevCRC = ByteOperations.ReadUInt32(gptbuffer, 0x10);
LogFile.Log("Previous CRC: " + PrevCRC, LogType.ConsoleOnly);
ByteOperations.WriteUInt32(gptbuffer, 0x10, 0);
uint NewCRC = ByteOperations.CRC32(gptbuffer, 0, HeaderSize);
LogFile.Log("New CRC: " + NewCRC, LogType.ConsoleOnly);
ByteOperations.WriteUInt32(gptbuffer, 0x10, NewCRC);
LogFile.Log("Writing", LogType.ConsoleOnly);
fil.Seek(0x200, SeekOrigin.Begin);
fil.Write(gptbuffer, 0, 0x4200);
LogFile.Log("Done!", LogType.ConsoleOnly);
}
}
internal static async Task TestProgrammer(System.Threading.SynchronizationContext UIContext, string ProgrammerPath)
{
LogFile.BeginAction("TestProgrammer");
+6 -2
View File
@@ -527,6 +527,8 @@ namespace WPinternals
FlashParts.Add(Part);
}
bool ClearFlashingStatus = true;
// We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock.
if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled)
{
@@ -536,13 +538,15 @@ namespace WPinternals
Part.StartSector = (UInt32)Target.FirstSector;
Part.Stream = new MemoryStream(new byte[0x40000]);
FlashParts.Add(Part);
ClearFlashingStatus = false;
}
if (FlashParts.Count > 0)
{
ActivateSubContext(new BusyViewModel("Restoring bootloader..."));
WPinternalsStatus LastStatus = WPinternalsStatus.Undefined;
LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, FFUPath, false, false, FlashParts, true, ClearFlashingStatusAtEnd: false,
LumiaV2UnlockBootViewModel.LumiaV2CustomFlash(PhoneNotifier, FFUPath, false, false, FlashParts, true, ClearFlashingStatusAtEnd: ClearFlashingStatus,
SetWorkingStatus: (m, s, v, a, st) =>
{
if ((st == WPinternalsStatus.Scanning) || (st == WPinternalsStatus.WaitingForManualReset))
@@ -583,7 +587,7 @@ namespace WPinternals
BusyViewModel Busy = new BusyViewModel("Flashing original FFU...", MaxProgressValue: FFU.TotalChunkCount, UIContext: UIContext);
ActivateSubContext(Busy);
byte Options = 0;
if (!Info.SecureFfuEnabled || Info.Authenticated || Info.RdcPresent)
if (!Info.IsBootloaderSecure)
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
Phone.FlashFFU(FFU, Busy.ProgressUpdater, true, Options);
}
+1 -3
View File
@@ -141,7 +141,7 @@ namespace WPinternals
PhoneInfo Info = ((NokiaFlashModel)PhoneNotifier.CurrentModel).ReadPhoneInfo();
if (SecurityStatus == null)
IsBootLoaderUnlocked = (Info.Authenticated || Info.RdcPresent || !Info.SecureFfuEnabled);
IsBootLoaderUnlocked = !Info.IsBootloaderSecure;
if (RootKeyHash == null)
{
@@ -210,8 +210,6 @@ namespace WPinternals
GPT GPT = FlashModel.ReadGPT();
if ((GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null))
{
//ExitMessage("Phone is already unlocked", null);
//return;
AlreadyUnlocked = true;
}
}
+193 -115
View File
@@ -104,33 +104,42 @@ namespace WPinternals
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
if (ExitFailure == null) ExitFailure = (m, s) => { };
await LumiaUnlockBootloaderViewModel.LumiaRelockUEFI(Notifier, FFUPath, DoResetFirst, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
SetWorkingStatus("Booting phone...");
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
ExitFailure tmpExitFailure = (m, s) =>
{
ExitFailure("Failed to relock phone", "Your phone is half relocked. You may need to reflash a stock ROM");
return;
}
ExitFailure(m, s);
};
ExitSuccess tmpExitSuccess = async (m, s) =>
{
SetWorkingStatus("Booting phone...");
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
{
ExitFailure("Failed to relock phone", "Your phone is half relocked. You may need to reflash a stock ROM");
return;
}
ExitSuccess("Bootloader restored successfully!");
};
await LumiaUnlockBootloaderViewModel.LumiaRelockUEFI(Notifier, FFUPath, DoResetFirst, SetWorkingStatus, UpdateWorkingStatus, tmpExitSuccess, tmpExitFailure);
ExitSuccess("Bootloader restored successfully!");
}
internal static async Task LumiaV2UnlockUEFI(PhoneNotifierViewModel Notifier, string ProfileFFUPath, string EDEPath, string SupportedFFUPath, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, bool ReUnlockDevice = false)
@@ -140,33 +149,42 @@ namespace WPinternals
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
if (ExitFailure == null) ExitFailure = (m, s) => { };
await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFUPath, EDEPath, SupportedFFUPath, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure, ReUnlockDevice: ReUnlockDevice);
SetWorkingStatus("Booting phone...");
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
ExitFailure tmpExitFailure = (m, s) =>
{
ExitFailure("Failed to unlock phone", "Your phone is half unlocked. You may need to reflash a stock ROM");
return;
}
ExitFailure(m, s);
};
ExitSuccess tmpExitSuccess = async (m, s) =>
{
SetWorkingStatus("Booting phone...");
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
await Notifier.WaitForArrival();
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
((NokiaFlashModel)Notifier.CurrentModel).ContinueBoot();
if (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Normal)
{
ExitFailure("Failed to unlock phone", "Your phone is half unlocked. You may need to reflash a stock ROM");
return;
}
ExitSuccess("Bootloader unlocked successfully!", null);
};
await LumiaUnlockBootloaderViewModel.LumiaUnlockUEFI(Notifier, ProfileFFUPath, EDEPath, SupportedFFUPath, SetWorkingStatus, UpdateWorkingStatus, tmpExitSuccess, tmpExitFailure, ReUnlockDevice: ReUnlockDevice);
ExitSuccess("Bootloader unlocked successfully!", null);
}
// Magic!
@@ -1278,7 +1296,7 @@ namespace WPinternals
PhoneInfo Info = FlashModel.ReadPhoneInfo(ExtendedInfo: false);
FlashAppType OriginalAppType = Info.App;
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent);
bool Switch = ((Info.App != FlashAppType.BootManager) && Info.IsBootloaderSecure);
if (Switch)
FlashModel.SwitchToBootManagerContext();
@@ -1608,15 +1626,14 @@ namespace WPinternals
}
LogFile.Log("Phone is relocked", LogType.FileAndConsole);
LogFile.EndAction("RelockPhone");
ExitSuccess("Phone is relocked", null);
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
ExitFailure("Error: " + Ex.Message, null);
}
finally
{
LogFile.EndAction("RelockPhone");
ExitFailure("Error: " + Ex.Message, null);
}
}
@@ -1640,14 +1657,12 @@ namespace WPinternals
PhoneInfo Info = FlashModel.ReadPhoneInfo();
bool IsSpecB = Info.FlashAppProtocolVersionMajor >= 2;
bool IsBootLoaderSecure = !Info.Authenticated && !Info.RdcPresent && Info.SecureFfuEnabled;
if (ProfileFFUPath == null)
throw new ArgumentNullException("Profile FFU path is missing");
FFU ProfileFFU = new FFU(ProfileFFUPath);
if (IsBootLoaderSecure)
if (Info.IsBootloaderSecure)
{
if (!Info.PlatformID.StartsWith(ProfileFFU.PlatformID, StringComparison.OrdinalIgnoreCase))
throw new ArgumentNullException("Profile FFU has wrong Platform ID for connected phone");
@@ -1677,13 +1692,91 @@ namespace WPinternals
LumiaUnlockBootloaderViewModel.LumiaPatchEFIESP(SupportedFFU, UnlockedEFIESP, IsSpecB);
// Create backup-partition for EFIESP
byte[] GPTChunk = GetGptChunk(FlashModel, (UInt32)ProfileFFU.ChunkSize);
byte[] GPTChunkBackup = new byte[GPTChunk.Length];
Buffer.BlockCopy(GPTChunk, 0, GPTChunkBackup, 0, GPTChunk.Length);
GPT GPT = new GPT(GPTChunk);
bool GPTChanged = false;
LogFile.Log("Enabling Test Signing", LogType.FileAndConsole);
SetWorkingStatus("Enabling Test Signing", null, null);
List<FlashPart> Parts = new List<FlashPart>();
FlashPart Part;
// Now add NV partition
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
Partition UEFI_BS_NV;
if (BACKUP_BS_NV == null)
{
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
UEFI_BS_NV = new Partition();
UEFI_BS_NV.Name = "UEFI_BS_NV";
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
GPT.Partitions.Add(UEFI_BS_NV);
GPTChanged = true;
}
Part = new FlashPart();
Partition TargetPartition = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)TargetPartition.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
string SBRes = IsSpecB ? "WPinternals.SB" : "WPinternals.SBA";
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB(A) resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
var stream = assembly.GetManifestResourceStream(SBRes);
return new DecompressedStream(stream);
});
Parts.Add(Part);
if (GPTChanged)
{
GPT.Rebuild();
Part = new FlashPart();
Part.StartSector = 0;
Part.Stream = new MemoryStream(GPTChunk);
Parts.Add(Part);
}
foreach (FlashPart _part in Parts)
{
_part.ProgressText = "Enabling Test Signing...";
}
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, false, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
await Notifier.WaitForArrival();
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
throw new WPinternalsException("Error: Phone is in wrong mode", "The phone should have been detected in bootloader or flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
if (Notifier.CurrentInterface == PhoneInterfaces.Lumia_Bootloader)
{
FlashModel = (NokiaFlashModel)Notifier.CurrentModel;
FlashModel.SwitchToFlashAppContext();
}
GPTChanged = false;
// Create backup-partition for EFIESP
bool SBL3Eng = GPT.GetPartition("IS_UNLOCKED_SBL3") != null;
bool ShouldApplyOldEFIESPMethod = true;
@@ -1695,8 +1788,8 @@ namespace WPinternals
if (!IsSpecB && !SBL3Eng)
ShouldApplyOldEFIESPMethod = false;
List<FlashPart> Parts = ShouldApplyOldEFIESPMethod ? new List<FlashPart>() : LumiaUnlockBootloaderViewModel.LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
FlashPart Part;
Parts = ShouldApplyOldEFIESPMethod ? new List<FlashPart>() : LumiaUnlockBootloaderViewModel.LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
Part = null;
UInt32 OriginalEfiespSizeInSectors = (UInt32)GPT.GetPartition("EFIESP").SizeInSectors;
UInt32 OriginalEfiespLastSector = (UInt32)GPT.GetPartition("EFIESP").LastSector;
@@ -1805,52 +1898,6 @@ namespace WPinternals
Parts.Add(Part);
}
if (IsSpecB)
Parts[0].ProgressText = "Flashing unlocked bootloader (part 1)...";
else
Parts[0].ProgressText = "Flashing unlocked bootloader (part 2)...";
// Now add NV partition
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
Partition UEFI_BS_NV;
if (BACKUP_BS_NV == null)
{
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
UEFI_BS_NV = new Partition();
UEFI_BS_NV.Name = "UEFI_BS_NV";
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
GPT.Partitions.Add(UEFI_BS_NV);
GPTChanged = true;
}
Part = new FlashPart();
Partition TargetPartition = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)TargetPartition.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
string SBRes = IsSpecB ? "WPinternals.SB" : "WPinternals.SBA";
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB(A) resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
var stream = assembly.GetManifestResourceStream(SBRes);
return new DecompressedStream(stream);
});
Parts.Add(Part);
if (GPTChanged)
{
GPT.Rebuild();
@@ -1860,7 +1907,19 @@ namespace WPinternals
Parts.Add(Part);
}
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, false, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
foreach (FlashPart _part in Parts)
{
if (IsSpecB)
{
_part.ProgressText = "Flashing unlocked bootloader (part 1)...";
}
else
{
_part.ProgressText = "Flashing unlocked bootloader (part 2)...";
}
}
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, true, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
await Notifier.WaitForArrival();
@@ -1969,7 +2028,7 @@ namespace WPinternals
// Copy the backed up unlocked EFIESP for future use
BackupUnlockedEFIESP = new byte[UnlockedEFIESP.Length];
Buffer.BlockCopy(BackupEFIESP, 0, BackupUnlockedEFIESP, 0, BackupEFIESP.Length);
Buffer.BlockCopy(BackupEFIESP, 0, BackupUnlockedEFIESP, 0, UnlockedEFIESP.Length);
LumiaUnlockBootloaderViewModel.LumiaPatchEFIESP(SupportedFFU, BackupUnlockedEFIESP, IsSpecB);
}
@@ -2083,7 +2142,6 @@ namespace WPinternals
Part = new FlashPart();
Part.StartSector = 0;
Part.Stream = new MemoryStream(GPTChunk);
Part.ProgressText = "Flashing unlocked bootloader (part 2)...";
Parts.Add(Part);
Part = new FlashPart();
Part.StartSector = OriginalEfiespFirstSector;
@@ -2094,6 +2152,11 @@ namespace WPinternals
Part.Stream = new MemoryStream(BackupEFIESP);
Parts.Add(Part);
foreach (FlashPart _part in Parts)
{
_part.ProgressText = "Flashing unlocked bootloader (part 2)...";
}
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, true, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
}
else
@@ -2146,10 +2209,17 @@ namespace WPinternals
Parts = LumiaUnlockBootloaderViewModel.LumiaGenerateEFIESPFlashPayload(UnlockedEFIESP, GPT, ProfileFFU, IsSpecB);
if (IsSpecB)
Parts[0].ProgressText = "Flashing unlocked bootloader (part 2)...";
else
Parts[0].ProgressText = "Flashing unlocked bootloader (part 3)...";
foreach (FlashPart _part in Parts)
{
if (IsSpecB)
{
_part.ProgressText = "Flashing unlocked bootloader (part 2)...";
}
else
{
_part.ProgressText = "Flashing unlocked bootloader (part 3)...";
}
}
await LumiaUnlockBootloaderViewModel.LumiaFlashParts(Notifier, ProfileFFU.Path, false, false, Parts, true, true, true, true, false, SetWorkingStatus, UpdateWorkingStatus, null, null, EDEPath);
@@ -2157,14 +2227,22 @@ namespace WPinternals
((NokiaFlashModel)Notifier.CurrentModel).ResetPhone();
}
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
await Notifier.WaitForArrival();
if ((Notifier.CurrentInterface != PhoneInterfaces.Lumia_Bootloader) && (Notifier.CurrentInterface != PhoneInterfaces.Lumia_Flash))
throw new WPinternalsException("Error: Phone is in wrong mode", "The phone should have been detected in bootloader or flash mode. Instead it has been detected in " + Notifier.CurrentInterface.ToString() + " mode.");
LogFile.Log("Bootloader unlocked!", LogType.FileAndConsole);
LogFile.EndAction("UnlockBootloader");
ExitSuccess("Bootloader unlocked!", null);
}
catch (Exception Ex)
{
LogFile.LogException(Ex);
LogFile.EndAction("UnlockBootloader");
ExitFailure(Ex.Message, Ex is WPinternalsException ? ((WPinternalsException)Ex).SubMessage : null);
}
LogFile.EndAction("UnlockBootloader");
}
// Magic!
+197 -80
View File
@@ -72,7 +72,7 @@ namespace WPinternals
SetWorkingStatus("Scanning for flashing-profile", "Your phone may appear to be in a reboot-loop. This is expected behavior. Don't interfere this process.", null, Status: WPinternalsStatus.Scanning);
await LumiaV2CustomFlash(Notifier, FFUPath, false, !Info.SecureFfuEnabled || Info.RdcPresent || Info.Authenticated, null, DoResetFirst, Experimental: Experimental, SetWorkingStatus:
await LumiaV2CustomFlash(Notifier, FFUPath, false, !Info.IsBootloaderSecure, null, DoResetFirst, Experimental: Experimental, SetWorkingStatus:
(m, s, v, a, st) =>
{
if (st == WPinternalsStatus.SwitchingMode)
@@ -440,8 +440,47 @@ namespace WPinternals
await LumiaV2CustomFlash(Notifier, FFUPath, PerformFullFlashFirst, SkipWrite, Parts, DoResetFirst, ClearFlashingStatusAtEnd, CheckSectorAlignment, ShowProgress, Experimental);
}
internal async static Task LumiaV2CustomFlash(PhoneNotifierViewModel Notifier, string FFUPath, bool PerformFullFlashFirst, bool SkipWrite, List<FlashPart> FlashParts, bool DoResetFirst = true, bool ClearFlashingStatusAtEnd = true, bool CheckSectorAlignment = true, bool ShowProgress = true, bool Experimental = false, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, string ProgrammerPath = null)
{
NokiaFlashModel Model = (NokiaFlashModel)Notifier.CurrentModel;
PhoneInfo Info = Model.ReadPhoneInfo();
byte[] GPTChunk = LumiaUnlockBootloaderViewModel.GetGptChunk(Model, 131072u);
GPT GPT = new GPT(GPTChunk);
Partition UefiBSNV = GPT.GetPartition("UEFI_BS_NV");
bool UseOlderExploit = Info.UefiSecureBootEnabled;
if (!UseOlderExploit && ClearFlashingStatusAtEnd)
{
if (FlashParts == null)
{
UseOlderExploit = true;
}
else
{
foreach (var part in FlashParts)
{
if (part.StartSector >= UefiBSNV.FirstSector && part.StartSector <= UefiBSNV.LastSector)
{
UseOlderExploit = true;
break;
}
}
}
}
if (UseOlderExploit || !ClearFlashingStatusAtEnd)
await LumiaV20CustomFlash(Notifier, FFUPath, PerformFullFlashFirst, SkipWrite, FlashParts, DoResetFirst, ClearFlashingStatusAtEnd, CheckSectorAlignment, ShowProgress, Experimental, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure, ProgrammerPath);
else
await LumiaV3FlashRomViewModel.LumiaV3CustomFlash(Notifier, FlashParts, CheckSectorAlignment, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
}
// Magic!
internal async static Task LumiaV2CustomFlash(PhoneNotifierViewModel Notifier, string FFUPath, bool PerformFullFlashFirst, bool SkipWrite, List<FlashPart> FlashParts, bool DoResetFirst = true, bool ClearFlashingStatusAtEnd = true, bool CheckSectorAlignment = true, bool ShowProgress = true, bool Experimental = false, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, string ProgrammerPath = null) //, string LoaderPath = null)
internal async static Task LumiaV20CustomFlash(PhoneNotifierViewModel Notifier, string FFUPath, bool PerformFullFlashFirst, bool SkipWrite, List<FlashPart> FlashParts, bool DoResetFirst = true, bool ClearFlashingStatusAtEnd = true, bool CheckSectorAlignment = true, bool ShowProgress = true, bool Experimental = false, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null, string ProgrammerPath = null) //, string LoaderPath = null)
{
// Both SecurityHeader and StoreHeader need to be modified.
// Those should both not fall in a memory-gap to allow modification.
@@ -528,7 +567,7 @@ namespace WPinternals
byte Options = 0;
if (SkipWrite)
Options = (byte)FlashOptions.SkipWrite;
if (!Info.SecureFfuEnabled || Info.Authenticated || Info.RdcPresent)
if (!Info.IsBootloaderSecure)
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
// Gap fill calculation:
@@ -1801,6 +1840,8 @@ namespace WPinternals
bool IsUnlocked = false;
bool GPTChanged = false;
bool ClearFlashingStatus = true;
if (SetWorkingStatus == null) SetWorkingStatus = (m, s, v, a, st) => { };
if (UpdateWorkingStatus == null) UpdateWorkingStatus = (m, s, v, st) => { };
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
@@ -1896,6 +1937,7 @@ namespace WPinternals
IsUnlockedFlag.LastSector = 0x40;
GPT.Partitions.Add(IsUnlockedFlag);
GPTChanged = true;
ClearFlashingStatus = false;
}
}
else
@@ -1905,6 +1947,7 @@ namespace WPinternals
{
GPT.Partitions.Remove(IsUnlockedFlag);
GPTChanged = true;
ClearFlashingStatus = false;
}
}
}
@@ -1952,46 +1995,81 @@ namespace WPinternals
return;
}
// Now add NV partition
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
Partition UEFI_BS_NV;
if (BACKUP_BS_NV == null)
if (!ClearFlashingStatus)
{
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
UEFI_BS_NV = new Partition();
UEFI_BS_NV.Name = "UEFI_BS_NV";
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
GPT.Partitions.Add(UEFI_BS_NV);
GPTChanged = true;
if (!IsUnlocked)
{
// Undo secure boot exploit
Partition NvBackupPartition = GPT.GetPartition("BACKUP_BS_NV");
if (NvBackupPartition != null)
{
// This must be a left over of a half unlocked bootloader
Partition NvPartition = GPT.GetPartition("UEFI_BS_NV");
NvBackupPartition.Name = "UEFI_BS_NV";
NvBackupPartition.PartitionGuid = NvPartition.PartitionGuid;
NvBackupPartition.PartitionTypeGuid = NvPartition.PartitionTypeGuid;
GPT.Partitions.Remove(NvPartition);
GPTChanged = true;
}
PhoneInfo Info = FlashModel.ReadPhoneInfo(false);
// We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock.
if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled)
{
// ClearNV
Part = new FlashPart();
Partition Target2 = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)Target2.FirstSector;
Part.Stream = new MemoryStream(new byte[0x40000]);
Parts.Add(Part);
}
}
else
{
// Now add NV partition
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
Partition UEFI_BS_NV;
if (BACKUP_BS_NV == null)
{
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
UEFI_BS_NV = new Partition();
UEFI_BS_NV.Name = "UEFI_BS_NV";
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
GPT.Partitions.Add(UEFI_BS_NV);
GPTChanged = true;
}
Part = new FlashPart();
Target = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});
Parts.Add(Part);
}
}
Part = new FlashPart();
Target = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});
Parts.Add(Part);
if (GPTChanged)
{
@@ -2037,7 +2115,7 @@ namespace WPinternals
});
// Do actual flashing!
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, false, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, ClearFlashingStatus, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
}
else
{
@@ -2116,6 +2194,7 @@ namespace WPinternals
Partition Partition;
bool IsUnlocked = false;
bool GPTChanged = false;
bool ClearFlashingStatus = true;
if (SetWorkingStatus == null) SetWorkingStatus = (m, s, v, a, st) => { };
if (UpdateWorkingStatus == null) UpdateWorkingStatus = (m, s, v, st) => { };
@@ -2155,6 +2234,7 @@ namespace WPinternals
IsUnlockedFlag.LastSector = 0x40;
GPT.Partitions.Add(IsUnlockedFlag);
GPTChanged = true;
ClearFlashingStatus = false;
}
}
else
@@ -2164,6 +2244,7 @@ namespace WPinternals
{
GPT.Partitions.Remove(IsUnlockedFlag);
GPTChanged = true;
ClearFlashingStatus = false;
}
}
}
@@ -2230,45 +2311,81 @@ namespace WPinternals
return;
}
// Now add NV partition
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
Partition UEFI_BS_NV;
if (BACKUP_BS_NV == null)
if (!ClearFlashingStatus)
{
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
UEFI_BS_NV = new Partition();
UEFI_BS_NV.Name = "UEFI_BS_NV";
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
GPT.Partitions.Add(UEFI_BS_NV);
GPTChanged = true;
if (!IsUnlocked)
{
// Undo secure boot exploit
Partition NvBackupPartition = GPT.GetPartition("BACKUP_BS_NV");
if (NvBackupPartition != null)
{
// This must be a left over of a half unlocked bootloader
Partition NvPartition = GPT.GetPartition("UEFI_BS_NV");
NvBackupPartition.Name = "UEFI_BS_NV";
NvBackupPartition.PartitionGuid = NvPartition.PartitionGuid;
NvBackupPartition.PartitionTypeGuid = NvPartition.PartitionTypeGuid;
GPT.Partitions.Remove(NvPartition);
GPTChanged = true;
}
PhoneInfo Info = FlashModel.ReadPhoneInfo(false);
// We should only clear NV if there was no backup NV to be restored and the current NV contains the SB unlock.
if ((NvBackupPartition == null) && !Info.UefiSecureBootEnabled)
{
// ClearNV
Part = new FlashPart();
Partition Target2 = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)Target2.FirstSector;
Part.Stream = new MemoryStream(new byte[0x40000]);
Parts.Add(Part);
}
}
else
{
// Now add NV partition
Partition BACKUP_BS_NV = GPT.GetPartition("BACKUP_BS_NV");
Partition UEFI_BS_NV;
if (BACKUP_BS_NV == null)
{
BACKUP_BS_NV = GPT.GetPartition("UEFI_BS_NV");
Guid OriginalPartitionTypeGuid = BACKUP_BS_NV.PartitionTypeGuid;
Guid OriginalPartitionGuid = BACKUP_BS_NV.PartitionGuid;
BACKUP_BS_NV.Name = "BACKUP_BS_NV";
BACKUP_BS_NV.PartitionGuid = Guid.NewGuid();
BACKUP_BS_NV.PartitionTypeGuid = Guid.NewGuid();
UEFI_BS_NV = new Partition();
UEFI_BS_NV.Name = "UEFI_BS_NV";
UEFI_BS_NV.Attributes = BACKUP_BS_NV.Attributes;
UEFI_BS_NV.PartitionGuid = OriginalPartitionGuid;
UEFI_BS_NV.PartitionTypeGuid = OriginalPartitionTypeGuid;
UEFI_BS_NV.FirstSector = BACKUP_BS_NV.LastSector + 1;
UEFI_BS_NV.LastSector = UEFI_BS_NV.FirstSector + BACKUP_BS_NV.LastSector - BACKUP_BS_NV.FirstSector;
GPT.Partitions.Add(UEFI_BS_NV);
GPTChanged = true;
}
Part = new FlashPart();
Target = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});
Parts.Add(Part);
}
}
Part = new FlashPart();
Target = GPT.GetPartition("UEFI_BS_NV");
Part.StartSector = (UInt32)Target.FirstSector; // GPT is prepared for 64-bit sector-offset, but flash app isn't.
Part.Stream = new SeekableStream(() =>
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
// Magic!
// The SB resource is a compressed version of a raw NV-variable-partition.
// In this partition the SecureBoot variable is disabled.
// It overwrites the variable in a different NV-partition than where this variable is stored usually.
// This normally leads to endless-loops when the NV-variables are enumerated.
// But the partition contains an extra hack to break out the endless loops.
var stream = assembly.GetManifestResourceStream("WPinternals.SB");
return new DecompressedStream(stream);
});
Parts.Add(Part);
if (GPTChanged)
{
@@ -2318,7 +2435,7 @@ namespace WPinternals
}
// Do actual flashing!
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, false, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
await LumiaV2CustomFlash(Notifier, null, false, false, Parts, true, ClearFlashingStatus, false, true, false, SetWorkingStatus, UpdateWorkingStatus, ExitSuccess, ExitFailure);
}
else
{
+435
View File
@@ -0,0 +1,435 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace WPinternals
{
internal class LumiaV3FlashRomViewModel : ContextViewModel
{
private static void RoundUpToChunks(Stream stream, UInt32 chunkSize)
{
Int64 Size = stream.Length;
if ((Size % chunkSize) > 0)
{
Int64 padding = (UInt32)(((Size / chunkSize) + 1) * chunkSize) - Size;
stream.Write(new byte[padding], 0, (Int32)padding);
}
}
internal class ImageHeader
{
public UInt32 Size = 24;
public string Signature = "ImageFlash ";
public UInt32 ManifestLength;
public UInt32 ChunkSize = 128;
}
public class StoreHeader
{
public UInt32 UpdateType = 0; // Full update
public UInt16 MajorVersion = 1;
public UInt16 MinorVersion = 0;
public UInt16 FullFlashMajorVersion = 2;
public UInt16 FullFlashMinorVersion = 0;
// Size is 0xC0
public string PlatformId;
public UInt32 BlockSizeInBytes = 131072;
public UInt32 WriteDescriptorCount;
public UInt32 WriteDescriptorLength;
public UInt32 ValidateDescriptorCount = 0;
public UInt32 ValidateDescriptorLength = 0;
public UInt32 InitialTableIndex = 0;
public UInt32 InitialTableCount = 0;
public UInt32 FlashOnlyTableIndex = 0; // Should be the index of the critical partitions, but for now we don't implement that
public UInt32 FlashOnlyTableCount = 1;
public UInt32 FinalTableIndex; //= WriteDescriptorCount - FinalTableCount;
public UInt32 FinalTableCount = 0;
}
public class SecurityHeader
{
public UInt32 Size = 32;
public string Signature = "SignedImage ";
public UInt32 ChunkSizeInKb = 128;
public UInt32 HashAlgorithm = 32780; // SHA256 algorithm id
public UInt32 CatalogSize;
public UInt32 HashTableSize;
}
internal class ManifestIni
{
internal static string BuildUpManifest(FullFlash fullFlash, Store store)
{
string Manifest = "[FullFlash]\r\n";
if (!string.IsNullOrEmpty(fullFlash.AntiTheftVersion))
Manifest += "AntiTheftVersion = " + fullFlash.AntiTheftVersion + "\r\n";
if (!string.IsNullOrEmpty(fullFlash.OSVersion))
Manifest += "OSVersion = " + fullFlash.OSVersion + "\r\n";
if (!string.IsNullOrEmpty(fullFlash.Description))
Manifest += "Description = " + fullFlash.Description + "\r\n";
if (!string.IsNullOrEmpty(fullFlash.Version))
Manifest += "Version = " + fullFlash.Version + "\r\n";
if (!string.IsNullOrEmpty(fullFlash.DevicePlatformId0))
Manifest += "DevicePlatformId0 = " + fullFlash.DevicePlatformId0 + "\r\n";
Manifest += "\r\n[Store]\r\n";
Manifest += "SectorSize = " + store.SectorSize + "\r\n";
Manifest += "MinSectorCount = " + store.MinSectorCount + "\r\n";
Manifest += "\r\n";
return Manifest;
}
}
internal class FullFlash
{
public string AntiTheftVersion = "1.1"; // Allow flashing on all devices
public string OSVersion;
public string Description = "Update on: " + DateTime.Now.ToString("u") + "::\r\n";
public string Version = "2.0";
public string DevicePlatformId0;
}
internal class Store
{
public UInt32 SectorSize;
public UInt32 MinSectorCount;
}
// V3 exploit
// Magic
//
private static byte[] GenerateCatalogFile(byte[] hashData)
{
byte[] catalog_first_part = new byte[] { 0x30, 0x82, 0x01, 0x44, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x01, 0x35, 0x30, 0x82, 0x01, 0x31, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x82, 0x01, 0x26, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x01, 0xA0, 0x82, 0x01, 0x17, 0x30, 0x82, 0x01, 0x13, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x01, 0x01, 0x04, 0x10, 0xA8, 0xCA, 0xD9, 0x7D, 0xBF, 0x6D, 0x67, 0x4D, 0xB1, 0x4D, 0x62, 0xFB, 0xE6, 0x26, 0x22, 0xD4, 0x17, 0x0D, 0x32, 0x30, 0x30, 0x31, 0x31, 0x30, 0x31, 0x32, 0x31, 0x32, 0x32, 0x37, 0x5A, 0x30, 0x0E, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x01, 0x02, 0x05, 0x00, 0x30, 0x81, 0xD1, 0x30, 0x81, 0xCE, 0x04, 0x1E, 0x48, 0x00, 0x61, 0x00, 0x73, 0x00, 0x68, 0x00, 0x54, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x2E, 0x00, 0x62, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x62, 0x00, 0x00, 0x00, 0x31, 0x81, 0xAB, 0x30, 0x45, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x31, 0x37, 0x30, 0x35, 0x30, 0x10, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x19, 0xA2, 0x02, 0x80, 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 };
byte[] catalog_second_part = new byte[] { 0x30, 0x62, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0C, 0x02, 0x02, 0x31, 0x54, 0x30, 0x52, 0x1E, 0x4C, 0x00, 0x7B, 0x00, 0x44, 0x00, 0x45, 0x00, 0x33, 0x00, 0x35, 0x00, 0x31, 0x00, 0x41, 0x00, 0x34, 0x00, 0x32, 0x00, 0x2D, 0x00, 0x38, 0x00, 0x45, 0x00, 0x35, 0x00, 0x39, 0x00, 0x2D, 0x00, 0x31, 0x00, 0x31, 0x00, 0x44, 0x00, 0x30, 0x00, 0x2D, 0x00, 0x38, 0x00, 0x43, 0x00, 0x34, 0x00, 0x37, 0x00, 0x2D, 0x00, 0x30, 0x00, 0x30, 0x00, 0x43, 0x00, 0x30, 0x00, 0x34, 0x00, 0x46, 0x00, 0x43, 0x00, 0x32, 0x00, 0x39, 0x00, 0x35, 0x00, 0x45, 0x00, 0x45, 0x00, 0x7D, 0x02, 0x02, 0x02, 0x00, 0x31, 0x00 };
byte[] hash = new SHA1Managed().ComputeHash(hashData);
byte[] catalog = new byte[catalog_first_part.Length + hash.Length + catalog_second_part.Length];
System.Buffer.BlockCopy(catalog_first_part, 0, catalog, 0, catalog_first_part.Length);
System.Buffer.BlockCopy(hash, 0, catalog, catalog_first_part.Length, hash.Length);
System.Buffer.BlockCopy(catalog_second_part, 0, catalog, catalog_first_part.Length + hash.Length, catalog_second_part.Length);
return catalog;
}
// V3 exploit
// Magic
//
internal async static Task LumiaV3CustomFlash(PhoneNotifierViewModel Notifier, List<FlashPart> FlashParts, bool CheckSectorAlignment = true, SetWorkingStatus SetWorkingStatus = null, UpdateWorkingStatus UpdateWorkingStatus = null, ExitSuccess ExitSuccess = null, ExitFailure ExitFailure = null)
{
if (SetWorkingStatus == null) SetWorkingStatus = (m, s, v, a, st) => { };
if (UpdateWorkingStatus == null) UpdateWorkingStatus = (m, s, v, st) => { };
if (ExitSuccess == null) ExitSuccess = (m, s) => { };
if (ExitFailure == null) ExitFailure = (m, s) => { };
uint chunkSize = 131072u;
int chunkSizes = 131072;
if (FlashParts != null)
{
foreach (FlashPart Part in FlashParts)
{
if (Part.Stream == null)
throw new ArgumentException("Stream is null");
if (!Part.Stream.CanSeek)
throw new ArgumentException("Streams must be seekable");
if (((Part.StartSector * 0x200) % chunkSize) != 0)
throw new ArgumentException("Invalid StartSector alignment");
if (CheckSectorAlignment)
{
if ((Part.Stream.Length % chunkSize) != 0)
throw new ArgumentException("Invalid Data length");
}
}
}
try
{
NokiaFlashModel Model = (NokiaFlashModel)Notifier.CurrentModel;
PhoneInfo Info = Model.ReadPhoneInfo();
if ((Info.SecureFfuSupportedProtocolMask & ((ushort)FfuProtocol.ProtocolSyncV2)) == 0) // Exploit needs protocol v2 -> This check is not conclusive, because old phones also report support for this protocol, although it is really not supported.
throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that it does not support the Protocol Sync V2.");
if (Info.FlashAppProtocolVersionMajor < 2) // Old phones do not support the hack. These phones have Flash protocol 1.x.
throw new WPinternalsException("Flash failed!", "Protocols not supported. The phone reports that Flash App communication protocol is lower than 2. Reported version by the phone: " + Info.FlashAppProtocolVersionMajor + ".");
if (Info.UefiSecureBootEnabled)
throw new WPinternalsException("Flash failed!", "UEFI Secureboot must be disabled for the Flash V3 exploit to work.");
// The payloads must be ordered by the number of locations
//
// FlashApp processes payloads like this:
// - First payloads which are with one location, those can be sent in bulk
// - Then payloads with more than one location, those should not be sent in bulk
//
// If you do not order payloads like this, you will get an error, most likely hash mismatch
//
LumiaV2UnlockBootViewModel.FlashingPayload[] payloads = new LumiaV2UnlockBootViewModel.FlashingPayload[0];
if (FlashParts != null)
{
payloads = LumiaV2UnlockBootViewModel.GetNonOptimizedPayloads(FlashParts, chunkSizes, (uint)(Info.WriteBufferSize / chunkSize), SetWorkingStatus, UpdateWorkingStatus).OrderBy(x => x.TargetLocations.Count()).ToArray();
}
MemoryStream Headerstream1 = new MemoryStream();
// ==============================
// Header 1 start
ImageHeader image = new ImageHeader();
FullFlash ffimage = new FullFlash();
Store simage = new Store();
// Todo make this read the image itself
ffimage.OSVersion = "10.0.11111.0";
ffimage.DevicePlatformId0 = Info.PlatformID;
ffimage.AntiTheftVersion = "1.1";
simage.SectorSize = 512;
simage.MinSectorCount = Info.EmmcSizeInSectors;
//Logging.Log("Generating image manifest...");
string manifest = ManifestIni.BuildUpManifest(ffimage, simage);//, partitions);
byte[] TextBytes = System.Text.Encoding.ASCII.GetBytes(manifest);
image.ManifestLength = (UInt32)TextBytes.Length;
byte[] ImageHeaderBuffer = new byte[0x18];
ByteOperations.WriteUInt32(ImageHeaderBuffer, 0, image.Size);
ByteOperations.WriteAsciiString(ImageHeaderBuffer, 0x04, image.Signature);
ByteOperations.WriteUInt32(ImageHeaderBuffer, 0x10, image.ManifestLength);
ByteOperations.WriteUInt32(ImageHeaderBuffer, 0x14, image.ChunkSize);
Headerstream1.Write(ImageHeaderBuffer, 0, 0x18);
Headerstream1.Write(TextBytes, 0, TextBytes.Length);
RoundUpToChunks(Headerstream1, chunkSize);
// Header 1 stop + round
// ==============================
MemoryStream Headerstream2 = new MemoryStream();
// ==============================
// Header 2 start
StoreHeader store = new StoreHeader();
store.WriteDescriptorCount = (UInt32)payloads.Count();
store.FinalTableIndex = (UInt32)payloads.Count() - store.FinalTableCount;
store.PlatformId = Info.PlatformID;
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
{
store.WriteDescriptorLength += payload.GetStoreHeaderSize();
}
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
{
/*if (payload.TargetLocations.First() > PlatEnd)
break;*/
store.FlashOnlyTableIndex += 1;
}
byte[] StoreHeaderBuffer = new byte[0xF8];
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0, store.UpdateType);
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x04, store.MajorVersion);
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x06, store.MinorVersion);
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x08, store.FullFlashMajorVersion);
ByteOperations.WriteUInt16(StoreHeaderBuffer, 0x0A, store.FullFlashMinorVersion);
ByteOperations.WriteAsciiString(StoreHeaderBuffer, 0x0C, store.PlatformId);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xCC, store.BlockSizeInBytes);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xD0, store.WriteDescriptorCount);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xD4, store.WriteDescriptorLength);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xD8, store.ValidateDescriptorCount);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xDC, store.ValidateDescriptorLength);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xE0, store.InitialTableIndex);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xE4, store.InitialTableCount);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xE8, store.FlashOnlyTableIndex);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xEC, store.FlashOnlyTableCount);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xF0, store.FinalTableIndex);
ByteOperations.WriteUInt32(StoreHeaderBuffer, 0xF4, store.FinalTableCount);
Headerstream2.Write(StoreHeaderBuffer, 0, 0xF8);
byte[] descriptorsBuffer = new byte[store.WriteDescriptorLength];
UInt32 NewWriteDescriptorOffset = 0;
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
{
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x00, (UInt32)payload.TargetLocations.Count()); // Location count
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x04, payload.ChunkCount); // Chunk count
NewWriteDescriptorOffset += 0x08;
foreach (UInt32 location in payload.TargetLocations)
{
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x00, 0x00000000); // Disk access method (0 = Begin, 2 = End)
ByteOperations.WriteUInt32(descriptorsBuffer, NewWriteDescriptorOffset + 0x04, location); // Chunk index
NewWriteDescriptorOffset += 0x08;
}
}
Headerstream2.Write(descriptorsBuffer, 0, (Int32)store.WriteDescriptorLength);
RoundUpToChunks(Headerstream2, chunkSize);
// Header 2 stop + round
// ==============================
SecurityHeader security = new SecurityHeader();
Headerstream1.Seek(0, SeekOrigin.Begin);
Headerstream2.Seek(0, SeekOrigin.Begin);
security.HashTableSize = 0x20 * (UInt32)((Headerstream1.Length + Headerstream2.Length) / chunkSize);
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
{
security.HashTableSize += payload.GetSecurityHeaderSize();
}
byte[] HashTable = new byte[security.HashTableSize];
BinaryWriter bw = new BinaryWriter(new MemoryStream(HashTable));
SHA256 crypto = SHA256.Create();
for (int i = 0; i < Headerstream1.Length / chunkSize; i++)
{
byte[] buffer = new byte[chunkSize];
Headerstream1.Read(buffer, 0, (Int32)chunkSize);
byte[] hash = crypto.ComputeHash(buffer);
bw.Write(hash, 0, hash.Length);
}
for (int i = 0; i < Headerstream2.Length / chunkSize; i++)
{
byte[] buffer = new byte[chunkSize];
Headerstream2.Read(buffer, 0, (Int32)chunkSize);
byte[] hash = crypto.ComputeHash(buffer);
bw.Write(hash, 0, hash.Length);
}
foreach (LumiaV2UnlockBootViewModel.FlashingPayload payload in payloads)
{
bw.Write(payload.ChunkHashes[0], 0, payload.ChunkHashes[0].Length);
}
bw.Close();
//Logging.Log("Generating image catalog...");
byte[] catalog = GenerateCatalogFile(HashTable);
security.CatalogSize = (UInt32)catalog.Length;
byte[] SecurityHeaderBuffer = new byte[0x20];
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0, security.Size);
ByteOperations.WriteAsciiString(SecurityHeaderBuffer, 0x04, security.Signature);
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x10, security.ChunkSizeInKb);
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x14, security.HashAlgorithm);
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x18, security.CatalogSize);
ByteOperations.WriteUInt32(SecurityHeaderBuffer, 0x1C, security.HashTableSize);
MemoryStream retstream = new MemoryStream();
retstream.Write(SecurityHeaderBuffer, 0, 0x20);
retstream.Write(catalog, 0, (Int32)security.CatalogSize);
retstream.Write(HashTable, 0, (Int32)security.HashTableSize);
RoundUpToChunks(retstream, chunkSize);
Headerstream1.Seek(0, SeekOrigin.Begin);
Headerstream2.Seek(0, SeekOrigin.Begin);
byte[] buff = new byte[Headerstream1.Length];
Headerstream1.Read(buff, 0, (Int32)Headerstream1.Length);
Headerstream1.Close();
retstream.Write(buff, 0, buff.Length);
buff = new byte[Headerstream2.Length];
Headerstream2.Read(buff, 0, (Int32)Headerstream2.Length);
Headerstream2.Close();
retstream.Write(buff, 0, buff.Length);
// --------
// Go back to the beginning
retstream.Seek(0, SeekOrigin.Begin);
byte[] FfuHeader = new byte[retstream.Length];
await retstream.ReadAsync(FfuHeader, 0, (int)retstream.Length);
retstream.Close();
byte Options = 0;
if (!Info.IsBootloaderSecure)
Options = (byte)((FlashOptions)Options | FlashOptions.SkipSignatureCheck);
LogFile.Log("Flash in progress...", LogType.ConsoleOnly);
SetWorkingStatus("Flashing...", null, (UInt64?)payloads.Count(), Status: WPinternalsStatus.Flashing);
Model.SendFfuHeaderV1(FfuHeader, Options);
UInt64 counter = 0;
int numberOfPayloadsToSendAtOnce = (int)Math.Round((double)Info.WriteBufferSize / chunkSize);
byte[] payloadBuffer;
for (int i = 0; i < payloads.Count(); i+= numberOfPayloadsToSendAtOnce)
{
if (i + numberOfPayloadsToSendAtOnce - 1 >= payloads.Count())
{
numberOfPayloadsToSendAtOnce = payloads.Count() - i;
}
payloadBuffer = new byte[numberOfPayloadsToSendAtOnce * chunkSizes];
string ProgressText = "Flashing resources";
for (int j = 0; j < numberOfPayloadsToSendAtOnce; j++)
{
LumiaV2UnlockBootViewModel.FlashingPayload payload = payloads[i + j];
UInt32 StreamIndex = payload.StreamIndexes.First();
FlashPart flashPart = FlashParts[(int)StreamIndex];
if (flashPart.ProgressText != null)
ProgressText = flashPart.ProgressText;
Stream Stream = flashPart.Stream;
Stream.Seek(payload.StreamLocations.First(), SeekOrigin.Begin);
Stream.Read(payloadBuffer, j * chunkSizes, chunkSizes);
counter++;
}
Model.SendFfuPayloadV2(payloadBuffer, int.Parse((counter * 100 / (ulong)payloads.Count()).ToString()));
UpdateWorkingStatus(ProgressText, null, counter, WPinternalsStatus.Flashing);
}
Model.ResetPhone();
await Notifier.WaitForRemoval();
ExitSuccess("Flash succeeded!", null);
}
catch
{
throw new WPinternalsException("Custom flash failed");
}
}
}
}
+1 -1
View File
@@ -272,7 +272,7 @@ namespace WPinternals
LogFile.Log("Bootloader Security Authentication Status: " + BootloaderSecurityAuthenticationStatus.ToString());
BootloaderSecurityRdcStatus = Info.RdcPresent;
LogFile.Log("Bootloader Security Rdc Status: " + BootloaderSecurityRdcStatus.ToString());
EffectiveBootloaderSecurityStatus = Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent;
EffectiveBootloaderSecurityStatus = !Info.IsBootloaderSecure;
LogFile.Log("Effective Bootloader Security Status: " + EffectiveBootloaderSecurityStatus.ToString());
NativeDebugStatus = !Info.JtagDisabled;
+1 -1
View File
@@ -77,7 +77,7 @@ namespace WPinternals
}
else
{
EffectiveBootloaderSecurityStatus = Info.SecureFfuEnabled && !Info.Authenticated && !Info.RdcPresent;
EffectiveBootloaderSecurityStatus = !Info.IsBootloaderSecure;
}
}
else
+13 -3
View File
@@ -229,13 +229,22 @@ namespace WPinternals
}
else if ((e.DevicePath.IndexOf("&PID_066E", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_0421&PID_0714 is for Lumia 930
(e.DevicePath.IndexOf("&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0)) // VID_045E&PID_0A02 is for Lumia 950
(e.DevicePath.IndexOf("&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0) || // VID_045E&PID_0A02 is for Lumia 950
(e.DevicePath.IndexOf("&PID_05EE", StringComparison.OrdinalIgnoreCase) >= 0)) // VID_0421&PID_05EE is for early RX100
{
CurrentModel = new NokiaFlashModel(e.DevicePath);
((NokiaFlashModel)CurrentModel).InterfaceChanged += InterfaceChanged;
FlashAppType type = ((NokiaFlashModel)CurrentModel).GetFlashAppType();
LogFile.Log("Flash App Type: " + type.ToString(), LogType.FileOnly);
FlashAppType type = FlashAppType.FlashApp;
try
{
type = ((NokiaFlashModel)CurrentModel).GetFlashAppType();
LogFile.Log("Flash App Type: " + type.ToString(), LogType.FileOnly);
}
catch
{
LogFile.Log("Flash App Type could not be determined, assuming " + type.ToString(), LogType.FileOnly);
}
switch (type)
{
@@ -406,6 +415,7 @@ namespace WPinternals
(e.DevicePath.IndexOf("VID_0421&PID_06FC", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("VID_0421&PID_066E", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("VID_0421&PID_0714", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("VID_0421&PID_05EE", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("VID_045E&PID_0A00", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("VID_045E&PID_0A02", StringComparison.OrdinalIgnoreCase) >= 0) ||
(e.DevicePath.IndexOf("VID_05C6&PID_9008", StringComparison.OrdinalIgnoreCase) >= 0) ||
+2 -2
View File
@@ -641,7 +641,7 @@ namespace WPinternals
GPT GPT = FlashModel.ReadGPT();
IsUnlockedNew = ((GPT.GetPartition("IS_UNLOCKED") != null) || (GPT.GetPartition("BACKUP_EFIESP") != null) || (GPT.GetPartition("BACKUP_BS_NV") != null));
}
bool IsOriginalEngineeringLumia = ((!Info.SecureFfuEnabled || Info.Authenticated || Info.RdcPresent) && !IsUnlockedNew);
bool IsOriginalEngineeringLumia = (!Info.IsBootloaderSecure && !IsUnlockedNew);
if (IsOldLumia || IsOriginalEngineeringLumia)
{
@@ -650,7 +650,7 @@ namespace WPinternals
byte[] RebootToMassStorageCommand = new byte[] { 0x4E, 0x4F, 0x4B, 0x4D }; // NOKM
IsSwitchingInterface = true;
byte[] RebootCommandResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(RebootToMassStorageCommand);
if ((RebootCommandResult != null) && (RebootCommandResult.Length == 4)) // This means fail: NOKU (unknow command)
if ((RebootCommandResult != null) && (RebootCommandResult.Length == 4)) // This means fail: NOKU (unknown command)
{
BootModeFlagCommand[0x0F] = 0x4D;
byte[] BootFlagResult = ((NokiaPhoneModel)CurrentModel).ExecuteRawMethod(BootModeFlagCommand);
+1
View File
@@ -928,6 +928,7 @@
<Compile Include="ViewModels\BusyViewModel.cs" />
<Compile Include="ViewModels\DisclaimerAndNdaViewModel.cs" />
<Compile Include="ViewModels\DownloadsViewModel.cs" />
<Compile Include="ViewModels\LumiaV3FlashRomViewModel.cs" />
<Compile Include="ViewModels\NokiaBootloaderViewModel.cs" />
<Compile Include="ViewModels\NokiaModeBootloaderViewModel.cs" />
<Compile Include="ViewModels\RegistrationViewModel.cs" />
+89 -88
View File
@@ -4,6 +4,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 16.0.29123.89
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WPinternals", "WPinternals.csproj", "{AED6DEB8-F54C-4B41-9655-793E7096AE6E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPinternals.Core", "WPinternals.Core.csproj", "{AED6DEB8-F54C-4B41-9655-793E7096AE6F}"
EndProject
Global
@@ -54,6 +55,94 @@ Global
Release-Test|Any CPU = Release-Test|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.ActiveCfg = Debug-Test|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.Build.0 = Debug-Test|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Debug-AddEmergency|Any CPU.ActiveCfg = Debug|Any CPU
@@ -142,94 +231,6 @@ Global
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Release|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Release-Test|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6F}.Release-Test|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-AddEmergency|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-BackupGPT|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ClearNV|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-930|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950 (no restart)|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-CustomFlash-950|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLall|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLEmergency|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DLFFU|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpFFU|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-DumpUEFI|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccess|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableRootAccessOnImage|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning (no restart)|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-EnableTestSigning|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfile|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FindFlashingProfileNoRestart|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FixBoot|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashCustomRom-640|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1073|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashFFU-RM1085|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-FlashRaw|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Help|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlXml|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MergeGptXmlZip|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-MSM|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ReadGPT|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RelockPhone|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-RestoreGPT|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowFFU|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-ShowPhoneInfo|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-Test|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-550|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-630|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-640|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-650|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-930|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-TestProgrammer-950|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.ActiveCfg = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Debug-UnlockBootloader|Any CPU.Build.0 = Debug|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Preview-Test|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release|Any CPU.Build.0 = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.ActiveCfg = Release|Any CPU
{AED6DEB8-F54C-4B41-9655-793E7096AE6E}.Release-Test|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE