public static bool Patch(IAssetsFileProvider apk, FilePatch patch) { string binaryFile = patch.Filename; if (!apk.FileExists(binaryFile)) { Console.WriteLine("Binary file to patch doesn't exist in the APK!"); return(false); } byte[] binaryBytes = apk.Read(binaryFile); if (binaryBytes.Length != patch.ExpectedFileSize) { Console.WriteLine("Binary file to patch is the wrong length!"); return(false); } List <Patch> toApply = new List <Patch>(); Console.WriteLine("Verifying patches binary..."); using (MemoryStream msBinary = new MemoryStream(binaryBytes)) { //verify each of the patches can be applied or already are applied foreach (Patch p in patch.Patches) { msBinary.Seek(p.Address, SeekOrigin.Begin); byte[] readVals = new byte[p.ExpectedData.Count]; msBinary.Read(readVals, 0, p.ExpectedData.Count); if (!readVals.SequenceEqual(p.ExpectedData)) { msBinary.Seek(p.Address, SeekOrigin.Begin); readVals = new byte[p.PatchData.Count]; msBinary.Read(readVals, 0, p.PatchData.Count); if (readVals.SequenceEqual(p.PatchData)) { Console.WriteLine($"Patch {p.Name} already appears to be applied."); continue; } else { Console.WriteLine($"Patch {p.Name} can't be applied to this binary, the code at the patch location doesn't match what was expected. Aborting any patching..."); //if one patch can't be applied, abort the whole thing return(false); } } } foreach (Patch p in toApply) { msBinary.Seek(p.Address, SeekOrigin.Begin); msBinary.Write(p.PatchData.ToArray(), 0, p.PatchData.Count); } msBinary.Seek(0, SeekOrigin.Begin); apk.Write(binaryFile, msBinary.ToArray(), true, true); } Console.WriteLine("Done patching binary!"); return(true); }
public static void WriteCombinedAssets(this IAssetsFileProvider fp, AssetsFile assetsFile, string assetsFilePath) { if (assetsFilePath.EndsWith("split0")) { throw new ArgumentException("Don't pass in filenames with split0, pass in the original."); } fp.DeleteFiles(assetsFilePath + ".split*"); using (var ms = new MemoryStream()) { assetsFile.Write(ms); ms.Seek(0, SeekOrigin.Begin); fp.Write(assetsFilePath, ms.ToArray(), true, true); } }
public void Sign(IAssetsFileProvider fileProvider) { MemoryStream msManifestFile = new MemoryStream(); MemoryStream msSigFile = new MemoryStream(); byte[] keyBlock; MemoryStream msSignatureFileBody = new MemoryStream(); try { //create the MF file header using (StreamWriter swManifest = GetSW(msManifestFile)) { swManifest.WriteLine("Manifest-Version: 1.0"); swManifest.WriteLine("Created-By: emulamer"); swManifest.WriteLine(); } //so that we can do it in one pass, write the MF and SF line items at the same time to their respective streams foreach (var infFile in fileProvider.FindFiles("*").Where(x => !x.StartsWith("META-INF"))) { WriteEntryHashes(fileProvider, infFile, msManifestFile, msSignatureFileBody); } //compute the hash on the entirety of the manifest file for the SF file msManifestFile.Seek(0, SeekOrigin.Begin); var manifestFileHash = _sha.ComputeHash(msManifestFile); //write the SF to memory then copy it out to the actual file- contents will be needed later to use for signing, don't want to hit the zip stream twice byte[] sigFileBytes = null; using (StreamWriter swSignatureFile = GetSW(msSigFile)) { swSignatureFile.WriteLine("Signature-Version: 1.0"); swSignatureFile.WriteLine($"SHA1-Digest-Manifest: {Convert.ToBase64String(manifestFileHash)}"); swSignatureFile.WriteLine("Created-By: emulamer"); swSignatureFile.WriteLine(); } msSignatureFileBody.Seek(0, SeekOrigin.Begin); msSignatureFileBody.CopyTo(msSigFile); msSigFile.Seek(0, SeekOrigin.Begin); sigFileBytes = msSigFile.ToArray(); //get the key block (all the hassle distilled into one line), then write it out to the RSA file keyBlock = SignIt(sigFileBytes); //delete all the META-INF stuff that exists already fileProvider.DeleteFiles("META-INF*"); //write the 3 files msManifestFile.Seek(0, SeekOrigin.Begin); fileProvider.Write("META-INF/MANIFEST.MF", msManifestFile.ToArray(), true, true); fileProvider.Write("META-INF/BS.SF", sigFileBytes, true, true); fileProvider.Write("META-INF/BS.RSA", keyBlock, true, true); fileProvider.Save(); } finally { if (msManifestFile != null) { msManifestFile.Dispose(); } if (msSignatureFileBody != null) { msSignatureFileBody.Dispose(); } if (msManifestFile != null) { msManifestFile.Dispose(); } if (msSigFile != null) { msSigFile.Dispose(); } } }