private void ProcessAll() { Dispatcher.Invoke(LogBox.Clear); Log( string.Format( "{0}{1}Start{1}{0}ExePath = {2}{0}Resources = {3}", Environment.NewLine, Line, _globalVariables.PathToExe, _globalVariables.PathToResources ) ); const int totalSteps = 3; _visualProgress.SetBarUsual(); _visualProgress.ShowBar(); _taskBarManager.SetProgress(0); _taskBarManager.SetUsualState(); void SetStep(int currentStep, string status) { int percentage = (currentStep - 1) * 100 / totalSteps; _visualProgress.SetBarValue(percentage); _visualProgress.SetLabelText(status); _taskBarManager.SetProgress(percentage); } #region Инициализация SetStep(1, MainResources.StepInitializing); _visualProgress.ShowIndeterminateLabel(); string sourceApkPath = ViewModel.CurrentApk.Value; bool alternativeSigning = _settings.AlternativeSigning; string popupText = ViewModel.PopupBoxText.Value; int messagesCount = ViewModel.MessagesCount.Value; bool needSave; bool needMessage; { bool onlySave = ViewModel.OnlySave.Value; bool savePlusMessage = ViewModel.SavePlusMess.Value; bool onlyMessage = ViewModel.OnlyMess.Value; needSave = onlySave || savePlusMessage; needMessage = (savePlusMessage || onlyMessage) && !string.IsNullOrEmpty(popupText) && messagesCount > 0; } BackupType backupType = ViewModel.BackupType.Value; ITempFileProvider tempFileProvider = _tempUtils.CreateTempFileProvider(); ITempFolderProvider tempFolderProvider = _tempUtils.CreateTempFolderProvider(); string resultApkPath = sourceApkPath.Remove(sourceApkPath.Length - Path.GetExtension(sourceApkPath).Length) + "_mod.apk"; string pathToSave = ViewModel.CurrentSave.Value; IApktool apktool = _apktoolProvider.Get(); IProcessDataHandler dataHandler = new ProcessDataCombinedHandler(data => Log(data)); #endregion #region Изменение apk using (var tempApk = ATempUtils.UseTempFile(tempFileProvider)) { LFile.Copy(sourceApkPath, tempApk.TempFile, true); #region Добавление данных SetStep(2, MainResources.StepAddingData); var aes = new AesManaged { KeySize = 128 }; aes.GenerateIV(); aes.GenerateKey(); bool backupFilesAdded = false; // adding local and external backup files if (needSave) { using (var internalDataBackup = ATempUtils.UseTempFile(tempFileProvider)) using (var externalDataBackup = ATempUtils.UseTempFile(tempFileProvider)) { ApkModifer.ParseBackup( pathToBackup: pathToSave, backupType: backupType, resultInternalDataPath: internalDataBackup.TempFile, resultExternalDataPath: externalDataBackup.TempFile, tempFolderProvider: tempFolderProvider ); string internalBackup = internalDataBackup.TempFile; string externalBackup = externalDataBackup.TempFile; var fileToAssetsName = new Dictionary <string, string> { { internalBackup, "data.save" }, { externalBackup, "extdata.save" } }; foreach (var(file, assetsName) in fileToAssetsName.Enumerate()) { if (!LFile.Exists(file) || FileUtils.FileLength(file) == 0) { continue; } using (var tempEncrypted = ATempUtils.UseTempFile(tempFileProvider)) { CommonUtils.EncryptFile( filePath: file, outputPath: tempEncrypted.TempFile, iv: aes.IV, key: aes.Key ); ApkModifer.AddFileToZip( zipPath: tempApk.TempFile, filePath: tempEncrypted.TempFile, pathInZip: "assets/" + assetsName, newEntryCompression: CompressionType.Store ); } backupFilesAdded = true; } } } // adding smali file for restoring if (backupFilesAdded || needMessage) { using (var decompiledFolder = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Baksmali( apkPath: tempApk.TempFile, resultFolder: decompiledFolder.TempFolder, tempFolderProvider: tempFolderProvider, dataHandler: dataHandler ); var manifestPath = Path.Combine(decompiledFolder.TempFolder, "AndroidManifest.xml"); apktool.ExtractSimpleManifest( apkPath: tempApk.TempFile, resultManifestPath: manifestPath, tempFolderProvider: tempFolderProvider ); // have to have smali folders in the same directory as manifest // to find the main smali var manifest = new AndroidManifest(manifestPath); if (manifest.MainSmaliFile == null) { throw new Exception("main smali file not found"); } // using this instead of just pasting "folder/smali" as there can be // no smali folder sometimes (smali_1, etc) string smaliDir = manifest.MainSmaliPath.Substring(decompiledFolder.TempFolder.Length + 1); smaliDir = smaliDir.Substring(0, smaliDir.IndexOf(Path.DirectorySeparatorChar)); string saveGameDir = Path.Combine(decompiledFolder.TempFolder, smaliDir, "com", "savegame"); LDirectory.CreateDirectory(saveGameDir); CommonUtils.GenerateAndSaveSmali( filePath: Path.Combine(saveGameDir, "SavesRestoringPortable.smali"), iv: aes.IV, key: aes.Key, addSave: backupFilesAdded, message: needMessage ? popupText : string.Empty, messagesCount: needMessage ? messagesCount : 0 ); manifest.MainSmaliFile.AddTextToMethod(FileResources.MainSmaliCall); manifest.MainSmaliFile.Save(); using (var folderWithDexes = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Smali( folderWithSmali: decompiledFolder.TempFolder, resultFolder: folderWithDexes.TempFolder, dataHandler: dataHandler ); string[] dexes = LDirectory.GetFiles(folderWithDexes.TempFolder, "*.dex"); ApkModifer.AddFilesToZip( zipPath: tempApk.TempFile, filePaths: dexes, pathsInZip: Array.ConvertAll(dexes, Path.GetFileName), newEntryCompression: CompressionType.Store ); } } } #endregion #region Подпись SetStep(3, MainResources.StepSigning); Log(Line); Log(MainResources.StepSigning); Log(Line); apktool.Sign( sourceApkPath: tempApk.TempFile, signedApkPath: resultApkPath, tempFileProvider: tempFileProvider, dataHandler: dataHandler, deleteMetaInf: !alternativeSigning ); #endregion } #endregion _visualProgress.HideIndeterminateLabel(); SetStep(4, MainResources.AllDone); Log(MainResources.AllDone); Log(string.Empty, false); Log($"{MainResources.Path_to_file} {resultApkPath}"); _globalVariables.LatestModdedApkPath = resultApkPath; if (_settings.Notifications) { _notificationManager.Show( title: MainResources.Information_Title, text: MainResources.ModificationCompletedContent ); } string dialogResult = MessBox.ShowDial( $"{MainResources.Path_to_file} {resultApkPath}", MainResources.Successful, MainResources.OK, MainResources.Open, MainResources.Install ); _visualProgress.HideBar(); _taskBarManager.SetNoneState(); if (dialogResult == MainResources.Open) { Process.Start("explorer.exe", $"/select,{resultApkPath}"); } else if (dialogResult == MainResources.Install) { Dispatcher.Invoke(() => _adbInstallWindowProvider.Get().ShowDialog()); } }
private void ProcessAll() { Dispatcher.Invoke(LogBox.Clear); Log( string.Format( "{0}{1}Start{1}{0}ExePath = {2}{0}Resources = {3}", Environment.NewLine, Line, _globalVariables.PathToExe, _globalVariables.PathToResources ) ); const int totalSteps = 3; _visualProgress.SetBarUsual(); _visualProgress.ShowBar(); _taskBarManager.SetProgress(0); _taskBarManager.SetUsualState(); void SetStep(int currentStep, string status) { int percentage = (currentStep - 1) * 100 / totalSteps; _visualProgress.SetBarValue(percentage); _visualProgress.SetLabelText(status); _taskBarManager.SetProgress(percentage); } #region Инициализация SetStep(1, MainResources.StepInitializing); _visualProgress.ShowIndeterminateLabel(); string sourceApkPath = ViewModel.CurrentApk.Value; bool alternativeSigning = _settings.AlternativeSigning; string popupText = ViewModel.PopupBoxText.Value; int messagesCount = ViewModel.MessagesCount.Value; bool needMessage = true; BackupType backupType = ViewModel.BackupType.Value; ITempFileProvider tempFileProvider = _tempUtils.CreateTempFileProvider(); ITempFolderProvider tempFolderProvider = _tempUtils.CreateTempFolderProvider(); string resultApkPath = sourceApkPath.Remove(sourceApkPath.Length - Path.GetExtension(sourceApkPath).Length) + "_signed.apk"; string pathToSave = ViewModel.CurrentSave.Value; IApktool apktool = _apktoolProvider.Get(); IProcessDataHandler dataHandler = new ProcessDataCombinedHandler(data => Log(data)); #endregion #region Change apk // Temp using (var tempApk = ATempUtils.UseTempFile(tempFileProvider)) { LFile.Copy(sourceApkPath, tempApk.TempFile, true); //Copy apk file to temp #region Adding data SetStep(2, MainResources.StepAddingData); var aes = new AesManaged { KeySize = 128 }; aes.GenerateIV(); aes.GenerateKey(); // adding smali file for restoring using (var decompiledFolder = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Baksmali( apkPath: tempApk.TempFile, resultFolder: decompiledFolder.TempFolder, tempFolderProvider: tempFolderProvider, dataHandler: dataHandler ); var manifestPath = Path.Combine(decompiledFolder.TempFolder, "AndroidManifest.xml"); apktool.ExtractSimpleManifest( apkPath: tempApk.TempFile, resultManifestPath: manifestPath, tempFolderProvider: tempFolderProvider ); // have to have smali folders in the same directory as manifest // to find the main smali var manifest = new AndroidManifest(manifestPath); if (manifest.MainSmaliFile == null) { throw new Exception("main smali file not found"); } // using this instead of just pasting "folder/smali" as there can be // no smali folder sometimes (smali_1, etc) string smaliDir = manifest.MainSmaliPath.Substring(decompiledFolder.TempFolder.Length + 1); smaliDir = smaliDir.Substring(0, smaliDir.IndexOf(Path.DirectorySeparatorChar)); string saveGameDir = Path.Combine(decompiledFolder.TempFolder, smaliDir, "com", "savegame"); LDirectory.CreateDirectory(saveGameDir); //Encrypt smali CommonUtils.GenerateAndSaveSmali( filePath: Path.Combine(saveGameDir, "SavesRestoringPortable.smali"), message: needMessage ? popupText : string.Empty, messagesCount: needMessage ? messagesCount : 0 ); manifest.MainSmaliFile.AddTextToMethod(FileResources.MainSmaliCall); manifest.MainSmaliFile.Save(); using (var folderWithDexes = ATempUtils.UseTempFolder(tempFolderProvider)) { apktool.Smali( folderWithSmali: decompiledFolder.TempFolder, resultFolder: folderWithDexes.TempFolder, dataHandler: dataHandler ); string[] dexes = LDirectory.GetFiles(folderWithDexes.TempFolder, "*.dex"); ApkModifer.AddFilesToZip( zipPath: tempApk.TempFile, filePaths: dexes, pathsInZip: Array.ConvertAll(dexes, Path.GetFileName), newEntryCompression: CompressionType.Store ); } } #endregion #region Подпись SetStep(3, MainResources.StepSigning); Log(Line); Log(MainResources.StepSigning); Log(Line); LFile.Copy(tempApk.TempFile, Path.GetDirectoryName(sourceApkPath) + "\\" + Path.GetFileNameWithoutExtension(sourceApkPath) + "_unsigned.apk", true); //Copy apk file to temp //Signing //tempApk.TempFile "C:\\Users\\xxxxx\\AppData\\Local\\SaveToGame\\temp\\temp_entry_1" apktool.Sign( sourceApkPath: tempApk.TempFile, signedApkPath: resultApkPath, tempFileProvider: tempFileProvider, dataHandler: dataHandler, deleteMetaInf: !alternativeSigning ); #endregion } #endregion _visualProgress.HideIndeterminateLabel(); SetStep(4, MainResources.AllDone); Log(MainResources.AllDone); Log(string.Empty, false); Log($"{MainResources.Path_to_file} {resultApkPath}"); _globalVariables.LatestModdedApkPath = resultApkPath; if (_settings.Notifications) { _notificationManager.Show( title: MainResources.Information_Title, text: MainResources.ModificationCompletedContent ); } string dialogResult = MessBox.ShowDial( $"{MainResources.Path_to_file} {resultApkPath}", MainResources.Successful, MainResources.OK, MainResources.Open, MainResources.Install ); _visualProgress.HideBar(); _taskBarManager.SetNoneState(); //Dialog result if (dialogResult == MainResources.Open) { Process.Start("explorer.exe", $"/select,{resultApkPath}"); } else if (dialogResult == MainResources.Install) { Dispatcher.Invoke(() => _adbInstallWindowProvider.Get().ShowDialog()); } }