public static Stream ReadCombinedAssets(this IAssetsFileProvider fp, string assetsFilePath) { string actualName = fp.CorrectAssetFilename(assetsFilePath); List <string> assetFiles = new List <string>(); if (actualName.ToLower().EndsWith("split0")) { assetFiles.AddRange(fp.FindFiles(actualName.Replace(".split0", ".split*")) .OrderBy(x => Convert.ToInt32(x.Split(new string[] { ".split" }, StringSplitOptions.None).Last()))); } else { return(fp.GetReadStream(actualName)); } MemoryStream msFullFile = new MemoryStream(); foreach (string assetsFile in assetFiles) { byte[] fileBytes = fp.Read(assetsFile); msFullFile.Write(fileBytes, 0, fileBytes.Length); } return(msFullFile); }
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 Stream ReadCombinedAssets(this IAssetsFileProvider fp, string assetsFilePath, out bool wasCombined) { string actualName = fp.CorrectAssetFilename(assetsFilePath); List <string> assetFiles = new List <string>(); if (actualName.ToLower().EndsWith("split0")) { assetFiles.AddRange(fp.FindFiles(actualName.Replace(".split0", ".split*")) .OrderBy(x => Convert.ToInt32(x.Split(new string[] { ".split" }, StringSplitOptions.None).Last()))); } else { wasCombined = false; return(fp.GetReadStream(actualName)); } wasCombined = true; //TODO: property or something on the file provider interface letting this code know if it should use the combined stream // I think combined stream may perform horribly on zip files or cause other issues. if (true) { return(new CombinedStream(assetFiles, fp)); } else { MemoryStream msFullFile = new MemoryStream(); foreach (string assetsFile in assetFiles) { byte[] fileBytes = fp.Read(assetsFile); msFullFile.Write(fileBytes, 0, fileBytes.Length); } return(msFullFile); } }
public static string ReadToString(this IAssetsFileProvider provider, string filename) { var data = provider.Read(filename); return(System.Text.Encoding.UTF8.GetString(data)); }