예제 #1
0
        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);
        }
예제 #2
0
 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);
     }
 }
예제 #3
0
        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();
                }
            }
        }