private static void DrawIL2CPPSection() { using (var changed = new EditorGUI.ChangeCheckScope()) { var fold = GUITools.DrawFoldHeader("IL2CPP", ACTkEditorPrefsSettings.IL2CPPFoldout); if (changed.changed) { ACTkEditorPrefsSettings.IL2CPPFoldout = fold; } } if (!ACTkEditorPrefsSettings.IL2CPPFoldout) { return; } GUILayout.Space(-3f); using (GUITools.Vertical(GUITools.PanelWithBackground)) { GUILayout.Label("IL2CPP prevents Mono injections and easy code decompilation. " + "Also consider obfuscating your metadata to make cheaters cry, see <b>readme</b> for details.", GUITools.RichLabel); GUILayout.Label("<b>Note: IL2CPP is AOT and does not support JIT!</b>", GUITools.RichMiniLabel); GUILayout.Space(5f); var supported = SettingsUtils.IsIL2CPPSupported(); var supportedColor = supported ? ColorTools.GetGreenString() : ColorTools.GetRedString(); var enabled = SettingsUtils.IsIL2CPPEnabled(); var enabledColor = enabled ? ColorTools.GetGreenString() : ColorTools.GetRedString(); GUILayout.Label("IL2CPP Supported: <color=#" + supportedColor + ">" + supported + "</color>", GUITools.RichLabel); GUILayout.Label("IL2CPP Enabled: <color=#" + enabledColor + ">" + enabled + "</color>", GUITools.RichLabel); if (!SettingsUtils.IsIL2CPPEnabled() && SettingsUtils.IsIL2CPPSupported()) { GUILayout.Space(5f); EditorGUILayout.HelpBox("Use IL2CPP to stop injections & easy code decompilation", MessageType.Warning, true); GUILayout.Space(5f); if (GUILayout.Button(new GUIContent("Switch to IL2CPP"))) { PlayerSettings.SetScriptingBackend(EditorUserBuildSettings.selectedBuildTargetGroup, ScriptingImplementation.IL2CPP); } } GUILayout.Space(3); } }
private static void DrawHashSection() { using (var changed = new EditorGUI.ChangeCheckScope()) { var betaColor = ColorTools.GetPurpleString(); var fold = GUITools.DrawFoldHeader("Code Hash Generator <color=#" + betaColor + ">BETA</color>", ACTkEditorPrefsSettings.HashFoldout); if (changed.changed) { ACTkEditorPrefsSettings.HashFoldout = fold; } } if (!ACTkEditorPrefsSettings.HashFoldout) { return; } GUILayout.Space(-3f); using (GUITools.Vertical(GUITools.PanelWithBackground)) { var option = ACTkSettings.Instance.PreGenerateBuildHash; EditorGUI.BeginChangeCheck(); option = EditorGUILayout.ToggleLeft(new GUIContent("Generate code hash on build completion", "Generates hash after build is finished, prints it to the console & sends it via CodeHashGeneratorPostprocessor."), option); if (EditorGUI.EndChangeCheck()) { ACTkSettings.Instance.PreGenerateBuildHash = option; } EditorGUILayout.Space(); GUILayout.Label("Can differ from runtime hash if you post-process code in resulting build (e.g. obfuscate, compress, etc.).", GUITools.RichLabel); GUILayout.Space(5f); EditorGUILayout.HelpBox("Always make sure post-build hash equals runtime one if you're using it for later comparison", MessageType.Info, true); if (!CodeHashGenerator.IsTargetPlatformCompatible()) { EditorGUILayout.HelpBox("Current platform is not supported: Windows or Android required", MessageType.Warning, true); } GUILayout.Space(3); } }
private static void DrawConditionalSection() { var header = "Conditional Compilation Symbols"; if (EditorApplication.isCompiling) { var redColor = ColorTools.GetRedString(); header += " [<color=#" + redColor + ">compiling</color>]"; } using (var changed = new EditorGUI.ChangeCheckScope()) { var fold = GUITools.DrawFoldHeader(header, ACTkEditorPrefsSettings.ConditionalFoldout); if (changed.changed) { ACTkEditorPrefsSettings.ConditionalFoldout = fold; } } if (EditorApplication.isCompiling) { GUI.enabled = false; } if (!ACTkEditorPrefsSettings.ConditionalFoldout) { return; } GUILayout.Space(-3f); using (GUITools.Vertical(GUITools.PanelWithBackground)) { GUILayout.Label("Here you may switch conditional compilation symbols used in ACTk.\n" + "Check Readme for more details on each symbol.", EditorStyles.wordWrappedLabel); EditorGUILayout.Space(); if (symbolsData == null) { symbolsData = SettingsUtils.GetSymbolsData(); } /*if (GUILayout.Button("Reset")) * { * var groups = (BuildTargetGroup[])Enum.GetValues(typeof(BuildTargetGroup)); * foreach (BuildTargetGroup buildTargetGroup in groups) * { * PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Empty); * } * }*/ //using (GUITools.Horizontal()) GUILayout.Label("Debug Symbols", GUITools.LargeBoldLabel); GUITools.Separator(); DrawSymbol(ref symbolsData.injectionDebug, ACTkEditorConstants.Conditionals.InjectionDebug, "Switches the Injection Detector debug."); DrawSymbol(ref symbolsData.injectionDebugVerbose, ACTkEditorConstants.Conditionals.InjectionDebugVerbose, "Switches the Injection Detector verbose debug level."); DrawSymbol(ref symbolsData.injectionDebugParanoid, ACTkEditorConstants.Conditionals.InjectionDebugParanoid, "Switches the Injection Detector paranoid debug level."); DrawSymbol(ref symbolsData.wallhackDebug, ACTkEditorConstants.Conditionals.WallhackDebug, "Switches the WallHack Detector debug - you'll see the WallHack objects in scene and get extra information in console."); DrawSymbol(ref symbolsData.detectionBacklogs, ACTkEditorConstants.Conditionals.DetectionBacklogs, "Enables additional logs in some detectors to make it easier to debug false positives."); EditorGUILayout.Space(); GUILayout.Label("Compatibility Symbols", GUITools.LargeBoldLabel); GUITools.Separator(); DrawSymbol(ref symbolsData.exposeThirdPartyIntegration, ACTkEditorConstants.Conditionals.ThirdPartyIntegration, "Enable to let other third-party code in project know you have ACTk added."); DrawSymbol(ref symbolsData.excludeObfuscation, ACTkEditorConstants.Conditionals.ExcludeObfuscation, "Enable if you use Unity-unaware obfuscators which support ObfuscationAttribute to help avoid names corruption."); DrawSymbol(ref symbolsData.preventReadPhoneState, ACTkEditorConstants.Conditionals.PreventReadPhoneState, "Disables ObscuredPrefs Lock To Device functionality."); DrawSymbol(ref symbolsData.preventInternetPermission, ACTkEditorConstants.Conditionals.PreventInternetPermission, "Disables TimeCheatingDetector functionality."); DrawSymbol(ref symbolsData.obscuredAutoMigration, ACTkEditorConstants.Conditionals.ObscuredAutoMigration, "Enables automatic migration of ObscuredFloat and ObscuredDouble instances from the ACTk 1.5.2.0-1.5.8.0 to the 1.5.9.0+ format. Reduces these types performance a bit."); DrawSymbol(ref symbolsData.usExportCompatible, ACTkEditorConstants.Conditionals.UsExportCompatible, "Enables US Encryption Export Regulations compatibility mode so ACTk do not force you to declare you're using encryption when publishing your application to the Apple App Store."); GUILayout.Space(3); } GUI.enabled = true; }
private static void DrawWallHackSection() { using (var changed = new EditorGUI.ChangeCheckScope()) { var fold = GUITools.DrawFoldHeader("WallHack Detector", ACTkEditorPrefsSettings.WallHackFoldout); if (changed.changed) { ACTkEditorPrefsSettings.WallHackFoldout = fold; } } if (!ACTkEditorPrefsSettings.WallHackFoldout) { return; } GUILayout.Space(-3f); using (GUITools.Vertical(GUITools.PanelWithBackground)) { GUILayout.Label( "Wireframe module uses own shader under the hood and it should be included into the build.", EditorStyles.wordWrappedLabel); ReadGraphicsAsset(); if (graphicsSettingsAsset != null && includedShaders != null) { // outputs whole included shaders list, use for debug //EditorGUILayout.PropertyField(includedShaders, true); var shaderIndex = GetWallhackDetectorShaderIndex(); EditorGUI.BeginChangeCheck(); var status = shaderIndex != -1 ? ColorTools.GetGreenString() + ">included" : ColorTools.GetRedString() + ">not included"; GUILayout.Label("Shader status: <color=#" + status + "</color>", GUITools.RichLabel); GUILayout.Space(5f); EditorGUILayout.HelpBox("You don't need to include it if you're not going to use Wireframe module", MessageType.Info, true); GUILayout.Space(5f); if (shaderIndex != -1) { if (GUILayout.Button("Remove shader")) { includedShaders.DeleteArrayElementAtIndex(shaderIndex); includedShaders.DeleteArrayElementAtIndex(shaderIndex); } GUILayout.Space(3); } else { using (GUITools.Horizontal()) { if (GUILayout.Button("Auto Include")) { var shader = Shader.Find(WallHackDetector.WireframeShaderName); if (shader != null) { includedShaders.InsertArrayElementAtIndex(includedShaders.arraySize); var newItem = includedShaders.GetArrayElementAtIndex(includedShaders.arraySize - 1); newItem.objectReferenceValue = shader; } else { Debug.LogError(ACTkConstants.LogPrefix + "Can't find " + WallHackDetector.WireframeShaderName + " shader! Please report this to the " + ACTkEditorConstants.SupportEmail + " including your Unity version number."); } } if (GUILayout.Button("Include manually (see readme.pdf)")) { #if UNITY_2018_3_OR_NEWER SettingsService.OpenProjectSettings("Project/Graphics"); #else EditorApplication.ExecuteMenuItem("Edit/Project Settings/Graphics"); #endif } } GUILayout.Space(3); } if (EditorGUI.EndChangeCheck()) { graphicsSettingsAsset.ApplyModifiedProperties(); } } else { GUILayout.Label("Can't automatically control " + WallHackDetector.WireframeShaderName + " shader existence at the Always Included Shaders list. Please, manage this manually in Graphics Settings."); if (GUILayout.Button("Open Graphics Settings")) { EditorApplication.ExecuteMenuItem("Edit/Project Settings/Graphics"); } } } }
private static void DrawInjectionSection() { using (var changed = new EditorGUI.ChangeCheckScope()) { var fold = GUITools.DrawFoldHeader("Injection Detector", ACTkEditorPrefsSettings.InjectionFoldout); if (changed.changed) { ACTkEditorPrefsSettings.InjectionFoldout = fold; } } if (!ACTkEditorPrefsSettings.InjectionFoldout) { return; } GUILayout.Space(-3f); using (GUITools.Vertical(GUITools.PanelWithBackground)) { var enableInjectionDetector = ACTkSettings.Instance.InjectionDetectorEnabled; if (SettingsUtils.IsIL2CPPEnabled()) { EditorGUILayout.HelpBox("Injection is not possible in IL2CPP,\n" + "this detector is not needed in IL2CPP builds", MessageType.Info, true); GUILayout.Space(5f); } else if (!InjectionRoutines.IsTargetPlatformCompatible()) { EditorGUILayout.HelpBox( "Injection Detection is only supported in non-IL2CPP Standalone and Android builds", MessageType.Warning, true); GUILayout.Space(5f); } using (new GUILayout.HorizontalScope()) { EditorGUI.BeginChangeCheck(); enableInjectionDetector = EditorGUILayout.ToggleLeft(new GUIContent( "Add mono injection detection support to build", "Injection Detector checks assemblies against whitelist. " + "Please enable this option if you're using Injection Detector " + "and default whitelist will be generated while Unity builds resulting build.\n" + "Has no effect for IL2CPP or unsupported platforms."), enableInjectionDetector ); if (EditorGUI.EndChangeCheck()) { ACTkSettings.Instance.InjectionDetectorEnabled = enableInjectionDetector; } } GUILayout.Space(3); if (GUILayout.Button(new GUIContent( "Edit Custom Whitelist (" + ACTkSettings.Instance.InjectionDetectorWhiteList.Count + ")", "Fill any external assemblies which are not included into the project to the user-defined whitelist to make Injection Detector aware of them.")) ) { UserWhitelistEditor.ShowWindow(); } GUILayout.Space(3); } }
// ------------------------------------------------------------------- // GUI // ------------------------------------------------------------------- private void OnGUI() { if (allRecords == null) { allRecords = new List <PrefsRecord>(); } if (filteredRecords == null) { filteredRecords = new List <PrefsRecord>(); } using (GUITools.Horizontal(GUITools.Toolbar)) { if (GUILayout.Button(new GUIContent("+", "Create new prefs record."), EditorStyles.toolbarButton, GUILayout.Width(20))) { addingNewRecord = true; } if (GUILayout.Button(new GUIContent("Refresh", "Re-read and re-parse all prefs."), EditorStyles.toolbarButton, GUILayout.Width(50))) { RefreshData(); GUIUtility.keyboardControl = 0; scrollPosition = Vector2.zero; recordsCurrentPage = 0; } EditorGUI.BeginChangeCheck(); sortingType = (SortingType)EditorGUILayout.EnumPopup(sortingType, EditorStyles.toolbarDropDown, GUILayout.Width(110)); if (EditorGUI.EndChangeCheck()) { ApplySorting(); } GUILayout.Space(10); EditorGUI.BeginChangeCheck(); searchPattern = GUITools.SearchToolbar(searchPattern); if (EditorGUI.EndChangeCheck()) { ApplyFiltering(); } } if (addingNewRecord) { using (GUITools.Horizontal(GUITools.PanelWithBackground)) { string[] types = { "String", "Int", "Float" }; newRecordType = EditorGUILayout.Popup(newRecordType, types, GUILayout.Width(50)); newRecordEncrypted = GUILayout.Toggle(newRecordEncrypted, new GUIContent("E", "Create new pref as encrypted ObscuredPref?"), GUITools.CompactButton, GUILayout.Width(25)); var guiColor = GUI.color; if (newRecordEncrypted) { GUI.color = obscuredColor; } GUILayout.Label("Key:", GUILayout.ExpandWidth(false)); newRecordKey = EditorGUILayout.TextField(newRecordKey); GUILayout.Label("Value:", GUILayout.ExpandWidth(false)); if (newRecordType == 0) { newRecordStringValue = EditorGUILayout.TextField(newRecordStringValue); } else if (newRecordType == 1) { newRecordIntValue = EditorGUILayout.IntField(newRecordIntValue); } else { newRecordFloatValue = EditorGUILayout.FloatField(newRecordFloatValue); } GUI.color = guiColor; if (GUILayout.Button("OK", GUITools.CompactButton, GUILayout.Width(30))) { if (string.IsNullOrEmpty(newRecordKey) || (newRecordType == 0 && string.IsNullOrEmpty(newRecordStringValue)) || (newRecordType == 1 && newRecordIntValue == 0) || (newRecordType == 2 && Math.Abs(newRecordFloatValue) < 0.00000001f)) { ShowNotification(new GUIContent("Please fill in the pref first!")); } else { PrefsRecord newRecord; if (newRecordType == 0) { newRecord = new PrefsRecord(newRecordKey, newRecordStringValue, newRecordEncrypted); } else if (newRecordType == 1) { newRecord = new PrefsRecord(newRecordKey, newRecordIntValue, newRecordEncrypted); } else { newRecord = new PrefsRecord(newRecordKey, newRecordFloatValue, newRecordEncrypted); } if (newRecord.Save()) { allRecords.Add(newRecord); ApplySorting(); CloseNewRecordPanel(); } } } if (GUILayout.Button("Cancel", GUITools.CompactButton, GUILayout.Width(60))) { CloseNewRecordPanel(); } } } using (GUITools.Vertical(GUITools.PanelWithBackground)) { GUILayout.Space(5); DrawRecordsPages(); GUILayout.Space(5); GUI.enabled = filteredRecords.Count > 0; using (GUITools.Horizontal()) { if (GUILayout.Button("Encrypt ALL", GUITools.CompactButton)) { if (EditorUtility.DisplayDialog("Obscure ALL prefs in list?", "This will apply obscuration to ALL unobscured prefs in the list.\nAre you sure you wish to do this?", "Yep", "Oh, no!")) { foreach (var record in filteredRecords) { record.Encrypt(); } GUIUtility.keyboardControl = 0; ApplySorting(); } } if (GUILayout.Button("Decrypt ALL", GUITools.CompactButton)) { if (EditorUtility.DisplayDialog("UnObscure ALL prefs in list?", "This will remove obscuration from ALL obscured prefs in the list if possible.\nAre you sure you wish to do this?", "Yep", "Oh, no!")) { foreach (var record in filteredRecords) { record.Decrypt(); } GUIUtility.keyboardControl = 0; ApplySorting(); } } if (GUILayout.Button("Save ALL", GUITools.CompactButton)) { if (EditorUtility.DisplayDialog("Save changes to ALL prefs in list?", "Are you sure you wish to save changes to ALL prefs in the list? This can't be undone!", "Yep", "Oh, no!")) { foreach (var record in filteredRecords) { record.Save(); } GUIUtility.keyboardControl = 0; ApplySorting(); } } if (GUILayout.Button("Delete ALL", GUITools.CompactButton)) { if (EditorUtility.DisplayDialog("Delete ALL prefs in list?", "Are you sure you wish to delete the ALL prefs in the list? This can't be undone!", "Yep", "Oh, no!")) { foreach (var record in filteredRecords) { record.Delete(); } RefreshData(); GUIUtility.keyboardControl = 0; } } } GUI.enabled = true; } }