From 2453acc1d3032211699ce46d60dd22fc70e9604f Mon Sep 17 00:00:00 2001 From: walon Date: Wed, 21 May 2025 09:26:04 +0800 Subject: [PATCH] remove Obfuz project --- Obfuz/Assets/Bootstrap.cs | 29 - Obfuz/Assets/Bootstrap.cs.meta | 11 - Obfuz/Assets/Obfuz.meta | 8 - .../GeneratedEncryptionVirtualMachine.cs | 4522 ----------------- .../GeneratedEncryptionVirtualMachine.cs.meta | 11 - Obfuz/Assets/Obfuz/SymbolObfus.meta | 8 - .../Obfuz/SymbolObfus/symbol-mapping.xml | 482 -- .../Obfuz/SymbolObfus/symbol-mapping.xml.meta | 7 - Obfuz/Assets/Resources.meta | 8 - Obfuz/Assets/Resources/Obfuz.meta | 8 - .../Obfuz/defaultDynamicSecretKey.bytes | Bin 1024 -> 0 bytes .../Obfuz/defaultDynamicSecretKey.bytes.meta | 7 - .../Obfuz/defaultStaticSecretKey.bytes | Bin 1024 -> 0 bytes .../Obfuz/defaultStaticSecretKey.bytes.meta | 7 - Obfuz/Assets/main.unity | 362 -- Obfuz/Assets/main.unity.meta | 7 - .../com.code-philosophy.obfuz/Editor.meta | 8 - .../Editor/Conf.meta | 8 - .../Conf/XmlAssemblyTypeMethodRuleParser.cs | 267 - .../XmlAssemblyTypeMethodRuleParser.cs.meta | 11 - .../Editor/Conf/XmlFieldRuleParser.cs | 208 - .../Editor/Conf/XmlFieldRuleParser.cs.meta | 11 - .../Editor/ConfigurablePassPolicy.cs | 547 -- .../Editor/ConfigurablePassPolicy.cs.meta | 11 - .../Editor/ConstValues.cs | 13 - .../Editor/ConstValues.cs.meta | 11 - .../Editor/Data.meta | 8 - .../Editor/Data/ConstFieldAllocator.cs | 344 -- .../Editor/Data/ConstFieldAllocator.cs.meta | 11 - .../Editor/Data/RvaDataAllocator.cs | 355 -- .../Editor/Data/RvaDataAllocator.cs.meta | 11 - .../Editor/Emit.meta | 8 - .../Editor/Emit/BasicBlockCollection.cs | 295 -- .../Editor/Emit/BasicBlockCollection.cs.meta | 11 - .../Editor/Emit/DefaultMetadataImporter.cs | 193 - .../Emit/DefaultMetadataImporter.cs.meta | 11 - .../Editor/Emit/GroupByModuleEntityManager.cs | 66 - .../Emit/GroupByModuleEntityManager.cs.meta | 11 - .../Editor/EncryptionVM.meta | 8 - .../EncryptionInstructionWithOpCode.cs | 25 - .../EncryptionInstructionWithOpCode.cs.meta | 11 - .../EncryptionVM/IEncryptionInstruction.cs | 24 - .../IEncryptionInstruction.cs.meta | 11 - .../Editor/EncryptionVM/Instructions.meta | 8 - .../Instructions/AddInstruction.cs | 35 - .../Instructions/AddInstruction.cs.meta | 11 - .../Instructions/AddRotateXorInstruction.cs | 66 - .../AddRotateXorInstruction.cs.meta | 11 - .../Instructions/AddXorRotateInstruction.cs | 66 - .../AddXorRotateInstruction.cs.meta | 11 - .../Instructions/BitRotateInstruction.cs | 46 - .../Instructions/BitRotateInstruction.cs.meta | 11 - .../Instructions/EncryptFunction.cs | 47 - .../Instructions/EncryptFunction.cs.meta | 11 - .../Instructions/MultipleInstruction.cs | 64 - .../Instructions/MultipleInstruction.cs.meta | 11 - .../MultipleRotateXorInstruction.cs | 68 - .../MultipleRotateXorInstruction.cs.meta | 11 - .../MultipleXorRotateInstruction.cs | 68 - .../MultipleXorRotateInstruction.cs.meta | 11 - .../Instructions/XorAddRotateInstruction.cs | 66 - .../XorAddRotateInstruction.cs.meta | 11 - .../Instructions/XorInstruction.cs | 36 - .../Instructions/XorInstruction.cs.meta | 11 - .../XorMultipleRotateInstruction.cs | 68 - .../XorMultipleRotateInstruction.cs.meta | 11 - .../Editor/EncryptionVM/VirtualMachine.cs | 17 - .../EncryptionVM/VirtualMachine.cs.meta | 11 - .../VirtualMachineCodeGenerator.cs | 207 - .../VirtualMachineCodeGenerator.cs.meta | 11 - .../EncryptionVM/VirtualMachineCreator.cs | 71 - .../VirtualMachineCreator.cs.meta | 11 - .../EncryptionVM/VirtualMachineSimulator.cs | 96 - .../VirtualMachineSimulator.cs.meta | 11 - .../Editor/IObfuscationPass.cs | 20 - .../Editor/IObfuscationPass.cs.meta | 11 - .../Editor/ObfusPasses.meta | 8 - .../BasicBlockObfuscationPassBase.cs | 87 - .../BasicBlockObfuscationPassBase.cs.meta | 11 - .../Editor/ObfusPasses/CallObfus.meta | 8 - .../ObfusPasses/CallObfus/CallObfusPass.cs | 92 - .../CallObfus/CallObfusPass.cs.meta | 11 - .../CallObfus/CallProxyAllocator.cs | 293 -- .../CallObfus/CallProxyAllocator.cs.meta | 11 - .../ConfigurableObfuscationPolicy.cs | 411 -- .../ConfigurableObfuscationPolicy.cs.meta | 11 - .../CallObfus/DefaultCallProxyObfuscator.cs | 53 - .../DefaultCallProxyObfuscator.cs.meta | 11 - .../CallObfus/IObfuscationPolicy.cs | 34 - .../CallObfus/IObfuscationPolicy.cs.meta | 11 - .../ObfusPasses/CallObfus/IObfuscator.cs | 23 - .../ObfusPasses/CallObfus/IObfuscator.cs.meta | 11 - .../Editor/ObfusPasses/CleanUp.meta | 8 - .../CleanUp/CleanUpInstructionPass.cs | 46 - .../CleanUp/CleanUpInstructionPass.cs.meta | 11 - .../CleanUp/RemoveObfuzAttributesPass.cs | 71 - .../CleanUp/RemoveObfuzAttributesPass.cs.meta | 11 - .../Editor/ObfusPasses/ConstEncrypt.meta | 8 - .../ConstEncrypt/ConfigurableEncryptPolicy.cs | 489 -- .../ConfigurableEncryptPolicy.cs.meta | 11 - .../ConstEncrypt/ConstEncryptPass.cs | 152 - .../ConstEncrypt/ConstEncryptPass.cs.meta | 11 - .../ConstEncrypt/DefaultConstEncryptor.cs | 204 - .../DefaultConstEncryptor.cs.meta | 11 - .../ConstEncrypt/IConstEncryptor.cs | 32 - .../ConstEncrypt/IConstEncryptor.cs.meta | 11 - .../ConstEncrypt/IEncryptPolicy.cs | 48 - .../ConstEncrypt/IEncryptPolicy.cs.meta | 11 - .../Editor/ObfusPasses/ExprObfus.meta | 8 - .../ObfusPasses/ExprObfus/ExprObfusPass.cs | 35 - .../ExprObfus/ExprObfusPass.cs.meta | 11 - .../Editor/ObfusPasses/FieldEncrypt.meta | 8 - .../FieldEncrypt/ConfigurableEncryptPolicy.cs | 44 - .../ConfigurableEncryptPolicy.cs.meta | 11 - .../FieldEncrypt/DefaultFieldEncryptor.cs | 182 - .../DefaultFieldEncryptor.cs.meta | 11 - .../FieldEncrypt/FieldEncryptPass.cs | 108 - .../FieldEncrypt/FieldEncryptPass.cs.meta | 11 - .../FieldEncrypt/IEncryptPolicy.cs | 19 - .../FieldEncrypt/IEncryptPolicy.cs.meta | 11 - .../FieldEncrypt/IFieldEncryptor.cs | 29 - .../FieldEncrypt/IFieldEncryptor.cs.meta | 11 - .../InstructionObfuscationPassBase.cs | 85 - .../InstructionObfuscationPassBase.cs.meta | 11 - .../Editor/ObfusPasses/ObfuscationPassBase.cs | 20 - .../ObfusPasses/ObfuscationPassBase.cs.meta | 11 - .../Editor/ObfusPasses/ObfuscationPassType.cs | 25 - .../ObfusPasses/ObfuscationPassType.cs.meta | 11 - .../Editor/ObfusPasses/SymbolObfus.meta | 8 - .../ObfusPasses/SymbolObfus/INameMaker.cs | 33 - .../SymbolObfus/INameMaker.cs.meta | 11 - .../SymbolObfus/IObfuscationPolicy.cs | 17 - .../SymbolObfus/IObfuscationPolicy.cs.meta | 11 - .../ObfusPasses/SymbolObfus/NameMakers.meta | 8 - .../SymbolObfus/NameMakers/DebugNameMaker.cs | 29 - .../NameMakers/DebugNameMaker.cs.meta | 11 - .../SymbolObfus/NameMakers/INameScope.cs | 9 - .../SymbolObfus/NameMakers/INameScope.cs.meta | 11 - .../SymbolObfus/NameMakers/NameMakerBase.cs | 103 - .../NameMakers/NameMakerBase.cs.meta | 11 - .../NameMakers/NameMakerFactory.cs | 28 - .../NameMakers/NameMakerFactory.cs.meta | 11 - .../SymbolObfus/NameMakers/NameScope.cs | 35 - .../SymbolObfus/NameMakers/NameScope.cs.meta | 11 - .../SymbolObfus/NameMakers/NameScopeBase.cs | 57 - .../NameMakers/NameScopeBase.cs.meta | 11 - .../NameMakers/WordSetNameMaker.cs | 26 - .../NameMakers/WordSetNameMaker.cs.meta | 11 - .../ObfusPasses/SymbolObfus/Policies.meta | 8 - .../SymbolObfus/Policies/CacheRenamePolicy.cs | 68 - .../Policies/CacheRenamePolicy.cs.meta | 11 - .../Policies/CombineRenamePolicy.cs | 40 - .../Policies/CombineRenamePolicy.cs.meta | 11 - .../Policies/ConfigurableRenamePolicy.cs | 699 --- .../Policies/ConfigurableRenamePolicy.cs.meta | 11 - .../Policies/ObfuscationPolicyBase.cs | 33 - .../Policies/ObfuscationPolicyBase.cs.meta | 11 - .../SymbolObfus/Policies/SupportPassPolicy.cs | 50 - .../Policies/SupportPassPolicy.cs.meta | 11 - .../Policies/SystemRenamePolicy.cs | 83 - .../Policies/SystemRenamePolicy.cs.meta | 11 - .../SymbolObfus/Policies/UnityRenamePolicy.cs | 97 - .../Policies/UnityRenamePolicy.cs.meta | 11 - .../SymbolObfus/RenameRecordMap.cs | 706 --- .../SymbolObfus/RenameRecordMap.cs.meta | 11 - .../SymbolObfus/SymbolObfusPass.cs | 36 - .../SymbolObfus/SymbolObfusPass.cs.meta | 11 - .../ObfusPasses/SymbolObfus/SymbolRename.cs | 759 --- .../SymbolObfus/SymbolRename.cs.meta | 11 - .../VirtualMethodGroupCalculator.cs | 100 - .../VirtualMethodGroupCalculator.cs.meta | 11 - .../Editor/ObfuscationMethodWhitelist.cs | 75 - .../Editor/ObfuscationMethodWhitelist.cs.meta | 11 - .../Editor/ObfuscationPassContext.cs | 83 - .../Editor/ObfuscationPassContext.cs.meta | 11 - .../Editor/Obfuscator.cs | 339 -- .../Editor/Obfuscator.cs.meta | 11 - .../Editor/ObfuscatorBuilder.cs | 216 - .../Editor/ObfuscatorBuilder.cs.meta | 11 - .../Editor/Obfuz.Editor.asmdef | 18 - .../Editor/Obfuz.Editor.asmdef.meta | 7 - .../Editor/Pipeline.cs | 43 - .../Editor/Pipeline.cs.meta | 11 - .../Editor/Settings.meta | 8 - .../Editor/Settings/AssemblySettings.cs | 27 - .../Editor/Settings/AssemblySettings.cs.meta | 11 - .../Settings/CallObfuscationSettings.cs | 20 - .../Settings/CallObfuscationSettings.cs.meta | 11 - .../Settings/ConstEncryptionSettings.cs | 20 - .../Settings/ConstEncryptionSettings.cs.meta | 11 - .../Editor/Settings/EncryptionVMSettings.cs | 23 - .../Settings/EncryptionVMSettings.cs.meta | 11 - .../Settings/FieldEncryptionSettings.cs | 20 - .../Settings/FieldEncryptionSettings.cs.meta | 11 - .../Settings/ObfuscationPassSettings.cs | 16 - .../Settings/ObfuscationPassSettings.cs.meta | 11 - .../Editor/Settings/ObfuzSettings.cs | 101 - .../Editor/Settings/ObfuzSettings.cs.meta | 11 - .../Editor/Settings/ObfuzSettingsProvider.cs | 104 - .../Settings/ObfuzSettingsProvider.cs.meta | 11 - .../Editor/Settings/SecretSettings.cs | 30 - .../Editor/Settings/SecretSettings.cs.meta | 11 - .../Settings/SymbolObfuscationSettings.cs | 27 - .../SymbolObfuscationSettings.cs.meta | 11 - .../Editor/Unity.meta | 8 - .../Editor/Unity/ObfuscationBeginEventArgs.cs | 8 - .../Unity/ObfuscationBeginEventArgs.cs.meta | 11 - .../Editor/Unity/ObfuscationEndEventArgs.cs | 9 - .../Unity/ObfuscationEndEventArgs.cs.meta | 11 - .../Editor/Unity/ObfuscationProcess.cs | 124 - .../Editor/Unity/ObfuscationProcess.cs.meta | 11 - .../Editor/Unity/ObfuzMenu.cs | 64 - .../Editor/Unity/ObfuzMenu.cs.meta | 11 - .../Editor/Utils.meta | 8 - .../Editor/Utils/AssemblyCache.cs | 91 - .../Editor/Utils/AssemblyCache.cs.meta | 11 - .../Editor/Utils/AssemblyResolverBase.cs | 13 - .../Editor/Utils/AssemblyResolverBase.cs.meta | 11 - .../Editor/Utils/CollectionExtensions.cs | 24 - .../Editor/Utils/CollectionExtensions.cs.meta | 11 - .../Editor/Utils/ConfigUtil.cs | 76 - .../Editor/Utils/ConfigUtil.cs.meta | 11 - .../Editor/Utils/EncryptionUtil.cs | 49 - .../Editor/Utils/EncryptionUtil.cs.meta | 11 - .../Editor/Utils/FileUtil.cs | 100 - .../Editor/Utils/FileUtil.cs.meta | 11 - .../Editor/Utils/GenericArgumentContext.cs | 126 - .../Utils/GenericArgumentContext.cs.meta | 11 - .../Editor/Utils/HashUtil.cs | 67 - .../Editor/Utils/HashUtil.cs.meta | 11 - .../Editor/Utils/IAssemblyResolver.cs | 13 - .../Editor/Utils/IAssemblyResolver.cs.meta | 11 - .../Editor/Utils/IRandom.cs | 13 - .../Editor/Utils/IRandom.cs.meta | 11 - .../Editor/Utils/KeyGenerator.cs | 41 - .../Editor/Utils/KeyGenerator.cs.meta | 11 - .../Editor/Utils/MetaUtil.cs | 813 --- .../Editor/Utils/MetaUtil.cs.meta | 11 - .../Editor/Utils/NameMatcher.cs | 41 - .../Editor/Utils/NameMatcher.cs.meta | 11 - .../Editor/Utils/NumberRange.cs | 14 - .../Editor/Utils/NumberRange.cs.meta | 11 - .../Editor/Utils/PathAssemblyResolver.cs | 34 - .../Editor/Utils/PathAssemblyResolver.cs.meta | 11 - .../Editor/Utils/PlatformUtil.cs | 18 - .../Editor/Utils/PlatformUtil.cs.meta | 11 - .../Editor/Utils/RandomWithKey.cs | 58 - .../Editor/Utils/RandomWithKey.cs.meta | 11 - .../Editor/Utils/ThisArgType.cs | 9 - .../Editor/Utils/ThisArgType.cs.meta | 11 - .../Editor/Utils/TypeSigUtil.cs | 198 - .../Editor/Utils/TypeSigUtil.cs.meta | 11 - .../com.code-philosophy.obfuz/LICENSE | 21 - .../com.code-philosophy.obfuz/LICENSE.meta | 7 - .../com.code-philosophy.obfuz/Plugins.meta | 8 - .../Plugins/dnlib.dll | Bin 1175040 -> 0 bytes .../Plugins/dnlib.dll.meta | 33 - .../com.code-philosophy.obfuz/Runtime.meta | 8 - .../Runtime/ConstUtility.cs | 82 - .../Runtime/ConstUtility.cs.meta | 11 - .../Runtime/EncryptFieldAttribute.cs | 13 - .../Runtime/EncryptFieldAttribute.cs.meta | 11 - .../Runtime/EncryptionScope.cs | 31 - .../Runtime/EncryptionScope.cs.meta | 11 - .../Runtime/EncryptionService.cs | 126 - .../Runtime/EncryptionService.cs.meta | 11 - .../Runtime/EncryptorBase.cs | 258 - .../Runtime/EncryptorBase.cs.meta | 11 - .../Runtime/IEncryptor.cs | 32 - .../Runtime/IEncryptor.cs.meta | 11 - .../Runtime/NullEncryptor.cs | 92 - .../Runtime/NullEncryptor.cs.meta | 11 - .../Runtime/Obfuz.Runtime.asmdef | 14 - .../Runtime/Obfuz.Runtime.asmdef.meta | 7 - .../Runtime/ObfuzIgnoreAttribute.cs | 13 - .../Runtime/ObfuzIgnoreAttribute.cs.meta | 11 - .../com.code-philosophy.obfuz/package.json | 21 - .../package.json.meta | 7 - .../Editor.meta | 8 - .../Editor/ObfuscateUtil.cs | 82 - .../Editor/ObfuscateUtil.cs.meta | 11 - .../Editor/Obfuz4HybridCLR.asmdef | 19 - .../Editor/Obfuz4HybridCLR.asmdef.meta | 7 - .../Editor/PrebuildCommandExt.cs | 38 - .../Editor/PrebuildCommandExt.cs.meta | 11 - .../LICENSE | 21 - .../LICENSE.meta | 7 - .../package.json | 21 - .../package.json.meta | 7 - Obfuz/Packages/manifest.json | 11 - Obfuz/Packages/packages-lock.json | 143 - Obfuz/ProjectSettings/AudioManager.asset | 19 - .../ProjectSettings/ClusterInputManager.asset | 6 - Obfuz/ProjectSettings/DynamicsManager.asset | 34 - .../ProjectSettings/EditorBuildSettings.asset | 11 - Obfuz/ProjectSettings/EditorSettings.asset | 30 - Obfuz/ProjectSettings/GraphicsSettings.asset | 66 - Obfuz/ProjectSettings/HybridCLRSettings.asset | 32 - Obfuz/ProjectSettings/InputManager.asset | 295 -- Obfuz/ProjectSettings/MemorySettings.asset | 35 - .../ProjectSettings/MultiplayerManager.asset | 7 - Obfuz/ProjectSettings/NavMeshAreas.asset | 91 - Obfuz/ProjectSettings/Obfuz.asset | 49 - .../PackageManagerSettings.asset | 35 - .../Settings.json | 5 - Obfuz/ProjectSettings/Physics2DSettings.asset | 56 - Obfuz/ProjectSettings/PresetManager.asset | 7 - Obfuz/ProjectSettings/ProjectSettings.asset | 994 ---- Obfuz/ProjectSettings/ProjectVersion.txt | 2 - Obfuz/ProjectSettings/QualitySettings.asset | 234 - .../SceneTemplateSettings.json | 121 - Obfuz/ProjectSettings/TagManager.asset | 43 - Obfuz/ProjectSettings/TimeManager.asset | 9 - .../UnityConnectSettings.asset | 36 - Obfuz/ProjectSettings/VFXManager.asset | 12 - .../VersionControlSettings.asset | 8 - Obfuz/ProjectSettings/XRSettings.asset | 10 - Obfuz/README.md | 55 - 318 files changed, 22498 deletions(-) delete mode 100644 Obfuz/Assets/Bootstrap.cs delete mode 100644 Obfuz/Assets/Bootstrap.cs.meta delete mode 100644 Obfuz/Assets/Obfuz.meta delete mode 100644 Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs delete mode 100644 Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs.meta delete mode 100644 Obfuz/Assets/Obfuz/SymbolObfus.meta delete mode 100644 Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml delete mode 100644 Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml.meta delete mode 100644 Obfuz/Assets/Resources.meta delete mode 100644 Obfuz/Assets/Resources/Obfuz.meta delete mode 100644 Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes delete mode 100644 Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes.meta delete mode 100644 Obfuz/Assets/Resources/Obfuz/defaultStaticSecretKey.bytes delete mode 100644 Obfuz/Assets/Resources/Obfuz/defaultStaticSecretKey.bytes.meta delete mode 100644 Obfuz/Assets/main.unity delete mode 100644 Obfuz/Assets/main.unity.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/LICENSE delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/LICENSE.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Plugins.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/package.json delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz/package.json.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE.meta delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json delete mode 100644 Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json.meta delete mode 100644 Obfuz/Packages/manifest.json delete mode 100644 Obfuz/Packages/packages-lock.json delete mode 100644 Obfuz/ProjectSettings/AudioManager.asset delete mode 100644 Obfuz/ProjectSettings/ClusterInputManager.asset delete mode 100644 Obfuz/ProjectSettings/DynamicsManager.asset delete mode 100644 Obfuz/ProjectSettings/EditorBuildSettings.asset delete mode 100644 Obfuz/ProjectSettings/EditorSettings.asset delete mode 100644 Obfuz/ProjectSettings/GraphicsSettings.asset delete mode 100644 Obfuz/ProjectSettings/HybridCLRSettings.asset delete mode 100644 Obfuz/ProjectSettings/InputManager.asset delete mode 100644 Obfuz/ProjectSettings/MemorySettings.asset delete mode 100644 Obfuz/ProjectSettings/MultiplayerManager.asset delete mode 100644 Obfuz/ProjectSettings/NavMeshAreas.asset delete mode 100644 Obfuz/ProjectSettings/Obfuz.asset delete mode 100644 Obfuz/ProjectSettings/PackageManagerSettings.asset delete mode 100644 Obfuz/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json delete mode 100644 Obfuz/ProjectSettings/Physics2DSettings.asset delete mode 100644 Obfuz/ProjectSettings/PresetManager.asset delete mode 100644 Obfuz/ProjectSettings/ProjectSettings.asset delete mode 100644 Obfuz/ProjectSettings/ProjectVersion.txt delete mode 100644 Obfuz/ProjectSettings/QualitySettings.asset delete mode 100644 Obfuz/ProjectSettings/SceneTemplateSettings.json delete mode 100644 Obfuz/ProjectSettings/TagManager.asset delete mode 100644 Obfuz/ProjectSettings/TimeManager.asset delete mode 100644 Obfuz/ProjectSettings/UnityConnectSettings.asset delete mode 100644 Obfuz/ProjectSettings/VFXManager.asset delete mode 100644 Obfuz/ProjectSettings/VersionControlSettings.asset delete mode 100644 Obfuz/ProjectSettings/XRSettings.asset delete mode 100644 Obfuz/README.md diff --git a/Obfuz/Assets/Bootstrap.cs b/Obfuz/Assets/Bootstrap.cs deleted file mode 100644 index 6adb0b8..0000000 --- a/Obfuz/Assets/Bootstrap.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Obfuz; -using Obfuz.EncryptionVM; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - - -public class Bootstrap : MonoBehaviour -{ - [ObfuzIgnore] - [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] - private static void SetUpStaticSecret() - { - Debug.Log("SetUpStaticSecret begin"); - EncryptionService.Encryptor = new GeneratedEncryptionVirtualMachine(Resources.Load("Obfuz/defaultStaticSecretKey").bytes); - Debug.Log("SetUpStaticSecret end"); - } - - public int Add(int a, int b) - { - return a + b; - } - - void Start() - { - int a = Add(100, 200); - Debug.Log($"a = {a}"); - } -} diff --git a/Obfuz/Assets/Bootstrap.cs.meta b/Obfuz/Assets/Bootstrap.cs.meta deleted file mode 100644 index ff424e0..0000000 --- a/Obfuz/Assets/Bootstrap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 639006a739675484884778c298eebdc4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Obfuz.meta b/Obfuz/Assets/Obfuz.meta deleted file mode 100644 index 5b730e1..0000000 --- a/Obfuz/Assets/Obfuz.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 5eee1172624990e4cb08bd171f20cbaf -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs b/Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs deleted file mode 100644 index 3e74008..0000000 --- a/Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs +++ /dev/null @@ -1,4522 +0,0 @@ -/// This file is auto-generated by Obfuz. Do not modify it. -/// -/// Version: 0 -/// SecretKey: Obfuz -/// OpCodeCount: 256 - -namespace Obfuz.EncryptionVM -{ - public class GeneratedEncryptionVirtualMachine : Obfuz.EncryptorBase - { - - private const int kOpCodeBits = 8; - - private const int kOpCodeCount = 256; - - private const int kOpCodeMask = 255; - - - - private readonly int[] _secretKey; - - public GeneratedEncryptionVirtualMachine(byte[] secretKey) - { - this._secretKey = ConvertToIntKey(secretKey); - } - - public override int OpCodeCount => kOpCodeCount; - - public override int Encrypt(int value, int opts, int salt) - { - uint uopts = (uint)opts; - uint revertOps = 0; - while (uopts != 0) - { - uint opCode = uopts & kOpCodeMask; - revertOps <<= kOpCodeBits; - revertOps |= opCode; - uopts >>= kOpCodeBits; - } - - while (revertOps != 0) - { - uint opCode = revertOps & kOpCodeMask; - value = ExecuteEncrypt(value, (int)opCode, salt); - revertOps >>= kOpCodeBits; - } - return value; - } - - public override int Decrypt(int value, int opts, int salt) - { - uint uopts = (uint)opts; - while (uopts != 0) - { - uint opCode = uopts & kOpCodeMask; - value = ExecuteDecrypt(value, (int)opCode, salt); - uopts >>= kOpCodeBits; - } - return value; - } - - - private int ExecuteEncrypt(int value, int opCode, int salt) - { - switch (opCode) - { - case 0: - { - // MultipleInstruction - value = value * 598188269 + _secretKey[84] + salt; - return value; - } - case 1: - { - // MultipleRotateXorInstruction - value = value * 1350058129 + _secretKey[136]; - uint part1 = (uint)value << 4; - uint part2 = (uint)value >> (32 - 4); - value = (int)(part1 | part2); - value ^= 1817406469 ^ salt; - return value; - } - case 2: - { - // MultipleXorRotateInstruction - value = value * -1144218503 + _secretKey[246]; - value ^= -1498541961 ^ salt; - uint part1 = (uint)value << 5; - uint part2 = (uint)value >> (32 - 5); - value = (int)(part1 | part2); - return value; - } - case 3: - { - // AddRotateXorInstruction - value += -1207833585 + _secretKey[26]; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - value ^= 29411710 ^ salt; - return value; - } - case 4: - { - // BitRotateInstruction - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = ((int)(part1 | part2) ^ _secretKey[85]) + salt; - return value; - } - case 5: - { - // MultipleXorRotateInstruction - value = value * -1447238259 + _secretKey[165]; - value ^= 86149918 ^ salt; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - return value; - } - case 6: - { - // AddRotateXorInstruction - value += -1856354856 + _secretKey[178]; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - value ^= -1262500500 ^ salt; - return value; - } - case 7: - { - // XorInstruction - value = ((value ^ _secretKey[53]) + salt) ^ 665464645; - return value; - } - case 8: - { - // XorMultipleRotateInstruction - value ^= -1044567439 ^ salt; - value = value * -1860181607 + _secretKey[206]; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - return value; - } - case 9: - { - // MultipleInstruction - value = value * 522878123 + _secretKey[196] + salt; - return value; - } - case 10: - { - // XorAddRotateInstruction - value ^= -755609206 ^ salt; - value += -1035239660 + _secretKey[199]; - uint part1 = (uint)value << 10; - uint part2 = (uint)value >> (32 - 10); - value = (int)(part1 | part2); - return value; - } - case 11: - { - // AddInstruction - value = ((value + _secretKey[89]) ^ salt) + -1177184477; - return value; - } - case 12: - { - // BitRotateInstruction - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = ((int)(part1 | part2) ^ _secretKey[23]) + salt; - return value; - } - case 13: - { - // XorMultipleRotateInstruction - value ^= -1510419150 ^ salt; - value = value * -93709937 + _secretKey[68]; - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = (int)(part1 | part2); - return value; - } - case 14: - { - // MultipleRotateXorInstruction - value = value * 2015893433 + _secretKey[156]; - uint part1 = (uint)value << 6; - uint part2 = (uint)value >> (32 - 6); - value = (int)(part1 | part2); - value ^= -1134639492 ^ salt; - return value; - } - case 15: - { - // BitRotateInstruction - uint part1 = (uint)value << 7; - uint part2 = (uint)value >> (32 - 7); - value = ((int)(part1 | part2) ^ _secretKey[95]) + salt; - return value; - } - case 16: - { - // XorMultipleRotateInstruction - value ^= -759315565 ^ salt; - value = value * -436699251 + _secretKey[79]; - uint part1 = (uint)value << 6; - uint part2 = (uint)value >> (32 - 6); - value = (int)(part1 | part2); - return value; - } - case 17: - { - // MultipleRotateXorInstruction - value = value * 1266530571 + _secretKey[75]; - uint part1 = (uint)value << 2; - uint part2 = (uint)value >> (32 - 2); - value = (int)(part1 | part2); - value ^= -3885258 ^ salt; - return value; - } - case 18: - { - // MultipleXorRotateInstruction - value = value * -259404705 + _secretKey[153]; - value ^= 1207613963 ^ salt; - uint part1 = (uint)value << 9; - uint part2 = (uint)value >> (32 - 9); - value = (int)(part1 | part2); - return value; - } - case 19: - { - // MultipleRotateXorInstruction - value = value * 1042624059 + _secretKey[86]; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - value ^= 792769043 ^ salt; - return value; - } - case 20: - { - // AddInstruction - value = ((value + _secretKey[194]) ^ salt) + -512520382; - return value; - } - case 21: - { - // XorInstruction - value = ((value ^ _secretKey[195]) + salt) ^ -1864951858; - return value; - } - case 22: - { - // BitRotateInstruction - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = ((int)(part1 | part2) ^ _secretKey[2]) + salt; - return value; - } - case 23: - { - // MultipleInstruction - value = value * -463118297 + _secretKey[203] + salt; - return value; - } - case 24: - { - // AddInstruction - value = ((value + _secretKey[110]) ^ salt) + 2026667919; - return value; - } - case 25: - { - // AddXorRotateInstruction - value += 848657810 + _secretKey[133]; - value ^= 392708821 ^ salt; - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 26: - { - // BitRotateInstruction - uint part1 = (uint)value << 5; - uint part2 = (uint)value >> (32 - 5); - value = ((int)(part1 | part2) ^ _secretKey[93]) + salt; - return value; - } - case 27: - { - // XorAddRotateInstruction - value ^= 1294662302 ^ salt; - value += 1284012732 + _secretKey[58]; - uint part1 = (uint)value << 30; - uint part2 = (uint)value >> (32 - 30); - value = (int)(part1 | part2); - return value; - } - case 28: - { - // XorMultipleRotateInstruction - value ^= -1438081752 ^ salt; - value = value * -1171400509 + _secretKey[138]; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - return value; - } - case 29: - { - // BitRotateInstruction - uint part1 = (uint)value << 6; - uint part2 = (uint)value >> (32 - 6); - value = ((int)(part1 | part2) ^ _secretKey[240]) + salt; - return value; - } - case 30: - { - // MultipleRotateXorInstruction - value = value * 1892661727 + _secretKey[215]; - uint part1 = (uint)value << 24; - uint part2 = (uint)value >> (32 - 24); - value = (int)(part1 | part2); - value ^= 1594594445 ^ salt; - return value; - } - case 31: - { - // BitRotateInstruction - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = ((int)(part1 | part2) ^ _secretKey[49]) + salt; - return value; - } - case 32: - { - // XorAddRotateInstruction - value ^= 226193183 ^ salt; - value += -1038657413 + _secretKey[247]; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - return value; - } - case 33: - { - // XorAddRotateInstruction - value ^= -484591087 ^ salt; - value += 459902223 + _secretKey[252]; - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = (int)(part1 | part2); - return value; - } - case 34: - { - // MultipleXorRotateInstruction - value = value * -1382643267 + _secretKey[211]; - value ^= 1186351980 ^ salt; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 35: - { - // XorAddRotateInstruction - value ^= 1658142493 ^ salt; - value += -283413931 + _secretKey[235]; - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 36: - { - // XorInstruction - value = ((value ^ _secretKey[90]) + salt) ^ -1892941953; - return value; - } - case 37: - { - // XorMultipleRotateInstruction - value ^= -1297440001 ^ salt; - value = value * -1166749617 + _secretKey[111]; - uint part1 = (uint)value << 31; - uint part2 = (uint)value >> (32 - 31); - value = (int)(part1 | part2); - return value; - } - case 38: - { - // MultipleRotateXorInstruction - value = value * -375439505 + _secretKey[213]; - uint part1 = (uint)value << 31; - uint part2 = (uint)value >> (32 - 31); - value = (int)(part1 | part2); - value ^= 1353158598 ^ salt; - return value; - } - case 39: - { - // XorAddRotateInstruction - value ^= -934836680 ^ salt; - value += 873171360 + _secretKey[72]; - uint part1 = (uint)value << 20; - uint part2 = (uint)value >> (32 - 20); - value = (int)(part1 | part2); - return value; - } - case 40: - { - // MultipleXorRotateInstruction - value = value * 1427441479 + _secretKey[140]; - value ^= -28088263 ^ salt; - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 41: - { - // AddRotateXorInstruction - value += 969234286 + _secretKey[116]; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - value ^= -312111197 ^ salt; - return value; - } - case 42: - { - // MultipleInstruction - value = value * -1130955295 + _secretKey[29] + salt; - return value; - } - case 43: - { - // BitRotateInstruction - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = ((int)(part1 | part2) ^ _secretKey[1]) + salt; - return value; - } - case 44: - { - // BitRotateInstruction - uint part1 = (uint)value << 4; - uint part2 = (uint)value >> (32 - 4); - value = ((int)(part1 | part2) ^ _secretKey[184]) + salt; - return value; - } - case 45: - { - // MultipleXorRotateInstruction - value = value * -1782633617 + _secretKey[199]; - value ^= 1068062556 ^ salt; - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 46: - { - // XorMultipleRotateInstruction - value ^= 196245895 ^ salt; - value = value * -1852817781 + _secretKey[200]; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - return value; - } - case 47: - { - // MultipleXorRotateInstruction - value = value * -50587953 + _secretKey[10]; - value ^= -1964107221 ^ salt; - uint part1 = (uint)value << 7; - uint part2 = (uint)value >> (32 - 7); - value = (int)(part1 | part2); - return value; - } - case 48: - { - // MultipleXorRotateInstruction - value = value * 1216851115 + _secretKey[238]; - value ^= -38668552 ^ salt; - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 49: - { - // MultipleInstruction - value = value * -2133817615 + _secretKey[172] + salt; - return value; - } - case 50: - { - // AddXorRotateInstruction - value += 1412414820 + _secretKey[219]; - value ^= -2098495662 ^ salt; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - return value; - } - case 51: - { - // BitRotateInstruction - uint part1 = (uint)value << 10; - uint part2 = (uint)value >> (32 - 10); - value = ((int)(part1 | part2) ^ _secretKey[97]) + salt; - return value; - } - case 52: - { - // MultipleRotateXorInstruction - value = value * -1791837593 + _secretKey[63]; - uint part1 = (uint)value << 24; - uint part2 = (uint)value >> (32 - 24); - value = (int)(part1 | part2); - value ^= -21948406 ^ salt; - return value; - } - case 53: - { - // BitRotateInstruction - uint part1 = (uint)value << 7; - uint part2 = (uint)value >> (32 - 7); - value = ((int)(part1 | part2) ^ _secretKey[221]) + salt; - return value; - } - case 54: - { - // MultipleInstruction - value = value * -1220403071 + _secretKey[96] + salt; - return value; - } - case 55: - { - // MultipleRotateXorInstruction - value = value * -867896207 + _secretKey[29]; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - value ^= -1022882984 ^ salt; - return value; - } - case 56: - { - // XorMultipleRotateInstruction - value ^= 2122077674 ^ salt; - value = value * 957274637 + _secretKey[235]; - uint part1 = (uint)value << 12; - uint part2 = (uint)value >> (32 - 12); - value = (int)(part1 | part2); - return value; - } - case 57: - { - // AddRotateXorInstruction - value += -503448718 + _secretKey[175]; - uint part1 = (uint)value << 21; - uint part2 = (uint)value >> (32 - 21); - value = (int)(part1 | part2); - value ^= -720824840 ^ salt; - return value; - } - case 58: - { - // MultipleInstruction - value = value * -280528271 + _secretKey[231] + salt; - return value; - } - case 59: - { - // BitRotateInstruction - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = ((int)(part1 | part2) ^ _secretKey[75]) + salt; - return value; - } - case 60: - { - // MultipleRotateXorInstruction - value = value * -1403438719 + _secretKey[171]; - uint part1 = (uint)value << 27; - uint part2 = (uint)value >> (32 - 27); - value = (int)(part1 | part2); - value ^= 1420744071 ^ salt; - return value; - } - case 61: - { - // XorMultipleRotateInstruction - value ^= 1366253139 ^ salt; - value = value * -1583570963 + _secretKey[84]; - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 62: - { - // MultipleXorRotateInstruction - value = value * 24444809 + _secretKey[132]; - value ^= -1974823163 ^ salt; - uint part1 = (uint)value << 6; - uint part2 = (uint)value >> (32 - 6); - value = (int)(part1 | part2); - return value; - } - case 63: - { - // BitRotateInstruction - uint part1 = (uint)value << 22; - uint part2 = (uint)value >> (32 - 22); - value = ((int)(part1 | part2) ^ _secretKey[119]) + salt; - return value; - } - case 64: - { - // XorInstruction - value = ((value ^ _secretKey[15]) + salt) ^ 1262347216; - return value; - } - case 65: - { - // AddInstruction - value = ((value + _secretKey[126]) ^ salt) + 1780280992; - return value; - } - case 66: - { - // MultipleXorRotateInstruction - value = value * -1871888237 + _secretKey[85]; - value ^= -1198162446 ^ salt; - uint part1 = (uint)value << 13; - uint part2 = (uint)value >> (32 - 13); - value = (int)(part1 | part2); - return value; - } - case 67: - { - // MultipleInstruction - value = value * 931252767 + _secretKey[128] + salt; - return value; - } - case 68: - { - // BitRotateInstruction - uint part1 = (uint)value << 24; - uint part2 = (uint)value >> (32 - 24); - value = ((int)(part1 | part2) ^ _secretKey[178]) + salt; - return value; - } - case 69: - { - // XorInstruction - value = ((value ^ _secretKey[61]) + salt) ^ 1649427052; - return value; - } - case 70: - { - // MultipleRotateXorInstruction - value = value * -100486091 + _secretKey[83]; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - value ^= 849172121 ^ salt; - return value; - } - case 71: - { - // BitRotateInstruction - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = ((int)(part1 | part2) ^ _secretKey[169]) + salt; - return value; - } - case 72: - { - // XorAddRotateInstruction - value ^= 1068287172 ^ salt; - value += -2092062916 + _secretKey[138]; - uint part1 = (uint)value << 20; - uint part2 = (uint)value >> (32 - 20); - value = (int)(part1 | part2); - return value; - } - case 73: - { - // MultipleInstruction - value = value * -729679733 + _secretKey[34] + salt; - return value; - } - case 74: - { - // MultipleRotateXorInstruction - value = value * -1624925351 + _secretKey[30]; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - value ^= -145743337 ^ salt; - return value; - } - case 75: - { - // MultipleRotateXorInstruction - value = value * -1768166349 + _secretKey[142]; - uint part1 = (uint)value << 4; - uint part2 = (uint)value >> (32 - 4); - value = (int)(part1 | part2); - value ^= 280941267 ^ salt; - return value; - } - case 76: - { - // MultipleInstruction - value = value * -1708700487 + _secretKey[156] + salt; - return value; - } - case 77: - { - // AddRotateXorInstruction - value += 314625916 + _secretKey[192]; - uint part1 = (uint)value << 7; - uint part2 = (uint)value >> (32 - 7); - value = (int)(part1 | part2); - value ^= 827331935 ^ salt; - return value; - } - case 78: - { - // MultipleInstruction - value = value * 875189907 + _secretKey[141] + salt; - return value; - } - case 79: - { - // AddXorRotateInstruction - value += 1607953190 + _secretKey[133]; - value ^= -11549173 ^ salt; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - return value; - } - case 80: - { - // XorAddRotateInstruction - value ^= -1454482890 ^ salt; - value += 687186546 + _secretKey[95]; - uint part1 = (uint)value << 25; - uint part2 = (uint)value >> (32 - 25); - value = (int)(part1 | part2); - return value; - } - case 81: - { - // XorInstruction - value = ((value ^ _secretKey[195]) + salt) ^ 814860713; - return value; - } - case 82: - { - // AddRotateXorInstruction - value += 1998643542 + _secretKey[171]; - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = (int)(part1 | part2); - value ^= 213310246 ^ salt; - return value; - } - case 83: - { - // AddRotateXorInstruction - value += 542686146 + _secretKey[249]; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - value ^= -696314173 ^ salt; - return value; - } - case 84: - { - // AddRotateXorInstruction - value += 1734820207 + _secretKey[2]; - uint part1 = (uint)value << 9; - uint part2 = (uint)value >> (32 - 9); - value = (int)(part1 | part2); - value ^= 118718247 ^ salt; - return value; - } - case 85: - { - // XorInstruction - value = ((value ^ _secretKey[143]) + salt) ^ 1553710234; - return value; - } - case 86: - { - // AddRotateXorInstruction - value += -217984331 + _secretKey[146]; - uint part1 = (uint)value << 5; - uint part2 = (uint)value >> (32 - 5); - value = (int)(part1 | part2); - value ^= -1402843691 ^ salt; - return value; - } - case 87: - { - // MultipleInstruction - value = value * 1078374119 + _secretKey[5] + salt; - return value; - } - case 88: - { - // MultipleRotateXorInstruction - value = value * -975647447 + _secretKey[158]; - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = (int)(part1 | part2); - value ^= -2044505542 ^ salt; - return value; - } - case 89: - { - // AddInstruction - value = ((value + _secretKey[40]) ^ salt) + -1213654475; - return value; - } - case 90: - { - // XorMultipleRotateInstruction - value ^= -1886972278 ^ salt; - value = value * 275510141 + _secretKey[206]; - uint part1 = (uint)value << 6; - uint part2 = (uint)value >> (32 - 6); - value = (int)(part1 | part2); - return value; - } - case 91: - { - // AddRotateXorInstruction - value += -1724625239 + _secretKey[223]; - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = (int)(part1 | part2); - value ^= -979249928 ^ salt; - return value; - } - case 92: - { - // XorInstruction - value = ((value ^ _secretKey[83]) + salt) ^ -1104541704; - return value; - } - case 93: - { - // XorInstruction - value = ((value ^ _secretKey[31]) + salt) ^ 311150152; - return value; - } - case 94: - { - // XorMultipleRotateInstruction - value ^= 116496631 ^ salt; - value = value * 13120561 + _secretKey[176]; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - return value; - } - case 95: - { - // MultipleRotateXorInstruction - value = value * -1932552195 + _secretKey[87]; - uint part1 = (uint)value << 2; - uint part2 = (uint)value >> (32 - 2); - value = (int)(part1 | part2); - value ^= 2133438141 ^ salt; - return value; - } - case 96: - { - // MultipleRotateXorInstruction - value = value * 126641773 + _secretKey[174]; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - value ^= 225535005 ^ salt; - return value; - } - case 97: - { - // MultipleRotateXorInstruction - value = value * -1013570837 + _secretKey[175]; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - value ^= -1703839105 ^ salt; - return value; - } - case 98: - { - // XorAddRotateInstruction - value ^= -447564571 ^ salt; - value += -1783079937 + _secretKey[78]; - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 99: - { - // XorInstruction - value = ((value ^ _secretKey[111]) + salt) ^ -316631669; - return value; - } - case 100: - { - // XorMultipleRotateInstruction - value ^= -405694625 ^ salt; - value = value * 1711408839 + _secretKey[252]; - uint part1 = (uint)value << 24; - uint part2 = (uint)value >> (32 - 24); - value = (int)(part1 | part2); - return value; - } - case 101: - { - // MultipleXorRotateInstruction - value = value * -910384311 + _secretKey[212]; - value ^= -1551058348 ^ salt; - uint part1 = (uint)value << 6; - uint part2 = (uint)value >> (32 - 6); - value = (int)(part1 | part2); - return value; - } - case 102: - { - // AddInstruction - value = ((value + _secretKey[18]) ^ salt) + -853736135; - return value; - } - case 103: - { - // AddInstruction - value = ((value + _secretKey[116]) ^ salt) + 1321376878; - return value; - } - case 104: - { - // MultipleRotateXorInstruction - value = value * 1039555235 + _secretKey[7]; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - value ^= 541697309 ^ salt; - return value; - } - case 105: - { - // AddRotateXorInstruction - value += -822594180 + _secretKey[1]; - uint part1 = (uint)value << 4; - uint part2 = (uint)value >> (32 - 4); - value = (int)(part1 | part2); - value ^= 1176608900 ^ salt; - return value; - } - case 106: - { - // AddInstruction - value = ((value + _secretKey[110]) ^ salt) + -882893600; - return value; - } - case 107: - { - // MultipleRotateXorInstruction - value = value * -346726819 + _secretKey[114]; - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = (int)(part1 | part2); - value ^= -1566546809 ^ salt; - return value; - } - case 108: - { - // MultipleInstruction - value = value * -981516343 + _secretKey[97] + salt; - return value; - } - case 109: - { - // XorAddRotateInstruction - value ^= -72794161 ^ salt; - value += 1161425930 + _secretKey[43]; - uint part1 = (uint)value << 7; - uint part2 = (uint)value >> (32 - 7); - value = (int)(part1 | part2); - return value; - } - case 110: - { - // AddInstruction - value = ((value + _secretKey[238]) ^ salt) + -1619543125; - return value; - } - case 111: - { - // XorAddRotateInstruction - value ^= 1170459122 ^ salt; - value += -1766468683 + _secretKey[241]; - uint part1 = (uint)value << 12; - uint part2 = (uint)value >> (32 - 12); - value = (int)(part1 | part2); - return value; - } - case 112: - { - // AddXorRotateInstruction - value += 251687012 + _secretKey[219]; - value ^= 323019346 ^ salt; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - return value; - } - case 113: - { - // AddInstruction - value = ((value + _secretKey[97]) ^ salt) + -1049972438; - return value; - } - case 114: - { - // XorMultipleRotateInstruction - value ^= -492239002 ^ salt; - value = value * -1496840897 + _secretKey[216]; - uint part1 = (uint)value << 10; - uint part2 = (uint)value >> (32 - 10); - value = (int)(part1 | part2); - return value; - } - case 115: - { - // AddInstruction - value = ((value + _secretKey[221]) ^ salt) + -748126329; - return value; - } - case 116: - { - // AddXorRotateInstruction - value += -441051263 + _secretKey[96]; - value ^= -5933889 ^ salt; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - return value; - } - case 117: - { - // MultipleRotateXorInstruction - value = value * -1850062787 + _secretKey[88]; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - value ^= 543895274 ^ salt; - return value; - } - case 118: - { - // MultipleInstruction - value = value * -747527445 + _secretKey[140] + salt; - return value; - } - case 119: - { - // BitRotateInstruction - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = ((int)(part1 | part2) ^ _secretKey[175]) + salt; - return value; - } - case 120: - { - // MultipleRotateXorInstruction - value = value * 345252089 + _secretKey[57]; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - value ^= 1300544743 ^ salt; - return value; - } - case 121: - { - // XorAddRotateInstruction - value ^= -547380749 ^ salt; - value += 678597707 + _secretKey[119]; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - return value; - } - case 122: - { - // XorMultipleRotateInstruction - value ^= 683601851 ^ salt; - value = value * -145367929 + _secretKey[191]; - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = (int)(part1 | part2); - return value; - } - case 123: - { - // BitRotateInstruction - uint part1 = (uint)value << 20; - uint part2 = (uint)value >> (32 - 20); - value = ((int)(part1 | part2) ^ _secretKey[15]) + salt; - return value; - } - case 124: - { - // BitRotateInstruction - uint part1 = (uint)value << 8; - uint part2 = (uint)value >> (32 - 8); - value = ((int)(part1 | part2) ^ _secretKey[132]) + salt; - return value; - } - case 125: - { - // MultipleInstruction - value = value * 1436085223 + _secretKey[120] + salt; - return value; - } - case 126: - { - // AddInstruction - value = ((value + _secretKey[197]) ^ salt) + -1374139785; - return value; - } - case 127: - { - // BitRotateInstruction - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = ((int)(part1 | part2) ^ _secretKey[26]) + salt; - return value; - } - case 128: - { - // XorAddRotateInstruction - value ^= 1415280510 ^ salt; - value += 723646816 + _secretKey[146]; - uint part1 = (uint)value << 21; - uint part2 = (uint)value >> (32 - 21); - value = (int)(part1 | part2); - return value; - } - case 129: - { - // AddRotateXorInstruction - value += 1410706317 + _secretKey[165]; - uint part1 = (uint)value << 30; - uint part2 = (uint)value >> (32 - 30); - value = (int)(part1 | part2); - value ^= 2132310656 ^ salt; - return value; - } - case 130: - { - // XorAddRotateInstruction - value ^= 1264971736 ^ salt; - value += -483221582 + _secretKey[93]; - uint part1 = (uint)value << 12; - uint part2 = (uint)value >> (32 - 12); - value = (int)(part1 | part2); - return value; - } - case 131: - { - // AddXorRotateInstruction - value += -1872731835 + _secretKey[53]; - value ^= 1531807059 ^ salt; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - return value; - } - case 132: - { - // AddXorRotateInstruction - value += 264114638 + _secretKey[240]; - value ^= 306666665 ^ salt; - uint part1 = (uint)value << 10; - uint part2 = (uint)value >> (32 - 10); - value = (int)(part1 | part2); - return value; - } - case 133: - { - // AddRotateXorInstruction - value += 824712252 + _secretKey[138]; - uint part1 = (uint)value << 20; - uint part2 = (uint)value >> (32 - 20); - value = (int)(part1 | part2); - value ^= -1266414649 ^ salt; - return value; - } - case 134: - { - // AddRotateXorInstruction - value += -766337246 + _secretKey[35]; - uint part1 = (uint)value << 25; - uint part2 = (uint)value >> (32 - 25); - value = (int)(part1 | part2); - value ^= 2133737246 ^ salt; - return value; - } - case 135: - { - // AddXorRotateInstruction - value += -1997614825 + _secretKey[165]; - value ^= 1683555122 ^ salt; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 136: - { - // MultipleXorRotateInstruction - value = value * 278699987 + _secretKey[57]; - value ^= -1305042504 ^ salt; - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = (int)(part1 | part2); - return value; - } - case 137: - { - // BitRotateInstruction - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = ((int)(part1 | part2) ^ _secretKey[192]) + salt; - return value; - } - case 138: - { - // XorInstruction - value = ((value ^ _secretKey[135]) + salt) ^ 1715223135; - return value; - } - case 139: - { - // MultipleInstruction - value = value * 1809423757 + _secretKey[79] + salt; - return value; - } - case 140: - { - // AddRotateXorInstruction - value += -408450171 + _secretKey[11]; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - value ^= 806320034 ^ salt; - return value; - } - case 141: - { - // AddInstruction - value = ((value + _secretKey[95]) ^ salt) + -433941646; - return value; - } - case 142: - { - // AddXorRotateInstruction - value += 1775820811 + _secretKey[169]; - value ^= 2132471747 ^ salt; - uint part1 = (uint)value << 26; - uint part2 = (uint)value >> (32 - 26); - value = (int)(part1 | part2); - return value; - } - case 143: - { - // MultipleXorRotateInstruction - value = value * 457346731 + _secretKey[19]; - value ^= 114258470 ^ salt; - uint part1 = (uint)value << 2; - uint part2 = (uint)value >> (32 - 2); - value = (int)(part1 | part2); - return value; - } - case 144: - { - // AddRotateXorInstruction - value += -650723591 + _secretKey[206]; - uint part1 = (uint)value << 3; - uint part2 = (uint)value >> (32 - 3); - value = (int)(part1 | part2); - value ^= -1181275232 ^ salt; - return value; - } - case 145: - { - // MultipleInstruction - value = value * 1369495811 + _secretKey[169] + salt; - return value; - } - case 146: - { - // XorInstruction - value = ((value ^ _secretKey[154]) + salt) ^ -1297404981; - return value; - } - case 147: - { - // MultipleRotateXorInstruction - value = value * 787548271 + _secretKey[181]; - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = (int)(part1 | part2); - value ^= 801710213 ^ salt; - return value; - } - case 148: - { - // AddXorRotateInstruction - value += -1933121809 + _secretKey[230]; - value ^= 1566976773 ^ salt; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - return value; - } - case 149: - { - // BitRotateInstruction - uint part1 = (uint)value << 30; - uint part2 = (uint)value >> (32 - 30); - value = ((int)(part1 | part2) ^ _secretKey[188]) + salt; - return value; - } - case 150: - { - // BitRotateInstruction - uint part1 = (uint)value << 30; - uint part2 = (uint)value >> (32 - 30); - value = ((int)(part1 | part2) ^ _secretKey[53]) + salt; - return value; - } - case 151: - { - // AddInstruction - value = ((value + _secretKey[138]) ^ salt) + -2119615805; - return value; - } - case 152: - { - // MultipleRotateXorInstruction - value = value * 1289692111 + _secretKey[102]; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - value ^= 221292457 ^ salt; - return value; - } - case 153: - { - // MultipleRotateXorInstruction - value = value * -414757417 + _secretKey[248]; - uint part1 = (uint)value << 13; - uint part2 = (uint)value >> (32 - 13); - value = (int)(part1 | part2); - value ^= 1486712056 ^ salt; - return value; - } - case 154: - { - // MultipleInstruction - value = value * 1625437745 + _secretKey[72] + salt; - return value; - } - case 155: - { - // MultipleRotateXorInstruction - value = value * 1500723835 + _secretKey[247]; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - value ^= -81016400 ^ salt; - return value; - } - case 156: - { - // MultipleRotateXorInstruction - value = value * -939493617 + _secretKey[252]; - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = (int)(part1 | part2); - value ^= -1187848798 ^ salt; - return value; - } - case 157: - { - // AddXorRotateInstruction - value += 605454035 + _secretKey[108]; - value ^= 1185916334 ^ salt; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - return value; - } - case 158: - { - // AddXorRotateInstruction - value += 2112611413 + _secretKey[235]; - value ^= -451761745 ^ salt; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - return value; - } - case 159: - { - // XorInstruction - value = ((value ^ _secretKey[229]) + salt) ^ 1660696922; - return value; - } - case 160: - { - // MultipleRotateXorInstruction - value = value * 1280312911 + _secretKey[111]; - uint part1 = (uint)value << 31; - uint part2 = (uint)value >> (32 - 31); - value = (int)(part1 | part2); - value ^= -431219573 ^ salt; - return value; - } - case 161: - { - // XorMultipleRotateInstruction - value ^= 1658933717 ^ salt; - value = value * 642349663 + _secretKey[198]; - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = (int)(part1 | part2); - return value; - } - case 162: - { - // AddRotateXorInstruction - value += -1278798944 + _secretKey[72]; - uint part1 = (uint)value << 20; - uint part2 = (uint)value >> (32 - 20); - value = (int)(part1 | part2); - value ^= 609336148 ^ salt; - return value; - } - case 163: - { - // MultipleXorRotateInstruction - value = value * -1217570675 + _secretKey[57]; - value ^= -1055021038 ^ salt; - uint part1 = (uint)value << 26; - uint part2 = (uint)value >> (32 - 26); - value = (int)(part1 | part2); - return value; - } - case 164: - { - // MultipleXorRotateInstruction - value = value * 1129428085 + _secretKey[225]; - value ^= 1389308323 ^ salt; - uint part1 = (uint)value << 7; - uint part2 = (uint)value >> (32 - 7); - value = (int)(part1 | part2); - return value; - } - case 165: - { - // XorAddRotateInstruction - value ^= 318043677 ^ salt; - value += -1939584600 + _secretKey[124]; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - return value; - } - case 166: - { - // MultipleXorRotateInstruction - value = value * 601748357 + _secretKey[184]; - value ^= 2047590880 ^ salt; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 167: - { - // XorInstruction - value = ((value ^ _secretKey[114]) + salt) ^ -312123044; - return value; - } - case 168: - { - // AddXorRotateInstruction - value += 1897551751 + _secretKey[139]; - value ^= -1299860280 ^ salt; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - return value; - } - case 169: - { - // BitRotateInstruction - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = ((int)(part1 | part2) ^ _secretKey[10]) + salt; - return value; - } - case 170: - { - // MultipleInstruction - value = value * -1716044921 + _secretKey[60] + salt; - return value; - } - case 171: - { - // XorMultipleRotateInstruction - value ^= 820953326 ^ salt; - value = value * 1295924473 + _secretKey[242]; - uint part1 = (uint)value << 21; - uint part2 = (uint)value >> (32 - 21); - value = (int)(part1 | part2); - return value; - } - case 172: - { - // XorInstruction - value = ((value ^ _secretKey[89]) + salt) ^ 921116076; - return value; - } - case 173: - { - // AddInstruction - value = ((value + _secretKey[82]) ^ salt) + -1261901861; - return value; - } - case 174: - { - // MultipleRotateXorInstruction - value = value * 1029416329 + _secretKey[42]; - uint part1 = (uint)value << 1; - uint part2 = (uint)value >> (32 - 1); - value = (int)(part1 | part2); - value ^= -1758870671 ^ salt; - return value; - } - case 175: - { - // XorAddRotateInstruction - value ^= -99371457 ^ salt; - value += 1254595032 + _secretKey[10]; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 176: - { - // AddXorRotateInstruction - value += 1901168605 + _secretKey[131]; - value ^= -2036462975 ^ salt; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - return value; - } - case 177: - { - // MultipleRotateXorInstruction - value = value * 383500913 + _secretKey[29]; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - value ^= -805817000 ^ salt; - return value; - } - case 178: - { - // AddXorRotateInstruction - value += 28490730 + _secretKey[13]; - value ^= 762578411 ^ salt; - uint part1 = (uint)value << 12; - uint part2 = (uint)value >> (32 - 12); - value = (int)(part1 | part2); - return value; - } - case 179: - { - // XorAddRotateInstruction - value ^= 1812019570 ^ salt; - value += -41308497 + _secretKey[85]; - uint part1 = (uint)value << 24; - uint part2 = (uint)value >> (32 - 24); - value = (int)(part1 | part2); - return value; - } - case 180: - { - // XorInstruction - value = ((value ^ _secretKey[231]) + salt) ^ 1563652208; - return value; - } - case 181: - { - // AddRotateXorInstruction - value += -542613261 + _secretKey[75]; - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = (int)(part1 | part2); - value ^= -1148350591 ^ salt; - return value; - } - case 182: - { - // AddXorRotateInstruction - value += 1462569147 + _secretKey[135]; - value ^= 1842755263 ^ salt; - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = (int)(part1 | part2); - return value; - } - case 183: - { - // MultipleXorRotateInstruction - value = value * 934570325 + _secretKey[15]; - value ^= -159244912 ^ salt; - uint part1 = (uint)value << 8; - uint part2 = (uint)value >> (32 - 8); - value = (int)(part1 | part2); - return value; - } - case 184: - { - // BitRotateInstruction - uint part1 = (uint)value << 5; - uint part2 = (uint)value >> (32 - 5); - value = ((int)(part1 | part2) ^ _secretKey[230]) + salt; - return value; - } - case 185: - { - // AddRotateXorInstruction - value += 45305078 + _secretKey[119]; - uint part1 = (uint)value << 5; - uint part2 = (uint)value >> (32 - 5); - value = (int)(part1 | part2); - value ^= 1218428368 ^ salt; - return value; - } - case 186: - { - // AddXorRotateInstruction - value += 148564506 + _secretKey[160]; - value ^= 567100030 ^ salt; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - return value; - } - case 187: - { - // BitRotateInstruction - uint part1 = (uint)value << 21; - uint part2 = (uint)value >> (32 - 21); - value = ((int)(part1 | part2) ^ _secretKey[242]) + salt; - return value; - } - case 188: - { - // MultipleRotateXorInstruction - value = value * -1881635163 + _secretKey[30]; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - value ^= 730302816 ^ salt; - return value; - } - case 189: - { - // BitRotateInstruction - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = ((int)(part1 | part2) ^ _secretKey[93]) + salt; - return value; - } - case 190: - { - // BitRotateInstruction - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = ((int)(part1 | part2) ^ _secretKey[69]) + salt; - return value; - } - case 191: - { - // XorMultipleRotateInstruction - value ^= 1474104403 ^ salt; - value = value * 1888537457 + _secretKey[153]; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 192: - { - // AddInstruction - value = ((value + _secretKey[170]) ^ salt) + 1345231273; - return value; - } - case 193: - { - // BitRotateInstruction - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = ((int)(part1 | part2) ^ _secretKey[138]) + salt; - return value; - } - case 194: - { - // AddRotateXorInstruction - value += -1649692985 + _secretKey[138]; - uint part1 = (uint)value << 2; - uint part2 = (uint)value >> (32 - 2); - value = (int)(part1 | part2); - value ^= -1086752221 ^ salt; - return value; - } - case 195: - { - // XorMultipleRotateInstruction - value ^= 216360478 ^ salt; - value = value * 198928957 + _secretKey[23]; - uint part1 = (uint)value << 5; - uint part2 = (uint)value >> (32 - 5); - value = (int)(part1 | part2); - return value; - } - case 196: - { - // XorAddRotateInstruction - value ^= 1736125070 ^ salt; - value += -922639548 + _secretKey[211]; - uint part1 = (uint)value << 25; - uint part2 = (uint)value >> (32 - 25); - value = (int)(part1 | part2); - return value; - } - case 197: - { - // XorAddRotateInstruction - value ^= -1590872932 ^ salt; - value += -1729078426 + _secretKey[124]; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - return value; - } - case 198: - { - // AddXorRotateInstruction - value += -2086916257 + _secretKey[135]; - value ^= 2101329043 ^ salt; - uint part1 = (uint)value << 13; - uint part2 = (uint)value >> (32 - 13); - value = (int)(part1 | part2); - return value; - } - case 199: - { - // XorInstruction - value = ((value ^ _secretKey[133]) + salt) ^ -1188487898; - return value; - } - case 200: - { - // MultipleInstruction - value = value * -165216181 + _secretKey[162] + salt; - return value; - } - case 201: - { - // XorAddRotateInstruction - value ^= 2087683186 ^ salt; - value += -1882888353 + _secretKey[153]; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - return value; - } - case 202: - { - // MultipleRotateXorInstruction - value = value * -1941291837 + _secretKey[58]; - uint part1 = (uint)value << 22; - uint part2 = (uint)value >> (32 - 22); - value = (int)(part1 | part2); - value ^= -1855365205 ^ salt; - return value; - } - case 203: - { - // MultipleInstruction - value = value * 2036569383 + _secretKey[66] + salt; - return value; - } - case 204: - { - // MultipleXorRotateInstruction - value = value * 795577849 + _secretKey[206]; - value ^= 1668989123 ^ salt; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - return value; - } - case 205: - { - // MultipleInstruction - value = value * -1063887357 + _secretKey[169] + salt; - return value; - } - case 206: - { - // XorMultipleRotateInstruction - value ^= -387621173 ^ salt; - value = value * 413706907 + _secretKey[143]; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 207: - { - // XorInstruction - value = ((value ^ _secretKey[133]) + salt) ^ -1302837102; - return value; - } - case 208: - { - // XorMultipleRotateInstruction - value ^= 1201861103 ^ salt; - value = value * -1349002009 + _secretKey[5]; - uint part1 = (uint)value << 29; - uint part2 = (uint)value >> (32 - 29); - value = (int)(part1 | part2); - return value; - } - case 209: - { - // AddInstruction - value = ((value + _secretKey[188]) ^ salt) + -1698116194; - return value; - } - case 210: - { - // XorAddRotateInstruction - value ^= 955827838 ^ salt; - value += -5412811 + _secretKey[40]; - uint part1 = (uint)value << 3; - uint part2 = (uint)value >> (32 - 3); - value = (int)(part1 | part2); - return value; - } - case 211: - { - // MultipleXorRotateInstruction - value = value * 1209501053 + _secretKey[206]; - value ^= -261186202 ^ salt; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - return value; - } - case 212: - { - // XorInstruction - value = ((value ^ _secretKey[215]) + salt) ^ 1451245279; - return value; - } - case 213: - { - // AddInstruction - value = ((value + _secretKey[248]) ^ salt) + -48271475; - return value; - } - case 214: - { - // MultipleRotateXorInstruction - value = value * -685299407 + _secretKey[72]; - uint part1 = (uint)value << 31; - uint part2 = (uint)value >> (32 - 31); - value = (int)(part1 | part2); - value ^= 280704379 ^ salt; - return value; - } - case 215: - { - // MultipleRotateXorInstruction - value = value * 1188587057 + _secretKey[176]; - uint part1 = (uint)value << 17; - uint part2 = (uint)value >> (32 - 17); - value = (int)(part1 | part2); - value ^= -1507466225 ^ salt; - return value; - } - case 216: - { - // BitRotateInstruction - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = ((int)(part1 | part2) ^ _secretKey[162]) + salt; - return value; - } - case 217: - { - // XorInstruction - value = ((value ^ _secretKey[108]) + salt) ^ -1329546797; - return value; - } - case 218: - { - // XorAddRotateInstruction - value ^= 846489904 ^ salt; - value += 1710889501 + _secretKey[85]; - uint part1 = (uint)value << 11; - uint part2 = (uint)value >> (32 - 11); - value = (int)(part1 | part2); - return value; - } - case 219: - { - // XorInstruction - value = ((value ^ _secretKey[127]) + salt) ^ -339712479; - return value; - } - case 220: - { - // XorAddRotateInstruction - value ^= -1008587035 ^ salt; - value += -308188673 + _secretKey[78]; - uint part1 = (uint)value << 15; - uint part2 = (uint)value >> (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 221: - { - // MultipleInstruction - value = value * -2016434293 + _secretKey[111] + salt; - return value; - } - case 222: - { - // MultipleInstruction - value = value * -491329185 + _secretKey[198] + salt; - return value; - } - case 223: - { - // AddInstruction - value = ((value + _secretKey[160]) ^ salt) + -449129672; - return value; - } - case 224: - { - // MultipleXorRotateInstruction - value = value * -86469931 + _secretKey[84]; - value ^= -180027834 ^ salt; - uint part1 = (uint)value << 12; - uint part2 = (uint)value >> (32 - 12); - value = (int)(part1 | part2); - return value; - } - case 225: - { - // XorInstruction - value = ((value ^ _secretKey[58]) + salt) ^ 946019090; - return value; - } - case 226: - { - // AddRotateXorInstruction - value += 694016884 + _secretKey[225]; - uint part1 = (uint)value << 3; - uint part2 = (uint)value >> (32 - 3); - value = (int)(part1 | part2); - value ^= 1350981383 ^ salt; - return value; - } - case 227: - { - // AddRotateXorInstruction - value += -870643939 + _secretKey[168]; - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = (int)(part1 | part2); - value ^= 1680252929 ^ salt; - return value; - } - case 228: - { - // BitRotateInstruction - uint part1 = (uint)value << 4; - uint part2 = (uint)value >> (32 - 4); - value = ((int)(part1 | part2) ^ _secretKey[184]) + salt; - return value; - } - case 229: - { - // AddRotateXorInstruction - value += 1785715822 + _secretKey[199]; - uint part1 = (uint)value << 28; - uint part2 = (uint)value >> (32 - 28); - value = (int)(part1 | part2); - value ^= -1727043214 ^ salt; - return value; - } - case 230: - { - // XorInstruction - value = ((value ^ _secretKey[139]) + salt) ^ -1277148537; - return value; - } - case 231: - { - // MultipleXorRotateInstruction - value = value * 1298248033 + _secretKey[226]; - value ^= 1940873679 ^ salt; - uint part1 = (uint)value << 10; - uint part2 = (uint)value >> (32 - 10); - value = (int)(part1 | part2); - return value; - } - case 232: - { - // XorMultipleRotateInstruction - value ^= -879839609 ^ salt; - value = value * 1286764861 + _secretKey[171]; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 233: - { - // AddInstruction - value = ((value + _secretKey[181]) ^ salt) + 328489970; - return value; - } - case 234: - { - // MultipleInstruction - value = value * -1393808723 + _secretKey[89] + salt; - return value; - } - case 235: - { - // XorAddRotateInstruction - value ^= 1290000091 ^ salt; - value += -1977097134 + _secretKey[203]; - uint part1 = (uint)value << 8; - uint part2 = (uint)value >> (32 - 8); - value = (int)(part1 | part2); - return value; - } - case 236: - { - // AddInstruction - value = ((value + _secretKey[113]) ^ salt) + 1890859361; - return value; - } - case 237: - { - // AddRotateXorInstruction - value += 1045620543 + _secretKey[216]; - uint part1 = (uint)value << 10; - uint part2 = (uint)value >> (32 - 10); - value = (int)(part1 | part2); - value ^= 1434413518 ^ salt; - return value; - } - case 238: - { - // AddXorRotateInstruction - value += -1706485027 + _secretKey[131]; - value ^= 1591345537 ^ salt; - uint part1 = (uint)value << 0; - uint part2 = (uint)value >> (32 - 0); - value = (int)(part1 | part2); - return value; - } - case 239: - { - // AddXorRotateInstruction - value += 1271081841 + _secretKey[29]; - value ^= 1117669949 ^ salt; - uint part1 = (uint)value << 24; - uint part2 = (uint)value >> (32 - 24); - value = (int)(part1 | part2); - return value; - } - case 240: - { - // XorMultipleRotateInstruction - value ^= -842525462 ^ salt; - value = value * 1426591501 + _secretKey[235]; - uint part1 = (uint)value << 12; - uint part2 = (uint)value >> (32 - 12); - value = (int)(part1 | part2); - return value; - } - case 241: - { - // AddInstruction - value = ((value + _secretKey[175]) ^ salt) + 1030822002; - return value; - } - case 242: - { - // MultipleRotateXorInstruction - value = value * 1176352505 + _secretKey[57]; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - value ^= 811922151 ^ salt; - return value; - } - case 243: - { - // AddRotateXorInstruction - value += 656680947 + _secretKey[75]; - uint part1 = (uint)value << 23; - uint part2 = (uint)value >> (32 - 23); - value = (int)(part1 | part2); - value ^= -1258702719 ^ salt; - return value; - } - case 244: - { - // XorMultipleRotateInstruction - value ^= 90809787 ^ salt; - value = value * -1741148537 + _secretKey[191]; - uint part1 = (uint)value << 19; - uint part2 = (uint)value >> (32 - 19); - value = (int)(part1 | part2); - return value; - } - case 245: - { - // AddRotateXorInstruction - value += -532913580 + _secretKey[15]; - uint part1 = (uint)value << 16; - uint part2 = (uint)value >> (32 - 16); - value = (int)(part1 | part2); - value ^= 99436168 ^ salt; - return value; - } - case 246: - { - // MultipleXorRotateInstruction - value = value * 1306804229 + _secretKey[230]; - value ^= 1471598712 ^ salt; - uint part1 = (uint)value << 22; - uint part2 = (uint)value >> (32 - 22); - value = (int)(part1 | part2); - return value; - } - case 247: - { - // XorMultipleRotateInstruction - value ^= 1941306053 ^ salt; - value = value * -939631919 + _secretKey[15]; - uint part1 = (uint)value << 26; - uint part2 = (uint)value >> (32 - 26); - value = (int)(part1 | part2); - return value; - } - case 248: - { - // AddRotateXorInstruction - value += 883137918 + _secretKey[96]; - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = (int)(part1 | part2); - value ^= 2045091157 ^ salt; - return value; - } - case 249: - { - // BitRotateInstruction - uint part1 = (uint)value << 13; - uint part2 = (uint)value >> (32 - 13); - value = ((int)(part1 | part2) ^ _secretKey[165]) + salt; - return value; - } - case 250: - { - // AddInstruction - value = ((value + _secretKey[96]) ^ salt) + -394947456; - return value; - } - case 251: - { - // BitRotateInstruction - uint part1 = (uint)value << 18; - uint part2 = (uint)value >> (32 - 18); - value = ((int)(part1 | part2) ^ _secretKey[93]) + salt; - return value; - } - case 252: - { - // AddInstruction - value = ((value + _secretKey[69]) ^ salt) + 1917332797; - return value; - } - case 253: - { - // AddXorRotateInstruction - value += 1006809939 + _secretKey[113]; - value ^= -1509317223 ^ salt; - uint part1 = (uint)value << 14; - uint part2 = (uint)value >> (32 - 14); - value = (int)(part1 | part2); - return value; - } - case 254: - { - // BitRotateInstruction - uint part1 = (uint)value << 9; - uint part2 = (uint)value >> (32 - 9); - value = ((int)(part1 | part2) ^ _secretKey[170]) + salt; - return value; - } - case 255: - { - // AddInstruction - value = ((value + _secretKey[138]) ^ salt) + 683715132; - return value; - } - - default: - throw new System.Exception($"Invalid opCode:{opCode}"); - } - } - - private int ExecuteDecrypt(int value, int opCode, int salt) - { - switch (opCode) - { - case 0: - { - // MultipleInstruction - value = (value - _secretKey[84] - salt) * -1954824987; - return value; - } - case 1: - { - // MultipleRotateXorInstruction - value ^= 1817406469 ^ salt; - uint value2 = (uint)value >> 4; - uint part1 = (uint)value << (32 - 4); - value = (int)(value2 | part1); - value = (value - _secretKey[136]) * -2114748303; - return value; - } - case 2: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 5; - uint part1 = (uint)value << (32 - 5); - value = (int)(value2 | part1); - value ^= -1498541961 ^ salt; - value = (value - _secretKey[246]) * -203485751; - return value; - } - case 3: - { - // AddRotateXorInstruction - value ^= 29411710 ^ salt; - uint value2 = (uint)value >> 0; - uint part1 = (uint)value << (32 - 0); - value = (int)(value2 | part1); - value -= -1207833585 + _secretKey[26]; - return value; - } - case 4: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[85]); - uint part1 = value2 >> 18; - uint part2 = value2 << (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 5: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 0; - uint part1 = (uint)value << (32 - 0); - value = (int)(value2 | part1); - value ^= 86149918 ^ salt; - value = (value - _secretKey[165]) * -327424699; - return value; - } - case 6: - { - // AddRotateXorInstruction - value ^= -1262500500 ^ salt; - uint value2 = (uint)value >> 29; - uint part1 = (uint)value << (32 - 29); - value = (int)(value2 | part1); - value -= -1856354856 + _secretKey[178]; - return value; - } - case 7: - { - // XorInstruction - value = ((value ^ 665464645) - salt) ^ _secretKey[53]; - return value; - } - case 8: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value = (value - _secretKey[206]) * -1476140375; - value ^= -1044567439 ^ salt; - return value; - } - case 9: - { - // MultipleInstruction - value = (value - _secretKey[196] - salt) * 2125307395; - return value; - } - case 10: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 10; - uint part1 = (uint)value << (32 - 10); - value = (int)(value2 | part1); - value -= -1035239660 + _secretKey[199]; - value ^= -755609206 ^ salt; - return value; - } - case 11: - { - // AddInstruction - value = ((value - -1177184477) ^ salt) - _secretKey[89]; - return value; - } - case 12: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[23]); - uint part1 = value2 >> 29; - uint part2 = value2 << (32 - 29); - value = (int)(part1 | part2); - return value; - } - case 13: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 19; - uint part1 = (uint)value << (32 - 19); - value = (int)(value2 | part1); - value = (value - _secretKey[68]) * 1170138479; - value ^= -1510419150 ^ salt; - return value; - } - case 14: - { - // MultipleRotateXorInstruction - value ^= -1134639492 ^ salt; - uint value2 = (uint)value >> 6; - uint part1 = (uint)value << (32 - 6); - value = (int)(value2 | part1); - value = (value - _secretKey[156]) * 275824265; - return value; - } - case 15: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[95]); - uint part1 = value2 >> 7; - uint part2 = value2 << (32 - 7); - value = (int)(part1 | part2); - return value; - } - case 16: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 6; - uint part1 = (uint)value << (32 - 6); - value = (int)(value2 | part1); - value = (value - _secretKey[79]) * 1552472901; - value ^= -759315565 ^ salt; - return value; - } - case 17: - { - // MultipleRotateXorInstruction - value ^= -3885258 ^ salt; - uint value2 = (uint)value >> 2; - uint part1 = (uint)value << (32 - 2); - value = (int)(value2 | part1); - value = (value - _secretKey[75]) * -1943909725; - return value; - } - case 18: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 9; - uint part1 = (uint)value << (32 - 9); - value = (int)(value2 | part1); - value ^= 1207613963 ^ salt; - value = (value - _secretKey[153]) * 1985974175; - return value; - } - case 19: - { - // MultipleRotateXorInstruction - value ^= 792769043 ^ salt; - uint value2 = (uint)value >> 11; - uint part1 = (uint)value << (32 - 11); - value = (int)(value2 | part1); - value = (value - _secretKey[86]) * 1412922099; - return value; - } - case 20: - { - // AddInstruction - value = ((value - -512520382) ^ salt) - _secretKey[194]; - return value; - } - case 21: - { - // XorInstruction - value = ((value ^ -1864951858) - salt) ^ _secretKey[195]; - return value; - } - case 22: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[2]); - uint part1 = value2 >> 15; - uint part2 = value2 << (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 23: - { - // MultipleInstruction - value = (value - _secretKey[203] - salt) * 891162519; - return value; - } - case 24: - { - // AddInstruction - value = ((value - 2026667919) ^ salt) - _secretKey[110]; - return value; - } - case 25: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 15; - uint part2 = (uint)value << (32 - 15); - value = (int)(part1 | part2); - value ^= 392708821 ^ salt; - value -= 848657810 + _secretKey[133]; - return value; - } - case 26: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[93]); - uint part1 = value2 >> 5; - uint part2 = value2 << (32 - 5); - value = (int)(part1 | part2); - return value; - } - case 27: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 30; - uint part1 = (uint)value << (32 - 30); - value = (int)(value2 | part1); - value -= 1284012732 + _secretKey[58]; - value ^= 1294662302 ^ salt; - return value; - } - case 28: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 29; - uint part1 = (uint)value << (32 - 29); - value = (int)(value2 | part1); - value = (value - _secretKey[138]) * -708470805; - value ^= -1438081752 ^ salt; - return value; - } - case 29: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[240]); - uint part1 = value2 >> 6; - uint part2 = value2 << (32 - 6); - value = (int)(part1 | part2); - return value; - } - case 30: - { - // MultipleRotateXorInstruction - value ^= 1594594445 ^ salt; - uint value2 = (uint)value >> 24; - uint part1 = (uint)value << (32 - 24); - value = (int)(value2 | part1); - value = (value - _secretKey[215]) * 1857241631; - return value; - } - case 31: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[49]); - uint part1 = value2 >> 19; - uint part2 = value2 << (32 - 19); - value = (int)(part1 | part2); - return value; - } - case 32: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 17; - uint part1 = (uint)value << (32 - 17); - value = (int)(value2 | part1); - value -= -1038657413 + _secretKey[247]; - value ^= 226193183 ^ salt; - return value; - } - case 33: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 23; - uint part1 = (uint)value << (32 - 23); - value = (int)(value2 | part1); - value -= 459902223 + _secretKey[252]; - value ^= -484591087 ^ salt; - return value; - } - case 34: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value ^= 1186351980 ^ salt; - value = (value - _secretKey[211]) * 1159592341; - return value; - } - case 35: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 15; - uint part1 = (uint)value << (32 - 15); - value = (int)(value2 | part1); - value -= -283413931 + _secretKey[235]; - value ^= 1658142493 ^ salt; - return value; - } - case 36: - { - // XorInstruction - value = ((value ^ -1892941953) - salt) ^ _secretKey[90]; - return value; - } - case 37: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 31; - uint part1 = (uint)value << (32 - 31); - value = (int)(value2 | part1); - value = (value - _secretKey[111]) * -674216273; - value ^= -1297440001 ^ salt; - return value; - } - case 38: - { - // MultipleRotateXorInstruction - value ^= 1353158598 ^ salt; - uint value2 = (uint)value >> 31; - uint part1 = (uint)value << (32 - 31); - value = (int)(value2 | part1); - value = (value - _secretKey[213]) * 803536783; - return value; - } - case 39: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 20; - uint part1 = (uint)value << (32 - 20); - value = (int)(value2 | part1); - value -= 873171360 + _secretKey[72]; - value ^= -934836680 ^ salt; - return value; - } - case 40: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 18; - uint part1 = (uint)value << (32 - 18); - value = (int)(value2 | part1); - value ^= -28088263 ^ salt; - value = (value - _secretKey[140]) * 1881436791; - return value; - } - case 41: - { - // AddRotateXorInstruction - value ^= -312111197 ^ salt; - uint value2 = (uint)value >> 1; - uint part1 = (uint)value << (32 - 1); - value = (int)(value2 | part1); - value -= 969234286 + _secretKey[116]; - return value; - } - case 42: - { - // MultipleInstruction - value = (value - _secretKey[29] - salt) * 2102789665; - return value; - } - case 43: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[1]); - uint part1 = value2 >> 28; - uint part2 = value2 << (32 - 28); - value = (int)(part1 | part2); - return value; - } - case 44: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[184]); - uint part1 = value2 >> 4; - uint part2 = value2 << (32 - 4); - value = (int)(part1 | part2); - return value; - } - case 45: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 18; - uint part1 = (uint)value << (32 - 18); - value = (int)(value2 | part1); - value ^= 1068062556 ^ salt; - value = (value - _secretKey[199]) * 85627791; - return value; - } - case 46: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 1; - uint part1 = (uint)value << (32 - 1); - value = (int)(value2 | part1); - value = (value - _secretKey[200]) * 1138735395; - value ^= 196245895 ^ salt; - return value; - } - case 47: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 7; - uint part1 = (uint)value << (32 - 7); - value = (int)(value2 | part1); - value ^= -1964107221 ^ salt; - value = (value - _secretKey[10]) * -1413533649; - return value; - } - case 48: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 18; - uint part1 = (uint)value << (32 - 18); - value = (int)(value2 | part1); - value ^= -38668552 ^ salt; - value = (value - _secretKey[238]) * 665251331; - return value; - } - case 49: - { - // MultipleInstruction - value = (value - _secretKey[172] - salt) * -818173423; - return value; - } - case 50: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 11; - uint part2 = (uint)value << (32 - 11); - value = (int)(part1 | part2); - value ^= -2098495662 ^ salt; - value -= 1412414820 + _secretKey[219]; - return value; - } - case 51: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[97]); - uint part1 = value2 >> 10; - uint part2 = value2 << (32 - 10); - value = (int)(part1 | part2); - return value; - } - case 52: - { - // MultipleRotateXorInstruction - value ^= -21948406 ^ salt; - uint value2 = (uint)value >> 24; - uint part1 = (uint)value << (32 - 24); - value = (int)(value2 | part1); - value = (value - _secretKey[63]) * -99761833; - return value; - } - case 53: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[221]); - uint part1 = value2 >> 7; - uint part2 = value2 << (32 - 7); - value = (int)(part1 | part2); - return value; - } - case 54: - { - // MultipleInstruction - value = (value - _secretKey[96] - salt) * -2034360447; - return value; - } - case 55: - { - // MultipleRotateXorInstruction - value ^= -1022882984 ^ salt; - uint value2 = (uint)value >> 29; - uint part1 = (uint)value << (32 - 29); - value = (int)(value2 | part1); - value = (value - _secretKey[29]) * -899658607; - return value; - } - case 56: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 12; - uint part1 = (uint)value << (32 - 12); - value = (int)(value2 | part1); - value = (value - _secretKey[235]) * 340919493; - value ^= 2122077674 ^ salt; - return value; - } - case 57: - { - // AddRotateXorInstruction - value ^= -720824840 ^ salt; - uint value2 = (uint)value >> 21; - uint part1 = (uint)value << (32 - 21); - value = (int)(value2 | part1); - value -= -503448718 + _secretKey[175]; - return value; - } - case 58: - { - // MultipleInstruction - value = (value - _secretKey[231] - salt) * 913639057; - return value; - } - case 59: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[75]); - uint part1 = value2 >> 19; - uint part2 = value2 << (32 - 19); - value = (int)(part1 | part2); - return value; - } - case 60: - { - // MultipleRotateXorInstruction - value ^= 1420744071 ^ salt; - uint value2 = (uint)value >> 27; - uint part1 = (uint)value << (32 - 27); - value = (int)(value2 | part1); - value = (value - _secretKey[171]) * 238093953; - return value; - } - case 61: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 15; - uint part1 = (uint)value << (32 - 15); - value = (int)(value2 | part1); - value = (value - _secretKey[84]) * -2096065051; - value ^= 1366253139 ^ salt; - return value; - } - case 62: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 6; - uint part1 = (uint)value << (32 - 6); - value = (int)(value2 | part1); - value ^= -1974823163 ^ salt; - value = (value - _secretKey[132]) * 303900345; - return value; - } - case 63: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[119]); - uint part1 = value2 >> 22; - uint part2 = value2 << (32 - 22); - value = (int)(part1 | part2); - return value; - } - case 64: - { - // XorInstruction - value = ((value ^ 1262347216) - salt) ^ _secretKey[15]; - return value; - } - case 65: - { - // AddInstruction - value = ((value - 1780280992) ^ salt) - _secretKey[126]; - return value; - } - case 66: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 13; - uint part1 = (uint)value << (32 - 13); - value = (int)(value2 | part1); - value ^= -1198162446 ^ salt; - value = (value - _secretKey[85]) * 1314512283; - return value; - } - case 67: - { - // MultipleInstruction - value = (value - _secretKey[128] - salt) * 463417823; - return value; - } - case 68: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[178]); - uint part1 = value2 >> 24; - uint part2 = value2 << (32 - 24); - value = (int)(part1 | part2); - return value; - } - case 69: - { - // XorInstruction - value = ((value ^ 1649427052) - salt) ^ _secretKey[61]; - return value; - } - case 70: - { - // MultipleRotateXorInstruction - value ^= 849172121 ^ salt; - uint value2 = (uint)value >> 17; - uint part1 = (uint)value << (32 - 17); - value = (int)(value2 | part1); - value = (value - _secretKey[83]) * 368180765; - return value; - } - case 71: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[169]); - uint part1 = value2 >> 16; - uint part2 = value2 << (32 - 16); - value = (int)(part1 | part2); - return value; - } - case 72: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 20; - uint part1 = (uint)value << (32 - 20); - value = (int)(value2 | part1); - value -= -2092062916 + _secretKey[138]; - value ^= 1068287172 ^ salt; - return value; - } - case 73: - { - // MultipleInstruction - value = (value - _secretKey[34] - salt) * -495145181; - return value; - } - case 74: - { - // MultipleRotateXorInstruction - value ^= -145743337 ^ salt; - uint value2 = (uint)value >> 29; - uint part1 = (uint)value << (32 - 29); - value = (int)(value2 | part1); - value = (value - _secretKey[30]) * 1735064809; - return value; - } - case 75: - { - // MultipleRotateXorInstruction - value ^= 280941267 ^ salt; - uint value2 = (uint)value >> 4; - uint part1 = (uint)value << (32 - 4); - value = (int)(value2 | part1); - value = (value - _secretKey[142]) * 442035963; - return value; - } - case 76: - { - // MultipleInstruction - value = (value - _secretKey[156] - salt) * -971441783; - return value; - } - case 77: - { - // AddRotateXorInstruction - value ^= 827331935 ^ salt; - uint value2 = (uint)value >> 7; - uint part1 = (uint)value << (32 - 7); - value = (int)(value2 | part1); - value -= 314625916 + _secretKey[192]; - return value; - } - case 78: - { - // MultipleInstruction - value = (value - _secretKey[141] - salt) * -1649657957; - return value; - } - case 79: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 11; - uint part2 = (uint)value << (32 - 11); - value = (int)(part1 | part2); - value ^= -11549173 ^ salt; - value -= 1607953190 + _secretKey[133]; - return value; - } - case 80: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 25; - uint part1 = (uint)value << (32 - 25); - value = (int)(value2 | part1); - value -= 687186546 + _secretKey[95]; - value ^= -1454482890 ^ salt; - return value; - } - case 81: - { - // XorInstruction - value = ((value ^ 814860713) - salt) ^ _secretKey[195]; - return value; - } - case 82: - { - // AddRotateXorInstruction - value ^= 213310246 ^ salt; - uint value2 = (uint)value >> 19; - uint part1 = (uint)value << (32 - 19); - value = (int)(value2 | part1); - value -= 1998643542 + _secretKey[171]; - return value; - } - case 83: - { - // AddRotateXorInstruction - value ^= -696314173 ^ salt; - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value -= 542686146 + _secretKey[249]; - return value; - } - case 84: - { - // AddRotateXorInstruction - value ^= 118718247 ^ salt; - uint value2 = (uint)value >> 9; - uint part1 = (uint)value << (32 - 9); - value = (int)(value2 | part1); - value -= 1734820207 + _secretKey[2]; - return value; - } - case 85: - { - // XorInstruction - value = ((value ^ 1553710234) - salt) ^ _secretKey[143]; - return value; - } - case 86: - { - // AddRotateXorInstruction - value ^= -1402843691 ^ salt; - uint value2 = (uint)value >> 5; - uint part1 = (uint)value << (32 - 5); - value = (int)(value2 | part1); - value -= -217984331 + _secretKey[146]; - return value; - } - case 87: - { - // MultipleInstruction - value = (value - _secretKey[5] - salt) * -814971689; - return value; - } - case 88: - { - // MultipleRotateXorInstruction - value ^= -2044505542 ^ salt; - uint value2 = (uint)value >> 28; - uint part1 = (uint)value << (32 - 28); - value = (int)(value2 | part1); - value = (value - _secretKey[158]) * 681320217; - return value; - } - case 89: - { - // AddInstruction - value = ((value - -1213654475) ^ salt) - _secretKey[40]; - return value; - } - case 90: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 6; - uint part1 = (uint)value << (32 - 6); - value = (int)(value2 | part1); - value = (value - _secretKey[206]) * 583163349; - value ^= -1886972278 ^ salt; - return value; - } - case 91: - { - // AddRotateXorInstruction - value ^= -979249928 ^ salt; - uint value2 = (uint)value >> 23; - uint part1 = (uint)value << (32 - 23); - value = (int)(value2 | part1); - value -= -1724625239 + _secretKey[223]; - return value; - } - case 92: - { - // XorInstruction - value = ((value ^ -1104541704) - salt) ^ _secretKey[83]; - return value; - } - case 93: - { - // XorInstruction - value = ((value ^ 311150152) - salt) ^ _secretKey[31]; - return value; - } - case 94: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 17; - uint part1 = (uint)value << (32 - 17); - value = (int)(value2 | part1); - value = (value - _secretKey[176]) * 1535026385; - value ^= 116496631 ^ salt; - return value; - } - case 95: - { - // MultipleRotateXorInstruction - value ^= 2133438141 ^ salt; - uint value2 = (uint)value >> 2; - uint part1 = (uint)value << (32 - 2); - value = (int)(value2 | part1); - value = (value - _secretKey[87]) * 1779203413; - return value; - } - case 96: - { - // MultipleRotateXorInstruction - value ^= 225535005 ^ salt; - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value = (value - _secretKey[174]) * 521638757; - return value; - } - case 97: - { - // MultipleRotateXorInstruction - value ^= -1703839105 ^ salt; - uint value2 = (uint)value >> 1; - uint part1 = (uint)value << (32 - 1); - value = (int)(value2 | part1); - value = (value - _secretKey[175]) * -1131776573; - return value; - } - case 98: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 15; - uint part1 = (uint)value << (32 - 15); - value = (int)(value2 | part1); - value -= -1783079937 + _secretKey[78]; - value ^= -447564571 ^ salt; - return value; - } - case 99: - { - // XorInstruction - value = ((value ^ -316631669) - salt) ^ _secretKey[111]; - return value; - } - case 100: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 24; - uint part1 = (uint)value << (32 - 24); - value = (int)(value2 | part1); - value = (value - _secretKey[252]) * 898292471; - value ^= -405694625 ^ salt; - return value; - } - case 101: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 6; - uint part1 = (uint)value << (32 - 6); - value = (int)(value2 | part1); - value ^= -1551058348 ^ salt; - value = (value - _secretKey[212]) * -22167815; - return value; - } - case 102: - { - // AddInstruction - value = ((value - -853736135) ^ salt) - _secretKey[18]; - return value; - } - case 103: - { - // AddInstruction - value = ((value - 1321376878) ^ salt) - _secretKey[116]; - return value; - } - case 104: - { - // MultipleRotateXorInstruction - value ^= 541697309 ^ salt; - uint value2 = (uint)value >> 0; - uint part1 = (uint)value << (32 - 0); - value = (int)(value2 | part1); - value = (value - _secretKey[7]) * -1964889845; - return value; - } - case 105: - { - // AddRotateXorInstruction - value ^= 1176608900 ^ salt; - uint value2 = (uint)value >> 4; - uint part1 = (uint)value << (32 - 4); - value = (int)(value2 | part1); - value -= -822594180 + _secretKey[1]; - return value; - } - case 106: - { - // AddInstruction - value = ((value - -882893600) ^ salt) - _secretKey[110]; - return value; - } - case 107: - { - // MultipleRotateXorInstruction - value ^= -1566546809 ^ salt; - uint value2 = (uint)value >> 23; - uint part1 = (uint)value << (32 - 23); - value = (int)(value2 | part1); - value = (value - _secretKey[114]) * 406480373; - return value; - } - case 108: - { - // MultipleInstruction - value = (value - _secretKey[97] - salt) * 200608377; - return value; - } - case 109: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 7; - uint part1 = (uint)value << (32 - 7); - value = (int)(value2 | part1); - value -= 1161425930 + _secretKey[43]; - value ^= -72794161 ^ salt; - return value; - } - case 110: - { - // AddInstruction - value = ((value - -1619543125) ^ salt) - _secretKey[238]; - return value; - } - case 111: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 12; - uint part1 = (uint)value << (32 - 12); - value = (int)(value2 | part1); - value -= -1766468683 + _secretKey[241]; - value ^= 1170459122 ^ salt; - return value; - } - case 112: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 11; - uint part2 = (uint)value << (32 - 11); - value = (int)(part1 | part2); - value ^= 323019346 ^ salt; - value -= 251687012 + _secretKey[219]; - return value; - } - case 113: - { - // AddInstruction - value = ((value - -1049972438) ^ salt) - _secretKey[97]; - return value; - } - case 114: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 10; - uint part1 = (uint)value << (32 - 10); - value = (int)(value2 | part1); - value = (value - _secretKey[216]) * 594045631; - value ^= -492239002 ^ salt; - return value; - } - case 115: - { - // AddInstruction - value = ((value - -748126329) ^ salt) - _secretKey[221]; - return value; - } - case 116: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 17; - uint part2 = (uint)value << (32 - 17); - value = (int)(part1 | part2); - value ^= -5933889 ^ salt; - value -= -441051263 + _secretKey[96]; - return value; - } - case 117: - { - // MultipleRotateXorInstruction - value ^= 543895274 ^ salt; - uint value2 = (uint)value >> 11; - uint part1 = (uint)value << (32 - 11); - value = (int)(value2 | part1); - value = (value - _secretKey[88]) * 1253478165; - return value; - } - case 118: - { - // MultipleInstruction - value = (value - _secretKey[140] - salt) * 1897067971; - return value; - } - case 119: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[175]); - uint part1 = value2 >> 18; - uint part2 = value2 << (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 120: - { - // MultipleRotateXorInstruction - value ^= 1300544743 ^ salt; - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value = (value - _secretKey[57]) * -927555255; - return value; - } - case 121: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 1; - uint part1 = (uint)value << (32 - 1); - value = (int)(value2 | part1); - value -= 678597707 + _secretKey[119]; - value ^= -547380749 ^ salt; - return value; - } - case 122: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 19; - uint part1 = (uint)value << (32 - 19); - value = (int)(value2 | part1); - value = (value - _secretKey[191]) * -1394333385; - value ^= 683601851 ^ salt; - return value; - } - case 123: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[15]); - uint part1 = value2 >> 20; - uint part2 = value2 << (32 - 20); - value = (int)(part1 | part2); - return value; - } - case 124: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[132]); - uint part1 = value2 >> 8; - uint part2 = value2 << (32 - 8); - value = (int)(part1 | part2); - return value; - } - case 125: - { - // MultipleInstruction - value = (value - _secretKey[120] - salt) * 412809175; - return value; - } - case 126: - { - // AddInstruction - value = ((value - -1374139785) ^ salt) - _secretKey[197]; - return value; - } - case 127: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[26]); - uint part1 = value2 >> 15; - uint part2 = value2 << (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 128: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 21; - uint part1 = (uint)value << (32 - 21); - value = (int)(value2 | part1); - value -= 723646816 + _secretKey[146]; - value ^= 1415280510 ^ salt; - return value; - } - case 129: - { - // AddRotateXorInstruction - value ^= 2132310656 ^ salt; - uint value2 = (uint)value >> 30; - uint part1 = (uint)value << (32 - 30); - value = (int)(value2 | part1); - value -= 1410706317 + _secretKey[165]; - return value; - } - case 130: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 12; - uint part1 = (uint)value << (32 - 12); - value = (int)(value2 | part1); - value -= -483221582 + _secretKey[93]; - value ^= 1264971736 ^ salt; - return value; - } - case 131: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 17; - uint part2 = (uint)value << (32 - 17); - value = (int)(part1 | part2); - value ^= 1531807059 ^ salt; - value -= -1872731835 + _secretKey[53]; - return value; - } - case 132: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 10; - uint part2 = (uint)value << (32 - 10); - value = (int)(part1 | part2); - value ^= 306666665 ^ salt; - value -= 264114638 + _secretKey[240]; - return value; - } - case 133: - { - // AddRotateXorInstruction - value ^= -1266414649 ^ salt; - uint value2 = (uint)value >> 20; - uint part1 = (uint)value << (32 - 20); - value = (int)(value2 | part1); - value -= 824712252 + _secretKey[138]; - return value; - } - case 134: - { - // AddRotateXorInstruction - value ^= 2133737246 ^ salt; - uint value2 = (uint)value >> 25; - uint part1 = (uint)value << (32 - 25); - value = (int)(value2 | part1); - value -= -766337246 + _secretKey[35]; - return value; - } - case 135: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 14; - uint part2 = (uint)value << (32 - 14); - value = (int)(part1 | part2); - value ^= 1683555122 ^ salt; - value -= -1997614825 + _secretKey[165]; - return value; - } - case 136: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 28; - uint part1 = (uint)value << (32 - 28); - value = (int)(value2 | part1); - value ^= -1305042504 ^ salt; - value = (value - _secretKey[57]) * 949096539; - return value; - } - case 137: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[192]); - uint part1 = value2 >> 28; - uint part2 = value2 << (32 - 28); - value = (int)(part1 | part2); - return value; - } - case 138: - { - // XorInstruction - value = ((value ^ 1715223135) - salt) ^ _secretKey[135]; - return value; - } - case 139: - { - // MultipleInstruction - value = (value - _secretKey[79] - salt) * -307106491; - return value; - } - case 140: - { - // AddRotateXorInstruction - value ^= 806320034 ^ salt; - uint value2 = (uint)value >> 11; - uint part1 = (uint)value << (32 - 11); - value = (int)(value2 | part1); - value -= -408450171 + _secretKey[11]; - return value; - } - case 141: - { - // AddInstruction - value = ((value - -433941646) ^ salt) - _secretKey[95]; - return value; - } - case 142: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 26; - uint part2 = (uint)value << (32 - 26); - value = (int)(part1 | part2); - value ^= 2132471747 ^ salt; - value -= 1775820811 + _secretKey[169]; - return value; - } - case 143: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 2; - uint part1 = (uint)value << (32 - 2); - value = (int)(value2 | part1); - value ^= 114258470 ^ salt; - value = (value - _secretKey[19]) * 1566112771; - return value; - } - case 144: - { - // AddRotateXorInstruction - value ^= -1181275232 ^ salt; - uint value2 = (uint)value >> 3; - uint part1 = (uint)value << (32 - 3); - value = (int)(value2 | part1); - value -= -650723591 + _secretKey[206]; - return value; - } - case 145: - { - // MultipleInstruction - value = (value - _secretKey[169] - salt) * 39803307; - return value; - } - case 146: - { - // XorInstruction - value = ((value ^ -1297404981) - salt) ^ _secretKey[154]; - return value; - } - case 147: - { - // MultipleRotateXorInstruction - value ^= 801710213 ^ salt; - uint value2 = (uint)value >> 18; - uint part1 = (uint)value << (32 - 18); - value = (int)(value2 | part1); - value = (value - _secretKey[181]) * -1217833329; - return value; - } - case 148: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 29; - uint part2 = (uint)value << (32 - 29); - value = (int)(part1 | part2); - value ^= 1566976773 ^ salt; - value -= -1933121809 + _secretKey[230]; - return value; - } - case 149: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[188]); - uint part1 = value2 >> 30; - uint part2 = value2 << (32 - 30); - value = (int)(part1 | part2); - return value; - } - case 150: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[53]); - uint part1 = value2 >> 30; - uint part2 = value2 << (32 - 30); - value = (int)(part1 | part2); - return value; - } - case 151: - { - // AddInstruction - value = ((value - -2119615805) ^ salt) - _secretKey[138]; - return value; - } - case 152: - { - // MultipleRotateXorInstruction - value ^= 221292457 ^ salt; - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value = (value - _secretKey[102]) * -1630338257; - return value; - } - case 153: - { - // MultipleRotateXorInstruction - value ^= 1486712056 ^ salt; - uint value2 = (uint)value >> 13; - uint part1 = (uint)value << (32 - 13); - value = (int)(value2 | part1); - value = (value - _secretKey[248]) * -1360595481; - return value; - } - case 154: - { - // MultipleInstruction - value = (value - _secretKey[72] - salt) * 1812161233; - return value; - } - case 155: - { - // MultipleRotateXorInstruction - value ^= -81016400 ^ salt; - uint value2 = (uint)value >> 17; - uint part1 = (uint)value << (32 - 17); - value = (int)(value2 | part1); - value = (value - _secretKey[247]) * -47344461; - return value; - } - case 156: - { - // MultipleRotateXorInstruction - value ^= -1187848798 ^ salt; - uint value2 = (uint)value >> 23; - uint part1 = (uint)value << (32 - 23); - value = (int)(value2 | part1); - value = (value - _secretKey[252]) * -1858496529; - return value; - } - case 157: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 16; - uint part2 = (uint)value << (32 - 16); - value = (int)(part1 | part2); - value ^= 1185916334 ^ salt; - value -= 605454035 + _secretKey[108]; - return value; - } - case 158: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 1; - uint part2 = (uint)value << (32 - 1); - value = (int)(part1 | part2); - value ^= -451761745 ^ salt; - value -= 2112611413 + _secretKey[235]; - return value; - } - case 159: - { - // XorInstruction - value = ((value ^ 1660696922) - salt) ^ _secretKey[229]; - return value; - } - case 160: - { - // MultipleRotateXorInstruction - value ^= -431219573 ^ salt; - uint value2 = (uint)value >> 31; - uint part1 = (uint)value << (32 - 31); - value = (int)(value2 | part1); - value = (value - _secretKey[111]) * 1706905775; - return value; - } - case 161: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 28; - uint part1 = (uint)value << (32 - 28); - value = (int)(value2 | part1); - value = (value - _secretKey[198]) * -580820577; - value ^= 1658933717 ^ salt; - return value; - } - case 162: - { - // AddRotateXorInstruction - value ^= 609336148 ^ salt; - uint value2 = (uint)value >> 20; - uint part1 = (uint)value << (32 - 20); - value = (int)(value2 | part1); - value -= -1278798944 + _secretKey[72]; - return value; - } - case 163: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 26; - uint part1 = (uint)value << (32 - 26); - value = (int)(value2 | part1); - value ^= -1055021038 ^ salt; - value = (value - _secretKey[57]) * -620746171; - return value; - } - case 164: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 7; - uint part1 = (uint)value << (32 - 7); - value = (int)(value2 | part1); - value ^= 1389308323 ^ salt; - value = (value - _secretKey[225]) * 2035776477; - return value; - } - case 165: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 1; - uint part1 = (uint)value << (32 - 1); - value = (int)(value2 | part1); - value -= -1939584600 + _secretKey[124]; - value ^= 318043677 ^ salt; - return value; - } - case 166: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value ^= 2047590880 ^ salt; - value = (value - _secretKey[184]) * -748679859; - return value; - } - case 167: - { - // XorInstruction - value = ((value ^ -312123044) - salt) ^ _secretKey[114]; - return value; - } - case 168: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 1; - uint part2 = (uint)value << (32 - 1); - value = (int)(part1 | part2); - value ^= -1299860280 ^ salt; - value -= 1897551751 + _secretKey[139]; - return value; - } - case 169: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[10]); - uint part1 = value2 >> 15; - uint part2 = value2 << (32 - 15); - value = (int)(part1 | part2); - return value; - } - case 170: - { - // MultipleInstruction - value = (value - _secretKey[60] - salt) * 609589815; - return value; - } - case 171: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 21; - uint part1 = (uint)value << (32 - 21); - value = (int)(value2 | part1); - value = (value - _secretKey[242]) * 893240649; - value ^= 820953326 ^ salt; - return value; - } - case 172: - { - // XorInstruction - value = ((value ^ 921116076) - salt) ^ _secretKey[89]; - return value; - } - case 173: - { - // AddInstruction - value = ((value - -1261901861) ^ salt) - _secretKey[82]; - return value; - } - case 174: - { - // MultipleRotateXorInstruction - value ^= -1758870671 ^ salt; - uint value2 = (uint)value >> 1; - uint part1 = (uint)value << (32 - 1); - value = (int)(value2 | part1); - value = (value - _secretKey[42]) * -1163763527; - return value; - } - case 175: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value -= 1254595032 + _secretKey[10]; - value ^= -99371457 ^ salt; - return value; - } - case 176: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 0; - uint part2 = (uint)value << (32 - 0); - value = (int)(part1 | part2); - value ^= -2036462975 ^ salt; - value -= 1901168605 + _secretKey[131]; - return value; - } - case 177: - { - // MultipleRotateXorInstruction - value ^= -805817000 ^ salt; - uint value2 = (uint)value >> 29; - uint part1 = (uint)value << (32 - 29); - value = (int)(value2 | part1); - value = (value - _secretKey[29]) * -1809334639; - return value; - } - case 178: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 12; - uint part2 = (uint)value << (32 - 12); - value = (int)(part1 | part2); - value ^= 762578411 ^ salt; - value -= 28490730 + _secretKey[13]; - return value; - } - case 179: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 24; - uint part1 = (uint)value << (32 - 24); - value = (int)(value2 | part1); - value -= -41308497 + _secretKey[85]; - value ^= 1812019570 ^ salt; - return value; - } - case 180: - { - // XorInstruction - value = ((value ^ 1563652208) - salt) ^ _secretKey[231]; - return value; - } - case 181: - { - // AddRotateXorInstruction - value ^= -1148350591 ^ salt; - uint value2 = (uint)value >> 23; - uint part1 = (uint)value << (32 - 23); - value = (int)(value2 | part1); - value -= -542613261 + _secretKey[75]; - return value; - } - case 182: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 19; - uint part2 = (uint)value << (32 - 19); - value = (int)(part1 | part2); - value ^= 1842755263 ^ salt; - value -= 1462569147 + _secretKey[135]; - return value; - } - case 183: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 8; - uint part1 = (uint)value << (32 - 8); - value = (int)(value2 | part1); - value ^= -159244912 ^ salt; - value = (value - _secretKey[15]) * -663204867; - return value; - } - case 184: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[230]); - uint part1 = value2 >> 5; - uint part2 = value2 << (32 - 5); - value = (int)(part1 | part2); - return value; - } - case 185: - { - // AddRotateXorInstruction - value ^= 1218428368 ^ salt; - uint value2 = (uint)value >> 5; - uint part1 = (uint)value << (32 - 5); - value = (int)(value2 | part1); - value -= 45305078 + _secretKey[119]; - return value; - } - case 186: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 0; - uint part2 = (uint)value << (32 - 0); - value = (int)(part1 | part2); - value ^= 567100030 ^ salt; - value -= 148564506 + _secretKey[160]; - return value; - } - case 187: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[242]); - uint part1 = value2 >> 21; - uint part2 = value2 << (32 - 21); - value = (int)(part1 | part2); - return value; - } - case 188: - { - // MultipleRotateXorInstruction - value ^= 730302816 ^ salt; - uint value2 = (uint)value >> 0; - uint part1 = (uint)value << (32 - 0); - value = (int)(value2 | part1); - value = (value - _secretKey[30]) * -1488719571; - return value; - } - case 189: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[93]); - uint part1 = value2 >> 18; - uint part2 = value2 << (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 190: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[69]); - uint part1 = value2 >> 29; - uint part2 = value2 << (32 - 29); - value = (int)(part1 | part2); - return value; - } - case 191: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value = (value - _secretKey[153]) * 1590990225; - value ^= 1474104403 ^ salt; - return value; - } - case 192: - { - // AddInstruction - value = ((value - 1345231273) ^ salt) - _secretKey[170]; - return value; - } - case 193: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[138]); - uint part1 = value2 >> 28; - uint part2 = value2 << (32 - 28); - value = (int)(part1 | part2); - return value; - } - case 194: - { - // AddRotateXorInstruction - value ^= -1086752221 ^ salt; - uint value2 = (uint)value >> 2; - uint part1 = (uint)value << (32 - 2); - value = (int)(value2 | part1); - value -= -1649692985 + _secretKey[138]; - return value; - } - case 195: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 5; - uint part1 = (uint)value << (32 - 5); - value = (int)(value2 | part1); - value = (value - _secretKey[23]) * -718602987; - value ^= 216360478 ^ salt; - return value; - } - case 196: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 25; - uint part1 = (uint)value << (32 - 25); - value = (int)(value2 | part1); - value -= -922639548 + _secretKey[211]; - value ^= 1736125070 ^ salt; - return value; - } - case 197: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 0; - uint part1 = (uint)value << (32 - 0); - value = (int)(value2 | part1); - value -= -1729078426 + _secretKey[124]; - value ^= -1590872932 ^ salt; - return value; - } - case 198: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 13; - uint part2 = (uint)value << (32 - 13); - value = (int)(part1 | part2); - value ^= 2101329043 ^ salt; - value -= -2086916257 + _secretKey[135]; - return value; - } - case 199: - { - // XorInstruction - value = ((value ^ -1188487898) - salt) ^ _secretKey[133]; - return value; - } - case 200: - { - // MultipleInstruction - value = (value - _secretKey[162] - salt) * -1592735389; - return value; - } - case 201: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 11; - uint part1 = (uint)value << (32 - 11); - value = (int)(value2 | part1); - value -= -1882888353 + _secretKey[153]; - value ^= 2087683186 ^ salt; - return value; - } - case 202: - { - // MultipleRotateXorInstruction - value ^= -1855365205 ^ salt; - uint value2 = (uint)value >> 22; - uint part1 = (uint)value << (32 - 22); - value = (int)(value2 | part1); - value = (value - _secretKey[58]) * -1429384213; - return value; - } - case 203: - { - // MultipleInstruction - value = (value - _secretKey[66] - salt) * 180652695; - return value; - } - case 204: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 0; - uint part1 = (uint)value << (32 - 0); - value = (int)(value2 | part1); - value ^= 1668989123 ^ salt; - value = (value - _secretKey[206]) * 715760713; - return value; - } - case 205: - { - // MultipleInstruction - value = (value - _secretKey[169] - salt) * -19415893; - return value; - } - case 206: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value = (value - _secretKey[143]) * 408562579; - value ^= -387621173 ^ salt; - return value; - } - case 207: - { - // XorInstruction - value = ((value ^ -1302837102) - salt) ^ _secretKey[133]; - return value; - } - case 208: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 29; - uint part1 = (uint)value << (32 - 29); - value = (int)(value2 | part1); - value = (value - _secretKey[5]) * 199587543; - value ^= 1201861103 ^ salt; - return value; - } - case 209: - { - // AddInstruction - value = ((value - -1698116194) ^ salt) - _secretKey[188]; - return value; - } - case 210: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 3; - uint part1 = (uint)value << (32 - 3); - value = (int)(value2 | part1); - value -= -5412811 + _secretKey[40]; - value ^= 955827838 ^ salt; - return value; - } - case 211: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value ^= -261186202 ^ salt; - value = (value - _secretKey[206]) * 250403797; - return value; - } - case 212: - { - // XorInstruction - value = ((value ^ 1451245279) - salt) ^ _secretKey[215]; - return value; - } - case 213: - { - // AddInstruction - value = ((value - -48271475) ^ salt) - _secretKey[248]; - return value; - } - case 214: - { - // MultipleRotateXorInstruction - value ^= 280704379 ^ salt; - uint value2 = (uint)value >> 31; - uint part1 = (uint)value << (32 - 31); - value = (int)(value2 | part1); - value = (value - _secretKey[72]) * -1743417391; - return value; - } - case 215: - { - // MultipleRotateXorInstruction - value ^= -1507466225 ^ salt; - uint value2 = (uint)value >> 17; - uint part1 = (uint)value << (32 - 17); - value = (int)(value2 | part1); - value = (value - _secretKey[176]) * -795921711; - return value; - } - case 216: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[162]); - uint part1 = value2 >> 23; - uint part2 = value2 << (32 - 23); - value = (int)(part1 | part2); - return value; - } - case 217: - { - // XorInstruction - value = ((value ^ -1329546797) - salt) ^ _secretKey[108]; - return value; - } - case 218: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 11; - uint part1 = (uint)value << (32 - 11); - value = (int)(value2 | part1); - value -= 1710889501 + _secretKey[85]; - value ^= 846489904 ^ salt; - return value; - } - case 219: - { - // XorInstruction - value = ((value ^ -339712479) - salt) ^ _secretKey[127]; - return value; - } - case 220: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 15; - uint part1 = (uint)value << (32 - 15); - value = (int)(value2 | part1); - value -= -308188673 + _secretKey[78]; - value ^= -1008587035 ^ salt; - return value; - } - case 221: - { - // MultipleInstruction - value = (value - _secretKey[111] - salt) * 773277731; - return value; - } - case 222: - { - // MultipleInstruction - value = (value - _secretKey[198] - salt) * 1149219487; - return value; - } - case 223: - { - // AddInstruction - value = ((value - -449129672) ^ salt) - _secretKey[160]; - return value; - } - case 224: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 12; - uint part1 = (uint)value << (32 - 12); - value = (int)(value2 | part1); - value ^= -180027834 ^ salt; - value = (value - _secretKey[84]) * 102372989; - return value; - } - case 225: - { - // XorInstruction - value = ((value ^ 946019090) - salt) ^ _secretKey[58]; - return value; - } - case 226: - { - // AddRotateXorInstruction - value ^= 1350981383 ^ salt; - uint value2 = (uint)value >> 3; - uint part1 = (uint)value << (32 - 3); - value = (int)(value2 | part1); - value -= 694016884 + _secretKey[225]; - return value; - } - case 227: - { - // AddRotateXorInstruction - value ^= 1680252929 ^ salt; - uint value2 = (uint)value >> 28; - uint part1 = (uint)value << (32 - 28); - value = (int)(value2 | part1); - value -= -870643939 + _secretKey[168]; - return value; - } - case 228: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[184]); - uint part1 = value2 >> 4; - uint part2 = value2 << (32 - 4); - value = (int)(part1 | part2); - return value; - } - case 229: - { - // AddRotateXorInstruction - value ^= -1727043214 ^ salt; - uint value2 = (uint)value >> 28; - uint part1 = (uint)value << (32 - 28); - value = (int)(value2 | part1); - value -= 1785715822 + _secretKey[199]; - return value; - } - case 230: - { - // XorInstruction - value = ((value ^ -1277148537) - salt) ^ _secretKey[139]; - return value; - } - case 231: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 10; - uint part1 = (uint)value << (32 - 10); - value = (int)(value2 | part1); - value ^= 1940873679 ^ salt; - value = (value - _secretKey[226]) * -528829791; - return value; - } - case 232: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 14; - uint part1 = (uint)value << (32 - 14); - value = (int)(value2 | part1); - value = (value - _secretKey[171]) * 1486956053; - value ^= -879839609 ^ salt; - return value; - } - case 233: - { - // AddInstruction - value = ((value - 328489970) ^ salt) - _secretKey[181]; - return value; - } - case 234: - { - // MultipleInstruction - value = (value - _secretKey[89] - salt) * -1387476699; - return value; - } - case 235: - { - // XorAddRotateInstruction - uint value2 = (uint)value >> 8; - uint part1 = (uint)value << (32 - 8); - value = (int)(value2 | part1); - value -= -1977097134 + _secretKey[203]; - value ^= 1290000091 ^ salt; - return value; - } - case 236: - { - // AddInstruction - value = ((value - 1890859361) ^ salt) - _secretKey[113]; - return value; - } - case 237: - { - // AddRotateXorInstruction - value ^= 1434413518 ^ salt; - uint value2 = (uint)value >> 10; - uint part1 = (uint)value << (32 - 10); - value = (int)(value2 | part1); - value -= 1045620543 + _secretKey[216]; - return value; - } - case 238: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 0; - uint part2 = (uint)value << (32 - 0); - value = (int)(part1 | part2); - value ^= 1591345537 ^ salt; - value -= -1706485027 + _secretKey[131]; - return value; - } - case 239: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 24; - uint part2 = (uint)value << (32 - 24); - value = (int)(part1 | part2); - value ^= 1117669949 ^ salt; - value -= 1271081841 + _secretKey[29]; - return value; - } - case 240: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 12; - uint part1 = (uint)value << (32 - 12); - value = (int)(value2 | part1); - value = (value - _secretKey[235]) * 1588287429; - value ^= -842525462 ^ salt; - return value; - } - case 241: - { - // AddInstruction - value = ((value - 1030822002) ^ salt) - _secretKey[175]; - return value; - } - case 242: - { - // MultipleRotateXorInstruction - value ^= 811922151 ^ salt; - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value = (value - _secretKey[57]) * 769862473; - return value; - } - case 243: - { - // AddRotateXorInstruction - value ^= -1258702719 ^ salt; - uint value2 = (uint)value >> 23; - uint part1 = (uint)value << (32 - 23); - value = (int)(value2 | part1); - value -= 656680947 + _secretKey[75]; - return value; - } - case 244: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 19; - uint part1 = (uint)value << (32 - 19); - value = (int)(value2 | part1); - value = (value - _secretKey[191]) * -883345609; - value ^= 90809787 ^ salt; - return value; - } - case 245: - { - // AddRotateXorInstruction - value ^= 99436168 ^ salt; - uint value2 = (uint)value >> 16; - uint part1 = (uint)value << (32 - 16); - value = (int)(value2 | part1); - value -= -532913580 + _secretKey[15]; - return value; - } - case 246: - { - // MultipleXorRotateInstruction - uint value2 = (uint)value >> 22; - uint part1 = (uint)value << (32 - 22); - value = (int)(value2 | part1); - value ^= 1471598712 ^ salt; - value = (value - _secretKey[230]) * -599880499; - return value; - } - case 247: - { - // XorMultipleRotateInstruction - uint value2 = (uint)value >> 26; - uint part1 = (uint)value << (32 - 26); - value = (int)(value2 | part1); - value = (value - _secretKey[15]) * -1447936463; - value ^= 1941306053 ^ salt; - return value; - } - case 248: - { - // AddRotateXorInstruction - value ^= 2045091157 ^ salt; - uint value2 = (uint)value >> 18; - uint part1 = (uint)value << (32 - 18); - value = (int)(value2 | part1); - value -= 883137918 + _secretKey[96]; - return value; - } - case 249: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[165]); - uint part1 = value2 >> 13; - uint part2 = value2 << (32 - 13); - value = (int)(part1 | part2); - return value; - } - case 250: - { - // AddInstruction - value = ((value - -394947456) ^ salt) - _secretKey[96]; - return value; - } - case 251: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[93]); - uint part1 = value2 >> 18; - uint part2 = value2 << (32 - 18); - value = (int)(part1 | part2); - return value; - } - case 252: - { - // AddInstruction - value = ((value - 1917332797) ^ salt) - _secretKey[69]; - return value; - } - case 253: - { - // AddXorRotateInstruction - uint part1 = (uint)value >> 14; - uint part2 = (uint)value << (32 - 14); - value = (int)(part1 | part2); - value ^= -1509317223 ^ salt; - value -= 1006809939 + _secretKey[113]; - return value; - } - case 254: - { - // BitRotateInstruction - uint value2 = (uint)((value - salt) ^ _secretKey[170]); - uint part1 = value2 >> 9; - uint part2 = value2 << (32 - 9); - value = (int)(part1 | part2); - return value; - } - case 255: - { - // AddInstruction - value = ((value - 683715132) ^ salt) - _secretKey[138]; - return value; - } - - default: - throw new System.Exception($"Invalid opCode:{opCode}"); - } - } - - } -} - diff --git a/Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs.meta b/Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs.meta deleted file mode 100644 index 8752a2b..0000000 --- a/Obfuz/Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 406c63e9d464ca544ac337bc8fcce30e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Obfuz/SymbolObfus.meta b/Obfuz/Assets/Obfuz/SymbolObfus.meta deleted file mode 100644 index c4c116b..0000000 --- a/Obfuz/Assets/Obfuz/SymbolObfus.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 75e20a8abe7b86247837ffce1117762a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml b/Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml deleted file mode 100644 index 32d891a..0000000 --- a/Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml +++ /dev/null @@ -1,482 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml.meta b/Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml.meta deleted file mode 100644 index cdb1441..0000000 --- a/Obfuz/Assets/Obfuz/SymbolObfus/symbol-mapping.xml.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: b8e3f4340cc69fa4889a61a211cf24c5 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Resources.meta b/Obfuz/Assets/Resources.meta deleted file mode 100644 index 56aa397..0000000 --- a/Obfuz/Assets/Resources.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4d42a5aa28dcabc428e7a06b13421410 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Resources/Obfuz.meta b/Obfuz/Assets/Resources/Obfuz.meta deleted file mode 100644 index 3a82b4c..0000000 --- a/Obfuz/Assets/Resources/Obfuz.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 5be12685e3d38a24ab47ccfde4f424a1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes b/Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes deleted file mode 100644 index 666203486e21874a44414fa9318f227e3e0ed94e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmV+b1poWg+~lD27bqc4$KVEi4UVl-IV#nod0ZH**l1jmp_mkF|B#~9*7#TsUhK+k z71&|ydybMXNJJIyaAVin@QkY092#ip$W|ZeD|32vQ?@%83;{RAv8=W^?9+qVjx+7D z@gF(q%Um*%3T#%O)-JQ)>9g3K^LlgP<)$ZWUT(5Dtsw$TuM(a^xyBfy&5DnXtJ8SPWXW`>b+x54(~# z)N?QWsn>Tg(BRzL;4DVvn}@-_U(0?OM;XMuC1^J zaB597P88Iu*wRT3^L%yL1yfoo?^eINa#BV_laBBl4(8HQ661INoxXt*^NW#ZwXmh! z<5k4Ep8V2FtrQQTIC&VOH~Hd_XXa_YmRMFb8iw-N1Ez${2x~a zDI5=F0_gsmj<0$OX$p4pyba6EyRo>+yGN_&dIc_J&b!KARJ%j#f=R^2QyIvvRb!mY zDJI$zNYH`wXCbd#I$)y$$TL2Ulm!sMj+K)rGEztZWI8l(Dl50aaCtzu(w6@?Rfzy+ zf_AzVgk2$YS=vutD?4jbrX!(q772{hpteh{)8F>sM9L{+{ws(#r@xF$bd&#G3WdsB zo&fTuRXT@*_%uCjyYORv6QZC@Ji@&9cnzURzd2M5vm`M*51&av+{UdiJoepZGM`6L zb3rHn;6GVwMS=qqV;IeX!ZskC$j1hp;WzLPL;72?wOnJF7TeNxS=q~ zFf~ACZr3T*O6fL%xxF-%#J9gL!!G9TO$Qjh=A1GoSy6m##K;SjsPeslp}*J9(kQA{ zb^gIsnRqE3k4DVG`xiTJh3xE!uJw2r6P#?72~yUv+QS~^9s#TQr43E06)X(D{{b=} zO`%M>C}Ij2<)qVb1a@=~EQnOb?#MoKx@b=U=(X7u#89vfDpgHga?m-gLFi5RNY5oG zyqt*FQgRu(MrkdvrZTH#kyy_0Atu|D7Z+$16FR7`*nYX}M{ly-Xt@wO0nIO&ga?iw ujO^{`zvJR~ZG{!VZ33ZtQY20PjZ)Ic$;ewkQYr`Yq*rfuc4{rsVd#X_rTQBH diff --git a/Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes.meta b/Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes.meta deleted file mode 100644 index cfaf37d..0000000 --- a/Obfuz/Assets/Resources/Obfuz/defaultDynamicSecretKey.bytes.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: c05b06a0efaf2b1449760b6e43a887d3 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Assets/Resources/Obfuz/defaultStaticSecretKey.bytes b/Obfuz/Assets/Resources/Obfuz/defaultStaticSecretKey.bytes deleted file mode 100644 index d91a82dafebb3f968af0759569b8a7b8b162caa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmV+b1poWuad=sgU47iFfE^dzNj-D}T&^6H@!3j69H%>yX!OuzZE>_-*Vn^UeVP~V znCw*zBLM6c-rl0iwZK-SOug5kv6fMroS^SoI3`j|5 z!SuGkggBksOZddck3SQXzp(i=D4!I#7r!RZ!+th_7!Txw;uE@H<=}jFB5XhJR5Z2m zz%x4np0VZ=SM~eT{6G9tV!zy)Iv0muv+vygbvI^QPf>8JdZT9imNrBK`}m_)JS$ej zmRD6KT~WC)bhJyO?@p#>D6ctTtp>f%5hx!9FGwGBr|M2qA#Uh8IRR3|Z!x>)abprW z9YHcNjICn{6mm(0dl}QQxmi?I2Zv%duwY*GkXTCzFQp@^H?`xe1c3!@?7BiY<-)RH z&Em2Gam4#bq=AC+L4zC*RzKUOG?HSS30m$cWAy6@OjbMQw(kDuC6^TTm|Bw znvkQl^CP4dw{iE>Tz@Q7N}rUJl?c@8X*H*idqHxBn{w5E#TB>CQF^fWyC)bA{!c+L z=K?neYbQzVb|t+%!S7yJD&=XysmLU;R~Xk)pGrs`rpsm~d*i9eL& zQD%&XlNpG|i7NxS`TV_r{^8K7x4?otR00pii2!Vde1(bi*{p4RoIEQRw-f+X3P_#( zrp!WG7ZBu9c!m1{XqO&+FP+7Y%8MYCC#IxsOs=$CusY55M;!>J$IJ&6KJp0Wv>8CM z>Zmav;(f&5xU(s8^&vz?i55tIo_#P;2;7SKze@gZ+6lpzHrihG6sD?()5Hrx?&inf zHot&$`tby?&W5Gz7*(g=z~%UF5_8DG8b+=V^~|&PC|8={-o7g&VTVDCVf|!2%IJRl zvQxF}W3D$G2C?hHlk!yzz;%&z+os2@p$kF?ki6cAcVW3UIcecP%fVzYAm*O*r-hQY~9md%2 zN*Yc~i;-p*j?JOV63t>ALm?;{$q=8!)NxKCXKy{7{+X4jc_j4(i!k^8y=>V7YaG(C z(N_x|t~iZLl3ctS06b`NK5tz!MQ~3Bgqeu$v?dx*9a<(t4iqxq98aKtP4<|tFT@4^ - { - void InheritParent(T parentRule); - } - - - public interface IMethodRule where R: IRule - { - string Name { get; set; } - NameMatcher NameMatcher { get; set; } - - R Rule { get; set; } - } - - public abstract class MethodRuleBase : IMethodRule where R : IRule - { - public string Name { get; set; } - public NameMatcher NameMatcher { get; set; } - - public R Rule { get; set; } - } - - public interface ITypeRule where T: IMethodRule where R : IRule - { - string Name { get; set; } - - NameMatcher NameMatcher { get; set; } - - R Rule { get; set; } - - List Methods { get; set; } - } - - public abstract class TypeRuleBase : ITypeRule where T : IMethodRule where R : IRule - { - public string Name { get; set; } - - public NameMatcher NameMatcher { get; set; } - - public R Rule { get; set; } - - public List Methods { get; set; } - } - - public interface IAssemblyRule where TType : ITypeRule where TMethod : IMethodRule where TRule : IRule - { - string Name { get; set; } - - TRule Rule { get; set; } - - List Types { get; set; } - } - public abstract class AssemblyRuleBase : IAssemblyRule where TType : ITypeRule where TMethod : IMethodRule where TRule : IRule - { - public string Name { get; set; } - - public TRule Rule { get; set; } - - public List Types { get; set; } - } - - public class XmlAssemblyTypeMethodRuleParser - where TMethod : IMethodRule, new() - where TType : ITypeRule, new() - where TAssembly : IAssemblyRule, new() - where TRule : IRule, new() - { - private readonly HashSet _toObfuscatedAssemblyNames; - private readonly Func _ruleParser; - private readonly Action _unknownNodeTypeHandler; - private readonly Dictionary _assemblySpecs = new Dictionary(); - - public XmlAssemblyTypeMethodRuleParser(IEnumerable toObfuscatedAssemblyNames, Func ruleParser, Action unknownNodeTypeHandler) - { - _toObfuscatedAssemblyNames = new HashSet(toObfuscatedAssemblyNames); - _ruleParser = ruleParser; - _unknownNodeTypeHandler = unknownNodeTypeHandler; - } - - public Dictionary AssemblySpecs => _assemblySpecs; - - public void LoadConfigs(IEnumerable configFiles) - { - foreach (var configFile in configFiles) - { - LoadConfig(configFile); - } - } - - public void LoadConfig(string configFile) - { - if (string.IsNullOrEmpty(configFile)) - { - throw new Exception($"Invalid xml file {configFile}, file name is empty"); - } - Debug.Log($"ConfigurableObfuscationPolicy::LoadConfig {configFile}"); - var doc = new XmlDocument(); - doc.Load(configFile); - var root = doc.DocumentElement; - if (root.Name != "obfuz") - { - throw new Exception($"Invalid xml file {configFile}, root name should be 'obfuz'"); - } - foreach (XmlNode node in root.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "assembly": - { - TAssembly assSpec = ParseAssembly(configFile, ele); - _assemblySpecs.Add(assSpec.Name, assSpec); - break; - } - default: - { - if (_unknownNodeTypeHandler == null) - { - throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); - } - _unknownNodeTypeHandler(configFile, ele); - break; - } - } - } - } - - private TAssembly ParseAssembly(string configFile, XmlElement ele) - { - var assemblySpec = new TAssembly(); - string name = ele.GetAttribute("name"); - if (!_toObfuscatedAssemblyNames.Contains(name)) - { - throw new Exception($"Invalid xml file {configFile}, assembly name {name} isn't in toObfuscatedAssemblyNames"); - } - if (_assemblySpecs.ContainsKey(name)) - { - throw new Exception($"Invalid xml file {configFile}, assembly name {name} is duplicated"); - } - assemblySpec.Name = name; - assemblySpec.Rule = _ruleParser(configFile, ele); - - var types = new List(); - assemblySpec.Types = types; - foreach (XmlNode node in ele.ChildNodes) - { - if (!(node is XmlElement childEle)) - { - continue; - } - switch (childEle.Name) - { - case "type": - { - types.Add(ParseType(configFile, childEle)); - break; - } - default: - { - throw new Exception($"Invalid xml file, unknown node {childEle.Name}"); - } - } - } - return assemblySpec; - } - - private TType ParseType(string configFile, XmlElement element) - { - var typeSpec = new TType(); - - string name = element.GetAttribute("name"); - typeSpec.Name = name; - typeSpec.NameMatcher = new NameMatcher(name); - typeSpec.Rule = _ruleParser(configFile, element); - - var methods = new List(); - typeSpec.Methods = methods; - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "method": - { - methods.Add(ParseMethod(configFile, ele)); - break; - } - default: - { - throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - } - return typeSpec; - } - - private TMethod ParseMethod(string configFile, XmlElement element) - { - var methodSpec = new TMethod(); - string name = element.GetAttribute("name"); - methodSpec.Name = name; - methodSpec.NameMatcher = new NameMatcher(name); - methodSpec.Rule = _ruleParser(configFile, element); - return methodSpec; - } - - public TRule GetMethodRule(MethodDef method, TRule defaultRule) - { - var assemblyName = method.DeclaringType.Module.Assembly.Name; - if (!_assemblySpecs.TryGetValue(assemblyName, out var assSpec)) - { - return defaultRule; - } - string declaringTypeName = method.DeclaringType.FullName; - foreach (var typeSpec in assSpec.Types) - { - if (typeSpec.NameMatcher.IsMatch(declaringTypeName)) - { - foreach (var methodSpec in typeSpec.Methods) - { - if (methodSpec.NameMatcher.IsMatch(method.Name)) - { - return methodSpec.Rule; - } - } - return typeSpec.Rule; - } - } - return assSpec.Rule; - } - - public void InheritParentRules(TRule defaultRule) - { - foreach (TAssembly assSpec in _assemblySpecs.Values) - { - assSpec.Rule.InheritParent(defaultRule); - foreach (TType typeSpec in assSpec.Types) - { - typeSpec.Rule.InheritParent(assSpec.Rule); - foreach (TMethod methodSpec in typeSpec.Methods) - { - methodSpec.Rule.InheritParent(typeSpec.Rule); - } - } - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs.meta deleted file mode 100644 index 84f5aa9..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 36a3e142db81f6d4bb54938525e31973 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs deleted file mode 100644 index 591271e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs +++ /dev/null @@ -1,208 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using UnityEditor.VersionControl; -using UnityEngine; - -namespace Obfuz.Conf -{ - - - - public class XmlFieldRuleParser where R : class, new() - { - private readonly HashSet _toObfuscatedAssemblyNames; - private readonly Func _ruleParser; - private readonly Action _unknownNodeTypeHandler; - private readonly Dictionary _assemblySpecs = new Dictionary(); - - - private class FieldSpec - { - public string Name { get; set; } - public NameMatcher NameMatcher { get; set; } - - public R Rule { get; set; } - } - - private class TypeSpec - { - public string Name { get; set; } - - public NameMatcher NameMatcher { get; set; } - - public List Fields { get; set; } - } - - private class AssemblySpec - { - public string Name { get; set; } - - public List Types { get; set; } - } - - public XmlFieldRuleParser(IEnumerable toObfuscatedAssemblyNames, Func ruleParser, Action unknownNodeTypeHandler) - { - _toObfuscatedAssemblyNames = new HashSet(toObfuscatedAssemblyNames); - _ruleParser = ruleParser; - _unknownNodeTypeHandler = unknownNodeTypeHandler; - } - - public void LoadConfigs(IEnumerable configFiles) - { - foreach (var configFile in configFiles) - { - LoadConfig(configFile); - } - } - - public void LoadConfig(string configFile) - { - if (string.IsNullOrEmpty(configFile)) - { - throw new Exception($"Invalid xml file {configFile}, file name is empty"); - } - var doc = new XmlDocument(); - doc.Load(configFile); - var root = doc.DocumentElement; - if (root.Name != "obfuz") - { - throw new Exception($"Invalid xml file {configFile}, root name should be 'obfuz'"); - } - foreach (XmlNode node in root.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "assembly": - { - AssemblySpec assSpec = ParseAssembly(configFile, ele); - _assemblySpecs.Add(assSpec.Name, assSpec); - break; - } - default: - { - if (_unknownNodeTypeHandler == null) - { - throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); - } - _unknownNodeTypeHandler(configFile, ele); - break; - } - } - } - } - - private AssemblySpec ParseAssembly(string configFile, XmlElement ele) - { - var assemblySpec = new AssemblySpec(); - string name = ele.GetAttribute("name"); - if (!_toObfuscatedAssemblyNames.Contains(name)) - { - throw new Exception($"Invalid xml file {configFile}, assembly name {name} isn't in toObfuscatedAssemblyNames"); - } - if (_assemblySpecs.ContainsKey(name)) - { - throw new Exception($"Invalid xml file {configFile}, assembly name {name} is duplicated"); - } - assemblySpec.Name = name; - - var types = new List(); - assemblySpec.Types = types; - foreach (XmlNode node in ele.ChildNodes) - { - if (!(node is XmlElement childEle)) - { - continue; - } - switch (childEle.Name) - { - case "type": - { - types.Add(ParseType(configFile, childEle)); - break; - } - default: - { - throw new Exception($"Invalid xml file, unknown node {childEle.Name}"); - } - } - } - return assemblySpec; - } - - private TypeSpec ParseType(string configFile, XmlElement element) - { - var typeSpec = new TypeSpec(); - - string name = element.GetAttribute("name"); - typeSpec.Name = name; - typeSpec.NameMatcher = new NameMatcher(name); - - var fields = new List(); - typeSpec.Fields = fields; - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "field": - { - fields.Add(ParseField(configFile, ele)); - break; - } - default: - { - throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - } - return typeSpec; - } - - private FieldSpec ParseField(string configFile, XmlElement element) - { - var fieldSpec = new FieldSpec(); - string name = element.GetAttribute("name"); - fieldSpec.Name = name; - fieldSpec.NameMatcher = new NameMatcher(name); - fieldSpec.Rule = _ruleParser(configFile, element); - return fieldSpec; - } - - public R GetFieldRule(FieldDef field) - { - var assemblyName = field.DeclaringType.Module.Assembly.Name; - if (!_assemblySpecs.TryGetValue(assemblyName, out var assSpec)) - { - return null; - } - string declaringTypeName = field.DeclaringType.FullName; - foreach (var typeSpec in assSpec.Types) - { - if (typeSpec.NameMatcher.IsMatch(declaringTypeName)) - { - foreach (var fieldSpec in typeSpec.Fields) - { - if (fieldSpec.NameMatcher.IsMatch(field.Name)) - { - return fieldSpec.Rule; - } - } - } - } - return null; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs.meta deleted file mode 100644 index d8995b9..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1578270b9b81e1e4dba84d562c91090f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs deleted file mode 100644 index 6d0fc7e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs +++ /dev/null @@ -1,547 +0,0 @@ -using dnlib.DotNet; -using Obfuz.ObfusPasses; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using UnityEngine; - -namespace Obfuz -{ - public class ConfigurablePassPolicy - { - class PassRule - { - public ObfuscationPassType? enablePasses; - public ObfuscationPassType? disablePasses; - public ObfuscationPassType? addPasses; - public ObfuscationPassType? removePasses; - public ObfuscationPassType finalPasses; - - public void InheritParent(PassRule parentRule, ObfuscationPassType globalEnabledPasses) - { - finalPasses = parentRule.finalPasses; - if (enablePasses != null) - { - finalPasses = enablePasses.Value; - } - if (disablePasses != null) - { - finalPasses = ~disablePasses.Value; - } - if (addPasses != null) - { - finalPasses |= addPasses.Value; - } - if (removePasses != null) - { - finalPasses &= ~removePasses.Value; - } - finalPasses &= globalEnabledPasses; - } - } - - class SpecBase - { - public string name; - public NameMatcher nameMatcher; - public PassRule rule; - } - - class MethodSpec : SpecBase - { - } - - class FieldSpec : SpecBase - { - } - - class PropertySpec : SpecBase - { - } - - class EventSpec : SpecBase - { - } - - class TypeSpec : SpecBase - { - public List fields = new List(); - public List methods = new List(); - public List properties = new List(); - public List events = new List(); - } - - class AssemblySpec - { - public string name; - public NameMatcher nameMatcher; - public PassRule rule; - public List types = new List(); - } - - private readonly ObfuscationPassType _enabledPasses; - private readonly HashSet _toObfuscatedAssemblyNames; - private readonly List _assemblySpecs = new List(); - private readonly PassRule _defaultPassRule; - - private string _curLoadingConfig; - - public ConfigurablePassPolicy(IEnumerable toObfuscatedAssemblyNames, ObfuscationPassType enabledPasses, List configFiles) - { - _toObfuscatedAssemblyNames = new HashSet(toObfuscatedAssemblyNames); - _enabledPasses = enabledPasses; - _defaultPassRule = new PassRule { finalPasses = enabledPasses }; - LoadConfigs(configFiles); - InheritParentRules(enabledPasses); - } - - private void LoadConfigs(IEnumerable configFiles) - { - foreach (var configFile in configFiles) - { - LoadConfig(configFile); - } - } - - private void InheritParentRules(ObfuscationPassType enablePasses) - { - var defaultRule = new PassRule - { - enablePasses = enablePasses, - finalPasses = enablePasses, - }; - foreach (AssemblySpec assSpec in _assemblySpecs) - { - assSpec.rule.InheritParent(defaultRule, enablePasses); - foreach (TypeSpec typeSpec in assSpec.types) - { - typeSpec.rule.InheritParent(assSpec.rule, enablePasses); - foreach (FieldSpec fieldSpec in typeSpec.fields) - { - fieldSpec.rule.InheritParent(typeSpec.rule, enablePasses); - } - foreach (MethodSpec methodSpec in typeSpec.methods) - { - methodSpec.rule.InheritParent(typeSpec.rule, enablePasses); - } - foreach (PropertySpec propertySpec in typeSpec.properties) - { - propertySpec.rule.InheritParent(typeSpec.rule, enablePasses); - } - foreach (EventSpec eventSpec in typeSpec.events) - { - eventSpec.rule.InheritParent(typeSpec.rule, enablePasses); - } - } - } - } - - public void LoadConfig(string configFile) - { - if (string.IsNullOrEmpty(configFile)) - { - throw new Exception($"Invalid xml file {configFile}, file name is empty"); - } - _curLoadingConfig = configFile; - - Debug.Log($"ConfigurablePassPolicy::LoadConfig {configFile}"); - var doc = new XmlDocument(); - doc.Load(configFile); - var root = doc.DocumentElement; - if (root.Name != "obfuz") - { - throw new Exception($"Invalid xml file {configFile}, root name should be 'obfuz'"); - } - foreach (XmlNode node in root.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "assembly": - { - AssemblySpec assSpec = ParseAssembly(ele); - _assemblySpecs.Add(assSpec); - break; - } - default: - { - throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); - } - } - } - } - - (bool, ObfuscationPassType) ParseObfuscationType(string obfuscationPassTypesStr) - { - bool delta = false; - if (obfuscationPassTypesStr[0] == '+' || obfuscationPassTypesStr[0] == '-') - { - delta = true; - obfuscationPassTypesStr = obfuscationPassTypesStr.Substring(1); - } - ObfuscationPassType passType = ObfuscationPassType.None; - foreach (var passName in obfuscationPassTypesStr.Split('|')) - { - if (Enum.TryParse< ObfuscationPassType>(passName, out var pass)) - { - passType |= pass; - } - else - { - throw new Exception($"Invalid xml file {_curLoadingConfig}, unknown pass type {passName}"); - } - } - return (delta, passType); - } - - private PassRule ParseRule(XmlElement ele) - { - var r = new PassRule(); - if (ele.HasAttribute("enable")) - { - string enablePassStr = ele.GetAttribute("enable"); - if (string.IsNullOrEmpty(enablePassStr)) - { - throw new Exception($"Invalid xml file {_curLoadingConfig}, enable attribute is empty"); - } - var (delta, passType) = ParseObfuscationType(enablePassStr); - if (delta) - { - r.addPasses = passType; - } - else - { - r.enablePasses = passType; - } - } - if (ele.HasAttribute("disable")) - { - string disablePassStr = ele.GetAttribute("disable"); - if (string.IsNullOrEmpty(disablePassStr)) - { - throw new Exception($"Invalid xml file {_curLoadingConfig}, disable attribute is empty"); - } - var (delta, passType) = ParseObfuscationType(disablePassStr); - if (delta) - { - r.removePasses = passType; - } - else - { - r.disablePasses = passType; - } - } - if (r.enablePasses != null && (r.disablePasses != null || r.addPasses != null || r.removePasses != null)) - { - throw new Exception($"Invalid xml file {_curLoadingConfig}, enable and disable can't be used together"); - } - if (r.disablePasses != null && (r.enablePasses != null || r.addPasses != null || r.removePasses != null)) - { - throw new Exception($"Invalid xml file {_curLoadingConfig}, disable and enable can't be used together"); - } - return r; - } - - private AssemblySpec ParseAssembly(XmlElement ele) - { - var assemblySpec = new AssemblySpec(); - string name = ele.GetAttribute("name"); - if (!_toObfuscatedAssemblyNames.Contains(name)) - { - throw new Exception($"Invalid xml file {_curLoadingConfig}, assembly name {name} isn't in toObfuscatedAssemblyNames"); - } - assemblySpec.name = name; - assemblySpec.nameMatcher = new NameMatcher(name); - assemblySpec.rule = ParseRule(ele); - - - var types = assemblySpec.types; - foreach (XmlNode node in ele.ChildNodes) - { - if (!(node is XmlElement childEle)) - { - continue; - } - switch (childEle.Name) - { - case "type": - { - types.Add(ParseType(childEle)); - break; - } - default: - { - throw new Exception($"Invalid xml file, unknown node {childEle.Name}"); - } - } - } - return assemblySpec; - } - - private TypeSpec ParseType(XmlElement element) - { - var typeSpec = new TypeSpec(); - - string name = element.GetAttribute("name"); - typeSpec.name = name; - typeSpec.nameMatcher = new NameMatcher(name); - typeSpec.rule = ParseRule(element); - - List fields = typeSpec.fields; - List methods = typeSpec.methods; - List properties = typeSpec.properties; - List events = typeSpec.events; - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "field": - { - fields.Add(ParseField(ele)); - break; - } - case "method": - { - methods.Add(ParseMethod(ele)); - break; - } - case "property": - { - properties.Add(ParseProperty(ele)); - break; - } - case "event": - { - events.Add(ParseEvent(ele)); - break; - } - default: - { - throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - } - return typeSpec; - } - - private void ParseSpecObject(XmlElement element, SpecBase obj) - { - string name = element.GetAttribute("name"); - obj.name = name; - obj.nameMatcher = new NameMatcher(name); - obj.rule = ParseRule(element); - } - - private FieldSpec ParseField(XmlElement element) - { - var fieldSpec = new FieldSpec(); - ParseSpecObject(element, fieldSpec); - return fieldSpec; - } - - private MethodSpec ParseMethod(XmlElement element) - { - var methodSpec = new MethodSpec(); - ParseSpecObject(element, methodSpec); - return methodSpec; - } - - private PropertySpec ParseProperty(XmlElement element) - { - var propertySpec = new PropertySpec(); - ParseSpecObject(element, propertySpec); - return propertySpec; - } - - private EventSpec ParseEvent(XmlElement element) - { - var eventSpec = new EventSpec(); - ParseSpecObject(element, eventSpec); - return eventSpec; - } - - private readonly Dictionary _modulePassRuleCaches = new Dictionary(); - private readonly Dictionary _typePassRuleCaches = new Dictionary(); - private readonly Dictionary _methodPassRuleCaches = new Dictionary(); - private readonly Dictionary _fieldPassRuleCaches = new Dictionary(); - private readonly Dictionary _propertyPassRuleCaches = new Dictionary(); - private readonly Dictionary _eventPassRuleCaches = new Dictionary(); - - - private (AssemblySpec, PassRule) GetAssemblySpec(ModuleDef module) - { - if (!_modulePassRuleCaches.TryGetValue(module, out var result)) - { - result = (null, _defaultPassRule); - string assName = module.Assembly.Name; - foreach (var ass in _assemblySpecs) - { - if (ass.nameMatcher.IsMatch(assName)) - { - result = (ass, _defaultPassRule); - break; - } - } - _modulePassRuleCaches.Add(module, result); - } - return result; - } - - private (TypeSpec, PassRule) GetTypeSpec(TypeDef type) - { - if (!_typePassRuleCaches.TryGetValue(type, out var result)) - { - var assResult = GetAssemblySpec(type.Module); - result = (null, assResult.Item2); - if (assResult.Item1 != null) - { - string typeName = type.FullName; - foreach (var typeSpec in assResult.Item1.types) - { - if (typeSpec.nameMatcher.IsMatch(typeName)) - { - result = (typeSpec, typeSpec.rule); - break; - } - } - } - _typePassRuleCaches.Add(type, result); - } - return result; - } - - private (MethodSpec, PassRule) GetMethodSpec(MethodDef method) - { - if (!_methodPassRuleCaches.TryGetValue(method, out var result)) - { - var typeResult = GetTypeSpec(method.DeclaringType); - result = (null, typeResult.Item2); - if (typeResult.Item1 != null) - { - string methodName = method.Name; - foreach (var methodSpec in typeResult.Item1.methods) - { - if (methodSpec.nameMatcher.IsMatch(methodName)) - { - result = (methodSpec, methodSpec.rule); - break; - } - } - } - _methodPassRuleCaches.Add(method, result); - } - return result; - } - - private (FieldSpec, PassRule) GetFieldSpec(FieldDef field) - { - if (!_fieldPassRuleCaches.TryGetValue(field, out var result)) - { - var typeResult = GetTypeSpec(field.DeclaringType); - result = (null, typeResult.Item2); - if (typeResult.Item1 != null) - { - string fieldName = field.Name; - foreach (var fieldSpec in typeResult.Item1.fields) - { - if (fieldSpec.nameMatcher.IsMatch(fieldName)) - { - result = (fieldSpec, fieldSpec.rule); - break; - } - } - } - _fieldPassRuleCaches.Add(field, result); - } - return result; - } - - private (PropertySpec, PassRule) GetPropertySpec(PropertyDef property) - { - if (!_propertyPassRuleCaches.TryGetValue(property, out var result)) - { - var typeResult = GetTypeSpec(property.DeclaringType); - result = (null, typeResult.Item2); - if (typeResult.Item1 != null) - { - string propertyName = property.Name; - foreach (var propertySpec in typeResult.Item1.properties) - { - if (propertySpec.nameMatcher.IsMatch(propertyName)) - { - result = (propertySpec, propertySpec.rule); - break; - } - } - } - _propertyPassRuleCaches.Add(property, result); - } - return result; - } - - private (EventSpec, PassRule) GetEventSpec(EventDef eventDef) - { - if (!_eventPassRuleCaches.TryGetValue(eventDef, out var result)) - { - var typeResult = GetTypeSpec(eventDef.DeclaringType); - result = (null, typeResult.Item2); - if (typeResult.Item1 != null) - { - string eventName = eventDef.Name; - foreach (var eventSpec in typeResult.Item1.events) - { - if (eventSpec.nameMatcher.IsMatch(eventName)) - { - result = (eventSpec, eventSpec.rule); - break; - } - } - } - _eventPassRuleCaches.Add(eventDef, result); - } - return result; - } - - - public ObfuscationPassType GetAssemblyObfuscationPasses(ModuleDef module) - { - return GetAssemblySpec(module).Item2.finalPasses; - } - - public ObfuscationPassType GetTypeObfuscationPasses(TypeDef type) - { - return GetTypeSpec(type).Item2.finalPasses; - } - - public ObfuscationPassType GetMethodObfuscationPasses(MethodDef method) - { - return GetMethodSpec(method).Item2.finalPasses; - } - - public ObfuscationPassType GetFieldObfuscationPasses(FieldDef field) - { - return GetFieldSpec(field).Item2.finalPasses; - } - - public ObfuscationPassType GetPropertyObfuscationPasses(PropertyDef property) - { - return GetPropertySpec(property).Item2.finalPasses; - } - - public ObfuscationPassType GetEventObfuscationPasses(EventDef eventDef) - { - return GetEventSpec(eventDef).Item2.finalPasses; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs.meta deleted file mode 100644 index 9b85183..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 41044699810a34f4780e14de084bf7d7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs deleted file mode 100644 index 2792a00..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Editor -{ - public static class ConstValues - { - public const string ObfuzInternalSymbolNamePrefix = "$Obfuz$"; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs.meta deleted file mode 100644 index 33f4160..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aee7817ed523a5e4ea42104013e8a775 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data.meta deleted file mode 100644 index d162ae8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3319ebe75a42f3d4d996846ca09ed099 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs deleted file mode 100644 index caf1725..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs +++ /dev/null @@ -1,344 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Editor; -using Obfuz.Emit; -using Obfuz.Utils; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; -using UnityEngine.Assertions; - -namespace Obfuz.Data -{ - public class ModuleConstFieldAllocator : IGroupByModuleEntity - { - private ModuleDef _module; - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly RvaDataAllocator _rvaDataAllocator; - private readonly GroupByModuleEntityManager _moduleEntityManager; - private EncryptionScopeInfo _encryptionScope; - private RandomCreator _randomCreator; - private IEncryptor _encryptor; - - private TypeDef _holderTypeDef; - - class ConstFieldInfo - { - public FieldDef field; - public object value; - } - - class AnyComparer : IEqualityComparer - { - public new bool Equals(object x, object y) - { - if (x is byte[] xBytes && y is byte[] yBytes) - { - return StructuralComparisons.StructuralEqualityComparer.Equals(xBytes, yBytes); - } - return x.Equals(y); - } - - public static int ComputeHashCode(object obj) - { - return HashUtil.ComputePrimitiveOrStringOrBytesHashCode(obj); - } - - public int GetHashCode(object obj) - { - return ComputeHashCode(obj); - } - } - - private readonly Dictionary _allocatedFields = new Dictionary(new AnyComparer()); - private readonly Dictionary _field2Fields = new Dictionary(); - - private readonly List _holderTypeDefs = new List(); - private bool _done; - - - public ModuleConstFieldAllocator(EncryptionScopeProvider encryptionScopeProvider, RvaDataAllocator rvaDataAllocator, GroupByModuleEntityManager moduleEntityManager) - { - _encryptionScopeProvider = encryptionScopeProvider; - _rvaDataAllocator = rvaDataAllocator; - _moduleEntityManager = moduleEntityManager; - } - - public void Init(ModuleDef mod) - { - _module = mod; - _encryptionScope = _encryptionScopeProvider.GetScope(mod); - _randomCreator = _encryptionScope.localRandomCreator; - _encryptor = _encryptionScope.encryptor; - } - - const int maxFieldCount = 1000; - - - private TypeSig GetTypeSigOfValue(object value) - { - if (value is int) - return _module.CorLibTypes.Int32; - if (value is long) - return _module.CorLibTypes.Int64; - if (value is float) - return _module.CorLibTypes.Single; - if (value is double) - return _module.CorLibTypes.Double; - if (value is string) - return _module.CorLibTypes.String; - if (value is byte[]) - return new SZArraySig(_module.CorLibTypes.Byte); - throw new NotSupportedException($"Unsupported type: {value.GetType()}"); - } - - private ConstFieldInfo CreateConstFieldInfo(object value) - { - if (_holderTypeDef == null || _holderTypeDef.Fields.Count >= maxFieldCount) - { - _module.EnableTypeDefFindCache = false; - ITypeDefOrRef objectTypeRef = _module.Import(typeof(object)); - _holderTypeDef = new TypeDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}ConstFieldHolder${_holderTypeDefs.Count}", objectTypeRef); - _module.Types.Add(_holderTypeDef); - _holderTypeDefs.Add(_holderTypeDef); - _module.EnableTypeDefFindCache = true; - } - - var field = new FieldDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}RVA_Value{_holderTypeDef.Fields.Count}", new FieldSig(GetTypeSigOfValue(value)), FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.InitOnly); - field.DeclaringType = _holderTypeDef; - return new ConstFieldInfo - { - field = field, - value = value, - }; - } - - private FieldDef AllocateAny(object value) - { - if (_done) - { - throw new Exception("can't Allocate after done"); - } - if (!_allocatedFields.TryGetValue(value, out var field)) - { - field = CreateConstFieldInfo(value); - _allocatedFields.Add(value, field); - _field2Fields.Add(field.field, field); - } - return field.field; - } - - public FieldDef Allocate(int value) - { - return AllocateAny(value); - } - - public FieldDef Allocate(long value) - { - return AllocateAny(value); - } - - public FieldDef Allocate(float value) - { - return AllocateAny(value); - } - - public FieldDef Allocate(double value) - { - return AllocateAny(value); - } - - public FieldDef Allocate(string value) - { - return AllocateAny(value); - } - - public FieldDef Allocate(byte[] value) - { - return AllocateAny(value); - } - - private DefaultMetadataImporter GetModuleMetadataImporter() - { - return _moduleEntityManager.GetDefaultModuleMetadataImporter(_module, _encryptionScopeProvider); - } - - private void CreateCCtorOfRvaTypeDef(TypeDef type) - { - var cctor = new MethodDefUser(".cctor", - MethodSig.CreateStatic(_module.CorLibTypes.Void), - MethodImplAttributes.IL | MethodImplAttributes.Managed, - MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Private); - cctor.DeclaringType = type; - //_rvaTypeDef.Methods.Add(cctor); - var body = new CilBody(); - cctor.Body = body; - var ins = body.Instructions; - - //IMethod method = _module.Import(typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray", new[] { typeof(Array), typeof(RuntimeFieldHandle) })); - //Assert.IsNotNull(method); - - - DefaultMetadataImporter importer = GetModuleMetadataImporter(); - // TODO. obfuscate init codes - foreach (var field in type.Fields) - { - ConstFieldInfo constInfo = _field2Fields[field]; - IRandom localRandom = _randomCreator(HashUtil.ComputePrimitiveOrStringOrBytesHashCode(constInfo.value)); - int ops = EncryptionUtil.GenerateEncryptionOpCodes(localRandom, _encryptor, 4); - int salt = localRandom.NextInt(); - switch (constInfo.value) - { - case int i: - { - int encryptedValue = _encryptor.Encrypt(i, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue); - ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - ins.Add(Instruction.CreateLdcI4(rvaData.offset)); - ins.Add(Instruction.CreateLdcI4(ops)); - ins.Add(Instruction.CreateLdcI4(salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaInt)); - break; - } - case long l: - { - long encryptedValue = _encryptor.Encrypt(l, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue); - ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - ins.Add(Instruction.CreateLdcI4(rvaData.offset)); - ins.Add(Instruction.CreateLdcI4(ops)); - ins.Add(Instruction.CreateLdcI4(salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaLong)); - break; - } - case float f: - { - float encryptedValue = _encryptor.Encrypt(f, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue); - ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - ins.Add(Instruction.CreateLdcI4(rvaData.offset)); - ins.Add(Instruction.CreateLdcI4(ops)); - ins.Add(Instruction.CreateLdcI4(salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaFloat)); - break; - } - case double d: - { - double encryptedValue = _encryptor.Encrypt(d, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue); - ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - ins.Add(Instruction.CreateLdcI4(rvaData.offset)); - ins.Add(Instruction.CreateLdcI4(ops)); - ins.Add(Instruction.CreateLdcI4(salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaDouble)); - break; - } - case string s: - { - byte[] encryptedValue = _encryptor.Encrypt(s, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue); - ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - ins.Add(Instruction.CreateLdcI4(rvaData.offset)); - Assert.AreEqual(encryptedValue.Length, rvaData.size); - ins.Add(Instruction.CreateLdcI4(encryptedValue.Length)); - ins.Add(Instruction.CreateLdcI4(ops)); - ins.Add(Instruction.CreateLdcI4(salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaString)); - break; - } - case byte[] bs: - { - byte[] encryptedValue = _encryptor.Encrypt(bs, 0, bs.Length, ops, salt); - Assert.AreEqual(encryptedValue.Length, bs.Length); - RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue); - ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - ins.Add(Instruction.CreateLdcI4(rvaData.offset)); - ins.Add(Instruction.CreateLdcI4(bs.Length)); - ins.Add(Instruction.CreateLdcI4(ops)); - ins.Add(Instruction.CreateLdcI4(salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaBytes)); - break; - } - default: throw new NotSupportedException($"Unsupported type: {constInfo.value.GetType()}"); - } - ins.Add(Instruction.Create(OpCodes.Stsfld, field)); - } - ins.Add(Instruction.Create(OpCodes.Ret)); - } - - public void Done() - { - if (_done) - { - throw new Exception("Already done"); - } - _done = true; - foreach (var typeDef in _holderTypeDefs) - { - CreateCCtorOfRvaTypeDef(typeDef); - } - } - } - - public class ConstFieldAllocator - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly RvaDataAllocator _rvaDataAllocator; - private readonly GroupByModuleEntityManager _moduleEntityManager; - - public ConstFieldAllocator(EncryptionScopeProvider encryptionScopeProvider, RvaDataAllocator rvaDataAllocator, GroupByModuleEntityManager moduleEntityManager) - { - _encryptionScopeProvider = encryptionScopeProvider; - _rvaDataAllocator = rvaDataAllocator; - _moduleEntityManager = moduleEntityManager; - } - - private ModuleConstFieldAllocator GetModuleAllocator(ModuleDef mod) - { - return _moduleEntityManager.GetEntity(mod, () => new ModuleConstFieldAllocator(_encryptionScopeProvider, _rvaDataAllocator, _moduleEntityManager)); - } - - public FieldDef Allocate(ModuleDef mod, int value) - { - return GetModuleAllocator(mod).Allocate(value); - } - - public FieldDef Allocate(ModuleDef mod, long value) - { - return GetModuleAllocator(mod).Allocate(value); - } - - public FieldDef Allocate(ModuleDef mod, float value) - { - return GetModuleAllocator(mod).Allocate(value); - } - - public FieldDef Allocate(ModuleDef mod, double value) - { - return GetModuleAllocator(mod).Allocate(value); - } - - public FieldDef Allocate(ModuleDef mod, byte[] value) - { - return GetModuleAllocator(mod).Allocate(value); - } - - public FieldDef Allocate(ModuleDef mod, string value) - { - return GetModuleAllocator(mod).Allocate(value); - } - - public void Done() - { - foreach (var moduleAllocator in _moduleEntityManager.GetEntities()) - { - moduleAllocator.Done(); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs.meta deleted file mode 100644 index 8e64e42..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e75f5cdfd47370d4ea6c4dee7e55a881 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs deleted file mode 100644 index 3d4d8dd..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs +++ /dev/null @@ -1,355 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Emit; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine.Assertions; - -namespace Obfuz.Data -{ - public struct RvaData - { - public readonly FieldDef field; - public readonly int offset; - public readonly int size; - - public RvaData(FieldDef field, int offset, int size) - { - this.field = field; - this.offset = offset; - this.size = size; - } - } - - public class ModuleRvaDataAllocator : GroupByModuleEntityBase - { - // randomized - const int maxRvaDataSize = 0x1000; - - private ModuleDef _module; - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly GroupByModuleEntityManager _moduleEntityManager; - - private EncryptionScopeInfo _encryptionScope; - private IRandom _random; - - class RvaField - { - public FieldDef holderDataField; - public FieldDef runtimeValueField; - public int encryptionOps; - public uint size; - public List bytes; - public int salt; - - public void FillPaddingToSize(int newSize) - { - for (int i = bytes.Count; i < newSize; i++) - { - bytes.Add(0xAB); - } - } - - public void FillPaddingToEnd() - { - // fill with random value - for (int i = bytes.Count; i < size; i++) - { - bytes.Add(0xAB); - } - } - } - - private readonly List _rvaFields = new List(); - private RvaField _currentField; - - - private TypeDef _rvaTypeDef; - - private readonly Dictionary _dataHolderTypeBySizes = new Dictionary(); - private bool _done; - - public ModuleRvaDataAllocator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager) - { - _encryptionScopeProvider = encryptionScopeProvider; - _moduleEntityManager = moduleEntityManager; - } - - public override void Init(ModuleDef mod) - { - _module = mod; - _encryptionScope = _encryptionScopeProvider.GetScope(mod); - _random = _encryptionScope.localRandomCreator(HashUtil.ComputeHash(mod.Name)); - } - - private (FieldDef, FieldDef) CreateDataHolderRvaField(TypeDef dataHolderType) - { - if (_rvaTypeDef == null) - { - _module.EnableTypeDefFindCache = false; - //_rvaTypeDef = _module.Find("$ObfuzRVA$", true); - //if (_rvaTypeDef != null) - //{ - // throw new Exception($"can't obfuscate a obfuscated assembly"); - //} - ITypeDefOrRef objectTypeRef = _module.Import(typeof(object)); - _rvaTypeDef = new TypeDefUser("$Obfuz$RVA$", objectTypeRef); - _module.Types.Add(_rvaTypeDef); - _module.EnableTypeDefFindCache = true; - } - - - var holderField = new FieldDefUser($"$RVA_Data{_rvaFields.Count}", new FieldSig(dataHolderType.ToTypeSig()), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA); - holderField.DeclaringType = _rvaTypeDef; - - var runtimeValueField = new FieldDefUser($"$RVA_Value{_rvaFields.Count}", new FieldSig(new SZArraySig(_module.CorLibTypes.Byte)), FieldAttributes.Static | FieldAttributes.Public); - runtimeValueField.DeclaringType = _rvaTypeDef; - return (holderField, runtimeValueField); - } - - private TypeDef GetDataHolderType(int size) - { - size = (size + 15) & ~15; // align to 6 bytes - if (_dataHolderTypeBySizes.TryGetValue(size, out var type)) - return type; - var dataHolderType = new TypeDefUser($"$ObfuzRVA$DataHolder{size}", _module.Import(typeof(ValueType))); - dataHolderType.Attributes = TypeAttributes.Public | TypeAttributes.Sealed; - dataHolderType.Layout = TypeAttributes.ExplicitLayout; - dataHolderType.PackingSize = 1; - dataHolderType.ClassSize = (uint)size; - _dataHolderTypeBySizes.Add(size, dataHolderType); - _module.Types.Add(dataHolderType); - return dataHolderType; - } - - private static int AlignTo(int size, int alignment) - { - return (size + alignment - 1) & ~(alignment - 1); - } - - private RvaField CreateRvaField(int size) - { - TypeDef dataHolderType = GetDataHolderType(size); - var (holderDataField, runtimeValueField) = CreateDataHolderRvaField(dataHolderType); - var newRvaField = new RvaField - { - holderDataField = holderDataField, - runtimeValueField = runtimeValueField, - size = dataHolderType.ClassSize, - bytes = new List((int)dataHolderType.ClassSize), - encryptionOps = _random.NextInt(), - salt = _random.NextInt(), - }; - _rvaFields.Add(newRvaField); - return newRvaField; - } - - private RvaField GetRvaField(int preservedSize, int alignment) - { - if (_done) - { - throw new Exception("can't GetRvaField after done"); - } - Assert.IsTrue(preservedSize % alignment == 0); - // for big size, create a new field - if (preservedSize >= maxRvaDataSize) - { - return CreateRvaField(preservedSize); - } - - if (_currentField != null) - { - int offset = AlignTo(_currentField.bytes.Count, alignment); - - int expectedSize = offset + preservedSize; - if (expectedSize <= _currentField.size) - { - _currentField.FillPaddingToSize(offset); - return _currentField; - } - - _currentField.FillPaddingToEnd(); - } - _currentField = CreateRvaField(maxRvaDataSize); - return _currentField; - } - - public RvaData Allocate(int value) - { - RvaField field = GetRvaField(4, 4); - int offset = field.bytes.Count; - Assert.IsTrue(offset % 4 == 0); - field.bytes.AddRange(BitConverter.GetBytes(value)); - return new RvaData(field.runtimeValueField, offset, 4); - } - - public RvaData Allocate(long value) - { - RvaField field = GetRvaField(8, 8); - int offset = field.bytes.Count; - Assert.IsTrue(offset % 8 == 0); - field.bytes.AddRange(BitConverter.GetBytes(value)); - return new RvaData(field.runtimeValueField, offset, 8); - } - - public RvaData Allocate(float value) - { - RvaField field = GetRvaField(4, 4); - int offset = field.bytes.Count; - Assert.IsTrue(offset % 4 == 0); - field.bytes.AddRange(BitConverter.GetBytes(value)); - return new RvaData(field.runtimeValueField, offset, 4); - } - - public RvaData Allocate(double value) - { - RvaField field = GetRvaField(8, 8); - int offset = field.bytes.Count; - Assert.IsTrue(offset % 8 == 0); - field.bytes.AddRange(BitConverter.GetBytes(value)); - return new RvaData(field.runtimeValueField, offset, 8); - } - - public RvaData Allocate(string value) - { - byte[] bytes = Encoding.UTF8.GetBytes(value); - return Allocate(bytes); - } - - public RvaData Allocate(byte[] value) - { - RvaField field = GetRvaField(value.Length, 1); - int offset = field.bytes.Count; - field.bytes.AddRange(value); - return new RvaData(field.runtimeValueField, offset, value.Length); - } - - private void CreateCCtorOfRvaTypeDef() - { - if (_rvaTypeDef == null) - { - return; - } - ModuleDef mod = _rvaTypeDef.Module; - var cctorMethod = new MethodDefUser(".cctor", - MethodSig.CreateStatic(_module.CorLibTypes.Void), - MethodImplAttributes.IL | MethodImplAttributes.Managed, - MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Private); - cctorMethod.DeclaringType = _rvaTypeDef; - //_rvaTypeDef.Methods.Add(cctor); - var body = new CilBody(); - cctorMethod.Body = body; - var ins = body.Instructions; - - DefaultMetadataImporter importer = _moduleEntityManager.GetDefaultModuleMetadataImporter(mod, _encryptionScopeProvider); - foreach (var field in _rvaFields) - { - // ldc - // newarr - // dup - // stsfld - // ldtoken - // RuntimeHelpers.InitializeArray(array, fieldHandle); - ins.Add(Instruction.Create(OpCodes.Ldc_I4, (int)field.size)); - ins.Add(Instruction.Create(OpCodes.Newarr, field.runtimeValueField.FieldType.Next.ToTypeDefOrRef())); - ins.Add(Instruction.Create(OpCodes.Dup)); - ins.Add(Instruction.Create(OpCodes.Dup)); - ins.Add(Instruction.Create(OpCodes.Stsfld, field.runtimeValueField)); - ins.Add(Instruction.Create(OpCodes.Ldtoken, field.holderDataField)); - ins.Add(Instruction.Create(OpCodes.Call, importer.InitializedArrayMethod)); - - // EncryptionService.DecryptBlock(array, field.encryptionOps, field.salt); - ins.Add(Instruction.CreateLdcI4(field.encryptionOps)); - ins.Add(Instruction.Create(OpCodes.Ldc_I4, field.salt)); - ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptBlock)); - - } - ins.Add(Instruction.Create(OpCodes.Ret)); - } - - private void SetFieldsRVA() - { - foreach (var field in _rvaFields) - { - Assert.IsTrue(field.bytes.Count <= field.size); - if (field.bytes.Count < field.size) - { - field.FillPaddingToEnd(); - } - byte[] data = field.bytes.ToArray(); - _encryptionScope.encryptor.EncryptBlock(data, field.encryptionOps, field.salt); - field.holderDataField.InitialValue = data; - } - } - - public void Done() - { - if (_done) - { - throw new Exception("can't call Done twice"); - } - _done = true; - SetFieldsRVA(); - CreateCCtorOfRvaTypeDef(); - } - } - - public class RvaDataAllocator - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly GroupByModuleEntityManager _moduleEntityManager; - - public RvaDataAllocator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager) - { - _encryptionScopeProvider = encryptionScopeProvider; - _moduleEntityManager = moduleEntityManager; - } - - private ModuleRvaDataAllocator GetModuleRvaDataAllocator(ModuleDef mod) - { - return _moduleEntityManager.GetEntity(mod, () => new ModuleRvaDataAllocator(_encryptionScopeProvider, _moduleEntityManager)); - } - - public RvaData Allocate(ModuleDef mod, int value) - { - return GetModuleRvaDataAllocator(mod).Allocate(value); - } - - public RvaData Allocate(ModuleDef mod, long value) - { - return GetModuleRvaDataAllocator(mod).Allocate(value); - } - - public RvaData Allocate(ModuleDef mod, float value) - { - return GetModuleRvaDataAllocator(mod).Allocate(value); - } - - public RvaData Allocate(ModuleDef mod, double value) - { - return GetModuleRvaDataAllocator(mod).Allocate(value); - } - - public RvaData Allocate(ModuleDef mod, string value) - { - return GetModuleRvaDataAllocator(mod).Allocate(value); - } - - public RvaData Allocate(ModuleDef mod, byte[] value) - { - return GetModuleRvaDataAllocator(mod).Allocate(value); - } - - public void Done() - { - foreach (var allocator in _moduleEntityManager.GetEntities()) - { - allocator.Done(); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs.meta deleted file mode 100644 index c1f94e8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c00ca514f46605645bf40b0135e7e504 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit.meta deleted file mode 100644 index d13f8ab..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a513a192808ba5f47b1ef8a3ecf02533 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs deleted file mode 100644 index acd80a7..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs +++ /dev/null @@ -1,295 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Remoting.Messaging; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Emit -{ - public class BasicBlock - { - public readonly List instructions = new List(); - - public readonly List inBlocks = new List(); - - public readonly List outBlocks = new List(); - - public bool inLoop; - - public void AddTargetBasicBlock(BasicBlock target) - { - if (!outBlocks.Contains(target)) - { - outBlocks.Add(target); - } - if (!target.inBlocks.Contains(this)) - { - target.inBlocks.Add(this); - } - } - } - - public class BasicBlockCollection - { - private readonly MethodDef _method; - - private readonly List _blocks = new List(); - private readonly Dictionary _inst2BlockMap = new Dictionary(); - - public IList Blocks => _blocks; - - public BasicBlockCollection(MethodDef method) - { - _method = method; - HashSet splitPoints = BuildSplitPoint(method); - BuildBasicBlocks(method, splitPoints); - BuildInOutGraph(method); - - var loopBlocks = FindLoopBlocks(_blocks); - foreach (var block in loopBlocks) - { - block.inLoop = true; - } - } - - public BasicBlock GetBasicBlockByInstruction(Instruction inst) - { - return _inst2BlockMap[inst]; - } - - private HashSet BuildSplitPoint(MethodDef method) - { - var insts = method.Body.Instructions; - var splitPoints = new HashSet(); - foreach (ExceptionHandler eh in method.Body.ExceptionHandlers) - { - if (eh.TryStart != null) - { - splitPoints.Add(eh.TryStart); - } - if (eh.TryEnd != null) - { - splitPoints.Add(eh.TryEnd); - } - if (eh.HandlerStart != null) - { - splitPoints.Add(eh.HandlerStart); - } - if (eh.HandlerEnd != null) - { - splitPoints.Add(eh.HandlerEnd); - } - if (eh.FilterStart != null) - { - splitPoints.Add(eh.FilterStart); - } - } - - for (int i = 0, n = insts.Count; i < n; i++) - { - Instruction curInst = insts[i]; - Instruction nextInst = i + 1 < n ? insts[i + 1] : null; - switch (curInst.OpCode.FlowControl) - { - case FlowControl.Branch: - { - if (nextInst != null) - { - splitPoints.Add(nextInst); - } - break; - } - case FlowControl.Cond_Branch: - { - if (nextInst != null) - { - splitPoints.Add(nextInst); - } - if (curInst.Operand is Instruction targetInst) - { - splitPoints.Add(targetInst); - } - else if (curInst.Operand is Instruction[] targetInsts) - { - foreach (var target in targetInsts) - { - splitPoints.Add(target); - } - } - break; - } - case FlowControl.Return: - { - if (nextInst != null) - { - splitPoints.Add(nextInst); - } - break; - } - case FlowControl.Throw: - { - if (nextInst != null) - { - splitPoints.Add(nextInst); - } - break; - } - } - } - return splitPoints; - } - - - private void BuildBasicBlocks(MethodDef method, HashSet splitPoints) - { - var insts = method.Body.Instructions; - - - BasicBlock curBlock = new BasicBlock(); - foreach (Instruction inst in insts) - { - if (splitPoints.Contains(inst) && curBlock.instructions.Count > 0) - { - _blocks.Add(curBlock); - curBlock = new BasicBlock(); - } - curBlock.instructions.Add(inst); - _inst2BlockMap.Add(inst, curBlock); - } - if (curBlock.instructions.Count > 0) - { - _blocks.Add(curBlock); - } - } - - private void BuildInOutGraph(MethodDef method) - { - var insts = method.Body.Instructions; - for (int i = 0, n = _blocks.Count; i < n; i++) - { - BasicBlock curBlock = _blocks[i]; - BasicBlock nextBlock = i + 1 < n ? _blocks[i + 1] : null; - Instruction lastInst = curBlock.instructions.Last(); - switch (lastInst.OpCode.FlowControl) - { - case FlowControl.Branch: - { - Instruction targetInst = (Instruction)lastInst.Operand; - BasicBlock targetBlock = GetBasicBlockByInstruction(targetInst); - curBlock.AddTargetBasicBlock(targetBlock); - break; - } - case FlowControl.Cond_Branch: - { - if (lastInst.Operand is Instruction targetInst) - { - BasicBlock targetBlock = GetBasicBlockByInstruction(targetInst); - curBlock.AddTargetBasicBlock(targetBlock); - } - else if (lastInst.Operand is Instruction[] targetInsts) - { - foreach (var target in targetInsts) - { - BasicBlock targetBlock = GetBasicBlockByInstruction(target); - curBlock.AddTargetBasicBlock(targetBlock); - } - } - else - { - throw new Exception("Invalid operand type for conditional branch"); - } - if (nextBlock != null) - { - curBlock.AddTargetBasicBlock(nextBlock); - } - break; - } - case FlowControl.Return: - case FlowControl.Throw: - { - break; - } - } - } - } - - private static HashSet FindLoopBlocks(List allBlocks) - { - // Tarjan算法找强连通分量 - var sccList = FindStronglyConnectedComponents(allBlocks); - - // 筛选有效循环 - var loopBlocks = new HashSet(); - foreach (var scc in sccList) - { - // 有效循环需满足以下条件之一: - // 1. 分量包含多个块 - // 2. 单个块有自环(跳转自己) - if (scc.Count > 1 || - (scc.Count == 1 && scc[0].outBlocks.Contains(scc[0]))) - { - foreach (var block in scc) - { - loopBlocks.Add(block); - } - } - } - return loopBlocks; - } - - private static List> FindStronglyConnectedComponents(List allBlocks) - { - int index = 0; - var stack = new Stack(); - var indexes = new Dictionary(); - var lowLinks = new Dictionary(); - var onStack = new HashSet(); - var sccList = new List>(); - - foreach (var block in allBlocks.Where(b => !indexes.ContainsKey(b))) - { - StrongConnect(block); - } - - return sccList; - - void StrongConnect(BasicBlock v) - { - indexes[v] = index; - lowLinks[v] = index; - index++; - stack.Push(v); - onStack.Add(v); - - foreach (var w in v.outBlocks) - { - if (!indexes.ContainsKey(w)) - { - StrongConnect(w); - lowLinks[v] = System.Math.Min(lowLinks[v], lowLinks[w]); - } - else if (onStack.Contains(w)) - { - lowLinks[v] = System.Math.Min(lowLinks[v], indexes[w]); - } - } - - if (lowLinks[v] == indexes[v]) - { - var scc = new List(); - BasicBlock w; - do - { - w = stack.Pop(); - onStack.Remove(w); - scc.Add(w); - } while (!w.Equals(v)); - sccList.Add(scc); - } - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs.meta deleted file mode 100644 index dabfa3b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 77c19c023bb7f77489998d994a3be1bd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs deleted file mode 100644 index 8a3c30d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs +++ /dev/null @@ -1,193 +0,0 @@ -using dnlib.DotNet; -using System; -using UnityEngine.Assertions; - -namespace Obfuz.Emit -{ - public class EncryptionServiceMetadataImporter - { - private readonly ModuleDef _module; - private readonly Type _encryptionServiceType; - - private IMethod _encryptBlock; - private IMethod _decryptBlock; - private IMethod _encryptInt; - private IMethod _decryptInt; - private IMethod _encryptLong; - private IMethod _decryptLong; - private IMethod _encryptFloat; - private IMethod _decryptFloat; - private IMethod _encryptDouble; - private IMethod _decryptDouble; - private IMethod _encryptString; - private IMethod _decryptString; - private IMethod _encryptBytes; - private IMethod _decryptBytes; - - private IMethod _decryptFromRvaInt; - private IMethod _decryptFromRvaLong; - private IMethod _decryptFromRvaFloat; - private IMethod _decryptFromRvaDouble; - private IMethod _decryptFromRvaString; - private IMethod _decryptFromRvaBytes; - - public IMethod EncryptBlock => _encryptBlock; - public IMethod DecryptBlock => _decryptBlock; - - public IMethod EncryptInt => _encryptInt; - public IMethod DecryptInt => _decryptInt; - public IMethod EncryptLong => _encryptLong; - public IMethod DecryptLong => _decryptLong; - public IMethod EncryptFloat => _encryptFloat; - public IMethod DecryptFloat => _decryptFloat; - public IMethod EncryptDouble => _encryptDouble; - public IMethod DecryptDouble => _decryptDouble; - public IMethod EncryptString => _encryptString; - public IMethod DecryptString => _decryptString; - public IMethod EncryptBytes => _encryptBytes; - public IMethod DecryptBytes => _decryptBytes; - - public IMethod DecryptFromRvaInt => _decryptFromRvaInt; - public IMethod DecryptFromRvaLong => _decryptFromRvaLong; - public IMethod DecryptFromRvaFloat => _decryptFromRvaFloat; - public IMethod DecryptFromRvaDouble => _decryptFromRvaDouble; - public IMethod DecryptFromRvaBytes => _decryptFromRvaBytes; - public IMethod DecryptFromRvaString => _decryptFromRvaString; - - public EncryptionServiceMetadataImporter(ModuleDef mod, Type encryptionServiceType) - { - _module = mod; - _encryptionServiceType = encryptionServiceType; - _encryptBlock = mod.Import(encryptionServiceType.GetMethod("EncryptBlock", new[] { typeof(byte[]), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptBlock); - _decryptBlock = mod.Import(encryptionServiceType.GetMethod("DecryptBlock", new[] { typeof(byte[]), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptBlock); - _encryptInt = mod.Import(encryptionServiceType.GetMethod("Encrypt", new[] { typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptInt); - _decryptInt = mod.Import(encryptionServiceType.GetMethod("Decrypt", new[] { typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptInt); - _encryptLong = mod.Import(encryptionServiceType.GetMethod("Encrypt", new[] { typeof(long), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptLong); - _decryptLong = mod.Import(encryptionServiceType.GetMethod("Decrypt", new[] { typeof(long), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptLong); - _encryptFloat = mod.Import(encryptionServiceType.GetMethod("Encrypt", new[] { typeof(float), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptFloat); - _decryptFloat = mod.Import(encryptionServiceType.GetMethod("Decrypt", new[] { typeof(float), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFloat); - _encryptDouble = mod.Import(encryptionServiceType.GetMethod("Encrypt", new[] { typeof(double), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptDouble); - _decryptDouble = mod.Import(encryptionServiceType.GetMethod("Decrypt", new[] { typeof(double), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptDouble); - _encryptString = mod.Import(encryptionServiceType.GetMethod("Encrypt", new[] { typeof(string), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptString); - _decryptString = mod.Import(encryptionServiceType.GetMethod("DecryptString", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptString); - _encryptBytes = mod.Import(encryptionServiceType.GetMethod("Encrypt", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_encryptBytes); - _decryptBytes = mod.Import(encryptionServiceType.GetMethod("Decrypt", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptBytes); - - _decryptFromRvaInt = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaInt", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFromRvaInt); - _decryptFromRvaLong = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaLong", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFromRvaLong); - _decryptFromRvaFloat = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaFloat", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFromRvaFloat); - _decryptFromRvaDouble = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaDouble", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFromRvaDouble); - _decryptFromRvaBytes = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaBytes", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFromRvaBytes); - _decryptFromRvaString = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaString", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) })); - Assert.IsNotNull(_decryptFromRvaString); - } - } - - public class DefaultMetadataImporter : GroupByModuleEntityBase - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private EncryptionScopeInfo _encryptionScope; - private EncryptionServiceMetadataImporter _defaultEncryptionServiceMetadataImporter; - - - private EncryptionServiceMetadataImporter _staticDefaultEncryptionServiceMetadataImporter; - private EncryptionServiceMetadataImporter _dynamicDefaultEncryptionServiceMetadataImporter; - - public DefaultMetadataImporter(EncryptionScopeProvider encryptionScopeProvider) - { - _encryptionScopeProvider = encryptionScopeProvider; - } - - public override void Init(ModuleDef mod) - { - _module = mod; - _encryptionScope = _encryptionScopeProvider.GetScope(mod); - var constUtilityType = typeof(ConstUtility); - - _castIntAsFloat = mod.Import(constUtilityType.GetMethod("CastIntAsFloat")); - Assert.IsNotNull(_castIntAsFloat, "CastIntAsFloat not found"); - _castLongAsDouble = mod.Import(constUtilityType.GetMethod("CastLongAsDouble")); - Assert.IsNotNull(_castLongAsDouble, "CastLongAsDouble not found"); - _castFloatAsInt = mod.Import(constUtilityType.GetMethod("CastFloatAsInt")); - Assert.IsNotNull(_castFloatAsInt, "CastFloatAsInt not found"); - _castDoubleAsLong = mod.Import(constUtilityType.GetMethod("CastDoubleAsLong")); - Assert.IsNotNull(_castDoubleAsLong, "CastDoubleAsLong not found"); - - _initializeArray = mod.Import(typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray", new[] { typeof(Array), typeof(RuntimeFieldHandle) })); - Assert.IsNotNull(_initializeArray); - - _staticDefaultEncryptionServiceMetadataImporter = new EncryptionServiceMetadataImporter(mod, typeof(EncryptionService)); - _dynamicDefaultEncryptionServiceMetadataImporter = new EncryptionServiceMetadataImporter(mod, typeof(EncryptionService)); - if (_encryptionScopeProvider.IsDynamicSecretAssembly(mod)) - { - _defaultEncryptionServiceMetadataImporter = _dynamicDefaultEncryptionServiceMetadataImporter; - } - else - { - _defaultEncryptionServiceMetadataImporter = _staticDefaultEncryptionServiceMetadataImporter; - } - } - - public EncryptionServiceMetadataImporter GetEncryptionServiceMetadataImporterOfModule(ModuleDef mod) - { - return _encryptionScopeProvider.IsDynamicSecretAssembly(mod) ? _dynamicDefaultEncryptionServiceMetadataImporter : _staticDefaultEncryptionServiceMetadataImporter; - } - - private ModuleDef _module; - private IMethod _castIntAsFloat; - private IMethod _castLongAsDouble; - private IMethod _castFloatAsInt; - private IMethod _castDoubleAsLong; - private IMethod _initializeArray; - - public IMethod CastIntAsFloat => _castIntAsFloat; - public IMethod CastLongAsDouble => _castLongAsDouble; - public IMethod CastFloatAsInt => _castFloatAsInt; - public IMethod CastDoubleAsLong => _castDoubleAsLong; - - public IMethod InitializedArrayMethod => _initializeArray; - - public IMethod EncryptBlock => _defaultEncryptionServiceMetadataImporter.EncryptBlock; - public IMethod DecryptBlock => _defaultEncryptionServiceMetadataImporter.DecryptBlock; - - public IMethod EncryptInt => _defaultEncryptionServiceMetadataImporter.EncryptInt; - public IMethod DecryptInt => _defaultEncryptionServiceMetadataImporter.DecryptInt; - public IMethod EncryptLong => _defaultEncryptionServiceMetadataImporter.EncryptLong; - public IMethod DecryptLong => _defaultEncryptionServiceMetadataImporter.DecryptLong; - public IMethod EncryptFloat => _defaultEncryptionServiceMetadataImporter.EncryptFloat; - public IMethod DecryptFloat => _defaultEncryptionServiceMetadataImporter.DecryptFloat; - public IMethod EncryptDouble => _defaultEncryptionServiceMetadataImporter.EncryptDouble; - public IMethod DecryptDouble => _defaultEncryptionServiceMetadataImporter.DecryptDouble; - public IMethod EncryptString => _defaultEncryptionServiceMetadataImporter.EncryptString; - public IMethod DecryptString => _defaultEncryptionServiceMetadataImporter.DecryptString; - public IMethod EncryptBytes => _defaultEncryptionServiceMetadataImporter.EncryptBytes; - public IMethod DecryptBytes => _defaultEncryptionServiceMetadataImporter.DecryptBytes; - - public IMethod DecryptFromRvaInt => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaInt; - public IMethod DecryptFromRvaLong => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaLong; - public IMethod DecryptFromRvaFloat => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaFloat; - public IMethod DecryptFromRvaDouble => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaDouble; - public IMethod DecryptFromRvaBytes => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaBytes; - public IMethod DecryptFromRvaString => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaString; - - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs.meta deleted file mode 100644 index c29c6a9..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 76438ce96146edd469872feada7857ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs deleted file mode 100644 index 860bdf8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs +++ /dev/null @@ -1,66 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Emit -{ - public interface IGroupByModuleEntity - { - void Init(ModuleDef mod); - } - - public abstract class GroupByModuleEntityBase : IGroupByModuleEntity - { - public abstract void Init(ModuleDef mod); - } - - public class GroupByModuleEntityManager - { - private readonly Dictionary<(ModuleDef, Type), IGroupByModuleEntity> _moduleEntityManagers = new Dictionary<(ModuleDef, Type), IGroupByModuleEntity>(); - - public T GetEntity(ModuleDef mod, Func creator = null) where T : IGroupByModuleEntity - { - var key = (mod, typeof(T)); - if (_moduleEntityManagers.TryGetValue(key, out var emitManager)) - { - return (T)emitManager; - } - else - { - T newEmitManager; - if (creator != null) - { - newEmitManager = creator(); - } - else - { - newEmitManager = (T)Activator.CreateInstance(typeof(T)); - } - newEmitManager.Init(mod); - _moduleEntityManagers[key] = newEmitManager; - return newEmitManager; - } - } - - public List GetEntities() where T: IGroupByModuleEntity - { - var managers = new List(); - foreach (var kv in _moduleEntityManagers) - { - if (kv.Key.Item2 == typeof(T)) - { - managers.Add((T)kv.Value); - } - } - return managers; - } - - public DefaultMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module, EncryptionScopeProvider encryptionScopeProvider) - { - return GetEntity(module, () => new DefaultMetadataImporter(encryptionScopeProvider)); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs.meta deleted file mode 100644 index a6b7602..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0bfcb2b5a87851f469d201fc8978c109 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM.meta deleted file mode 100644 index e8e65c1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: fec4187cc1b96d5439ff908bcecd988f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs deleted file mode 100644 index 19ded45..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Obfuz.EncryptionVM -{ - public class EncryptionInstructionWithOpCode - { - public readonly ushort code; - - public readonly IEncryptionInstruction function; - - public EncryptionInstructionWithOpCode(ushort code, IEncryptionInstruction function) - { - this.code = code; - this.function = function; - } - - public int Encrypt(int value, int[] secretKey, int salt) - { - return function.Encrypt(value, secretKey, salt); - } - - public int Decrypt(int value, int[] secretKey, int salt) - { - return function.Decrypt(value, secretKey, salt); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs.meta deleted file mode 100644 index cd63f21..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ca9bd232ed2583f4bb5f330886a329e6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs deleted file mode 100644 index 49808c4..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; - -namespace Obfuz.EncryptionVM -{ - public interface IEncryptionInstruction - { - int Encrypt(int value, int[] secretKey, int salt); - - int Decrypt(int value, int[] secretKey, int salt); - - void GenerateEncryptCode(List lines, string indent); - - void GenerateDecryptCode(List lines, string indent); - } - - public abstract class EncryptionInstructionBase : IEncryptionInstruction - { - public abstract int Encrypt(int value, int[] secretKey, int salt); - public abstract int Decrypt(int value, int[] secretKey, int salt); - - public abstract void GenerateEncryptCode(List lines, string indent); - public abstract void GenerateDecryptCode(List lines, string indent); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs.meta deleted file mode 100644 index ab7f3a6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f7b9d087de770a5488a9069ddf697c2f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions.meta deleted file mode 100644 index fa56988..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 981355cf75a9d234883b2a15c446f478 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs deleted file mode 100644 index 2681fff..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class AddInstruction : EncryptionInstructionBase - { - private readonly int _addValue; - private readonly int _opKeyIndex; - - public AddInstruction(int addValue, int opKeyIndex) - { - _addValue = addValue; - _opKeyIndex = opKeyIndex; - } - public override int Encrypt(int value, int[] secretKey, int salt) - { - return ((value + secretKey[_opKeyIndex]) ^ salt) + _addValue; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - return ((value - _addValue) ^ salt) - secretKey[_opKeyIndex]; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value = ((value + _secretKey[{_opKeyIndex}]) ^ salt) + {_addValue};"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"value = ((value - {_addValue}) ^ salt) - _secretKey[{_opKeyIndex}];"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs.meta deleted file mode 100644 index d1d2031..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6bdbdc5fd983f044a87e7b8ab8647aeb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs deleted file mode 100644 index 099a566..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class AddRotateXorInstruction : EncryptionInstructionBase - { - // x = x + p1 + secretKey[index1]; - // x = Rotate(x, p2) - // x = x ^ p3 ^ salt; - - private readonly int _addValue; - private readonly int _index1; - private readonly int _rotateBitNum; - private readonly int _xorValue; - - public AddRotateXorInstruction(int addValue, int index1, int rotateBitNum, int xorValue) - { - _addValue = addValue; - _index1 = index1; - _rotateBitNum = rotateBitNum; - _xorValue = xorValue; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - value += _addValue + secretKey[_index1]; - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - value = (int)(part1 | part2); - value ^= _xorValue ^ salt; - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - value ^= _xorValue ^ salt; - uint value2 = (uint)value >> _rotateBitNum; - uint part1 = (uint)value << (32 - _rotateBitNum); - value = (int)(value2 | part1); - value -= _addValue + secretKey[_index1]; - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value += {_addValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"uint value2 = (uint)value >> {_rotateBitNum};"); - lines.Add(indent + $"uint part1 = (uint)value << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(value2 | part1);"); - lines.Add(indent + $"value -= {_addValue} + _secretKey[{_index1}];"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs.meta deleted file mode 100644 index 6101fdb..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cda67c0dd0cadd24ea02c2988e34281a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs deleted file mode 100644 index cc453a7..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class AddXorRotateInstruction : EncryptionInstructionBase - { - // x = x + p1 + secretKey[index1]; - // x = x ^ p3 ^ salt; - // x = Rotate(x, p2) - - private readonly int _addValue; - private readonly int _index1; - private readonly int _rotateBitNum; - private readonly int _xorValue; - - public AddXorRotateInstruction(int addValue, int index1, int xorValue, int rotateBitNum) - { - _addValue = addValue; - _index1 = index1; - _rotateBitNum = rotateBitNum; - _xorValue = xorValue; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - value += _addValue + secretKey[_index1]; - value ^= _xorValue ^ salt; - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - value = (int)(part1 | part2); - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - uint value2 = (uint)value >> _rotateBitNum; - uint part1 = (uint)value << (32 - _rotateBitNum); - value = (int)(value2 | part1); - value ^= _xorValue ^ salt; - value -= _addValue + secretKey[_index1]; - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value += {_addValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"uint part1 = (uint)value >> {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"value -= {_addValue} + _secretKey[{_index1}];"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs.meta deleted file mode 100644 index abde16f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d806305e627be06469fb2d2c2cf98816 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs deleted file mode 100644 index 2d9dcd1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class BitRotateInstruction : EncryptionInstructionBase - { - private readonly int _rotateBitNum; - private readonly int _opKeyIndex; - - public BitRotateInstruction(int rotateBitNum, int opKeyIndex) - { - _rotateBitNum = rotateBitNum; - _opKeyIndex = opKeyIndex; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - return ((int)(part1 | part2) ^ secretKey[_opKeyIndex]) + salt; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - uint value2 = (uint)((value - salt) ^ secretKey[_opKeyIndex]); - uint part1 = value2 >> _rotateBitNum; - uint part2 = value2 << (32 - _rotateBitNum); - return (int)(part1 | part2); - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = ((int)(part1 | part2) ^ _secretKey[{_opKeyIndex}]) + salt;"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"uint value2 = (uint)((value - salt) ^ _secretKey[{_opKeyIndex}]);"); - lines.Add(indent + $"uint part1 = value2 >> {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = value2 << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs.meta deleted file mode 100644 index b4b0b9a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bccff31b9f07fcf4f821cee671f82caf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs deleted file mode 100644 index ed59848..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - - public class EncryptFunction : EncryptionInstructionBase - { - private readonly IEncryptionInstruction[] _instructions; - - public EncryptFunction(IEncryptionInstruction[] instructions) - { - _instructions = instructions; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - foreach (var instruction in _instructions) - { - value = instruction.Encrypt(value, secretKey, salt); - } - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - for (int i = _instructions.Length - 1; i >= 0; i--) - { - value = _instructions[i].Decrypt(value, secretKey, salt); - } - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - throw new NotImplementedException(); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - throw new NotImplementedException(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs.meta deleted file mode 100644 index 0ee2250..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: feafdb30f7b6d5143a89c7659bc16171 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs deleted file mode 100644 index 2635f5e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs +++ /dev/null @@ -1,64 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections.Generic; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class MultipleInstruction : EncryptionInstructionBase - { - private readonly int _multiValue; - private readonly int _revertMultiValue; - private readonly int _opKeyIndex; - - public MultipleInstruction(int addValue, int opKeyIndex) - { - _multiValue = addValue; - _opKeyIndex = opKeyIndex; - _revertMultiValue = (int)ModInverseOdd((uint)addValue); - Verify(); - } - - private void Verify() - { - int a = 1122334; - Assert.AreEqual(a, a * _multiValue * _revertMultiValue); - } - - public static uint ModInverseOdd(uint a) - { - if (a % 2 == 0) - throw new ArgumentException("Input must be an odd number.", nameof(a)); - - uint x = 1; // 初始解:x₀ = 1 (mod 2) - for (int i = 0; i < 5; i++) // 迭代5次(2^1 → 2^32) - { - int shift = 2 << i; // 当前模数为 2^(2^(i+1)) - ulong mod = 1UL << shift; // 使用 ulong 避免溢出 - ulong ax = (ulong)a * x; // 计算 a*x(64位避免截断) - ulong term = (2 - ax) % mod; - x = (uint)((x * term) % mod); // 更新 x,结果截断为 uint - } - return x; // 最终解为 x₅ mod 2^32 - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - return value * _multiValue + secretKey[_opKeyIndex] + salt; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - return (value - secretKey[_opKeyIndex] - salt) * _revertMultiValue; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value = value * {_multiValue} + _secretKey[{_opKeyIndex}] + salt;"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"value = (value - _secretKey[{_opKeyIndex}] - salt) * {_revertMultiValue};"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs.meta deleted file mode 100644 index 478ba08..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fd5fdfad694e0ae469bf6ca04c913220 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs deleted file mode 100644 index 75e4c5c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class MultipleRotateXorInstruction : EncryptionInstructionBase - { - // x = x * p1 + secretKey[index1]; - // x = Rotate(x, p2) - // x = x ^ p3 ^ salt; - - private readonly int _multipleValue; - private readonly int _revertMultipleValue; - private readonly int _index1; - private readonly int _rotateBitNum; - private readonly int _xorValue; - - public MultipleRotateXorInstruction(int multipleValue, int index1, int rotateBitNum, int xorValue) - { - _multipleValue = multipleValue; - _revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue); - _index1 = index1; - _rotateBitNum = rotateBitNum; - _xorValue = xorValue; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - value = value * _multipleValue + secretKey[_index1]; - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - value = (int)(part1 | part2); - value ^= _xorValue ^ salt; - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - value ^= _xorValue ^ salt; - uint value2 = (uint)value >> _rotateBitNum; - uint part1 = (uint)value << (32 - _rotateBitNum); - value = (int)(value2 | part1); - value = (value - secretKey[_index1]) * _revertMultipleValue; - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value = value * {_multipleValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"uint value2 = (uint)value >> {_rotateBitNum};"); - lines.Add(indent + $"uint part1 = (uint)value << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(value2 | part1);"); - lines.Add(indent + $"value = (value - _secretKey[{_index1}]) * {_revertMultipleValue};"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs.meta deleted file mode 100644 index 7f4e53a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e3c8b55b35ff1554489fa657a714f485 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs deleted file mode 100644 index 9733776..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class MultipleXorRotateInstruction : EncryptionInstructionBase - { - // x = x * p1 + secretKey[index1]; - // x = x ^ p3 ^ salt; - // x = Rotate(x, p2) - - private readonly int _multipleValue; - private readonly int _revertMultipleValue; - private readonly int _index1; - private readonly int _rotateBitNum; - private readonly int _xorValue; - - public MultipleXorRotateInstruction(int multipleValue, int index1, int xorValue, int rotateBitNum) - { - _multipleValue = multipleValue; - _revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue); - _index1 = index1; - _rotateBitNum = rotateBitNum; - _xorValue = xorValue; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - value = value * _multipleValue + secretKey[_index1]; - value ^= _xorValue ^ salt; - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - value = (int)(part1 | part2); - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - uint value2 = (uint)value >> _rotateBitNum; - uint part1 = (uint)value << (32 - _rotateBitNum); - value = (int)(value2 | part1); - value ^= _xorValue ^ salt; - value = (value - secretKey[_index1]) * _revertMultipleValue; - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value = value * {_multipleValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"uint value2 = (uint)value >> {_rotateBitNum};"); - lines.Add(indent + $"uint part1 = (uint)value << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(value2 | part1);"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"value = (value - _secretKey[{_index1}]) * {_revertMultipleValue};"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs.meta deleted file mode 100644 index 0e6a653..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: adc3dcde66795744fa4bdc753a2c599f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs deleted file mode 100644 index 10a9226..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class XorAddRotateInstruction : EncryptionInstructionBase - { - // x = x ^ p3 ^ salt; - // x = x + p1 + secretKey[index1]; - // x = Rotate(x, p2) - - private readonly int _addValue; - private readonly int _index1; - private readonly int _rotateBitNum; - private readonly int _xorValue; - - public XorAddRotateInstruction(int xorValue, int addValue, int index1, int rotateBitNum) - { - _addValue = addValue; - _index1 = index1; - _rotateBitNum = rotateBitNum; - _xorValue = xorValue; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - value ^= _xorValue ^ salt; - value += _addValue + secretKey[_index1]; - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - value = (int)(part1 | part2); - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - uint value2 = (uint)value >> _rotateBitNum; - uint part1 = (uint)value << (32 - _rotateBitNum); - value = (int)(value2 | part1); - value -= _addValue + secretKey[_index1]; - value ^= _xorValue ^ salt; - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"value += {_addValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"uint value2 = (uint)value >> {_rotateBitNum};"); - lines.Add(indent + $"uint part1 = (uint)value << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(value2 | part1);"); - lines.Add(indent + $"value -= {_addValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs.meta deleted file mode 100644 index d1a6d08..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ad8f4dd724d7ff845b0dd65861054d37 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs deleted file mode 100644 index ec5fb9f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class XorInstruction : EncryptionInstructionBase - { - private readonly int _xorValue; - private readonly int _opKeyIndex; - - public XorInstruction(int xorValue, int opKeyIndex) - { - _xorValue = xorValue; - _opKeyIndex = opKeyIndex; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - return ((value ^ secretKey[_opKeyIndex]) + salt) ^ _xorValue; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - return ((value ^ _xorValue) - salt) ^ secretKey[_opKeyIndex]; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value = ((value ^ _secretKey[{_opKeyIndex}]) + salt) ^ {_xorValue};"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"value = ((value ^ {_xorValue}) - salt) ^ _secretKey[{_opKeyIndex}];"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs.meta deleted file mode 100644 index e246896..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2f16dd868e4473b45bfa9daaf7fabaf8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs deleted file mode 100644 index 7a10395..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.EncryptionVM.Instructions -{ - public class XorMultipleRotateInstruction : EncryptionInstructionBase - { - // x = x ^ p3 ^ salt; - // x = x * p1 + secretKey[index1]; - // x = Rotate(x, p2) - - private readonly int _multipleValue; - private readonly int _revertMultipleValue; - private readonly int _index1; - private readonly int _rotateBitNum; - private readonly int _xorValue; - - public XorMultipleRotateInstruction(int xorValue, int multipleValue, int index1, int rotateBitNum) - { - _multipleValue = multipleValue; - _revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue); - _index1 = index1; - _rotateBitNum = rotateBitNum; - _xorValue = xorValue; - } - - public override int Encrypt(int value, int[] secretKey, int salt) - { - value ^= _xorValue ^ salt; - value = value * _multipleValue + secretKey[_index1]; - uint part1 = (uint)value << _rotateBitNum; - uint part2 = (uint)value >> (32 - _rotateBitNum); - value = (int)(part1 | part2); - return value; - } - - public override int Decrypt(int value, int[] secretKey, int salt) - { - uint value2 = (uint)value >> _rotateBitNum; - uint part1 = (uint)value << (32 - _rotateBitNum); - value = (int)(value2 | part1); - value = (value - secretKey[_index1]) * _revertMultipleValue; - value ^= _xorValue ^ salt; - return value; - } - - public override void GenerateEncryptCode(List lines, string indent) - { - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - lines.Add(indent + $"value = value * {_multipleValue} + _secretKey[{_index1}];"); - lines.Add(indent + $"uint part1 = (uint)value << {_rotateBitNum};"); - lines.Add(indent + $"uint part2 = (uint)value >> (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(part1 | part2);"); - } - - public override void GenerateDecryptCode(List lines, string indent) - { - lines.Add(indent + $"uint value2 = (uint)value >> {_rotateBitNum};"); - lines.Add(indent + $"uint part1 = (uint)value << (32 - {_rotateBitNum});"); - lines.Add(indent + $"value = (int)(value2 | part1);"); - lines.Add(indent + $"value = (value - _secretKey[{_index1}]) * {_revertMultipleValue};"); - lines.Add(indent + $"value ^= {_xorValue} ^ salt;"); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs.meta deleted file mode 100644 index e95af06..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3eb7e6d475cfc14459d3850c5964ba52 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs deleted file mode 100644 index 1ca1a59..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Obfuz.EncryptionVM -{ - public class VirtualMachine - { - public const int SecretKeyLength = 1024; - - public readonly int version; - public readonly string codeGenerationSecretKey; - public readonly EncryptionInstructionWithOpCode[] opCodes; - - public VirtualMachine(int version, string codeGenerationSecretKey, EncryptionInstructionWithOpCode[] opCodes) - { - this.codeGenerationSecretKey = codeGenerationSecretKey; - this.opCodes = opCodes; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs.meta deleted file mode 100644 index e932d33..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c6970e037654dcb49912783a40f3e1ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs deleted file mode 100644 index b05f000..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs +++ /dev/null @@ -1,207 +0,0 @@ -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.EncryptionVM -{ - public class VirtualMachineCodeGenerator - { - private readonly int _opCodeCount; - private readonly int _opCodeBits; - private readonly VirtualMachine _vm; - - public VirtualMachineCodeGenerator(string vmCodeGenerateSecretKey, int opCodeCount) - { - _opCodeCount = opCodeCount; - _opCodeBits = EncryptionUtil.GetBitCount(opCodeCount - 1); - _vm = new VirtualMachineCreator(vmCodeGenerateSecretKey).CreateVirtualMachine(opCodeCount); - } - - public VirtualMachineCodeGenerator(VirtualMachine vm) - { - _opCodeCount = vm.opCodes.Length; - _opCodeBits = EncryptionUtil.GetBitCount(_opCodeCount - 1); - _vm = vm; - } - - - public bool ValidateMatch(string outputFile) - { - if (!File.Exists(outputFile)) - { - return false; - } - string oldCode = NormalizeText(File.ReadAllText(outputFile, Encoding.UTF8)); - string newCode = NormalizeText(GenerateCode()); - return oldCode == newCode; - } - - private static string NormalizeText(string input) - { - return Regex.Replace(input, @"\s+", string.Empty); - } - - public void Generate(string outputFile) - { - FileUtil.CreateParentDir(outputFile); - - string code = GenerateCode(); - - File.WriteAllText(outputFile, code, Encoding.UTF8); - Debug.Log($"Generate EncryptionVM code to {outputFile}"); - UnityEditor.AssetDatabase.Refresh(); - } - - private string GenerateCode() - { - var lines = new List(); - AppendHeader(lines); - AppendEncryptCodes(lines); - AppendDecryptCodes(lines); - AppendTailer(lines); - return string.Join("\n", lines); - } - - private void AppendEncryptCodes(List lines) - { - lines.Add(@" - private int ExecuteEncrypt(int value, int opCode, int salt) - { - switch (opCode) - {"); - foreach (var opCode in _vm.opCodes) - { - lines.Add($@" case {opCode.code}: - {{ - // {opCode.function.GetType().Name}"); - AppendEncryptCode(lines, opCode.function); - lines.Add(@" return value; - }"); - } - - lines.Add(@" - default: - throw new System.Exception($""Invalid opCode:{opCode}""); - } - }"); - } - - private void AppendDecryptCodes(List lines) - { - lines.Add(@" - private int ExecuteDecrypt(int value, int opCode, int salt) - { - switch (opCode) - {"); - foreach (var opCode in _vm.opCodes) - { - lines.Add($@" case {opCode.code}: - {{ - // {opCode.function.GetType().Name}"); - AppendDecryptCode(lines, opCode.function); - lines.Add(@" return value; - }"); - } - - lines.Add(@" - default: - throw new System.Exception($""Invalid opCode:{opCode}""); - } - }"); - } - - private void AppendHeader(List lines) - { - - lines.Add($"/// This file is auto-generated by Obfuz. Do not modify it."); - lines.Add($"///"); - //lines.Add($"/// Created Time: {DateTime.Now}"); - - lines.Add($"/// Version: {_vm.version}"); - lines.Add($"/// SecretKey: {_vm.codeGenerationSecretKey}"); - lines.Add($"/// OpCodeCount: {_vm.opCodes.Length}"); - - lines.Add(@" -namespace Obfuz.EncryptionVM -{ - public class GeneratedEncryptionVirtualMachine : Obfuz.EncryptorBase - {"); - lines.Add($@" - private const int kOpCodeBits = {_opCodeBits}; - - private const int kOpCodeCount = {_opCodeCount}; - - private const int kOpCodeMask = {_opCodeCount - 1}; -"); - lines.Add(@" - - private readonly int[] _secretKey; - - public GeneratedEncryptionVirtualMachine(byte[] secretKey) - { - this._secretKey = ConvertToIntKey(secretKey); - } - - public override int OpCodeCount => kOpCodeCount; - - public override int Encrypt(int value, int opts, int salt) - { - uint uopts = (uint)opts; - uint revertOps = 0; - while (uopts != 0) - { - uint opCode = uopts & kOpCodeMask; - revertOps <<= kOpCodeBits; - revertOps |= opCode; - uopts >>= kOpCodeBits; - } - - while (revertOps != 0) - { - uint opCode = revertOps & kOpCodeMask; - value = ExecuteEncrypt(value, (int)opCode, salt); - revertOps >>= kOpCodeBits; - } - return value; - } - - public override int Decrypt(int value, int opts, int salt) - { - uint uopts = (uint)opts; - while (uopts != 0) - { - uint opCode = uopts & kOpCodeMask; - value = ExecuteDecrypt(value, (int)opCode, salt); - uopts >>= kOpCodeBits; - } - return value; - } -"); - } - - private void AppendTailer(List lines) - { - lines.Add(@" - } -} - -"); - } - - private void AppendEncryptCode(List lines, IEncryptionInstruction instruction) - { - instruction.GenerateEncryptCode(lines, " "); - } - - private void AppendDecryptCode(List lines, IEncryptionInstruction instruction) - { - instruction.GenerateDecryptCode(lines, " "); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs.meta deleted file mode 100644 index 956402c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2246e9d3369eb3c45bc19ae0748d76ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs deleted file mode 100644 index 8035ad0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs +++ /dev/null @@ -1,71 +0,0 @@ -using NUnit.Framework; -using Obfuz.EncryptionVM.Instructions; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using UnityEngine.Assertions; -using UnityEngine.UIElements; - -namespace Obfuz.EncryptionVM -{ - public class VirtualMachineCreator - { - private readonly string _vmGenerationSecretKey; - private readonly IRandom _random; - - public const int CodeGenerationSecretKeyLength = 1024; - - public const int VirtualMachineVersion = 1; - - public VirtualMachineCreator(string vmGenerationSecretKey) - { - _vmGenerationSecretKey = vmGenerationSecretKey; - byte[] byteGenerationSecretKey = KeyGenerator.GenerateKey(vmGenerationSecretKey, CodeGenerationSecretKeyLength); - int[] intGenerationSecretKey = KeyGenerator.ConvertToIntKey(byteGenerationSecretKey); - _random = new RandomWithKey(intGenerationSecretKey, 0); - } - - private readonly List> _instructionCreators = new List> - { - (r, len) => new AddInstruction(r.NextInt(), r.NextInt(len)), - (r, len) => new XorInstruction(r.NextInt(), r.NextInt(len)), - (r, len) => new BitRotateInstruction(r.NextInt(32), r.NextInt(len)), - (r, len) => new MultipleInstruction(r.NextInt() | 0x1, r.NextInt(len)), - (r, len) => new AddRotateXorInstruction(r.NextInt(), r.NextInt(len), r.NextInt(32), r.NextInt()), - (r, len) => new AddXorRotateInstruction(r.NextInt(), r.NextInt(len), r.NextInt(), r.NextInt(32)), - (r, len) => new XorAddRotateInstruction(r.NextInt(), r.NextInt(), r.NextInt(len), r.NextInt(32)), - (r, len) => new MultipleRotateXorInstruction(r.NextInt() | 0x1, r.NextInt(len), r.NextInt(32), r.NextInt()), - (r, len) => new MultipleXorRotateInstruction(r.NextInt() | 0x1, r.NextInt(len), r.NextInt(), r.NextInt(32)), - (r, len) => new XorMultipleRotateInstruction(r.NextInt(), r.NextInt() | 0x1, r.NextInt(len), r.NextInt(32)), - }; - - private IEncryptionInstruction CreateRandomInstruction(int intSecretKeyLength) - { - return _instructionCreators[_random.NextInt(_instructionCreators.Count)](_random, intSecretKeyLength); - } - - private EncryptionInstructionWithOpCode CreateEncryptOpCode(ushort code) - { - IEncryptionInstruction inst = CreateRandomInstruction(VirtualMachine.SecretKeyLength / sizeof(int)); - return new EncryptionInstructionWithOpCode(code, inst); - } - - public VirtualMachine CreateVirtualMachine(int opCodeCount) - { - if (opCodeCount < 64) - { - throw new System.Exception("OpCode count should be >= 64"); - } - if ((opCodeCount & (opCodeCount - 1)) != 0) - { - throw new System.Exception("OpCode count should be power of 2"); - } - var opCodes = new EncryptionInstructionWithOpCode[opCodeCount]; - for (int i = 0; i < opCodes.Length; i++) - { - opCodes[i] = CreateEncryptOpCode((ushort)i); - } - return new VirtualMachine(VirtualMachineVersion, _vmGenerationSecretKey, opCodes); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs.meta deleted file mode 100644 index 3124bb7..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 77d95ff5cf0b3aa4e96a055e37c381ba -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs deleted file mode 100644 index a8e25c8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs +++ /dev/null @@ -1,96 +0,0 @@ -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Runtime.CompilerServices; -using System.Text; -using UnityEngine; -using UnityEngine.Assertions; -using UnityEngine.UIElements; - -namespace Obfuz.EncryptionVM -{ - - public class VirtualMachineSimulator : EncryptorBase - { - private readonly EncryptionInstructionWithOpCode[] _opCodes; - private readonly int[] _secretKey; - - public override int OpCodeCount => _opCodes.Length; - - public VirtualMachineSimulator(VirtualMachine vm, byte[] byteSecretKey) - { - _opCodes = vm.opCodes; - _secretKey = KeyGenerator.ConvertToIntKey(byteSecretKey); - - VerifyInstructions(); - } - - private void VerifyInstructions() - { - int value = 0x11223344; - for (int i = 0; i < _opCodes.Length; i++) - { - int encryptedValue = _opCodes[i].Encrypt(value, _secretKey, i); - int decryptedValue = _opCodes[i].Decrypt(encryptedValue, _secretKey, i); - //Debug.Log($"instruction type:{_opCodes[i].function.GetType()}"); - Assert.AreEqual(value, decryptedValue); - } - - int ops = 11223344; - int salt = 789; - Assert.AreEqual(1, Decrypt(Encrypt(1, ops, salt), ops, salt)); - Assert.AreEqual(1L, Decrypt(Encrypt(1L, ops, salt), ops, salt)); - Assert.AreEqual(1.0f, Decrypt(Encrypt(1.0f, ops, salt), ops, salt)); - Assert.AreEqual(1.0, Decrypt(Encrypt(1.0, ops, salt), ops, salt)); - - byte[] strBytes = Encrypt("abcdef", ops, salt); - Assert.AreEqual("abcdef", DecryptString(strBytes, 0, strBytes.Length, ops, salt)); - var arr = new byte[100]; - for (int i = 0; i < arr.Length ; i++) - { - arr[i] = (byte)i; - } - EncryptBlock(arr, ops, salt); - DecryptBlock(arr, ops, salt); - for (int i = 0; i < arr.Length; i++) - { - Assert.AreEqual(i, arr[i]); - } - } - - private List DecodeOps(uint ops) - { - var codes = new List(); - while (ops != 0) - { - uint code = ops % (uint)_opCodes.Length; - codes.Add(code); - ops /= (uint)_opCodes.Length; - } - return codes; - } - - public override int Encrypt(int value, int ops, int salt) - { - var codes = DecodeOps((uint)ops); - for (int i = codes.Count - 1; i >= 0; i--) - { - var opCode = _opCodes[codes[i]]; - value = opCode.Encrypt(value, _secretKey, salt); - } - return value; - } - - public override int Decrypt(int value, int ops, int salt) - { - var codes = DecodeOps((uint)ops); - foreach (var code in codes) - { - var opCode = _opCodes[code]; - value = opCode.Decrypt(value, _secretKey, salt); - } - return value; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs.meta deleted file mode 100644 index 532a498..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4f86f4d6faf49764a915d5c675091375 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs deleted file mode 100644 index 16d875f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Obfuz.ObfusPasses; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - public interface IObfuscationPass - { - ObfuscationPassType Type { get; } - - void Start(); - - void Stop(); - - void Process(); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs.meta deleted file mode 100644 index cd501ad..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b7003f9503025794b8aa775d9ade335c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses.meta deleted file mode 100644 index ed7f92c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 120b2dcffd582e84dbb92003240824d1 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs deleted file mode 100644 index 916a9ef..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs +++ /dev/null @@ -1,87 +0,0 @@ -using dnlib.DotNet.Emit; -using dnlib.DotNet; -using System.Collections.Generic; -using System.Linq; -using Obfuz.Emit; - -namespace Obfuz.ObfusPasses -{ - public abstract class BasicBlockObfuscationPassBase : ObfuscationPassBase - { - protected abstract bool NeedObfuscateMethod(MethodDef method); - - public override void Process() - { - var ctx = ObfuscationPassContext.Current; - ObfuscationMethodWhitelist whiteList = ctx.whiteList; - ConfigurablePassPolicy passPolicy = ctx.passPolicy; - foreach (ModuleDef mod in ctx.modulesToObfuscate) - { - if (whiteList.IsInWhiteList(mod) || !Support(passPolicy.GetAssemblyObfuscationPasses(mod))) - { - continue; - } - // ToArray to avoid modify list exception - foreach (TypeDef type in mod.GetTypes().ToArray()) - { - if (whiteList.IsInWhiteList(type) || !Support(passPolicy.GetTypeObfuscationPasses(type))) - { - continue; - } - // ToArray to avoid modify list exception - foreach (MethodDef method in type.Methods.ToArray()) - { - if (!method.HasBody || ctx.whiteList.IsInWhiteList(method) || !Support(passPolicy.GetMethodObfuscationPasses(method)) || !NeedObfuscateMethod(method)) - { - continue; - } - // TODO if isGeneratedBy Obfuscator, continue - ObfuscateData(method); - } - } - } - } - - - protected abstract bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, BasicBlock block, int instructionIndex, - IList globalInstructions, List outputInstructions, List totalFinalInstructions); - - private void ObfuscateData(MethodDef method) - { - BasicBlockCollection bbc = new BasicBlockCollection(method); - - IList instructions = method.Body.Instructions; - - var outputInstructions = new List(); - var totalFinalInstructions = new List(); - for (int i = 0; i < instructions.Count; i++) - { - Instruction inst = instructions[i]; - BasicBlock block = bbc.GetBasicBlockByInstruction(inst); - outputInstructions.Clear(); - if (TryObfuscateInstruction(method, inst, block, i, instructions, outputInstructions, totalFinalInstructions)) - { - // current instruction may be the target of control flow instruction, so we can't remove it directly. - // we replace it with nop now, then remove it in CleanUpInstructionPass - inst.OpCode = outputInstructions[0].OpCode; - inst.Operand = outputInstructions[0].Operand; - totalFinalInstructions.Add(inst); - for (int k = 1; k < outputInstructions.Count; k++) - { - totalFinalInstructions.Add(outputInstructions[k]); - } - } - else - { - totalFinalInstructions.Add(inst); - } - } - - instructions.Clear(); - foreach (var obInst in totalFinalInstructions) - { - instructions.Add(obInst); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs.meta deleted file mode 100644 index 027d02b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ae83aaf003665614092aabceabff3cf8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus.meta deleted file mode 100644 index a5ed333..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: cf68e45551825c547b137f6e5189937e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs deleted file mode 100644 index 9b32359..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs +++ /dev/null @@ -1,92 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Utils; -using Obfuz.Emit; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using UnityEngine.Assertions; -using Obfuz.Settings; - -namespace Obfuz.ObfusPasses.CallObfus -{ - public class CallObfusPass : BasicBlockObfuscationPassBase - { - private readonly List _configFiles; - private readonly int _obfuscationLevel; - private IObfuscator _dynamicProxyObfuscator; - private IObfuscationPolicy _dynamicProxyPolicy; - - public override ObfuscationPassType Type => ObfuscationPassType.CallObfus; - - public CallObfusPass(CallObfuscationSettings settings) - { - _configFiles = settings.ruleFiles.ToList(); - _obfuscationLevel = settings.obfuscationLevel; - } - - public override void Stop() - { - _dynamicProxyObfuscator.Done(); - } - - public override void Start() - { - var ctx = ObfuscationPassContext.Current; - _dynamicProxyObfuscator = new DefaultCallProxyObfuscator(ctx.encryptionScopeProvider, ctx.constFieldAllocator, ctx.moduleEntityManager, _obfuscationLevel); - _dynamicProxyPolicy = new ConfigurableObfuscationPolicy(ctx.assembliesToObfuscate, _configFiles); - } - - protected override bool NeedObfuscateMethod(MethodDef method) - { - return _dynamicProxyPolicy.NeedObfuscateCallInMethod(method); - } - - protected override bool TryObfuscateInstruction(MethodDef callerMethod, Instruction inst, BasicBlock block, - int instructionIndex, IList globalInstructions, List outputInstructions, List totalFinalInstructions) - { - IMethod calledMethod = inst.Operand as IMethod; - if (calledMethod == null || !calledMethod.IsMethod) - { - return false; - } - if (MetaUtil.ContainsContainsGenericParameter(calledMethod)) - { - return false; - } - - bool callVir; - switch (inst.OpCode.Code) - { - case Code.Call: - { - callVir = false; - break; - } - case Code.Callvirt: - { - if (instructionIndex > 0 && globalInstructions[instructionIndex - 1].OpCode.Code == Code.Constrained) - { - return false; - } - callVir = true; - break; - } - default: return false; - } - - if (!_dynamicProxyPolicy.NeedObfuscateCalledMethod(callerMethod, calledMethod, callVir, block.inLoop)) - { - return false; - } - - ObfuscationCachePolicy cachePolicy = _dynamicProxyPolicy.GetMethodObfuscationCachePolicy(callerMethod); - bool cachedCallIndex = block.inLoop ? cachePolicy.cacheInLoop : cachePolicy.cacheNotInLoop; - _dynamicProxyObfuscator.Obfuscate(callerMethod, calledMethod, callVir, cachedCallIndex, outputInstructions); - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs.meta deleted file mode 100644 index b15eb81..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 112178b770868274fb8119a4997a3420 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs deleted file mode 100644 index 1164db6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs +++ /dev/null @@ -1,293 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Editor; -using Obfuz.Emit; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using MethodImplAttributes = dnlib.DotNet.MethodImplAttributes; -using TypeAttributes = dnlib.DotNet.TypeAttributes; - -namespace Obfuz.ObfusPasses.CallObfus -{ - public struct ProxyCallMethodData - { - public readonly MethodDef proxyMethod; - public readonly int encryptOps; - public readonly int salt; - public readonly int encryptedIndex; - public readonly int index; - - public ProxyCallMethodData(MethodDef proxyMethod, int encryptOps, int salt, int encryptedIndex, int index) - { - this.proxyMethod = proxyMethod; - this.encryptOps = encryptOps; - this.salt = salt; - this.encryptedIndex = encryptedIndex; - this.index = index; - } - } - - class ModuleCallProxyAllocator : IGroupByModuleEntity - { - private ModuleDef _module; - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly int _encryptionLevel; - - private EncryptionScopeInfo _encryptionScope; - private bool _done; - - class MethodKey : IEquatable - { - public readonly IMethod _method; - public readonly bool _callVir; - private readonly int _hashCode; - - public MethodKey(IMethod method, bool callVir) - { - _method = method; - _callVir = callVir; - _hashCode = HashUtil.CombineHash(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method), callVir ? 1 : 0); - } - - public override int GetHashCode() - { - return _hashCode; - } - - public bool Equals(MethodKey other) - { - return MethodEqualityComparer.CompareDeclaringTypes.Equals(_method, other._method) && _callVir == other._callVir; - } - } - - class MethodProxyInfo - { - public MethodDef proxyMethod; - - public int index; - public int encryptedOps; - public int salt; - public int encryptedIndex; - } - - private readonly Dictionary _methodProxys = new Dictionary(); - - - const int maxProxyMethodPerDispatchMethod = 1000; - - class CallInfo - { - public IMethod method; - public bool callVir; - } - - class DispatchMethodInfo - { - public MethodDef methodDef; - public List methods = new List(); - } - - private readonly Dictionary> _dispatchMethods = new Dictionary>(SignatureEqualityComparer.Instance); - - - private TypeDef _proxyTypeDef; - - public ModuleCallProxyAllocator(EncryptionScopeProvider encryptionScopeProvider, int encryptionLevel) - { - _encryptionScopeProvider = encryptionScopeProvider; - _encryptionLevel = encryptionLevel; - } - - public void Init(ModuleDef mod) - { - _module = mod; - _encryptionScope = _encryptionScopeProvider.GetScope(mod); - } - - private TypeDef CreateProxyTypeDef() - { - var typeDef = new TypeDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}ProxyCall", _module.CorLibTypes.Object.ToTypeDefOrRef()); - typeDef.Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed; - _module.EnableTypeDefFindCache = false; - _module.Types.Add(typeDef); - _module.EnableTypeDefFindCache = true; - return typeDef; - } - - private MethodDef CreateDispatchMethodInfo(MethodSig methodSig) - { - if (_proxyTypeDef == null) - { - _proxyTypeDef = CreateProxyTypeDef(); - } - MethodDef methodDef = new MethodDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}ProxyCall$Dispatch${_proxyTypeDef.Methods.Count}", methodSig, - MethodImplAttributes.IL | MethodImplAttributes.Managed, - MethodAttributes.Static | MethodAttributes.Public); - methodDef.DeclaringType = _proxyTypeDef; - return methodDef; - } - - private MethodSig CreateDispatchMethodSig(IMethod method) - { - MethodSig methodSig = MetaUtil.ToSharedMethodSig(_module.CorLibTypes, MetaUtil.GetInflatedMethodSig(method)); - //MethodSig methodSig = MetaUtil.GetInflatedMethodSig(method).Clone(); - //methodSig.Params - switch (MetaUtil.GetThisArgType(method)) - { - case ThisArgType.Class: - { - methodSig.Params.Insert(0, _module.CorLibTypes.Object); - break; - } - case ThisArgType.ValueType: - { - methodSig.Params.Insert(0, _module.CorLibTypes.IntPtr); - break; - } - } - // extra param for index - methodSig.Params.Add(_module.CorLibTypes.Int32); - return MethodSig.CreateStatic(methodSig.RetType, methodSig.Params.ToArray()); - } - - private int GenerateSalt(IRandom random) - { - return random.NextInt(); - } - - private int GenerateEncryptOps(IRandom random) - { - return EncryptionUtil.GenerateEncryptionOpCodes(random, _encryptionScope.encryptor, _encryptionLevel); - } - - private DispatchMethodInfo GetDispatchMethod(IMethod method) - { - MethodSig methodSig = CreateDispatchMethodSig(method); - if (!_dispatchMethods.TryGetValue(methodSig, out var dispatchMethods)) - { - dispatchMethods = new List(); - _dispatchMethods.Add(methodSig, dispatchMethods); - } - if (dispatchMethods.Count == 0 || dispatchMethods.Last().methods.Count >= maxProxyMethodPerDispatchMethod) - { - var newDispatchMethodInfo = new DispatchMethodInfo - { - methodDef = CreateDispatchMethodInfo(methodSig), - }; - dispatchMethods.Add(newDispatchMethodInfo); - } - return dispatchMethods.Last(); - } - - private IRandom CreateRandomForMethod(IMethod method, bool callVir) - { - int seed = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method); - return _encryptionScope.localRandomCreator(seed); - } - - public ProxyCallMethodData Allocate(IMethod method, bool callVir) - { - if (_done) - { - throw new Exception("can't Allocate after done"); - } - var key = new MethodKey(method, callVir); - if (!_methodProxys.TryGetValue(key, out var proxyInfo)) - { - var methodDispatcher = GetDispatchMethod(method); - - int index = methodDispatcher.methods.Count; - IRandom localRandom = CreateRandomForMethod(method, callVir); - int encryptOps = GenerateEncryptOps(localRandom); - int salt = GenerateSalt(localRandom); - int encryptedIndex = _encryptionScope.encryptor.Encrypt(index, encryptOps, salt); - proxyInfo = new MethodProxyInfo() - { - proxyMethod = methodDispatcher.methodDef, - index = index, - encryptedOps = encryptOps, - salt = salt, - encryptedIndex = encryptedIndex, - }; - methodDispatcher.methods.Add(new CallInfo { method = method, callVir = callVir}); - _methodProxys.Add(key, proxyInfo); - } - return new ProxyCallMethodData(proxyInfo.proxyMethod, proxyInfo.encryptedOps, proxyInfo.salt, proxyInfo.encryptedIndex, proxyInfo.index); - } - - public void Done() - { - if (_done) - { - throw new Exception("Already done"); - } - _done = true; - - foreach (DispatchMethodInfo dispatchMethod in _dispatchMethods.Values.SelectMany(ms => ms)) - { - var methodDef = dispatchMethod.methodDef; - var methodSig = methodDef.MethodSig; - - - var body = new CilBody(); - methodDef.Body = body; - var ins = body.Instructions; - - foreach (Parameter param in methodDef.Parameters) - { - ins.Add(Instruction.Create(OpCodes.Ldarg, param)); - } - - var switchCases = new List(); - var switchInst = Instruction.Create(OpCodes.Switch, switchCases); - ins.Add(switchInst); - var ret = Instruction.Create(OpCodes.Ret); - foreach (CallInfo ci in dispatchMethod.methods) - { - var callTargetMethod = Instruction.Create(ci.callVir ? OpCodes.Callvirt : OpCodes.Call, ci.method); - switchCases.Add(callTargetMethod); - ins.Add(callTargetMethod); - ins.Add(Instruction.Create(OpCodes.Br, ret)); - } - ins.Add(ret); - } - } - } - - public class CallProxyAllocator - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private GroupByModuleEntityManager _moduleEntityManager; - private readonly int _encryptionLevel; - - public CallProxyAllocator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager, int encryptionLevel) - { - _encryptionScopeProvider = encryptionScopeProvider; - _moduleEntityManager = moduleEntityManager; - _encryptionLevel = encryptionLevel; - } - - private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod) - { - return _moduleEntityManager.GetEntity(mod, () => new ModuleCallProxyAllocator(_encryptionScopeProvider, _encryptionLevel)); - } - - public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir) - { - ModuleCallProxyAllocator allocator = GetModuleAllocator(mod); - return allocator.Allocate(method, callVir); - } - - public void Done() - { - foreach (var allocator in _moduleEntityManager.GetEntities()) - { - allocator.Done(); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs.meta deleted file mode 100644 index a6a06f8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 16b960455f093854d927c2dbd47a4826 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs deleted file mode 100644 index 4deb16a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs +++ /dev/null @@ -1,411 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Conf; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using UnityEngine; - -namespace Obfuz.ObfusPasses.CallObfus -{ - public class ConfigurableObfuscationPolicy : ObfuscationPolicyBase - { - class WhiteListAssembly - { - public string name; - public NameMatcher nameMatcher; - public bool? obfuscate; - public List types = new List(); - } - - class WhiteListType - { - public string name; - public NameMatcher nameMatcher; - public bool? obfuscate; - public List methods = new List(); - } - - class WhiteListMethod - { - public string name; - public NameMatcher nameMatcher; - public bool? obfuscate; - } - - class ObfuscationRule : IRule - { - public bool? disableObfuscation; - public bool? obfuscateCallInLoop; - public bool? cacheCallIndexInLoop; - public bool? cacheCallIndexNotLoop; - - public void InheritParent(ObfuscationRule parentRule) - { - if (disableObfuscation == null) - { - disableObfuscation = parentRule.disableObfuscation; - } - if (obfuscateCallInLoop == null) - { - obfuscateCallInLoop = parentRule.obfuscateCallInLoop; - } - if (cacheCallIndexInLoop == null) - { - cacheCallIndexInLoop = parentRule.cacheCallIndexInLoop; - } - if (cacheCallIndexNotLoop == null) - { - cacheCallIndexNotLoop = parentRule.cacheCallIndexNotLoop; - } - } - } - - class AssemblySpec : AssemblyRuleBase - { - } - - class TypeSpec : TypeRuleBase - { - } - - class MethodSpec : MethodRuleBase - { - - } - - private static readonly ObfuscationRule s_default = new ObfuscationRule() - { - disableObfuscation = false, - obfuscateCallInLoop = true, - cacheCallIndexInLoop = true, - cacheCallIndexNotLoop = false, - }; - - private readonly XmlAssemblyTypeMethodRuleParser _configParser; - - private ObfuscationRule _global; - private readonly List _whiteListAssemblies = new List(); - - private readonly Dictionary _whiteListMethodCache = new Dictionary(MethodEqualityComparer.CompareDeclaringTypes); - private readonly Dictionary _methodRuleCache = new Dictionary(); - - public ConfigurableObfuscationPolicy(List toObfuscatedAssemblyNames, List xmlConfigFiles) - { - _configParser = new XmlAssemblyTypeMethodRuleParser(toObfuscatedAssemblyNames, - ParseObfuscationRule, ParseGlobalElement); - LoadConfigs(xmlConfigFiles); - } - - private void LoadConfigs(List configFiles) - { - _configParser.LoadConfigs(configFiles); - - if (_global == null) - { - _global = s_default; - } - else - { - _global.InheritParent(s_default); - } - _configParser.InheritParentRules(_global); - InheritWhitelistRules(); - } - - private void InheritWhitelistRules() - { - foreach (var ass in _whiteListAssemblies) - { - foreach (var type in ass.types) - { - if (type.obfuscate == null) - { - type.obfuscate = ass.obfuscate; - } - foreach (var method in type.methods) - { - if (method.obfuscate == null) - { - method.obfuscate = type.obfuscate; - } - } - } - } - } - - private void ParseGlobalElement(string configFile, XmlElement ele) - { - switch (ele.Name) - { - case "global": _global = ParseObfuscationRule(configFile, ele); break; - case "whitelist": ParseWhitelist(ele); break; - default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); - } - } - - private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele) - { - var rule = new ObfuscationRule(); - if (ele.HasAttribute("disableObfuscation")) - { - rule.disableObfuscation = ConfigUtil.ParseBool(ele.GetAttribute("disableObfuscation")); - } - if (ele.HasAttribute("obfuscateCallInLoop")) - { - rule.obfuscateCallInLoop = ConfigUtil.ParseBool(ele.GetAttribute("obfuscateCallInLoop")); - } - if (ele.HasAttribute("cacheCallIndexInLoop")) - { - rule.cacheCallIndexInLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheCallIndexInLoop")); - } - if (ele.HasAttribute("cacheCallIndexNotLoop")) - { - rule.cacheCallIndexNotLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheCallIndexNotLoop")); - } - return rule; - } - - private void ParseWhitelist(XmlElement ruleEle) - { - foreach (XmlNode xmlNode in ruleEle.ChildNodes) - { - if (!(xmlNode is XmlElement childEle)) - { - continue; - } - switch (childEle.Name) - { - case "assembly": - { - var ass = ParseWhiteListAssembly(childEle); - _whiteListAssemblies.Add(ass); - break; - } - default: throw new Exception($"Invalid xml file, unknown node {childEle.Name}"); - } - } - } - - private WhiteListAssembly ParseWhiteListAssembly(XmlElement element) - { - var ass = new WhiteListAssembly(); - ass.name = element.GetAttribute("name"); - ass.nameMatcher = new NameMatcher(ass.name); - - ass.obfuscate = ConfigUtil.ParseNullableBool(element.GetAttribute("obfuscate")) ?? false; - - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "type": - ass.types.Add(ParseWhiteListType(ele)); - break; - default: - throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - return ass; - } - - private WhiteListType ParseWhiteListType(XmlElement element) - { - var type = new WhiteListType(); - type.name = element.GetAttribute("name"); - type.nameMatcher = new NameMatcher(type.name); - type.obfuscate = ConfigUtil.ParseNullableBool(element.GetAttribute("obfuscate")); - - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement ele)) - { - continue; - } - switch (ele.Name) - { - case "method": - { - type.methods.Add(ParseWhiteListMethod(ele)); - break; - } - default: throw new Exception($"Invalid xml file, unknown node {ele.Name}"); - } - } - - return type; - } - - private WhiteListMethod ParseWhiteListMethod(XmlElement element) - { - var method = new WhiteListMethod(); - method.name = element.GetAttribute("name"); - method.nameMatcher = new NameMatcher(method.name); - method.obfuscate = ConfigUtil.ParseNullableBool(element.GetAttribute("obfuscate")); - return method; - } - - private ObfuscationRule GetMethodObfuscationRule(MethodDef method) - { - if (!_methodRuleCache.TryGetValue(method, out var rule)) - { - rule = _configParser.GetMethodRule(method, s_default); - _methodRuleCache[method] = rule; - } - return rule; - } - - public override bool NeedObfuscateCallInMethod(MethodDef method) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - return rule.disableObfuscation != true; - } - - public override ObfuscationCachePolicy GetMethodObfuscationCachePolicy(MethodDef method) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - return new ObfuscationCachePolicy() - { - cacheInLoop = rule.cacheCallIndexInLoop.Value, - cacheNotInLoop = rule.cacheCallIndexNotLoop.Value, - }; - } - - - private bool IsSpecialNotObfuscatedMethod(TypeDef typeDef, IMethod method) - { - if (typeDef.IsDelegate || typeDef.IsEnum) - return true; - - string methodName = method.Name; - - // doesn't proxy call if the method is a constructor - if (methodName == ".ctor") - { - return true; - } - - if (typeDef.Name == "EncryptionService`1") - { - return true; - } - // special handle - // don't proxy call for List.Enumerator GetEnumerator() - if (methodName == "GetEnumerator") - { - return true; - } - return false; - } - - private bool ComputeIsInWhiteList(IMethod calledMethod) - { - ITypeDefOrRef declaringType = calledMethod.DeclaringType; - TypeSig declaringTypeSig = calledMethod.DeclaringType.ToTypeSig(); - declaringTypeSig = declaringTypeSig.RemovePinnedAndModifiers(); - switch (declaringTypeSig.ElementType) - { - case ElementType.ValueType: - case ElementType.Class: - { - break; - } - case ElementType.GenericInst: - { - if (MetaUtil.ContainsContainsGenericParameter(calledMethod)) - { - return true; - } - break; - } - default: return true; - } - - TypeDef typeDef = declaringType.ResolveTypeDef(); - - if (IsSpecialNotObfuscatedMethod(typeDef, calledMethod)) - { - return true; - } - - string assName = typeDef.Module.Assembly.Name; - string typeFullName = typeDef.FullName; - string methodName = calledMethod.Name; - foreach (var ass in _whiteListAssemblies) - { - if (!ass.nameMatcher.IsMatch(assName)) - { - continue; - } - foreach (var type in ass.types) - { - if (!type.nameMatcher.IsMatch(typeFullName)) - { - continue; - } - foreach (var method in type.methods) - { - if (method.nameMatcher.IsMatch(methodName)) - { - return !method.obfuscate.Value; - } - } - return !type.obfuscate.Value; - } - return !ass.obfuscate.Value; - } - return false; - } - - private bool IsInWhiteList(IMethod method) - { - if (!_whiteListMethodCache.TryGetValue(method, out var isWhiteList)) - { - isWhiteList = ComputeIsInWhiteList(method); - _whiteListMethodCache.Add(method, isWhiteList); - } - return isWhiteList; - } - - private bool IsTypeSelfAndParentPublic(TypeDef type) - { - if (type.DeclaringType != null && !IsTypeSelfAndParentPublic(type.DeclaringType)) - { - return false; - } - - return type.IsPublic; - } - - public override bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir, bool currentInLoop) - { - if (IsInWhiteList(calledMethod)) - { - return false; - } - - // mono has more strict access control, calls non-public method will raise exception. - if (PlatformUtil.IsMonoBackend()) - { - MethodDef calledMethodDef = calledMethod.ResolveMethodDef(); - if (calledMethodDef != null && (!calledMethodDef.IsPublic || !IsTypeSelfAndParentPublic(calledMethodDef.DeclaringType))) - { - return false; - } - } - ObfuscationRule rule = GetMethodObfuscationRule(callerMethod); - if (currentInLoop && rule.obfuscateCallInLoop == false) - { - return false; - } - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs.meta deleted file mode 100644 index c970eec..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d9ea12b16c4b296459db8a60fb1615d6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs deleted file mode 100644 index e171909..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs +++ /dev/null @@ -1,53 +0,0 @@ -using dnlib.DotNet.Emit; -using dnlib.DotNet; -using System.Collections.Generic; -using Obfuz.Utils; -using Obfuz.Emit; -using Obfuz.Data; -using UnityEngine; - -namespace Obfuz.ObfusPasses.CallObfus -{ - public class DefaultCallProxyObfuscator : ObfuscatorBase - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly ConstFieldAllocator _constFieldAllocator; - private readonly CallProxyAllocator _proxyCallAllocator; - private readonly GroupByModuleEntityManager _moduleEntityManager; - - public DefaultCallProxyObfuscator(EncryptionScopeProvider encryptionScopeProvider, ConstFieldAllocator constFieldAllocator, GroupByModuleEntityManager moduleEntityManager, int encryptionLevel) - { - _encryptionScopeProvider = encryptionScopeProvider; - _constFieldAllocator = constFieldAllocator; - _moduleEntityManager = moduleEntityManager; - _proxyCallAllocator = new CallProxyAllocator(encryptionScopeProvider, moduleEntityManager, encryptionLevel); - } - - public override void Done() - { - _proxyCallAllocator.Done(); - } - - public override void Obfuscate(MethodDef callerMethod, IMethod calledMethod, bool callVir, bool needCacheCall, List obfuscatedInstructions) - { - - MethodSig sharedMethodSig = MetaUtil.ToSharedMethodSig(calledMethod.Module.CorLibTypes, MetaUtil.GetInflatedMethodSig(calledMethod)); - ProxyCallMethodData proxyCallMethodData = _proxyCallAllocator.Allocate(callerMethod.Module, calledMethod, callVir); - DefaultMetadataImporter importer = _moduleEntityManager.GetDefaultModuleMetadataImporter(callerMethod.Module, _encryptionScopeProvider); - - if (needCacheCall) - { - FieldDef cacheField = _constFieldAllocator.Allocate(callerMethod.Module, proxyCallMethodData.index); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - } - else - { - obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.encryptedIndex)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.encryptOps)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(proxyCallMethodData.salt)); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptInt)); - } - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, proxyCallMethodData.proxyMethod)); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs.meta deleted file mode 100644 index 78ae2a2..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e13ba01b03439e049af0e09367825cde -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs deleted file mode 100644 index 43c505f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs +++ /dev/null @@ -1,34 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.CallObfus -{ - - public struct ObfuscationCachePolicy - { - public bool cacheInLoop; - public bool cacheNotInLoop; - } - - public interface IObfuscationPolicy - { - bool NeedObfuscateCallInMethod(MethodDef method); - - ObfuscationCachePolicy GetMethodObfuscationCachePolicy(MethodDef method); - - bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir, bool currentInLoop); - } - - public abstract class ObfuscationPolicyBase : IObfuscationPolicy - { - public abstract bool NeedObfuscateCallInMethod(MethodDef method); - - public abstract ObfuscationCachePolicy GetMethodObfuscationCachePolicy(MethodDef method); - - public abstract bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir, bool currentInLoop); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs.meta deleted file mode 100644 index 96009d1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6af3cd881fdefd14d9a55b77088dd5a4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs deleted file mode 100644 index 4135b0d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs +++ /dev/null @@ -1,23 +0,0 @@ -using dnlib.DotNet.Emit; -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.CallObfus -{ - public interface IObfuscator - { - void Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, bool needCacheCall, List obfuscatedInstructions); - - void Done(); - } - - public abstract class ObfuscatorBase : IObfuscator - { - public abstract void Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, bool needCacheCall, List obfuscatedInstructions); - public abstract void Done(); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs.meta deleted file mode 100644 index c75fd40..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4156317478f8b1d438ef6d5a280d409f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp.meta deleted file mode 100644 index 37096d7..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2764442d8fc2b914dbc39dcfa2699698 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs deleted file mode 100644 index 1a526eb..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs +++ /dev/null @@ -1,46 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.CleanUp -{ - public class CleanUpInstructionPass : ObfuscationPassBase - { - public override ObfuscationPassType Type => ObfuscationPassType.None; - - public override void Start() - { - } - - public override void Stop() - { - - } - - public override void Process() - { - var ctx = ObfuscationPassContext.Current; - foreach (ModuleDef mod in ctx.modulesToObfuscate) - { - foreach (TypeDef type in mod.GetTypes()) - { - foreach (MethodDef method in type.Methods) - { - if (method.HasBody) - { - CilBody body = method.Body; - body.SimplifyBranches(); - body.OptimizeMacros(); - body.OptimizeBranches(); - // TODO remove dup - } - } - } - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs.meta deleted file mode 100644 index cc97432..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 78cc056cd929d70409a0f0737b571a6d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs deleted file mode 100644 index 2855136..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs +++ /dev/null @@ -1,71 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.CleanUp -{ - public class RemoveObfuzAttributesPass : ObfuscationPassBase - { - public override ObfuscationPassType Type => ObfuscationPassType.None; - - public override void Start() - { - } - - public override void Stop() - { - - } - - - private void RemoveObfuzAttributes(IHasCustomAttribute provider) - { - CustomAttributeCollection customAttributes = provider.CustomAttributes; - if (customAttributes.Count == 0) - return; - var toRemove = new List(); - customAttributes.RemoveAll("Obfuz.ObfuzIgnoreAttribute"); - customAttributes.RemoveAll("Obfuz.EncryptFieldAttribute"); - } - - public override void Process() - { - var ctx = ObfuscationPassContext.Current; - foreach (ModuleDef mod in ctx.modulesToObfuscate) - { - RemoveObfuzAttributes(mod); - foreach (TypeDef type in mod.GetTypes()) - { - RemoveObfuzAttributes(type); - foreach (FieldDef field in type.Fields) - { - RemoveObfuzAttributes(field); - } - foreach (MethodDef method in type.Methods) - { - RemoveObfuzAttributes(method); - foreach (Parameter param in method.Parameters) - { - if (param.ParamDef != null) - { - RemoveObfuzAttributes(param.ParamDef); - } - } - } - foreach (PropertyDef property in type.Properties) - { - RemoveObfuzAttributes(property); - } - foreach (EventDef eventDef in type.Events) - { - RemoveObfuzAttributes(eventDef); - } - } - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs.meta deleted file mode 100644 index ff6039e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6b475010a7656a0439ca8664a3d2dbc0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt.meta deleted file mode 100644 index 1fdfee0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 18104d0c3c665ea489e566eec67f2aea -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs deleted file mode 100644 index 3b3445c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs +++ /dev/null @@ -1,489 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Conf; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using UnityEngine; - -namespace Obfuz.ObfusPasses.ConstEncrypt -{ - - public class ConfigurableEncryptPolicy : EncryptPolicyBase - { - class ObfuscationRule : IRule - { - public bool? disableEncrypt; - public bool? encryptInt; - public bool? encryptLong; - public bool? encryptFloat; - public bool? encryptDouble; - public bool? encryptArray; - public bool? encryptString; - - public bool? encryptConstInLoop; - public bool? encryptStringInLoop; - - public bool? cacheConstInLoop; - public bool? cacheConstNotInLoop; - public bool? cacheStringInLoop; - public bool? cacheStringNotInLoop; - - public void InheritParent(ObfuscationRule parentRule) - { - if (disableEncrypt == null) - disableEncrypt = parentRule.disableEncrypt; - if (encryptInt == null) - encryptInt = parentRule.encryptInt; - if (encryptLong == null) - encryptLong = parentRule.encryptLong; - if (encryptFloat == null) - encryptFloat = parentRule.encryptFloat; - if (encryptDouble == null) - encryptDouble = parentRule.encryptDouble; - if (encryptArray == null) - encryptArray = parentRule.encryptArray; - if (encryptString == null) - encryptString = parentRule.encryptString; - - if (encryptConstInLoop == null) - encryptConstInLoop = parentRule.encryptConstInLoop; - if (encryptStringInLoop == null) - encryptStringInLoop = parentRule.encryptStringInLoop; - - if (cacheConstInLoop == null) - cacheConstInLoop = parentRule.cacheConstInLoop; - if (cacheConstNotInLoop == null) - cacheConstNotInLoop = parentRule.cacheConstNotInLoop; - if (cacheStringInLoop == null) - cacheStringInLoop = parentRule.cacheStringInLoop; - if (cacheStringNotInLoop == null) - cacheStringNotInLoop = parentRule.cacheStringNotInLoop; - } - } - - class MethodSpec : MethodRuleBase - { - } - - class TypeSpec : TypeRuleBase - { - } - - class AssemblySpec : AssemblyRuleBase - { - } - - private static readonly ObfuscationRule s_default = new ObfuscationRule() - { - disableEncrypt = false, - encryptInt = true, - encryptLong = true, - encryptFloat = true, - encryptDouble = true, - encryptArray = true, - encryptString = true, - encryptConstInLoop = true, - encryptStringInLoop = true, - cacheConstInLoop = true, - cacheConstNotInLoop = false, - cacheStringInLoop = true, - cacheStringNotInLoop = true, - }; - - private ObfuscationRule _global; - - public HashSet notEncryptInts = new HashSet(); - public HashSet notEncryptLongs = new HashSet(); - public HashSet notEncryptStrings = new HashSet(); - public List> notEncryptIntRanges = new List>(); - public List> notEncryptLongRanges = new List>(); - public List> notEncryptFloatRanges = new List>(); - public List> notEncryptDoubleRanges = new List>(); - public List> notEncryptArrayLengthRanges = new List>(); - public List> notEncryptStringLengthRanges = new List>(); - - private readonly XmlAssemblyTypeMethodRuleParser _xmlParser; - - private readonly Dictionary _assemblySpecs = new Dictionary(); - private readonly Dictionary _methodRuleCache = new Dictionary(); - - public ConfigurableEncryptPolicy(List toObfuscatedAssemblyNames, List xmlConfigFiles) - { - _xmlParser = new XmlAssemblyTypeMethodRuleParser( - toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobalElement); - LoadConfigs(xmlConfigFiles); - } - - private void LoadConfigs(List configFiles) - { - _xmlParser.LoadConfigs(configFiles); - if (_global == null) - { - _global = s_default; - } - else - { - _global.InheritParent(s_default); - } - _xmlParser.InheritParentRules(_global); - } - - private void ParseGlobalElement(string configFile, XmlElement ele) - { - switch (ele.Name) - { - case "global": _global = ParseObfuscationRule(configFile, ele); break; - case "whitelist": ParseWhitelist(configFile, ele); break; - default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}"); - } - } - - private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele) - { - var rule = new ObfuscationRule(); - if (ele.HasAttribute("disableEncrypt")) - { - rule.disableEncrypt = ConfigUtil.ParseBool(ele.GetAttribute("disableEncrypt")); - } - if (ele.HasAttribute("encryptInt")) - { - rule.encryptInt = ConfigUtil.ParseBool(ele.GetAttribute("encryptInt")); - } - if (ele.HasAttribute("encryptLong")) - { - rule.encryptLong = ConfigUtil.ParseBool(ele.GetAttribute("encryptLong")); - } - if (ele.HasAttribute("encryptFloat")) - { - rule.encryptFloat = ConfigUtil.ParseBool(ele.GetAttribute("encryptFloat")); - } - if (ele.HasAttribute("encryptDouble")) - { - rule.encryptDouble = ConfigUtil.ParseBool(ele.GetAttribute("encryptDouble")); - } - if (ele.HasAttribute("encryptBytes")) - { - rule.encryptArray = ConfigUtil.ParseBool(ele.GetAttribute("encryptArray")); - } - if (ele.HasAttribute("encryptString")) - { - rule.encryptString = ConfigUtil.ParseBool(ele.GetAttribute("encryptString")); - } - - if (ele.HasAttribute("encryptConstInLoop")) - { - rule.encryptConstInLoop = ConfigUtil.ParseBool(ele.GetAttribute("encryptConstInLoop")); - } - if (ele.HasAttribute("encryptStringInLoop")) - { - rule.encryptStringInLoop = ConfigUtil.ParseBool(ele.GetAttribute("encryptStringInLoop")); - } - if (ele.HasAttribute("cacheConstInLoop")) - { - rule.cacheConstInLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheConstInLoop")); - } - if (ele.HasAttribute("cacheConstNotInLoop")) - { - rule.cacheConstNotInLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheConstNotInLoop")); - } - if (ele.HasAttribute("cacheStringInLoop")) - { - rule.cacheStringInLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheStringInLoop")); - } - if (ele.HasAttribute("cacheStringNotInLoop")) - { - rule.cacheStringNotInLoop = ConfigUtil.ParseBool(ele.GetAttribute("cacheStringNotInLoop")); - } - return rule; - } - - private void ParseWhitelist(string configFile, XmlElement childEle) - { - string type = childEle.GetAttribute("type"); - if (string.IsNullOrEmpty(type)) - { - throw new Exception($"Invalid xml file, whitelist type is empty"); - } - string value = childEle.InnerText; - switch (type) - { - case "int": - { - notEncryptInts.AddRange(value.Split(',').Select(s => int.Parse(s.Trim()))); - break; - } - case "long": - { - notEncryptLongs.AddRange(value.Split(',').Select(s => long.Parse(s.Trim()))); - break; - } - case "string": - { - notEncryptStrings.AddRange(value.Split(',').Select(s => s.Trim())); - break; - } - case "int-range": - { - var parts = value.Split(','); - if (parts.Length != 2) - { - throw new Exception($"Invalid xml file, int-range {value} is invalid"); - } - notEncryptIntRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); - break; - } - case "long-range": - { - var parts = value.Split(','); - if (parts.Length != 2) - { - throw new Exception($"Invalid xml file, long-range {value} is invalid"); - } - notEncryptLongRanges.Add(new NumberRange(ConfigUtil.ParseNullableLong(parts[0]), ConfigUtil.ParseNullableLong(parts[1]))); - break; - } - case "float-range": - { - var parts = value.Split(','); - if (parts.Length != 2) - { - throw new Exception($"Invalid xml file, float-range {value} is invalid"); - } - notEncryptFloatRanges.Add(new NumberRange(ConfigUtil.ParseNullableFloat(parts[0]), ConfigUtil.ParseNullableFloat(parts[1]))); - break; - } - case "double-range": - { - var parts = value.Split(','); - if (parts.Length != 2) - { - throw new Exception($"Invalid xml file, double-range {value} is invalid"); - } - notEncryptDoubleRanges.Add(new NumberRange(ConfigUtil.ParseNullableDouble(parts[0]), ConfigUtil.ParseNullableDouble(parts[1]))); - break; - } - case "string-length-range": - { - var parts = value.Split(','); - if (parts.Length != 2) - { - throw new Exception($"Invalid xml file, string-length-range {value} is invalid"); - } - notEncryptStringLengthRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); - break; - } - case "array-length-range": - { - var parts = value.Split(','); - if (parts.Length != 2) - { - throw new Exception($"Invalid xml file, array-length-range {value} is invalid"); - } - notEncryptArrayLengthRanges.Add(new NumberRange(ConfigUtil.ParseNullableInt(parts[0]), ConfigUtil.ParseNullableInt(parts[1]))); - break; - } - default: throw new Exception($"Invalid xml file, unknown whitelist type {type} in {childEle.Name} node"); - } - } - - private ObfuscationRule GetMethodObfuscationRule(MethodDef method) - { - if (!_methodRuleCache.TryGetValue(method, out var rule)) - { - rule = _xmlParser.GetMethodRule(method, _global); - _methodRuleCache[method] = rule; - } - return rule; - } - - public override bool NeedObfuscateMethod(MethodDef method) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - return rule.disableEncrypt != true; - } - - public override ConstCachePolicy GetMethodConstCachePolicy(MethodDef method) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - return new ConstCachePolicy - { - cacheConstInLoop = rule.cacheConstInLoop.Value, - cacheConstNotInLoop = rule.cacheConstNotInLoop.Value, - cacheStringInLoop = rule.cacheStringInLoop.Value, - cacheStringNotInLoop = rule.cacheStringNotInLoop.Value, - }; - } - - public override bool NeedObfuscateInt(MethodDef method, bool currentInLoop, int value) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - if (rule.encryptInt == false) - { - return false; - } - if (currentInLoop && rule.encryptConstInLoop == false) - { - return false; - } - if (notEncryptInts.Contains(value)) - { - return false; - } - foreach (var range in notEncryptIntRanges) - { - if (range.min != null && value < range.min) - { - continue; - } - if (range.max != null && value > range.max) - { - continue; - } - return false; - } - return true; - } - - public override bool NeedObfuscateLong(MethodDef method, bool currentInLoop, long value) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - if (rule.encryptLong == false) - { - return false; - } - if (currentInLoop && rule.encryptConstInLoop == false) - { - return false; - } - if (notEncryptLongs.Contains(value)) - { - return false; - } - foreach (var range in notEncryptLongRanges) - { - if (range.min != null && value < range.min) - { - continue; - } - if (range.max != null && value > range.max) - { - continue; - } - return false; - } - return true; - } - - public override bool NeedObfuscateFloat(MethodDef method, bool currentInLoop, float value) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - if (rule.encryptFloat == false) - { - return false; - } - if (currentInLoop && rule.encryptConstInLoop == false) - { - return false; - } - foreach (var range in notEncryptFloatRanges) - { - if (range.min != null && value < range.min) - { - continue; - } - if (range.max != null && value > range.max) - { - continue; - } - return false; - } - return true; - } - - public override bool NeedObfuscateDouble(MethodDef method, bool currentInLoop, double value) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - if (rule.encryptDouble == false) - { - return false; - } - if (currentInLoop && rule.encryptConstInLoop == false) - { - return false; - } - foreach (var range in notEncryptDoubleRanges) - { - if (range.min != null && value < range.min) - { - continue; - } - if (range.max != null && value > range.max) - { - continue; - } - return false; - } - return true; - } - - public override bool NeedObfuscateString(MethodDef method, bool currentInLoop, string value) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - if (rule.encryptString == false) - { - return false; - } - if (currentInLoop && rule.encryptConstInLoop == false) - { - return false; - } - if (notEncryptStrings.Contains(value)) - { - return false; - } - foreach (var range in notEncryptStringLengthRanges) - { - if (range.min != null && value.Length < range.min) - { - continue; - } - if (range.max != null && value.Length > range.max) - { - continue; - } - return false; - } - return true; - } - - public override bool NeedObfuscateArray(MethodDef method, bool currentInLoop, byte[] array) - { - ObfuscationRule rule = GetMethodObfuscationRule(method); - if (rule.encryptArray == false) - { - return false; - } - if (currentInLoop && rule.encryptConstInLoop == false) - { - return false; - } - foreach (var range in notEncryptArrayLengthRanges) - { - if (range.min != null && array.Length < range.min) - { - continue; - } - if (range.max != null && array.Length > range.max) - { - continue; - } - return false; - } - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs.meta deleted file mode 100644 index 73c07be..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: da25453bc1fda394097c052af7733260 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs deleted file mode 100644 index b39d304..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs +++ /dev/null @@ -1,152 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Emit; -using Obfuz.Settings; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using UnityEngine.Assertions; - -namespace Obfuz.ObfusPasses.ConstEncrypt -{ - - public class ConstEncryptPass : BasicBlockObfuscationPassBase - { - private readonly List _configFiles; - private readonly int _encryptionLevel; - private IEncryptPolicy _dataObfuscatorPolicy; - private IConstEncryptor _dataObfuscator; - public override ObfuscationPassType Type => ObfuscationPassType.ConstEncrypt; - - public ConstEncryptPass(ConstEncryptionSettings settings) - { - _configFiles = settings.ruleFiles.ToList(); - _encryptionLevel = settings.encryptionLevel; - } - - public override void Start() - { - var ctx = ObfuscationPassContext.Current; - _dataObfuscatorPolicy = new ConfigurableEncryptPolicy(ctx.assembliesToObfuscate, _configFiles); - _dataObfuscator = new DefaultConstEncryptor(ctx.encryptionScopeProvider, ctx.rvaDataAllocator, ctx.constFieldAllocator, ctx.moduleEntityManager, _encryptionLevel); - } - - public override void Stop() - { - - } - - protected override bool NeedObfuscateMethod(MethodDef method) - { - return _dataObfuscatorPolicy.NeedObfuscateMethod(method); - } - - protected override bool TryObfuscateInstruction(MethodDef method, Instruction inst, BasicBlock block, int instructionIndex, IList globalInstructions, - List outputInstructions, List totalFinalInstructions) - { - bool currentInLoop = block.inLoop; - ConstCachePolicy constCachePolicy = _dataObfuscatorPolicy.GetMethodConstCachePolicy(method); - bool needCache = currentInLoop ? constCachePolicy.cacheConstInLoop : constCachePolicy.cacheConstNotInLoop; - switch (inst.OpCode.Code) - { - case Code.Ldc_I4: - case Code.Ldc_I4_S: - case Code.Ldc_I4_0: - case Code.Ldc_I4_1: - case Code.Ldc_I4_2: - case Code.Ldc_I4_3: - case Code.Ldc_I4_4: - case Code.Ldc_I4_5: - case Code.Ldc_I4_6: - case Code.Ldc_I4_7: - case Code.Ldc_I4_8: - case Code.Ldc_I4_M1: - { - int value = inst.GetLdcI4Value(); - if (_dataObfuscatorPolicy.NeedObfuscateInt(method, currentInLoop, value)) - { - _dataObfuscator.ObfuscateInt(method, needCache, value, outputInstructions); - return true; - } - return false; - } - case Code.Ldc_I8: - { - long value = (long)inst.Operand; - if (_dataObfuscatorPolicy.NeedObfuscateLong(method, currentInLoop, value)) - { - _dataObfuscator.ObfuscateLong(method, needCache, value, outputInstructions); - return true; - } - return false; - } - case Code.Ldc_R4: - { - float value = (float)inst.Operand; - if (_dataObfuscatorPolicy.NeedObfuscateFloat(method, currentInLoop, value)) - { - _dataObfuscator.ObfuscateFloat(method, needCache, value, outputInstructions); - return true; - } - return false; - } - case Code.Ldc_R8: - { - double value = (double)inst.Operand; - if (_dataObfuscatorPolicy.NeedObfuscateDouble(method, currentInLoop, value)) - { - _dataObfuscator.ObfuscateDouble(method, needCache, value, outputInstructions); - return true; - } - return false; - } - case Code.Ldstr: - { - string value = (string)inst.Operand; - if (_dataObfuscatorPolicy.NeedObfuscateString(method, currentInLoop, value)) - { - _dataObfuscator.ObfuscateString(method, needCache, value, outputInstructions); - return true; - } - return false; - } - case Code.Call: - { - //if (((IMethod)inst.Operand).FullName == "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") - //{ - // Instruction prevInst = globalInstructions[instructionIndex - 1]; - // if (prevInst.OpCode.Code == Code.Ldtoken) - // { - // IField rvaField = (IField)prevInst.Operand; - // FieldDef ravFieldDef = rvaField.ResolveFieldDefThrow(); - // byte[] data = ravFieldDef.InitialValue; - // if (data != null && _dataObfuscatorPolicy.NeedObfuscateArray(method, currentInLoop, data)) - // { - // if (_encryptedRvaFields.Add(ravFieldDef)) - // { - - // } - - // // remove prev ldtoken instruction - // Assert.AreEqual(Code.Ldtoken, totalFinalInstructions.Last().OpCode.Code); - // //totalFinalInstructions.RemoveAt(totalFinalInstructions.Count - 1); - // // dup arr argument for decryption operation - // totalFinalInstructions.Insert(totalFinalInstructions.Count - 1, Instruction.Create(OpCodes.Dup)); - // totalFinalInstructions.Add(inst.Clone()); - // //bool needCache = currentInLoop ? constCachePolicy.cacheStringInLoop : constCachePolicy.cacheStringNotInLoop; - // bool needCache = false; - // _dataObfuscator.ObfuscateBytes(method, needCache, data, outputInstructions); - // return true; - // } - // } - //} - return false; - } - default: return false; - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs.meta deleted file mode 100644 index da7fdfb..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: aa0e9191126d4e24c92546b6af2c52cf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs deleted file mode 100644 index 75f98dc..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs +++ /dev/null @@ -1,204 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Emit; -using Obfuz.Data; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using NUnit.Framework; -using System.Text; - -namespace Obfuz.ObfusPasses.ConstEncrypt -{ - public class DefaultConstEncryptor : IConstEncryptor - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly RvaDataAllocator _rvaDataAllocator; - private readonly ConstFieldAllocator _constFieldAllocator; - private readonly GroupByModuleEntityManager _moduleEntityManager; - private readonly int _encryptionLevel; - - public DefaultConstEncryptor(EncryptionScopeProvider encryptionScopeProvider, RvaDataAllocator rvaDataAllocator, ConstFieldAllocator constFieldAllocator, GroupByModuleEntityManager moduleEntityManager, int encryptionLevel) - { - _encryptionScopeProvider = encryptionScopeProvider; - _rvaDataAllocator = rvaDataAllocator; - _constFieldAllocator = constFieldAllocator; - _moduleEntityManager = moduleEntityManager; - _encryptionLevel = encryptionLevel; - } - - private IRandom CreateRandomForValue(EncryptionScopeInfo encryptionScope, int value) - { - return encryptionScope.localRandomCreator(value); - } - - private int GenerateEncryptionOperations(EncryptionScopeInfo encryptionScope, IRandom random) - { - return EncryptionUtil.GenerateEncryptionOpCodes(random, encryptionScope.encryptor, _encryptionLevel); - } - - public int GenerateSalt(IRandom random) - { - return random.NextInt(); - } - - private DefaultMetadataImporter GetModuleMetadataImporter(MethodDef method) - { - return _moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, _encryptionScopeProvider); - } - - public void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List obfuscatedInstructions) - { - if (needCacheValue) - { - FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - return; - } - - EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module); - IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode()); - int ops = GenerateEncryptionOperations(encryptionScope, random); - int salt = GenerateSalt(random); - int encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue); - - DefaultMetadataImporter importer = GetModuleMetadataImporter(method); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt)); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaInt)); - } - - public void ObfuscateLong(MethodDef method, bool needCacheValue, long value, List obfuscatedInstructions) - { - if (needCacheValue) - { - FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - return; - } - - EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module); - IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode()); - int ops = GenerateEncryptionOperations(encryptionScope, random); - int salt = GenerateSalt(random); - long encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue); - - DefaultMetadataImporter importer = GetModuleMetadataImporter(method); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt)); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaLong)); - } - - public void ObfuscateFloat(MethodDef method, bool needCacheValue, float value, List obfuscatedInstructions) - { - if (needCacheValue) - { - FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - return; - } - - EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module); - IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode()); - int ops = GenerateEncryptionOperations(encryptionScope, random); - int salt = GenerateSalt(random); - float encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue); - - DefaultMetadataImporter importer = GetModuleMetadataImporter(method); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt)); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaFloat)); - } - - public void ObfuscateDouble(MethodDef method, bool needCacheValue, double value, List obfuscatedInstructions) - { - if (needCacheValue) - { - FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - return; - } - - EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module); - IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode()); - int ops = GenerateEncryptionOperations(encryptionScope, random); - int salt = GenerateSalt(random); - double encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt); - RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue); - - DefaultMetadataImporter importer = GetModuleMetadataImporter(method); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt)); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaDouble)); - } - - public void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List obfuscatedInstructions) - { - throw new NotSupportedException("ObfuscateBytes is not supported yet."); - //if (needCacheValue) - //{ - // FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value); - // obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - // return; - //} - - //int ops = GenerateEncryptionOperations(); - //int salt = GenerateSalt(); - //byte[] encryptedValue = _encryptor.Encrypt(value, 0, value.Length, ops, salt); - //Assert.IsTrue(encryptedValue.Length % 4 == 0); - //RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue); - - //DefaultMetadataImporter importer = GetModuleMetadataImporter(method); - //obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - //obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset)); - //// should use value.Length, can't use rvaData.size, because rvaData.size is align to 4, it's not the actual length. - //obfuscatedInstructions.Add(Instruction.CreateLdcI4(value.Length)); - //obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops)); - //obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt)); - //obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaBytes)); - } - - public void ObfuscateString(MethodDef method, bool needCacheValue, string value, List obfuscatedInstructions) - { - if (needCacheValue) - { - FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField)); - return; - } - - EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module); - IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode()); - int ops = GenerateEncryptionOperations(encryptionScope, random); - int salt = GenerateSalt(random); - int stringByteLength = Encoding.UTF8.GetByteCount(value); - byte[] encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt); - Assert.AreEqual(stringByteLength, encryptedValue.Length); - RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue); - - DefaultMetadataImporter importer = GetModuleMetadataImporter(method); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset)); - // should use stringByteLength, can't use rvaData.size, because rvaData.size is align to 4, it's not the actual length. - obfuscatedInstructions.Add(Instruction.CreateLdcI4(stringByteLength)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops)); - obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt)); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaString)); - } - - public void Done() - { - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs.meta deleted file mode 100644 index 1e0977a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4c6a0ecde97527e4694731e4d4de129a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs deleted file mode 100644 index 7043aec..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs +++ /dev/null @@ -1,32 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using System; -using System.Collections.Generic; - -namespace Obfuz.ObfusPasses.ConstEncrypt -{ - public interface IConstEncryptor - { - void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List obfuscatedInstructions); - - void ObfuscateLong(MethodDef method, bool needCacheValue, long value, List obfuscatedInstructions); - - void ObfuscateFloat(MethodDef method, bool needCacheValue, float value, List obfuscatedInstructions); - - void ObfuscateDouble(MethodDef method, bool needCacheValue, double value, List obfuscatedInstructions); - - void ObfuscateString(MethodDef method, bool needCacheValue, string value, List obfuscatedInstructions); - - void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List obfuscatedInstructions); - } - - public abstract class ConstEncryptorBase : IConstEncryptor - { - public abstract void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List obfuscatedInstructions); - public abstract void ObfuscateDouble(MethodDef method, bool needCacheValue, double value, List obfuscatedInstructions); - public abstract void ObfuscateFloat(MethodDef method, bool needCacheValue, float value, List obfuscatedInstructions); - public abstract void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List obfuscatedInstructions); - public abstract void ObfuscateLong(MethodDef method, bool needCacheValue, long value, List obfuscatedInstructions); - public abstract void ObfuscateString(MethodDef method, bool needCacheValue, string value, List obfuscatedInstructions); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs.meta deleted file mode 100644 index 7f8d587..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0ccbcdadf1913b6498eaee53abac5d0b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs deleted file mode 100644 index 1db7f0e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs +++ /dev/null @@ -1,48 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.ConstEncrypt -{ - public struct ConstCachePolicy - { - public bool cacheConstInLoop; - public bool cacheConstNotInLoop; - public bool cacheStringInLoop; - public bool cacheStringNotInLoop; - } - - public interface IEncryptPolicy - { - bool NeedObfuscateMethod(MethodDef method); - - ConstCachePolicy GetMethodConstCachePolicy(MethodDef method); - - bool NeedObfuscateInt(MethodDef method, bool currentInLoop, int value); - - bool NeedObfuscateLong(MethodDef method, bool currentInLoop, long value); - - bool NeedObfuscateFloat(MethodDef method, bool currentInLoop, float value); - - bool NeedObfuscateDouble(MethodDef method, bool currentInLoop, double value); - - bool NeedObfuscateString(MethodDef method, bool currentInLoop, string value); - - bool NeedObfuscateArray(MethodDef method, bool currentInLoop, byte[] array); - } - - public abstract class EncryptPolicyBase : IEncryptPolicy - { - public abstract bool NeedObfuscateMethod(MethodDef method); - public abstract ConstCachePolicy GetMethodConstCachePolicy(MethodDef method); - public abstract bool NeedObfuscateDouble(MethodDef method, bool currentInLoop, double value); - public abstract bool NeedObfuscateFloat(MethodDef method, bool currentInLoop, float value); - public abstract bool NeedObfuscateInt(MethodDef method, bool currentInLoop, int value); - public abstract bool NeedObfuscateLong(MethodDef method, bool currentInLoop, long value); - public abstract bool NeedObfuscateString(MethodDef method, bool currentInLoop, string value); - public abstract bool NeedObfuscateArray(MethodDef method, bool currentInLoop, byte[] array); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs.meta deleted file mode 100644 index 0a44790..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 18e57864070430a44ac561bdd7d00b2e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus.meta deleted file mode 100644 index 24080ec..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9fdb2c243b1ea0f489e67233fda287c9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs deleted file mode 100644 index 468bfce..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs +++ /dev/null @@ -1,35 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.ExprObfus -{ - public class ExprObfusPass : InstructionObfuscationPassBase - { - public override ObfuscationPassType Type => ObfuscationPassType.ExprObfus; - - public override void Start() - { - - } - - public override void Stop() - { - - } - - protected override bool NeedObfuscateMethod(MethodDef method) - { - return false; - } - - protected override bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, IList instructions, int instructionIndex, List outputInstructions, List totalFinalInstructions) - { - return false; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs.meta deleted file mode 100644 index f108ce3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 477e081ffc0072e4fa1a06100269e4a3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt.meta deleted file mode 100644 index 24c7b1d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0b789725c4848bd4fb4b3ce1f2e2a9c9 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs deleted file mode 100644 index 15ce929..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs +++ /dev/null @@ -1,44 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Conf; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Xml; - -namespace Obfuz.ObfusPasses.FieldEncrypt -{ - public class ConfigurableEncryptPolicy : EncryptPolicyBase - { - class ObfuscationRule - { - - } - - private readonly XmlFieldRuleParser _configParser; - - public ConfigurableEncryptPolicy(List toObfuscatedAssemblyNames, List configFiles) - { - _configParser = new XmlFieldRuleParser(toObfuscatedAssemblyNames, ParseRule, null); - _configParser.LoadConfigs(configFiles); - } - - private ObfuscationRule ParseRule(string configFile, XmlElement ele) - { - return new ObfuscationRule(); - } - - public override bool NeedEncrypt(FieldDef field) - { - if (MetaUtil.HasEncryptFieldAttribute(field)) - { - return true; - } - if (MetaUtil.HasObfuzIgnoreAttribute(field) || MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(field.DeclaringType)) - { - return false; - } - var rule = _configParser.GetFieldRule(field); - return rule != null; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs.meta deleted file mode 100644 index bcc4d60..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6b17fa09ce58526459f2b9e375c31cad -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs deleted file mode 100644 index 05c9c63..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs +++ /dev/null @@ -1,182 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz.Emit; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using UnityEngine.Assertions; - -namespace Obfuz.ObfusPasses.FieldEncrypt -{ - public class DefaultFieldEncryptor : FieldEncryptorBase - { - private readonly EncryptionScopeProvider _encryptionScopeProvider; - private readonly GroupByModuleEntityManager _moduleEntityManager; - private readonly int _encryptionLevel; - - public DefaultFieldEncryptor(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager, int encryptionLevel) - { - _encryptionScopeProvider = encryptionScopeProvider; - _moduleEntityManager = moduleEntityManager; - _encryptionLevel = encryptionLevel; - } - - private DefaultMetadataImporter GetMetadataImporter(MethodDef method) - { - return _moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, _encryptionScopeProvider); - } - - class FieldEncryptInfo - { - public int encryptOps; - public int salt; - public ElementType fieldType; - public long xorValueForZero; - } - - private readonly Dictionary _fieldEncryptInfoCache = new Dictionary(); - - - private long CalcXorValueForZero(IEncryptor encryptor, ElementType type, int encryptOps, int salt) - { - switch (type) - { - case ElementType.I4: - case ElementType.U4: - case ElementType.R4: - return encryptor.Encrypt(0, encryptOps, salt); - case ElementType.I8: - case ElementType.U8: - case ElementType.R8: - return encryptor.Encrypt(0L, encryptOps, salt); - default: - throw new NotSupportedException($"Unsupported field type: {type} for encryption"); - } - } - - - private IRandom CreateRandomForField(RandomCreator randomCreator, FieldDef field) - { - return randomCreator(FieldEqualityComparer.CompareDeclaringTypes.GetHashCode(field)); - } - - private int GenerateEncryptionOperations(IRandom random, IEncryptor encryptor) - { - return EncryptionUtil.GenerateEncryptionOpCodes(random, encryptor, _encryptionLevel); - } - - public int GenerateSalt(IRandom random) - { - return random.NextInt(); - } - - private FieldEncryptInfo GetFieldEncryptInfo(FieldDef field) - { - if (_fieldEncryptInfoCache.TryGetValue(field, out var info)) - { - return info; - } - EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(field.Module); - - IRandom random = CreateRandomForField(encryptionScope.localRandomCreator, field); - IEncryptor encryptor = encryptionScope.encryptor; - int encryptOps = GenerateEncryptionOperations(random, encryptor); - int salt = GenerateSalt(random); - ElementType fieldType = field.FieldSig.Type.RemovePinnedAndModifiers().ElementType; - long xorValueForZero = CalcXorValueForZero(encryptor, fieldType, encryptOps, salt); - - info = new FieldEncryptInfo - { - encryptOps = encryptOps, - salt = salt, - fieldType = fieldType, - xorValueForZero = xorValueForZero, - }; - _fieldEncryptInfoCache[field] = info; - return info; - } - - public override void Encrypt(MethodDef method, FieldDef field, List outputInstructions, Instruction currentInstruction) - { - DefaultMetadataImporter importer = GetMetadataImporter(method); - EncryptionServiceMetadataImporter encryptionServiceMetadataImporter = importer.GetEncryptionServiceMetadataImporterOfModule(field.Module); - FieldEncryptInfo fei = GetFieldEncryptInfo(field); - if (fei.fieldType == ElementType.I4 || fei.fieldType == ElementType.U4 || fei.fieldType == ElementType.R4) - { - // value has been put on stack - - // encrypt - outputInstructions.Add(Instruction.CreateLdcI4(fei.encryptOps)); - outputInstructions.Add(Instruction.CreateLdcI4(fei.salt)); - outputInstructions.Add(Instruction.Create(OpCodes.Call, encryptionServiceMetadataImporter.EncryptInt)); - // xor - outputInstructions.Add(Instruction.CreateLdcI4((int)fei.xorValueForZero)); - outputInstructions.Add(Instruction.Create(OpCodes.Xor)); - } - else if (fei.fieldType == ElementType.I8 || fei.fieldType == ElementType.U8 || fei.fieldType == ElementType.R8) - { - // value has been put on stack - - // encrypt - outputInstructions.Add(Instruction.CreateLdcI4(fei.encryptOps)); - outputInstructions.Add(Instruction.CreateLdcI4(fei.salt)); - outputInstructions.Add(Instruction.Create(OpCodes.Call, encryptionServiceMetadataImporter.EncryptLong)); - // xor - outputInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, fei.xorValueForZero)); - outputInstructions.Add(Instruction.Create(OpCodes.Xor)); - } - else - { - Assert.IsTrue(false, $"Unsupported field type: {fei.fieldType} for encryption"); - } - - outputInstructions.Add(currentInstruction.Clone()); - } - - public override void Decrypt(MethodDef method, FieldDef field, List outputInstructions, Instruction currentInstruction) - { - outputInstructions.Add(currentInstruction.Clone()); - DefaultMetadataImporter importer = GetMetadataImporter(method); - EncryptionServiceMetadataImporter encryptionServiceMetadataImporter = importer.GetEncryptionServiceMetadataImporterOfModule(field.Module); - FieldEncryptInfo fei = GetFieldEncryptInfo(field); - if (fei.fieldType == ElementType.I4 || fei.fieldType == ElementType.U4 || fei.fieldType == ElementType.R4) - { - // value has been put on stack - // xor - if (fei.fieldType == ElementType.R4) - { - outputInstructions.Add(Instruction.Create(OpCodes.Call, importer.CastFloatAsInt)); - } - outputInstructions.Add(Instruction.CreateLdcI4((int)fei.xorValueForZero)); - outputInstructions.Add(Instruction.Create(OpCodes.Xor)); - - // decrypt - outputInstructions.Add(Instruction.CreateLdcI4(fei.encryptOps)); - outputInstructions.Add(Instruction.CreateLdcI4(fei.salt)); - outputInstructions.Add(Instruction.Create(OpCodes.Call, encryptionServiceMetadataImporter.DecryptInt)); - } - else if (fei.fieldType == ElementType.I8 || fei.fieldType == ElementType.U8 || fei.fieldType == ElementType.R8) - { - // value has been put on stack - // xor - if (fei.fieldType == ElementType.R8) - { - outputInstructions.Add(Instruction.Create(OpCodes.Call, importer.CastDoubleAsLong)); - } - outputInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, fei.xorValueForZero)); - outputInstructions.Add(Instruction.Create(OpCodes.Xor)); - - // decrypt - outputInstructions.Add(Instruction.CreateLdcI4(fei.encryptOps)); - outputInstructions.Add(Instruction.CreateLdcI4(fei.salt)); - outputInstructions.Add(Instruction.Create(OpCodes.Call, encryptionServiceMetadataImporter.DecryptLong)); - } - else - { - Assert.IsTrue(false, $"Unsupported field type: {fei.fieldType} for decryption"); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs.meta deleted file mode 100644 index 905f446..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b6707a66ae63e2c498d55088c6e8ef4a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs deleted file mode 100644 index 054044e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs +++ /dev/null @@ -1,108 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using Obfuz; -using Obfuz.Settings; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace Obfuz.ObfusPasses.FieldEncrypt -{ - - public class FieldEncryptPass : InstructionObfuscationPassBase - { - private readonly List _configFiles; - private readonly int _encryptionLevel; - private IEncryptPolicy _encryptionPolicy; - private IFieldEncryptor _memoryEncryptor; - - public override ObfuscationPassType Type => ObfuscationPassType.FieldEncrypt; - - public FieldEncryptPass(FieldEncryptionSettings settings) - { - _configFiles = settings.ruleFiles.ToList(); - _encryptionLevel = settings.encryptionLevel; - } - - protected override bool ForceProcessAllAssembliesAndIgnoreAllPolicy => true; - - public override void Start() - { - var ctx = ObfuscationPassContext.Current; - _memoryEncryptor = new DefaultFieldEncryptor(ctx.encryptionScopeProvider, ctx.moduleEntityManager, _encryptionLevel); - _encryptionPolicy = new ConfigurableEncryptPolicy(ctx.assembliesToObfuscate, _configFiles); - } - - public override void Stop() - { - - } - - protected override bool NeedObfuscateMethod(MethodDef method) - { - return true; - } - - private bool IsSupportedFieldType(TypeSig type) - { - type = type.RemovePinnedAndModifiers(); - switch (type.ElementType) - { - case ElementType.I4: - case ElementType.I8: - case ElementType.U4: - case ElementType.U8: - case ElementType.R4: - case ElementType.R8: - return true; - default: return false; - } - } - - protected override bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, IList instructions, int instructionIndex, List outputInstructions, List totalFinalInstructions) - { - Code code = inst.OpCode.Code; - if (!(inst.Operand is IField field) || !field.IsField) - { - return false; - } - FieldDef fieldDef = field.ResolveFieldDefThrow(); - if (!IsSupportedFieldType(fieldDef.FieldSig.Type) || !_encryptionPolicy.NeedEncrypt(fieldDef)) - { - return false; - } - switch (code) - { - case Code.Ldfld: - { - _memoryEncryptor.Decrypt(callingMethod, fieldDef, outputInstructions, inst); - break; - } - case Code.Stfld: - { - _memoryEncryptor.Encrypt(callingMethod, fieldDef, outputInstructions, inst); - break; - } - case Code.Ldsfld: - { - _memoryEncryptor.Decrypt(callingMethod, fieldDef, outputInstructions, inst); - break; - } - case Code.Stsfld: - { - _memoryEncryptor.Encrypt(callingMethod, fieldDef, outputInstructions, inst); - break; - } - case Code.Ldflda: - case Code.Ldsflda: - { - throw new System.Exception($"You shouldn't get reference to memory encryption field: {field}"); - } - default: return false; - } - //Debug.Log($"memory encrypt field: {field}"); - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs.meta deleted file mode 100644 index 1e60f28..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f3da24d0f1f1fc7449cbd0e7ddd03aa2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs deleted file mode 100644 index a1a7705..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs +++ /dev/null @@ -1,19 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.FieldEncrypt -{ - public interface IEncryptPolicy - { - bool NeedEncrypt(FieldDef field); - } - - public abstract class EncryptPolicyBase : IEncryptPolicy - { - public abstract bool NeedEncrypt(FieldDef field); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs.meta deleted file mode 100644 index d5c1047..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a48d0500d0737404cad9c9ef23a9467c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs deleted file mode 100644 index 7c9f7c3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs +++ /dev/null @@ -1,29 +0,0 @@ -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.FieldEncrypt -{ - public class MemoryEncryptionContext - { - public ModuleDef module; - - public Instruction currentInstruction; - } - - public interface IFieldEncryptor - { - void Encrypt(MethodDef method, FieldDef field, List outputInstructions, Instruction currentInstruction); - - void Decrypt(MethodDef method, FieldDef field, List outputInstructions, Instruction currentInstruction); - } - - public abstract class FieldEncryptorBase : IFieldEncryptor - { - public abstract void Encrypt(MethodDef method, FieldDef field, List outputInstructions, Instruction currentInstruction); - public abstract void Decrypt(MethodDef method, FieldDef field, List outputInstructions, Instruction currentInstruction); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs.meta deleted file mode 100644 index dca5071..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8a3ec14fca5169d479529d21b2eeada1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs deleted file mode 100644 index 4028c41..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs +++ /dev/null @@ -1,85 +0,0 @@ -using dnlib.DotNet.Emit; -using dnlib.DotNet; -using System.Collections.Generic; -using System.Linq; - -namespace Obfuz.ObfusPasses -{ - public abstract class InstructionObfuscationPassBase : ObfuscationPassBase - { - protected virtual bool ForceProcessAllAssembliesAndIgnoreAllPolicy => false; - - protected abstract bool NeedObfuscateMethod(MethodDef method); - - public override void Process() - { - var ctx = ObfuscationPassContext.Current; - var modules = ForceProcessAllAssembliesAndIgnoreAllPolicy ? ctx.allObfuscationRelativeModules : ctx.modulesToObfuscate; - ObfuscationMethodWhitelist whiteList = ctx.whiteList; - ConfigurablePassPolicy passPolicy = ctx.passPolicy; - foreach (ModuleDef mod in modules) - { - if (!ForceProcessAllAssembliesAndIgnoreAllPolicy && (whiteList.IsInWhiteList(mod) || !Support(passPolicy.GetAssemblyObfuscationPasses(mod)))) - { - continue; - } - // ToArray to avoid modify list exception - foreach (TypeDef type in mod.GetTypes().ToArray()) - { - if (!ForceProcessAllAssembliesAndIgnoreAllPolicy && (whiteList.IsInWhiteList(type) || !Support(passPolicy.GetTypeObfuscationPasses(type)))) - { - continue; - } - // ToArray to avoid modify list exception - foreach (MethodDef method in type.Methods.ToArray()) - { - if (!method.HasBody || (!ForceProcessAllAssembliesAndIgnoreAllPolicy && (ctx.whiteList.IsInWhiteList(method) || !Support(passPolicy.GetMethodObfuscationPasses(method)) || !NeedObfuscateMethod(method)))) - { - continue; - } - // TODO if isGeneratedBy Obfuscator, continue - ObfuscateData(method); - } - } - } - } - - - protected abstract bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, IList instructions, int instructionIndex, - List outputInstructions, List totalFinalInstructions); - - private void ObfuscateData(MethodDef method) - { - IList instructions = method.Body.Instructions; - var outputInstructions = new List(); - var totalFinalInstructions = new List(); - for (int i = 0; i < instructions.Count; i++) - { - Instruction inst = instructions[i]; - outputInstructions.Clear(); - if (TryObfuscateInstruction(method, inst, instructions, i, outputInstructions, totalFinalInstructions)) - { - // current instruction may be the target of control flow instruction, so we can't remove it directly. - // we replace it with nop now, then remove it in CleanUpInstructionPass - inst.OpCode = outputInstructions[0].OpCode; - inst.Operand = outputInstructions[0].Operand; - totalFinalInstructions.Add(inst); - for (int k = 1; k < outputInstructions.Count; k++) - { - totalFinalInstructions.Add(outputInstructions[k]); - } - } - else - { - totalFinalInstructions.Add(inst); - } - } - - instructions.Clear(); - foreach (var obInst in totalFinalInstructions) - { - instructions.Add(obInst); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs.meta deleted file mode 100644 index ba2497a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e0cad4b764050f44f8c9b225056a4f49 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs deleted file mode 100644 index b3aaf0c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Obfuz.Emit; - -namespace Obfuz.ObfusPasses -{ - public abstract class ObfuscationPassBase : IObfuscationPass - { - public abstract ObfuscationPassType Type { get; } - - public bool Support(ObfuscationPassType passType) - { - return passType.HasFlag(Type); - } - - public abstract void Start(); - - public abstract void Stop(); - - public abstract void Process(); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs.meta deleted file mode 100644 index 335ee27..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2f3e7e1d2a3ad3a4fb1a81e97730b5a4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs deleted file mode 100644 index ec28ad3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace Obfuz.ObfusPasses -{ - [Flags] - public enum ObfuscationPassType - { - None = 0, - - ConstEncrypt = 0x1, - FieldEncrypt = 0x2, - - SymbolObfus = 0x100, - CallObfus = 0x200, - ExprObfus = 0x400, - ControlFlowObfus = 0x800, - - AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus, - AllEncrypt = ConstEncrypt | FieldEncrypt, - - MethodBodyObfusOrEncrypt = ConstEncrypt | CallObfus | ExprObfus | ControlFlowObfus, - - All = ~0, - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs.meta deleted file mode 100644 index b03ea20..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5addd02f6f3dc0a4d888a0f74bd5ce4d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus.meta deleted file mode 100644 index 331b3d1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b746569f7c0d9754fa6f2925538eddbd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs deleted file mode 100644 index 184ce1b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs +++ /dev/null @@ -1,33 +0,0 @@ -using dnlib.DotNet; - -namespace Obfuz.ObfusPasses.SymbolObfus -{ - public interface INameMaker - { - void AddPreservedName(TypeDef typeDef, string name); - - void AddPreservedNamespace(TypeDef typeDef, string name); - - void AddPreservedName(MethodDef methodDef, string name); - - void AddPreservedName(FieldDef fieldDef, string name); - - void AddPreservedName(PropertyDef propertyDef, string name); - - void AddPreservedName(EventDef eventDef, string name); - - string GetNewName(TypeDef typeDef, string originalName); - - string GetNewNamespace(TypeDef typeDef, string originalNamespace, bool reuse); - - string GetNewName(MethodDef methodDef, string originalName); - - string GetNewName(ParamDef param, string originalName); - - string GetNewName(FieldDef fieldDef, string originalName); - - string GetNewName(PropertyDef propertyDef, string originalName); - - string GetNewName(EventDef eventDef, string originalName); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs.meta deleted file mode 100644 index 8062197..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0c24d29f654d00b44bb6aa3b4bf222dd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs deleted file mode 100644 index 2a39e45..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs +++ /dev/null @@ -1,17 +0,0 @@ -using dnlib.DotNet; - -namespace Obfuz.ObfusPasses.SymbolObfus -{ - public interface IObfuscationPolicy - { - bool NeedRename(TypeDef typeDef); - - bool NeedRename(MethodDef methodDef); - - bool NeedRename(FieldDef fieldDef); - - bool NeedRename(PropertyDef propertyDef); - - bool NeedRename(EventDef eventDef); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs.meta deleted file mode 100644 index ffe0fee..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bd640b26c1d868544a7a91a0f986fdde -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers.meta deleted file mode 100644 index 9cd6e53..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c970ffd992fbc154aaa37a2c48c24d5c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs deleted file mode 100644 index b7b4e3f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs +++ /dev/null @@ -1,29 +0,0 @@ -using dnlib.DotNet; -using System.Text; - -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - public class DebugNameMaker : NameMakerBase - { - private class TestNameScope : NameScopeBase - { - private int _nextIndex; - protected override void BuildNewName(StringBuilder nameBuilder, string originalName, string lastName) - { - if (string.IsNullOrEmpty(lastName)) - { - nameBuilder.Append($"${originalName}"); - } - else - { - nameBuilder.Append($"${originalName}{_nextIndex++}"); - } - } - } - - protected override INameScope CreateNameScope() - { - return new TestNameScope(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs.meta deleted file mode 100644 index 11b505b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: abc1adfad5c7754499ceed4d4646eb58 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs deleted file mode 100644 index 9fb5a98..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - public interface INameScope - { - void AddPreservedName(string name); - - string GetNewName(string originalName, bool reuse); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs.meta deleted file mode 100644 index 4c63253..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6c3884d338faf564eab48d58f02adc39 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs deleted file mode 100644 index 157aeab..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs +++ /dev/null @@ -1,103 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - public abstract class NameMakerBase : INameMaker - { - - private readonly Dictionary _nameScopes = new Dictionary(); - - private readonly object _namespaceScope = new object(); - - protected abstract INameScope CreateNameScope(); - - protected INameScope GetNameScope(object key) - { - if (!_nameScopes.TryGetValue(key, out var nameScope)) - { - nameScope = CreateNameScope(); - _nameScopes[key] = nameScope; - } - return nameScope; - } - - public void AddPreservedName(TypeDef typeDef, string name) - { - GetNameScope(typeDef.Module).AddPreservedName(name); - } - - public void AddPreservedName(MethodDef methodDef, string name) - { - GetNameScope(methodDef.DeclaringType).AddPreservedName(name); - } - - public void AddPreservedName(FieldDef fieldDef, string name) - { - GetNameScope(fieldDef.DeclaringType).AddPreservedName(name); - } - - public void AddPreservedName(PropertyDef propertyDef, string name) - { - GetNameScope(propertyDef.DeclaringType).AddPreservedName(name); - } - - public void AddPreservedName(EventDef eventDef, string name) - { - GetNameScope(eventDef.DeclaringType).AddPreservedName(name); - } - - public void AddPreservedNamespace(TypeDef typeDef, string name) - { - GetNameScope(_namespaceScope).AddPreservedName(name); - } - - private string GetDefaultNewName(object scope, string originName) - { - return GetNameScope(scope).GetNewName(originName, false); - } - - public string GetNewNamespace(TypeDef typeDef, string originalNamespace, bool reuse) - { - if (string.IsNullOrEmpty(originalNamespace)) - { - return string.Empty; - } - return GetNameScope(_namespaceScope).GetNewName(originalNamespace, reuse); - } - - public string GetNewName(TypeDef typeDef, string originalName) - { - return GetDefaultNewName(typeDef.Module, originalName); - } - - public string GetNewName(MethodDef methodDef, string originalName) - { - return (methodDef.IsVirtual ? ">" : "") + GetDefaultNewName(methodDef.DeclaringType, originalName); - } - - public virtual string GetNewName(ParamDef param, string originalName) - { - return "1"; - } - - public string GetNewName(FieldDef fieldDef, string originalName) - { - return GetDefaultNewName(fieldDef.DeclaringType, originalName); - } - - public string GetNewName(PropertyDef propertyDef, string originalName) - { - return GetDefaultNewName(propertyDef.DeclaringType, originalName); - } - - public string GetNewName(EventDef eventDef, string originalName) - { - return GetDefaultNewName(eventDef.DeclaringType, originalName); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs.meta deleted file mode 100644 index d3ca8a0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 205da3a8ebfd4ae4ba72d27db4b92d3f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs deleted file mode 100644 index b0ba913..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Remoting.Messaging; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - public static class NameMakerFactory - { - public static INameMaker CreateDebugNameMaker() - { - return new DebugNameMaker(); - } - - public static INameMaker CreateNameMakerBaseASCIICharSet(string namePrefix) - { - var words = new List(); - for (int i = 0; i < 26; i++) - { - words.Add(((char)('a' + i)).ToString()); - words.Add(((char)('A' + i)).ToString()); - } - return new WordSetNameMaker(namePrefix, words); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs.meta deleted file mode 100644 index e1fb22c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: afa0e87123ec9854b806098330c4980a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs deleted file mode 100644 index 610f845..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Microsoft.SqlServer.Server; -using System.Collections.Generic; -using System.Text; - -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - - public class NameScope : NameScopeBase - { - private readonly string _namePrefix; - private readonly List _wordSet; - private int _nextIndex; - - public NameScope(string namePrefix, List wordSet) - { - _namePrefix = namePrefix; - _wordSet = wordSet; - _nextIndex = 0; - } - - protected override void BuildNewName(StringBuilder nameBuilder, string originalName, string lastName) - { - nameBuilder.Append(_namePrefix); - for (int i = _nextIndex++; ;) - { - nameBuilder.Append(_wordSet[i % _wordSet.Count]); - i = i / _wordSet.Count; - if (i == 0) - { - break; - } - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs.meta deleted file mode 100644 index e224237..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a35c5c4b49c98a84f94b690c26900c33 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs deleted file mode 100644 index 4f3d213..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using System.Text; - -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - public abstract class NameScopeBase : INameScope - { - - private readonly Dictionary _nameMap = new Dictionary(); - - private readonly HashSet _preservedNames = new HashSet(); - - - public void AddPreservedName(string name) - { - if (!string.IsNullOrEmpty(name)) - { - _preservedNames.Add(name); - } - } - - - protected abstract void BuildNewName(StringBuilder nameBuilder, string originalName, string lastName); - - private string CreateNewName(string originalName) - { - var nameBuilder = new StringBuilder(); - string lastName = null; - while (true) - { - nameBuilder.Clear(); - BuildNewName(nameBuilder, originalName, lastName); - string newName = nameBuilder.ToString(); - lastName = newName; - if (_preservedNames.Add(newName)) - { - return newName; - } - } - } - - public string GetNewName(string originalName, bool reuse) - { - if (!reuse) - { - return CreateNewName(originalName); - } - if (_nameMap.TryGetValue(originalName, out var newName)) - { - return newName; - } - newName = CreateNewName(originalName); - _nameMap[originalName] = newName; - return newName; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs.meta deleted file mode 100644 index 17853c8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 26e6ae1f35e7f094c844cf1567b88a19 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs deleted file mode 100644 index 8e8b5db..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs +++ /dev/null @@ -1,26 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus.NameMakers -{ - - public class WordSetNameMaker : NameMakerBase - { - private readonly string _namePrefix; - private readonly List _wordSet; - - public WordSetNameMaker(string namePrefix, List wordSet) - { - _namePrefix = namePrefix; - _wordSet = wordSet; - } - - protected override INameScope CreateNameScope() - { - return new NameScope(_namePrefix, _wordSet); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs.meta deleted file mode 100644 index 23706b3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 47c92aea40a66e34b92f9eb5c0d380ca -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies.meta deleted file mode 100644 index c16875c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 98e496436c90c0a4f82711af059471c7 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs deleted file mode 100644 index ba6e9c6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs +++ /dev/null @@ -1,68 +0,0 @@ -using dnlib.DotNet; -using System.Collections.Generic; -using System.Linq; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - public class CacheRenamePolicy : ObfuscationPolicyBase - { - private readonly IObfuscationPolicy _underlyingPolicy; - - private readonly Dictionary _computeCache = new Dictionary(); - - public CacheRenamePolicy(IObfuscationPolicy underlyingPolicy) - { - _underlyingPolicy = underlyingPolicy; - } - - public override bool NeedRename(TypeDef typeDef) - { - if (!_computeCache.TryGetValue(typeDef, out var value)) - { - value = _underlyingPolicy.NeedRename(typeDef); - _computeCache[typeDef] = value; - } - return value; - } - - public override bool NeedRename(MethodDef methodDef) - { - if (!_computeCache.TryGetValue(methodDef, out var value)) - { - value = _underlyingPolicy.NeedRename(methodDef); - _computeCache[methodDef] = value; - } - return value; - } - - public override bool NeedRename(FieldDef fieldDef) - { - if (!_computeCache.TryGetValue(fieldDef, out var value)) - { - value = _underlyingPolicy.NeedRename(fieldDef); - _computeCache[fieldDef] = value; - } - return value; - } - - public override bool NeedRename(PropertyDef propertyDef) - { - if (!_computeCache.TryGetValue(propertyDef, out var value)) - { - value = _underlyingPolicy.NeedRename(propertyDef); - _computeCache[propertyDef] = value; - } - return value; - } - - public override bool NeedRename(EventDef eventDef) - { - if (!_computeCache.TryGetValue(eventDef, out var value)) - { - value = _underlyingPolicy.NeedRename(eventDef); - _computeCache[eventDef] = value; - } - return value; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs.meta deleted file mode 100644 index ab4330f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c319b2ad62ad8794f9a8bc234c856d7f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs deleted file mode 100644 index a84a587..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs +++ /dev/null @@ -1,40 +0,0 @@ -using dnlib.DotNet; -using System.Linq; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - public class CombineRenamePolicy : IObfuscationPolicy - { - private readonly IObfuscationPolicy[] _policies; - - public CombineRenamePolicy(params IObfuscationPolicy[] policies) - { - _policies = policies; - } - - public bool NeedRename(TypeDef typeDef) - { - return _policies.All(policy => policy.NeedRename(typeDef)); - } - - public bool NeedRename(MethodDef methodDef) - { - return _policies.All(policy => policy.NeedRename(methodDef)); - } - - public bool NeedRename(FieldDef fieldDef) - { - return _policies.All(policy => policy.NeedRename(fieldDef)); - } - - public bool NeedRename(PropertyDef propertyDef) - { - return _policies.All(policy => policy.NeedRename(propertyDef)); - } - - public bool NeedRename(EventDef eventDef) - { - return _policies.All(policy => policy.NeedRename(eventDef)); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs.meta deleted file mode 100644 index fcf6ea9..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 97be4546adeb71947bf644949c3a9e82 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs deleted file mode 100644 index 7122956..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs +++ /dev/null @@ -1,699 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Conf; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using System.Xml.Linq; -using UnityEngine; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - - public class ConfigurableRenamePolicy : ObfuscationPolicyBase - { - enum RuleType - { - Assembly = 1, - Type = 2, - Method = 3, - Field = 4, - Property = 5, - Event = 6, - } - - enum ModifierType - { - None = 0x0, - Private = 0x1, - Protected = 0x2, - Public = 0x3, - } - - class MethodRuleSpec - { - public NameMatcher nameMatcher; - public ModifierType? modifierType; - public bool? obfuscateName; - } - - class FieldRuleSpec - { - public NameMatcher nameMatcher; - public ModifierType? modifierType; - public bool? obfuscateName; - } - - class PropertyRuleSpec - { - public NameMatcher nameMatcher; - public ModifierType? modifierType; - public bool? obfuscateName; - public bool? obfuscateGetter; - public bool? obfuscateSetter; - } - - class EventRuleSpec - { - public NameMatcher nameMatcher; - public ModifierType? modifierType; - public bool? obfuscateName; - public bool? obfuscateAdd; - public bool? obfuscateRemove; - public bool? obfuscateFire; - } - - class TypeRuleSpec - { - public NameMatcher nameMatcher; - public ModifierType? modifierType; - public ClassType? classType; - public bool? obfuscateName; - public bool? obfuscateNamespace; - public List fields; - public List methods; - public List properties; - public List events; - } - - class AssemblyRuleSpec - { - public string assemblyName; - public bool? obfuscateName; - public List types; - } - - private readonly Dictionary _assemblyRuleSpecs = new Dictionary(); - - private AssemblyRuleSpec ParseAssembly(XmlElement ele) - { - string assemblyName = ele.GetAttribute("name"); - if (string.IsNullOrEmpty(assemblyName)) - { - throw new Exception($"Invalid xml file, assembly name is empty"); - } - if (!_obfuscationAssemblyNames.Contains(assemblyName)) - { - throw new Exception($"unknown assembly name:{assemblyName}, not in ObfuzSettings.obfuscationAssemblyNames"); - } - if (_assemblyRuleSpecs.ContainsKey(assemblyName)) - { - throw new Exception($"Invalid xml file, duplicate assembly name {assemblyName}"); - } - var rule = new AssemblyRuleSpec() - { - assemblyName = assemblyName, - obfuscateName = ConfigUtil.ParseNullableBool(ele.GetAttribute("obName")), - types = new List(), - }; - - foreach (XmlNode node in ele.ChildNodes) - { - if (!(node is XmlElement childElement)) - { - continue; - } - if (childElement.Name != "type") - { - throw new Exception($"Invalid xml file, unknown node {childElement.Name}"); - } - TypeRuleSpec type = ParseType(childElement); - rule.types.Add(type); - } - return rule; - } - - private enum ClassType - { - None = 0x0, - Class = 0x1, - Struct = 0x2, - Interface = 0x4, - Enum = 0x8, - Delegate = 0x10, - } - - private ClassType? ParseClassType(string classType) - { - if (string.IsNullOrEmpty(classType)) - { - return null; - } - - ClassType type = ClassType.None; - foreach (var s in classType.Split('|')) - { - switch (s) - { - case "class": type |= ClassType.Class; break; - case "struct": type |= ClassType.Struct; break; - case "interface": type |= ClassType.Interface; break; - case "enum": type |= ClassType.Enum; break; - case "delegate": type |= ClassType.Delegate; break; - default: throw new Exception($"Invalid class type {s}"); - } - } - return type; - } - - private ModifierType? ParseModifierType(string modifierType) - { - if (string.IsNullOrEmpty(modifierType)) - { - return null; - } - ModifierType type = ModifierType.None; - foreach (var s in modifierType.Split('|')) - { - switch (s) - { - case "public": type |= ModifierType.Public; break; - case "protected": type |= ModifierType.Protected; break; - case "private": type |= ModifierType.Private; break; - default: throw new Exception($"Invalid modifier type {s}"); - } - } - return type; - } - - private TypeRuleSpec ParseType(XmlElement element) - { - var rule = new TypeRuleSpec(); - - rule.nameMatcher = new NameMatcher(element.GetAttribute("name")); - rule.obfuscateName = ConfigUtil.ParseNullableBool(element.GetAttribute("obName")); - rule.obfuscateNamespace = ConfigUtil.ParseNullableBool(element.GetAttribute("obNamespace")); - rule.modifierType = ParseModifierType(element.GetAttribute("modifier")); - rule.classType = ParseClassType(element.GetAttribute("classType")); - - //rule.nestTypeRuleSpecs = new List(); - rule.fields = new List(); - rule.methods = new List(); - rule.properties = new List(); - rule.events = new List(); - foreach (XmlNode node in element.ChildNodes) - { - if (!(node is XmlElement childElement)) - { - continue; - } - switch (childElement.Name) - { - case "field": - { - var fieldRuleSpec = new FieldRuleSpec(); - fieldRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); - fieldRuleSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); - fieldRuleSpec.obfuscateName = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obName")); - rule.fields.Add(fieldRuleSpec); - break; - } - case "method": - { - var methodRuleSpec = new MethodRuleSpec(); - methodRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); - methodRuleSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); - methodRuleSpec.obfuscateName = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obName")); - rule.methods.Add(methodRuleSpec); - break; - } - case "property": - { - var propertyRulerSpec = new PropertyRuleSpec(); - propertyRulerSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); - propertyRulerSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); - propertyRulerSpec.obfuscateName = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obName")); - propertyRulerSpec.obfuscateGetter = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obGetter")); - propertyRulerSpec.obfuscateSetter = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obSetter")); - rule.properties.Add(propertyRulerSpec); - break; - } - case "event": - { - var eventRuleSpec = new EventRuleSpec(); - eventRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); - eventRuleSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); - eventRuleSpec.obfuscateName = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obName")); - eventRuleSpec.obfuscateAdd = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obAdd")); - eventRuleSpec.obfuscateRemove = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obRemove")); - eventRuleSpec.obfuscateFire = ConfigUtil.ParseNullableBool(childElement.GetAttribute("obFire")); - rule.events.Add(eventRuleSpec); - break; - } - default: throw new Exception($"Invalid xml file, unknown node {childElement.Name} in type node"); - } - } - return rule; - } - - private void LoadXmls(List xmlFiles) - { - var rawAssemblySpecElements = new List(); - foreach (string file in xmlFiles) - { - LoadRawXml(file, rawAssemblySpecElements); - } - ResolveAssemblySpecs(rawAssemblySpecElements); - } - - private void ResolveAssemblySpecs(List rawAssemblySpecElements) - { - foreach (XmlElement ele in rawAssemblySpecElements) - { - var assemblyRule = ParseAssembly(ele); - _assemblyRuleSpecs.Add(assemblyRule.assemblyName, assemblyRule); - } - } - - private void LoadRawXml(string xmlFile, List rawAssemblyElements) - { - Debug.Log($"ObfuscateRule::LoadXml {xmlFile}"); - var doc = new XmlDocument(); - doc.Load(xmlFile); - var root = doc.DocumentElement; - if (root.Name != "obfuz") - { - throw new Exception($"Invalid xml file {xmlFile}, root name should be 'obfuz'"); - } - foreach (XmlNode node in root.ChildNodes) - { - if (!(node is XmlElement element)) - { - continue; - } - switch (element.Name) - { - case "assembly": - { - rawAssemblyElements.Add(element); - break; - } - default: - { - throw new Exception($"Invalid xml file {xmlFile}, unknown node {element.Name}"); - } - } - } - } - - private ModifierType ComputeModifierType(TypeAttributes visibility) - { - if (visibility == TypeAttributes.NotPublic || visibility == TypeAttributes.NestedPrivate) - { - return ModifierType.Private; - } - if (visibility == TypeAttributes.Public || visibility == TypeAttributes.NestedPublic) - { - return ModifierType.Public; - } - return ModifierType.Protected; - } - - private ModifierType ComputeModifierType(FieldAttributes access) - { - if (access == FieldAttributes.Private || access == FieldAttributes.PrivateScope) - { - return ModifierType.Private; - } - if (access == FieldAttributes.Public) - { - return ModifierType.Public; - } - return ModifierType.Protected; - } - - //private ModifierType ComputeModifierType(MethodAttributes access) - //{ - // if (access == MethodAttributes.Private || access == MethodAttributes.PrivateScope) - // { - // return ModifierType.Private; - // } - // if (access == MethodAttributes.Public) - // { - // return ModifierType.Public; - // } - // return ModifierType.Protected; - //} - - private bool MatchModifier(ModifierType? modifierType, TypeDef typeDef) - { - return modifierType == null || (modifierType & ComputeModifierType(typeDef.Visibility)) != 0; - } - - private bool MatchModifier(ModifierType? modifierType, FieldDef fieldDef) - { - return modifierType == null || (modifierType & ComputeModifierType(fieldDef.Access)) != 0; - } - - private bool MatchModifier(ModifierType? modifierType, MethodDef methodDef) - { - return modifierType == null || (modifierType & ComputeModifierType((FieldAttributes)methodDef.Access)) != 0; - } - - private bool MatchModifier(ModifierType? modifierType, PropertyDef propertyDef) - { - return modifierType == null || (modifierType & ComputeModifierType((FieldAttributes)propertyDef.Attributes)) != 0; - } - - private bool MatchModifier(ModifierType? modifierType, EventDef eventDef) - { - return modifierType == null || (modifierType & ComputeModifierType((FieldAttributes)eventDef.Attributes)) != 0; - } - - private class MethodComputeCache - { - public bool obfuscateName = true; - public bool obfuscateParam = true; - public bool obfuscateBody = true; - } - - //private class TypeDefComputeCache - //{ - // public bool obfuscateName = true; - // public bool obfuscateNamespace = true; - - // public readonly Dictionary methods = new Dictionary(); - - // public readonly HashSet notObfuscatedFields = new HashSet(); - - // public readonly HashSet notObfuscatedProperties = new HashSet(); - - // public readonly HashSet notObfuscatedEvents = new HashSet(); - //} - - private readonly Dictionary _typeSpecCache = new Dictionary(); - private readonly Dictionary _methodSpecCache = new Dictionary(); - private readonly Dictionary _fieldSpecCache = new Dictionary(); - private readonly Dictionary _propertySpecCache = new Dictionary(); - private readonly Dictionary _eventSpecCache = new Dictionary(); - - - private readonly HashSet _obfuscationAssemblyNames; - - public ConfigurableRenamePolicy(List obfuscationAssemblyNames, List xmlFiles) - { - _obfuscationAssemblyNames = new HashSet(obfuscationAssemblyNames); - LoadXmls(xmlFiles); - } - - private void BuildDefaultTypeMemberCache(TypeDef typeDef, TypeRuleSpec typeRule) - { - foreach (var fieldDef in typeDef.Fields) - { - var fieldRule = new FieldRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - }; - _fieldSpecCache.Add(fieldDef, fieldRule); - } - foreach (var eventDef in typeDef.Events) - { - var eventRule = new EventRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - obfuscateAdd = typeRule.obfuscateName, - obfuscateRemove = typeRule.obfuscateName, - obfuscateFire = typeRule.obfuscateName, - }; - _eventSpecCache.Add(eventDef, eventRule); - } - foreach (var propertyDef in typeDef.Properties) - { - var propertyRule = new PropertyRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - obfuscateGetter = typeRule.obfuscateName, - obfuscateSetter = typeRule.obfuscateName, - }; - _propertySpecCache.Add(propertyDef, propertyRule); - } - foreach (MethodDef methodDef in typeDef.Methods) - { - var methodRule = new MethodRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - }; - _methodSpecCache.Add(methodDef, methodRule); - } - } - - private bool MatchClassType(ClassType? classType, TypeDef typeDef) - { - if (classType == null) - { - return true; - } - if (typeDef.IsInterface && (classType & ClassType.Interface) != 0) - { - return true; - } - if (typeDef.IsEnum && (classType & ClassType.Enum) != 0) - { - return true; - } - if (typeDef.IsDelegate && (classType & ClassType.Delegate) != 0) - { - return true; - } - if (typeDef.IsValueType && !typeDef.IsEnum && (classType & ClassType.Struct) != 0) - { - return true; - } - if (!typeDef.IsValueType && !typeDef.IsInterface && !typeDef.IsDelegate && (classType & ClassType.Class) != 0) - { - return true; - } - return false; - } - - private TypeRuleSpec GetOrCreateTypeDefRenameComputeCache(TypeDef typeDef) - { - if (_typeSpecCache.TryGetValue(typeDef, out var typeRule)) - { - return typeRule; - } - typeRule = new TypeRuleSpec(); - _typeSpecCache.Add(typeDef, typeRule); - - if (!_assemblyRuleSpecs.TryGetValue(typeDef.Module.Assembly.Name, out var assemblyRuleSpec)) - { - typeRule.obfuscateName = true; - typeRule.obfuscateNamespace = true; - BuildDefaultTypeMemberCache(typeDef, typeRule); - return typeRule; - } - - typeRule.obfuscateName = assemblyRuleSpec.obfuscateName ?? true; - typeRule.obfuscateNamespace = assemblyRuleSpec.obfuscateName ?? true; - - if (typeDef.DeclaringType != null) - { - TypeRuleSpec declaringTypeSpec = GetOrCreateTypeDefRenameComputeCache(typeDef.DeclaringType); - if (declaringTypeSpec.obfuscateName != null) - { - typeRule.obfuscateName = declaringTypeSpec.obfuscateName; - } - if (declaringTypeSpec.obfuscateNamespace != null) - { - typeRule.obfuscateNamespace = declaringTypeSpec.obfuscateNamespace; - } - } - - string typeName = typeDef.FullName; - bool findMatch = false; - foreach (var typeSpec in assemblyRuleSpec.types) - { - if (!typeSpec.nameMatcher.IsMatch(typeName) || !MatchModifier(typeSpec.modifierType, typeDef) || !MatchClassType(typeSpec.classType, typeDef)) - { - continue; - } - findMatch = true; - if (typeSpec.obfuscateName != null) - { - typeRule.obfuscateName = typeSpec.obfuscateName; - } - if (typeSpec.obfuscateNamespace != null) - { - typeRule.obfuscateNamespace = typeSpec.obfuscateNamespace; - } - - - foreach (var fieldDef in typeDef.Fields) - { - var fieldRule = new FieldRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - }; - _fieldSpecCache.Add(fieldDef, fieldRule); - foreach (var fieldSpec in typeSpec.fields) - { - if (fieldSpec.nameMatcher.IsMatch(fieldDef.Name) && MatchModifier(fieldSpec.modifierType, fieldDef)) - { - if (fieldSpec.obfuscateName != null) - { - fieldRule.obfuscateName = fieldSpec.obfuscateName; - } - break; - } - } - } - - var methodObfuscateFromPropertyOrEvent = new Dictionary(); - - foreach (var eventDef in typeDef.Events) - { - var eventRule = new EventRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - obfuscateAdd = typeRule.obfuscateName, - obfuscateRemove = typeRule.obfuscateName, - obfuscateFire = typeRule.obfuscateName, - }; - _eventSpecCache.Add(eventDef, eventRule); - foreach (var eventSpec in typeSpec.events) - { - if (!eventSpec.nameMatcher.IsMatch(eventDef.Name) || !MatchModifier(eventSpec.modifierType, eventDef)) - { - continue; - } - if (eventSpec.obfuscateName != null) - { - eventRule.obfuscateName = eventSpec.obfuscateName; - } - if (eventSpec.obfuscateAdd != null) - { - eventRule.obfuscateAdd = eventSpec.obfuscateAdd; - } - if (eventSpec.obfuscateRemove != null) - { - eventRule.obfuscateRemove = eventSpec.obfuscateRemove; - } - if (eventSpec.obfuscateFire != null) - { - eventRule.obfuscateFire = eventSpec.obfuscateFire; - } - if (eventDef.AddMethod != null && eventRule.obfuscateAdd != null) - { - methodObfuscateFromPropertyOrEvent.Add(eventDef.AddMethod, eventRule.obfuscateAdd.Value); - } - if (eventDef.RemoveMethod != null && eventRule.obfuscateRemove != null) - { - methodObfuscateFromPropertyOrEvent.Add(eventDef.RemoveMethod, eventRule.obfuscateRemove.Value); - } - if (eventDef.InvokeMethod != null && eventRule.obfuscateFire != null) - { - methodObfuscateFromPropertyOrEvent.Add(eventDef.InvokeMethod, eventRule.obfuscateFire.Value); - } - break; - } - } - foreach (var propertyDef in typeDef.Properties) - { - var propertyRule = new PropertyRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - obfuscateGetter = typeRule.obfuscateName, - obfuscateSetter = typeRule.obfuscateName, - }; - _propertySpecCache.Add(propertyDef, propertyRule); - foreach (var propertySpec in typeSpec.properties) - { - if (!propertySpec.nameMatcher.IsMatch(propertyDef.Name) || !MatchModifier(propertySpec.modifierType, propertyDef)) - { - continue; - } - if (propertySpec.obfuscateName != null) - { - propertyRule.obfuscateName = propertySpec.obfuscateName; - } - if (propertySpec.obfuscateGetter != null) - { - propertyRule.obfuscateGetter = propertySpec.obfuscateGetter; - } - if (propertySpec.obfuscateSetter != null) - { - propertyRule.obfuscateSetter = propertySpec.obfuscateSetter; - } - - if (propertyDef.GetMethod != null && propertyRule.obfuscateGetter != null) - { - methodObfuscateFromPropertyOrEvent.Add(propertyDef.GetMethod, propertyRule.obfuscateGetter.Value); - } - if (propertyDef.SetMethod != null && propertyRule.obfuscateSetter != null) - { - methodObfuscateFromPropertyOrEvent.Add(propertyDef.SetMethod, propertyRule.obfuscateSetter.Value); - } - break; - } - } - foreach (MethodDef methodDef in typeDef.Methods) - { - var methodRule = new MethodRuleSpec() - { - obfuscateName = typeRule.obfuscateName, - }; - _methodSpecCache.Add(methodDef, methodRule); - if (methodObfuscateFromPropertyOrEvent.TryGetValue(methodDef, out var obfuscateName)) - { - methodRule.obfuscateName = obfuscateName; - } - foreach (MethodRuleSpec methodSpec in typeSpec.methods) - { - if (!methodSpec.nameMatcher.IsMatch(methodDef.Name) || !MatchModifier(methodSpec.modifierType, methodDef)) - { - continue; - } - if (methodSpec.obfuscateName != null) - { - methodRule.obfuscateName = methodSpec.obfuscateName; - } - break; - } - } - } - if (!findMatch) - { - BuildDefaultTypeMemberCache(typeDef, typeRule); - } - - return typeRule; - } - - public override bool NeedRename(TypeDef typeDef) - { - var cache = GetOrCreateTypeDefRenameComputeCache(typeDef); - return cache.obfuscateName != false; - } - - public override bool NeedRename(MethodDef methodDef) - { - TypeDef typeDef = methodDef.DeclaringType; - GetOrCreateTypeDefRenameComputeCache(typeDef); - return _methodSpecCache[methodDef].obfuscateName != false; - } - - public override bool NeedRename(FieldDef fieldDef) - { - TypeDef typeDef = fieldDef.DeclaringType; - GetOrCreateTypeDefRenameComputeCache(typeDef); - return _fieldSpecCache[fieldDef].obfuscateName != false; - } - - public override bool NeedRename(PropertyDef propertyDef) - { - TypeDef typeDef = propertyDef.DeclaringType; - GetOrCreateTypeDefRenameComputeCache(typeDef); - return _propertySpecCache[propertyDef].obfuscateName != false; - } - - public override bool NeedRename(EventDef eventDef) - { - TypeDef typeDef = eventDef.DeclaringType; - GetOrCreateTypeDefRenameComputeCache(typeDef); - return _eventSpecCache[eventDef].obfuscateName != false; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs.meta deleted file mode 100644 index e6b4fee..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9c063bc949939fe44972c3d99870527e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs deleted file mode 100644 index 6a271ad..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs +++ /dev/null @@ -1,33 +0,0 @@ -using dnlib.DotNet; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - public abstract class ObfuscationPolicyBase : IObfuscationPolicy - { - - public virtual bool NeedRename(TypeDef typeDef) - { - return true; - } - - public virtual bool NeedRename(MethodDef methodDef) - { - return true; - } - - public virtual bool NeedRename(FieldDef fieldDef) - { - return true; - } - - public virtual bool NeedRename(PropertyDef propertyDef) - { - return true; - } - - public virtual bool NeedRename(EventDef eventDef) - { - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs.meta deleted file mode 100644 index 2d0bf05..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6ab98107a2ef9624b9b8a53061f682c3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs deleted file mode 100644 index 1d0cb6b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs +++ /dev/null @@ -1,50 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - internal class SupportPassPolicy : ObfuscationPolicyBase - { - private readonly ConfigurablePassPolicy _policy; - - - private bool Support(ObfuscationPassType passType) - { - return passType.HasFlag(ObfuscationPassType.SymbolObfus); - } - - public SupportPassPolicy(ConfigurablePassPolicy policy) - { - _policy = policy; - } - - public override bool NeedRename(TypeDef typeDef) - { - return Support(_policy.GetTypeObfuscationPasses(typeDef)); - } - - public override bool NeedRename(MethodDef methodDef) - { - return Support(_policy.GetMethodObfuscationPasses(methodDef)); - } - - public override bool NeedRename(FieldDef fieldDef) - { - return Support(_policy.GetFieldObfuscationPasses(fieldDef)); - } - - public override bool NeedRename(PropertyDef propertyDef) - { - return Support(_policy.GetPropertyObfuscationPasses(propertyDef)); - } - - public override bool NeedRename(EventDef eventDef) - { - return Support(_policy.GetEventObfuscationPasses(eventDef)); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs.meta deleted file mode 100644 index bf7d3b8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 584dd4d4e9b9fa64090611d84b50980b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs deleted file mode 100644 index de0854d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs +++ /dev/null @@ -1,83 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Utils; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - public class SystemRenamePolicy : ObfuscationPolicyBase - { - public override bool NeedRename(TypeDef typeDef) - { - string name = typeDef.Name; - if (name == "" || name == "ObfuzIgnoreAttribute") - { - return false; - } - if (MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(typeDef)) - { - return false; - } - return true; - } - - public override bool NeedRename(MethodDef methodDef) - { - if (methodDef.DeclaringType.IsDelegate) - { - return false; - } - if (methodDef.Name == ".ctor" || methodDef.Name == ".cctor") - { - return false; - } - - if (MetaUtil.HasObfuzIgnoreAttribute(methodDef) || MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(methodDef.DeclaringType)) - { - return false; - } - return true; - } - - public override bool NeedRename(FieldDef fieldDef) - { - if (fieldDef.DeclaringType.IsDelegate) - { - return false; - } - if (MetaUtil.HasObfuzIgnoreAttribute(fieldDef) || MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(fieldDef.DeclaringType)) - { - return false; - } - if (fieldDef.DeclaringType.IsEnum && fieldDef.Name == "value__") - { - return false; - } - return true; - } - - public override bool NeedRename(PropertyDef propertyDef) - { - if (propertyDef.DeclaringType.IsDelegate) - { - return false; - } - if (MetaUtil.HasObfuzIgnoreAttribute(propertyDef) || MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(propertyDef.DeclaringType)) - { - return false; - } - return true; - } - - public override bool NeedRename(EventDef eventDef) - { - if (eventDef.DeclaringType.IsDelegate) - { - return false; - } - if (MetaUtil.HasObfuzIgnoreAttribute(eventDef) || MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(eventDef.DeclaringType)) - { - return false; - } - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs.meta deleted file mode 100644 index b7d45e3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7b7b98f2ff075c04aa9bd989f8797f00 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs deleted file mode 100644 index 9878973..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs +++ /dev/null @@ -1,97 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus.Policies -{ - - public class UnityRenamePolicy : ObfuscationPolicyBase - { - private static HashSet s_monoBehaviourEvents = new HashSet { - "Awake", - "OnEnable", - "Start", - "FixedUpdate", - "Update", - "LateUpdate", - "OnDisable", - "OnDestroy", - "OnApplicationQuit", - "OnTriggerEnter", - "OnTriggerExit", - "OnTriggerStay", - "OnCollisionEnter", - "OnCollisionExit", - "OnCollisionStay", - "OnMouseDown", - "OnMouseUp", - "OnMouseEnter", - "OnMouseExit", - "OnMouseOver", - "OnMouseDrag", - "OnBecameVisible", - "OnBecameInvisible", - "OnGUI", - "OnPreRender", - "OnPostRender", - "OnRenderObject", - "OnDrawGizmos", - "OnDrawGizmosSelected", - "OnValidate", - "OnAnimatorIK", - "OnAnimatorMove", - "OnApplicationFocus", - "OnApplicationPause", - "OnAudioFilterRead", - "OnJointBreak", - "OnParticleCollision", - "OnTransformChildrenChanged", - "OnTransformParentChanged", - "OnRectTransformDimensionsChange", - "OnWillRenderObject" -}; - public override bool NeedRename(TypeDef typeDef) - { - if (MetaUtil.IsScriptOrSerializableType(typeDef)) - { - return false; - } - if (typeDef.FullName.StartsWith("UnitySourceGeneratedAssemblyMonoScriptTypes_")) - { - return false; - } - return true; - } - - public override bool NeedRename(MethodDef methodDef) - { - if (MetaUtil.IsInheritFromUnityObject(methodDef.DeclaringType)) - { - return !s_monoBehaviourEvents.Contains(methodDef.Name); - } - if (methodDef.DeclaringType.FullName.StartsWith("UnitySourceGeneratedAssemblyMonoScriptTypes_")) - { - return false; - } - return true; - } - - public override bool NeedRename(FieldDef fieldDef) - { - TypeDef typeDef = fieldDef.DeclaringType; - if (MetaUtil.IsScriptOrSerializableType(typeDef)) - { - return !MetaUtil.IsSerializableField(fieldDef); - } - if (fieldDef.DeclaringType.FullName.StartsWith("UnitySourceGeneratedAssemblyMonoScriptTypes_")) - { - return false; - } - return true; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs.meta deleted file mode 100644 index f8f6f99..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4357f35c667599246b2481b093f41f04 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs deleted file mode 100644 index 791f95d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs +++ /dev/null @@ -1,706 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Xml; -using System.Xml.Linq; -using UnityEngine; - -namespace Obfuz.ObfusPasses.SymbolObfus -{ - - public class RenameRecordMap - { - private enum RenameStatus - { - NotRenamed, - Renamed, - } - - private class RenameRecord - { - public RenameStatus status; - public string signature; - public string oldName; - public string newName; - public string oldStackTraceSignature; // only for MethodDef - public object renameMappingData; - } - - private class RenameMappingField - { - public RenameStatus status; - public string signature; - public string newName; - } - - private class RenameMappingMethod - { - public RenameStatus status; - public string signature; - public string newName; - } - - private class RenameMappingMethodParam - { - public RenameStatus status; - public int index; - public string newName; - } - - private class RenameMappingProperty - { - public RenameStatus status; - public string signature; - public string newName; - } - - private class RenameMappingEvent - { - public RenameStatus status; - public string signature; - public string newName; - } - - private class RenameMappingType - { - public RenameStatus status; - public string oldFullName; - public string newFullName; - - public Dictionary fields = new Dictionary(); - public Dictionary methods = new Dictionary(); - public Dictionary properties = new Dictionary(); - public Dictionary events = new Dictionary(); - } - - private class RenameMappingAssembly - { - public string assName; - - public Dictionary types = new Dictionary(); - } - - private readonly string _mappingFile; - private readonly Dictionary _assemblies = new Dictionary(); - - - private readonly Dictionary _modRenames = new Dictionary(); - private readonly Dictionary _typeRenames = new Dictionary(); - private readonly Dictionary _methodRenames = new Dictionary(); - private readonly Dictionary _paramRenames = new Dictionary(); - private readonly Dictionary _fieldRenames = new Dictionary(); - private readonly Dictionary _propertyRenames = new Dictionary(); - private readonly Dictionary _eventRenames = new Dictionary(); - private readonly Dictionary _virtualMethodGroups = new Dictionary(); - - - public RenameRecordMap(string mappingFile) - { - _mappingFile = mappingFile; - } - - public void Init(List assemblies, INameMaker nameMaker) - { - LoadXmlMappingFile(_mappingFile); - foreach (ModuleDef mod in assemblies) - { - string name = mod.Assembly.Name; - - RenameMappingAssembly rma = _assemblies.GetValueOrDefault(name); - - _modRenames.Add(mod, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = name, - oldName = name, - newName = null, - renameMappingData = rma, - }); - - foreach (TypeDef type in mod.GetTypes()) - { - nameMaker.AddPreservedName(type, name); - nameMaker.AddPreservedNamespace(type, type.Namespace); - string fullTypeName = type.FullName; - RenameMappingType rmt = rma?.types.GetValueOrDefault(fullTypeName); - if (rmt != null) - { - var (newNamespace, newName) = MetaUtil.SplitNamespaceAndName(rmt.newFullName); - nameMaker.AddPreservedNamespace(type, newNamespace); - nameMaker.AddPreservedName(type, newName); - } - - _typeRenames.Add(type, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = fullTypeName, - oldName = fullTypeName, - newName = null, - renameMappingData = rmt, - }); - foreach (MethodDef method in type.Methods) - { - nameMaker.AddPreservedName(method, method.Name); - string methodSig = TypeSigUtil.ComputeMethodDefSignature(method); - nameMaker.AddPreservedName(method, method.Name); - - RenameMappingMethod rmm = rmt?.methods.GetValueOrDefault(methodSig); - if (rmm != null) - { - nameMaker.AddPreservedName(method, rmm.newName); - } - _methodRenames.Add(method, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = methodSig, - oldName = method.Name, - newName = null, - renameMappingData = rmm, - oldStackTraceSignature = MetaUtil.CreateMethodDefIl2CppStackTraceSignature(method), - }); - foreach (Parameter param in method.Parameters) - { - if (param.ParamDef != null) - { - _paramRenames.Add(param.ParamDef, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = param.Name, - oldName = param.Name, - newName = null, - }); - } - } - } - foreach (FieldDef field in type.Fields) - { - nameMaker.AddPreservedName(field, field.Name); - string fieldSig = TypeSigUtil.ComputeFieldDefSignature(field); - RenameMappingField rmf = rmt?.fields.GetValueOrDefault(fieldSig); - if (rmf != null) - { - nameMaker.AddPreservedName(field, rmf.newName); - } - _fieldRenames.Add(field, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = fieldSig, - oldName = field.Name, - newName = null, - renameMappingData = rmf, - }); - } - foreach (PropertyDef property in type.Properties) - { - nameMaker.AddPreservedName(property, property.Name); - string propertySig = TypeSigUtil.ComputePropertyDefSignature(property); - RenameMappingProperty rmp = rmt?.properties.GetValueOrDefault(propertySig); - if (rmp != null) - { - nameMaker.AddPreservedName(property, rmp.newName); - } - _propertyRenames.Add(property, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = propertySig, - oldName = property.Name, - newName = null, - renameMappingData = rmp, - }); - } - foreach (EventDef eventDef in type.Events) - { - nameMaker.AddPreservedName(eventDef, eventDef.Name); - string eventSig = TypeSigUtil.ComputeEventDefSignature(eventDef); - RenameMappingEvent rme = rmt?.events.GetValueOrDefault(eventSig); - if (rme != null) - { - nameMaker.AddPreservedName(eventDef, rme.newName); - } - _eventRenames.Add(eventDef, new RenameRecord - { - status = RenameStatus.NotRenamed, - signature = eventSig, - oldName = eventDef.Name, - newName = null, - renameMappingData = rme, - }); - } - } - } - } - - private void LoadXmlMappingFile(string mappingFile) - { - if (string.IsNullOrEmpty(mappingFile) || !File.Exists(mappingFile)) - { - return; - } - var doc = new XmlDocument(); - doc.Load(mappingFile); - var root = doc.DocumentElement; - foreach (XmlNode node in root.ChildNodes) - { - if (!(node is XmlElement element)) - { - continue; - } - LoadAssemblyMapping(element); - } - } - - private void LoadAssemblyMapping(XmlElement ele) - { - if (ele.Name != "assembly") - { - throw new System.Exception($"Invalid node name: {ele.Name}. Expected 'assembly'."); - } - - var assemblyName = ele.Attributes["name"].Value; - var rma = new RenameMappingAssembly - { - assName = assemblyName, - }; - foreach (XmlNode node in ele.ChildNodes) - { - if (!(node is XmlElement element)) - { - continue; - } - if (element.Name != "type") - { - throw new System.Exception($"Invalid node name: {element.Name}. Expected 'type'."); - } - LoadTypeMapping(element, rma); - } - _assemblies.Add(assemblyName, rma); - } - - private void LoadTypeMapping(XmlElement ele, RenameMappingAssembly ass) - { - var typeName = ele.Attributes["fullName"].Value; - var newTypeName = ele.Attributes["newFullName"].Value; - var rmt = new RenameMappingType - { - oldFullName = typeName, - newFullName = newTypeName, - status = (RenameStatus)System.Enum.Parse(typeof(RenameStatus), ele.Attributes["status"].Value), - }; - foreach (XmlNode node in ele.ChildNodes) - { - if (!(node is XmlElement c)) - { - continue; - } - switch (node.Name) - { - case "field": LoadFieldMapping(c, rmt); break; - case "event": LoadEventMapping(c, rmt); break; - case "property": LoadPropertyMapping(c, rmt); break; - case "method": LoadMethodMapping(c, rmt); break; - default: throw new System.Exception($"Invalid node name:{node.Name}"); - } - } - ass.types.Add(typeName, rmt); - } - - private void LoadMethodMapping(XmlElement ele, RenameMappingType type) - { - string signature = ele.Attributes["signature"].Value; - string newName = ele.Attributes["newName"].Value; - var rmm = new RenameMappingMethod - { - signature = signature, - newName = newName, - status = RenameStatus.Renamed, - }; - type.methods.Add(signature, rmm); - } - - private void LoadFieldMapping(XmlElement ele, RenameMappingType type) - { - string signature = ele.Attributes["signature"].Value; - string newName = ele.Attributes["newName"].Value; - var rmf = new RenameMappingField - { - signature = signature, - newName = newName, - status = RenameStatus.Renamed, - }; - type.fields.Add(signature, rmf); - } - - private void LoadPropertyMapping(XmlElement ele, RenameMappingType type) - { - string signature = ele.Attributes["signature"].Value; - string newName = ele.Attributes["newName"].Value; - var rmp = new RenameMappingProperty - { - signature = signature, - newName = newName, - status = RenameStatus.Renamed, - }; - type.properties.Add(signature, rmp); - } - - private void LoadEventMapping(XmlElement ele, RenameMappingType type) - { - string signature = ele.Attributes["signature"].Value; - string newName = ele.Attributes["newName"].Value; - var rme = new RenameMappingEvent - { - signature = signature, - newName = newName, - status = RenameStatus.Renamed, - }; - type.events.Add(signature, rme); - } - - private List GetSortedValueList(Dictionary dic, Comparison comparer) - { - var list = dic.Values.ToList(); - list.Sort(comparer); - return list; - } - - public void WriteXmlMappingFile() - { - if (string.IsNullOrEmpty(_mappingFile)) - { - return; - } - var doc = new XmlDocument(); - var root = doc.CreateElement("mapping"); - doc.AppendChild(root); - - var sortedModRenames = _modRenames.ToList(); - sortedModRenames.Sort((a, b) => a.Value.oldName.CompareTo(b.Value.oldName)); - foreach (var kvp in sortedModRenames) - { - ModuleDef mod = kvp.Key; - RenameRecord record = kvp.Value; - var assemblyNode = doc.CreateElement("assembly"); - assemblyNode.SetAttribute("name", mod.Assembly.Name); - foreach (TypeDef type in mod.GetTypes()) - { - WriteTypeMapping(assemblyNode, type); - } - root.AppendChild(assemblyNode); - } - - var sortedAsses = GetSortedValueList(_assemblies, (a, b) => a.assName.CompareTo(b.assName)); - foreach (RenameMappingAssembly ass in sortedAsses) - { - if (_modRenames.Keys.Any(m => m.Assembly.Name == ass.assName)) - { - continue; - } - var assemblyNode = doc.CreateElement("assembly"); - assemblyNode.SetAttribute("name", ass.assName); - - var sortedTypes = GetSortedValueList(ass.types, (a, b) => a.oldFullName.CompareTo(b.oldFullName)); - foreach (var type in sortedTypes) - { - WriteTypeMapping(assemblyNode, type.oldFullName, type); - } - root.AppendChild(assemblyNode); - } - Directory.CreateDirectory(Path.GetDirectoryName(_mappingFile)); - doc.Save(_mappingFile); - Debug.Log($"Mapping file saved to {Path.GetFullPath(_mappingFile)}"); - } - - private void WriteTypeMapping(XmlElement assNode, TypeDef type) - { - _typeRenames.TryGetValue(type, out var record); - var typeNode = assNode.OwnerDocument.CreateElement("type"); - typeNode.SetAttribute("fullName", record?.signature ?? type.FullName); - typeNode.SetAttribute("newFullName", record != null && record.status == RenameStatus.Renamed ? record.newName : ""); - typeNode.SetAttribute("status", record != null ? record.status.ToString() : RenameStatus.NotRenamed.ToString()); - - foreach (FieldDef field in type.Fields) - { - WriteFieldMapping(typeNode, field); - } - foreach (PropertyDef property in type.Properties) - { - WritePropertyMapping(typeNode, property); - } - foreach (EventDef eventDef in type.Events) - { - WriteEventMapping(typeNode, eventDef); - } - foreach (MethodDef method in type.Methods) - { - WriteMethodMapping(typeNode, method); - } - if ((record != null && record.status == RenameStatus.Renamed) || typeNode.ChildNodes.Count > 0) - { - assNode.AppendChild(typeNode); - } - } - - private void WriteTypeMapping(XmlElement assNode, string fullName, RenameMappingType type) - { - var typeNode = assNode.OwnerDocument.CreateElement("type"); - typeNode.SetAttribute("fullName", fullName); - typeNode.SetAttribute("newFullName", type.status == RenameStatus.Renamed ? type.newFullName : ""); - typeNode.SetAttribute("status", type.status.ToString()); - - foreach (var e in type.fields) - { - string signature = e.Key; - RenameMappingField field = e.Value; - WriteFieldMapping(typeNode, e.Key, e.Value); - } - foreach (var e in type.properties) - { - WritePropertyMapping(typeNode, e.Key, e.Value); - } - foreach (var e in type.events) - { - WriteEventMapping(typeNode, e.Key, e.Value); - } - foreach (var e in type.methods) - { - WriteMethodMapping(typeNode, e.Key, e.Value); - } - - assNode.AppendChild(typeNode); - } - - private void WriteFieldMapping(XmlElement typeEle, FieldDef field) - { - if (!_fieldRenames.TryGetValue(field, out var record) || record.status == RenameStatus.NotRenamed) - { - return; - } - var fieldNode = typeEle.OwnerDocument.CreateElement("field"); - fieldNode.SetAttribute("signature", record?.signature); - fieldNode.SetAttribute("newName", record.newName); - //fieldNode.SetAttribute("status", record.status.ToString()); - typeEle.AppendChild(fieldNode); - } - - private void WriteFieldMapping(XmlElement typeEle, string signature, RenameMappingField field) - { - var fieldNode = typeEle.OwnerDocument.CreateElement("field"); - fieldNode.SetAttribute("signature", signature); - fieldNode.SetAttribute("newName", field.newName); - //fieldNode.SetAttribute("status", record.status.ToString()); - typeEle.AppendChild(fieldNode); - } - - private void WritePropertyMapping(XmlElement typeEle, PropertyDef property) - { - if (!_propertyRenames.TryGetValue(property, out var record) || record.status == RenameStatus.NotRenamed) - { - return; - } - var propertyNode = typeEle.OwnerDocument.CreateElement("property"); - propertyNode.SetAttribute("signature", record.signature); - propertyNode.SetAttribute("newName", record.newName); - //propertyNode.SetAttribute("status", record.status.ToString()); - typeEle.AppendChild(propertyNode); - } - - private void WritePropertyMapping(XmlElement typeEle, string signature, RenameMappingProperty property) - { - var propertyNode = typeEle.OwnerDocument.CreateElement("property"); - propertyNode.SetAttribute("signature", signature); - propertyNode.SetAttribute("newName", property.newName); - //propertyNode.SetAttribute("status", record.status.ToString()); - typeEle.AppendChild(propertyNode); - } - - private void WriteEventMapping(XmlElement typeEle, EventDef eventDef) - { - if (!_eventRenames.TryGetValue(eventDef, out var record) || record.status == RenameStatus.NotRenamed) - { - return; - } - var eventNode = typeEle.OwnerDocument.CreateElement("event"); - eventNode.SetAttribute("signature", record.signature); - eventNode.SetAttribute("newName", record.newName); - typeEle.AppendChild(eventNode); - } - - private void WriteEventMapping(XmlElement typeEle, string signature, RenameMappingEvent eventDef) - { - var eventNode = typeEle.OwnerDocument.CreateElement("event"); - eventNode.SetAttribute("signature", signature); - eventNode.SetAttribute("newName", eventDef.newName); - typeEle.AppendChild(eventNode); - } - - private void WriteMethodMapping(XmlElement typeEle, MethodDef method) - { - if (!_methodRenames.TryGetValue(method, out var record) || record.status == RenameStatus.NotRenamed) - { - return; - } - var methodNode = typeEle.OwnerDocument.CreateElement("method"); - methodNode.SetAttribute("signature", record.signature); - methodNode.SetAttribute("newName", record.newName); - methodNode.SetAttribute("oldStackTraceSignature", record.oldStackTraceSignature); - methodNode.SetAttribute("newStackTraceSignature", MetaUtil.CreateMethodDefIl2CppStackTraceSignature(method)); - //methodNode.SetAttribute("status", record != null ? record.status.ToString() : RenameStatus.NotRenamed.ToString()); - foreach (Parameter param in method.Parameters) - { - if (param.ParamDef != null) - { - WriteMethodParamMapping(methodNode, param.ParamDef); - } - } - typeEle.AppendChild(methodNode); - } - - private void WriteMethodMapping(XmlElement typeEle, string signature, RenameMappingMethod method) - { - var methodNode = typeEle.OwnerDocument.CreateElement("method"); - methodNode.SetAttribute("signature", signature); - methodNode.SetAttribute("newName", method.newName); - typeEle.AppendChild(methodNode); - } - - private void WriteMethodParamMapping(XmlElement methodEle, ParamDef param) - { - if (!_paramRenames.TryGetValue(param, out var record) || record.status == RenameStatus.NotRenamed) - { - return; - } - var paramNode = methodEle.OwnerDocument.CreateElement("param"); - paramNode.SetAttribute("index", param.Sequence.ToString()); - paramNode.SetAttribute("newName", record.newName); - //paramNode.SetAttribute("status", record.status.ToString()); - methodEle.AppendChild(paramNode); - } - - public void AddRename(ModuleDef mod, string newName) - { - RenameRecord record = _modRenames[mod]; - record.status = RenameStatus.Renamed; - record.newName = newName; - } - - public void AddRename(TypeDef type, string newName) - { - RenameRecord record = _typeRenames[type]; - record.status = RenameStatus.Renamed; - record.newName = newName; - } - - public void AddRename(MethodDef method, string newName) - { - RenameRecord record = _methodRenames[method]; - record.status = RenameStatus.Renamed; - record.newName = newName; - } - - public void InitAndAddRename(VirtualMethodGroup methodGroup, string newName) - { - RenameRecord methodRecord = _methodRenames[methodGroup.methods[0]]; - _virtualMethodGroups.Add(methodGroup, new RenameRecord - { - status = RenameStatus.Renamed, - signature = methodRecord.signature, - oldName = methodRecord.oldName, - newName = newName, - }); - } - - public void AddRename(FieldDef field, string newName) - { - RenameRecord record = _fieldRenames[field]; - record.status = RenameStatus.Renamed; - record.newName = newName; - } - - public void AddRename(PropertyDef property, string newName) - { - RenameRecord record = _propertyRenames[property]; - record.status = RenameStatus.Renamed; - record.newName = newName; - } - - public void AddRename(EventDef eventDef, string newName) - { - RenameRecord record = _eventRenames[eventDef]; - record.status = RenameStatus.Renamed; - record.newName = newName; - } - - public bool TryGetExistRenameMapping(TypeDef type, out string newNamespace, out string newName) - { - if (_typeRenames.TryGetValue(type, out var record) && record.renameMappingData != null) - { - var rmt = (RenameMappingType)record.renameMappingData; - (newNamespace, newName) = MetaUtil.SplitNamespaceAndName(rmt.newFullName); - return true; - } - newNamespace = null; - newName = null; - return false; - } - - public bool TryGetExistRenameMapping(MethodDef method, out string newName) - { - if (_methodRenames.TryGetValue(method, out var record) && record.renameMappingData != null) - { - newName = ((RenameMappingMethod)record.renameMappingData).newName; - return true; - } - newName = null; - return false; - } - - public bool TryGetExistRenameMapping(FieldDef field, out string newName) - { - if (_fieldRenames.TryGetValue(field, out var record) && record.renameMappingData != null) - { - newName = ((RenameMappingField)record.renameMappingData).newName; - return true; - } - newName = null; - return false; - } - - public bool TryGetExistRenameMapping(PropertyDef property, out string newName) - { - if (_propertyRenames.TryGetValue(property, out var record) && record.renameMappingData != null) - { - newName = ((RenameMappingProperty)record.renameMappingData).newName; - return true; - } - newName = null; - return false; - } - - public bool TryGetExistRenameMapping(EventDef eventDef, out string newName) - { - if (_eventRenames.TryGetValue(eventDef, out var record) && record.renameMappingData != null) - { - newName = ((RenameMappingEvent)record.renameMappingData).newName; - return true; - } - newName = null; - return false; - } - - public bool TryGetRename(VirtualMethodGroup group, out string newName) - { - if (_virtualMethodGroups.TryGetValue(group, out var record)) - { - newName = record.newName; - return true; - } - newName = null; - return false; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs.meta deleted file mode 100644 index 2a91341..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a3ffbd28624d87c4382f62eb4fc19c70 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs deleted file mode 100644 index 2501f1d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Obfuz.Settings; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus -{ - public class SymbolObfusPass : ObfuscationPassBase - { - private SymbolRename _symbolRename; - - public override ObfuscationPassType Type => ObfuscationPassType.SymbolObfus; - - public SymbolObfusPass(SymbolObfuscationSettings settings) - { - _symbolRename = new SymbolRename(settings); - } - - public override void Start() - { - _symbolRename.Init(); - } - - public override void Stop() - { - _symbolRename.Save(); - } - - public override void Process() - { - _symbolRename.Process(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs.meta deleted file mode 100644 index a86c04b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a4c9a37b51ade6b46a299be7ad2155d6 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs deleted file mode 100644 index cda7d4f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs +++ /dev/null @@ -1,759 +0,0 @@ -using dnlib.DotNet; -using Obfuz.ObfusPasses.SymbolObfus; -using Obfuz.ObfusPasses.SymbolObfus.NameMakers; -using Obfuz.ObfusPasses.SymbolObfus.Policies; -using Obfuz.Settings; -using Obfuz.Utils; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data.OleDb; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using UnityEditor.SceneManagement; -using UnityEngine; -using UnityEngine.Assertions; - -namespace Obfuz.ObfusPasses.SymbolObfus -{ - public class SymbolRename - { - private readonly bool _useConsistentNamespaceObfuscation; - private readonly List _obfuscationRuleFiles; - private readonly string _mappingXmlPath; - - private AssemblyCache _assemblyCache; - - private List _toObfuscatedModules; - private List _obfuscatedAndNotObfuscatedModules; - private HashSet _toObfuscatedModuleSet; - private IObfuscationPolicy _renamePolicy; - private INameMaker _nameMaker; - private readonly Dictionary> _customAttributeArgumentsWithTypeByMods = new Dictionary>(); - private readonly RenameRecordMap _renameRecordMap; - private readonly VirtualMethodGroupCalculator _virtualMethodGroupCalculator; - - class CustomAttributeInfo - { - public CustomAttributeCollection customAttributes; - public int index; - public List arguments; - public List namedArguments; - } - - public SymbolRename(SymbolObfuscationSettings settings) - { - _useConsistentNamespaceObfuscation = settings.useConsistentNamespaceObfuscation; - _mappingXmlPath = settings.symbolMappingFile; - _obfuscationRuleFiles = settings.ruleFiles.ToList(); - _renameRecordMap = new RenameRecordMap(settings.debug ? null : settings.symbolMappingFile); - _virtualMethodGroupCalculator = new VirtualMethodGroupCalculator(); - _nameMaker = settings.debug ? NameMakerFactory.CreateDebugNameMaker() : NameMakerFactory.CreateNameMakerBaseASCIICharSet(settings.obfuscatedNamePrefix); - } - - public void Init() - { - var ctx = ObfuscationPassContext.Current; - _assemblyCache = ctx.assemblyCache; - _toObfuscatedModules = ctx.modulesToObfuscate; - _obfuscatedAndNotObfuscatedModules = ctx.allObfuscationRelativeModules; - _toObfuscatedModuleSet = new HashSet(ctx.modulesToObfuscate); - var obfuscateRuleConfig = new ConfigurableRenamePolicy(ctx.assembliesToObfuscate, _obfuscationRuleFiles); - _renamePolicy = new CacheRenamePolicy(new CombineRenamePolicy(new SupportPassPolicy(ctx.passPolicy), new SystemRenamePolicy(), new UnityRenamePolicy(), obfuscateRuleConfig)); - BuildCustomAttributeArguments(); - } - - private void CollectCArgumentWithTypeOf(IHasCustomAttribute meta, List customAttributes) - { - int index = 0; - foreach (CustomAttribute ca in meta.CustomAttributes) - { - List arguments = null; - if (ca.ConstructorArguments.Any(a => MetaUtil.MayRenameCustomDataType(a.Type.ElementType))) - { - arguments = ca.ConstructorArguments.ToList(); - } - List namedArguments = null; - if (ca.NamedArguments.Any(a => MetaUtil.MayRenameCustomDataType(a.Type.ElementType))) - { - namedArguments = ca.NamedArguments.ToList(); - } - if (arguments != null | namedArguments != null) - { - customAttributes.Add(new CustomAttributeInfo - { - customAttributes = meta.CustomAttributes, - index = index, - arguments = arguments, - namedArguments = namedArguments - }); - } - ++index; - } - } - - private void BuildCustomAttributeArguments() - { - foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules) - { - var customAttributes = new List(); - CollectCArgumentWithTypeOf(mod, customAttributes); - foreach (TypeDef type in mod.GetTypes()) - { - CollectCArgumentWithTypeOf(type, customAttributes); - foreach (FieldDef field in type.Fields) - { - CollectCArgumentWithTypeOf(field, customAttributes); - } - foreach (MethodDef method in type.Methods) - { - CollectCArgumentWithTypeOf(method, customAttributes); - foreach (Parameter param in method.Parameters) - { - if (param.ParamDef != null) - { - CollectCArgumentWithTypeOf(param.ParamDef, customAttributes); - } - } - } - foreach (PropertyDef property in type.Properties) - { - CollectCArgumentWithTypeOf(property, customAttributes); - } - foreach (EventDef eventDef in type.Events) - { - CollectCArgumentWithTypeOf (eventDef, customAttributes); - } - } - - _customAttributeArgumentsWithTypeByMods.Add(mod, customAttributes); - } - } - - public void Process() - { - _renameRecordMap.Init(_toObfuscatedModules, _nameMaker); - - RenameTypes(); - RenameFields(); - RenameMethods(); - RenameProperties(); - RenameEvents(); - } - - class RefTypeDefMetas - { - public readonly List typeRefs = new List(); - - public readonly List customAttributes = new List(); - } - - private void BuildRefTypeDefMetasMap(Dictionary refTypeDefMetasMap) - { - foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules) - { - foreach (TypeRef typeRef in mod.GetTypeRefs()) - { - if (typeRef.DefinitionAssembly.IsCorLib()) - { - continue; - } - TypeDef typeDef = typeRef.ResolveThrow(); - if (!refTypeDefMetasMap.TryGetValue(typeDef, out var typeDefMetas)) - { - typeDefMetas = new RefTypeDefMetas(); - refTypeDefMetasMap.Add(typeDef, typeDefMetas); - } - typeDefMetas.typeRefs.Add(typeRef); - } - } - - foreach (CustomAttributeInfo cai in _customAttributeArgumentsWithTypeByMods.Values.SelectMany(cas => cas)) - { - CustomAttribute ca = cai.customAttributes[cai.index]; - TypeDef typeDef = MetaUtil.GetTypeDefOrGenericTypeBaseThrowException(ca.Constructor.DeclaringType); - if (!refTypeDefMetasMap.TryGetValue(typeDef, out var typeDefMetas)) - { - typeDefMetas = new RefTypeDefMetas(); - refTypeDefMetasMap.Add(typeDef, typeDefMetas); - } - typeDefMetas.customAttributes.Add(ca); - } - } - - private void RetargetTypeRefInCustomAttributes() - { - foreach (CustomAttributeInfo cai in _customAttributeArgumentsWithTypeByMods.Values.SelectMany(cas => cas)) - { - CustomAttribute ca = cai.customAttributes[cai.index]; - bool anyChange = false; - if (cai.arguments != null) - { - for (int i = 0; i < cai.arguments.Count; i++) - { - CAArgument oldArg = cai.arguments[i]; - if (MetaUtil.TryRetargetTypeRefInArgument(oldArg, out CAArgument newArg)) - { - anyChange = true; - cai.arguments[i] = newArg; - } - } - } - if (cai.namedArguments != null) - { - for (int i = 0; i < cai.namedArguments.Count; i++) - { - if (MetaUtil.TryRetargetTypeRefInNamedArgument(cai.namedArguments[i])) - { - anyChange = true; - } - } - } - if (anyChange) - { - cai.customAttributes[cai.index] = new CustomAttribute(ca.Constructor, - cai.arguments != null ? cai.arguments : ca.ConstructorArguments, - cai.namedArguments != null ? cai.namedArguments : ca.NamedArguments); - } - } - } - - private readonly Dictionary _refTypeRefMetasMap = new Dictionary(); - - private void RenameTypes() - { - Debug.Log("RenameTypes begin"); - - RetargetTypeRefInCustomAttributes(); - - BuildRefTypeDefMetasMap(_refTypeRefMetasMap); - _assemblyCache.EnableTypeDefCache = false; - - foreach (ModuleDef mod in _toObfuscatedModules) - { - foreach (TypeDef type in mod.GetTypes()) - { - if (_renamePolicy.NeedRename(type)) - { - Rename(type, _refTypeRefMetasMap.GetValueOrDefault(type)); - } - } - } - - // clean cache - _assemblyCache.EnableTypeDefCache = true; - Debug.Log("Rename Types end"); - } - - - class RefFieldMetas - { - public readonly List fieldRefs = new List(); - public readonly List customAttributes = new List(); - } - - - private void BuildHierarchyFields(TypeDef type, List fields) - { - while (type != null) - { - fields.AddRange(type.Fields); - type = MetaUtil.GetBaseTypeDef(type); - } - } - - private IEnumerable WalkMemberRefs(ModuleDef mod) - { - foreach (TypeDef type in mod.GetTypes()) - { - foreach (MethodDef method in type.Methods) - { - if (!method.HasBody) - { - continue; - } - foreach (var instr in method.Body.Instructions) - { - if (instr.Operand is MemberRef memberRef) - { - yield return memberRef; - } - } - } - } - } - - private void BuildRefFieldMetasMap(Dictionary refFieldMetasMap) - { - foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules) - { - foreach (MemberRef memberRef in WalkMemberRefs(mod)) - { - if (!memberRef.IsFieldRef) - { - continue; - } - - IMemberRefParent parent = memberRef.Class; - TypeDef parentTypeDef = MetaUtil.GetMemberRefTypeDefParentOrNull(parent); - if (parentTypeDef == null) - { - continue; - } - foreach (FieldDef field in parentTypeDef.Fields) - { - if (field.Name == memberRef.Name && TypeEqualityComparer.Instance.Equals(field.FieldSig.Type, memberRef.FieldSig.Type)) - { - if (!refFieldMetasMap.TryGetValue(field, out var fieldMetas)) - { - fieldMetas = new RefFieldMetas(); - refFieldMetasMap.Add(field, fieldMetas); - } - fieldMetas.fieldRefs.Add(memberRef); - break; - } - } - } - } - foreach (var e in _refTypeRefMetasMap) - { - TypeDef typeDef = e.Key; - var hierarchyFields = new List(); - BuildHierarchyFields(typeDef, hierarchyFields); - RefTypeDefMetas typeDefMetas = e.Value; - foreach (CustomAttribute ca in typeDefMetas.customAttributes) - { - foreach (var arg in ca.NamedArguments) - { - if (arg.IsProperty) - { - continue; - } - foreach (FieldDef field in hierarchyFields) - { - // FIXME. field of Generic Base Type may not be same - if (field.Name == arg.Name && TypeEqualityComparer.Instance.Equals(field.FieldType, arg.Type)) - { - if (!refFieldMetasMap.TryGetValue(field, out var fieldMetas)) - { - fieldMetas = new RefFieldMetas(); - refFieldMetasMap.Add(field, fieldMetas); - } - fieldMetas.customAttributes.Add(ca); - break; - } - } - } - } - } - } - - private void RenameFields() - { - Debug.Log("Rename fields begin"); - var refFieldMetasMap = new Dictionary(); - BuildRefFieldMetasMap(refFieldMetasMap); - - foreach (ModuleDef mod in _toObfuscatedModules) - { - foreach (TypeDef type in mod.GetTypes()) - { - foreach (FieldDef field in type.Fields) - { - if (_renamePolicy.NeedRename(field)) - { - Rename(field, refFieldMetasMap.GetValueOrDefault(field)); - } - } - } - } - Debug.Log("Rename fields end"); - } - - class RefMethodMetas - { - public readonly List memberRefs = new List(); - } - - private void BuildRefMethodMetasMap(Dictionary refMethodMetasMap) - { - foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules) - { - foreach (MemberRef memberRef in WalkMemberRefs(mod)) - { - if (!memberRef.IsMethodRef) - { - continue; - } - - IMemberRefParent parent = memberRef.Class; - TypeDef parentTypeDef = MetaUtil.GetMemberRefTypeDefParentOrNull(parent); - if (parentTypeDef == null) - { - continue; - } - foreach (MethodDef method in parentTypeDef.Methods) - { - if (method.Name == memberRef.Name && new SigComparer(default).Equals(method.MethodSig, memberRef.MethodSig)) - { - if (!refMethodMetasMap.TryGetValue(method, out var refMethodMetas)) - { - refMethodMetas = new RefMethodMetas(); - refMethodMetasMap.Add(method, refMethodMetas); - } - refMethodMetas.memberRefs.Add(memberRef); - break; - } - } - } - } - } - - private void RenameMethods() - { - Debug.Log("Rename methods begin"); - Debug.Log("Rename not virtual methods begin"); - var virtualMethods = new List(); - var refMethodMetasMap = new Dictionary(); - BuildRefMethodMetasMap(refMethodMetasMap); - foreach (ModuleDef mod in _toObfuscatedModules) - { - foreach (TypeDef type in mod.GetTypes()) - { - foreach (MethodDef method in type.Methods) - { - if (method.IsVirtual) - { - continue; - } - if (_renamePolicy.NeedRename(method)) - { - Rename(method, refMethodMetasMap.GetValueOrDefault(method)); - } - } - } - } - - foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules) - { - foreach (TypeDef type in mod.GetTypes()) - { - _virtualMethodGroupCalculator.CalculateType(type); - foreach (MethodDef method in type.Methods) - { - if (method.IsVirtual) - { - virtualMethods.Add(method); - } - } - } - } - - Debug.Log("Rename not virtual methods end"); - - - Debug.Log("Rename virtual methods begin"); - var visitedVirtualMethods = new HashSet(); - var groupNeedRenames = new Dictionary(); - foreach (var method in virtualMethods) - { - if (!visitedVirtualMethods.Add(method)) - { - continue; - } - VirtualMethodGroup group = _virtualMethodGroupCalculator.GetMethodGroup(method); - if (!groupNeedRenames.TryGetValue(group, out var needRename)) - { - needRename = group.methods.All(m => _toObfuscatedModuleSet.Contains(m.DeclaringType.Module) && _renamePolicy.NeedRename(m)); - groupNeedRenames.Add(group, needRename); - if (needRename) - { - _renameRecordMap.InitAndAddRename(group, _renameRecordMap.TryGetExistRenameMapping(method, out var nn) ? nn : _nameMaker.GetNewName(method, method.Name)); - } - } - if (!needRename) - { - continue; - } - if (_renameRecordMap.TryGetRename(group, out var newName)) - { - Rename(method, refMethodMetasMap.GetValueOrDefault(method), newName); - } - else - { - throw new Exception($"group:{group} method:{method} not found in rename record map"); - } - } - Debug.Log("Rename virtual methods end"); - Debug.Log("Rename methods end"); - } - - class RefPropertyMetas - { - public List customAttributes = new List(); - } - - private void BuildHierarchyProperties(TypeDef type, List properties) - { - while (type != null) - { - properties.AddRange(type.Properties); - type = MetaUtil.GetBaseTypeDef(type); - } - } - - private void BuildRefPropertyMetasMap(Dictionary refPropertyMetasMap) - { - foreach (var e in _refTypeRefMetasMap) - { - TypeDef typeDef = e.Key; - var hierarchyProperties = new List(); - BuildHierarchyProperties(typeDef, hierarchyProperties); - RefTypeDefMetas typeDefMetas = e.Value; - foreach (CustomAttribute ca in typeDefMetas.customAttributes) - { - foreach (var arg in ca.NamedArguments) - { - if (arg.IsField) - { - continue; - } - foreach (PropertyDef field in hierarchyProperties) - { - // FIXME. field of Generic Base Type may not be same - if (field.Name == arg.Name && TypeEqualityComparer.Instance.Equals(arg.Type, field.PropertySig.RetType)) - { - if (!refPropertyMetasMap.TryGetValue(field, out var fieldMetas)) - { - fieldMetas = new RefPropertyMetas(); - refPropertyMetasMap.Add(field, fieldMetas); - } - fieldMetas.customAttributes.Add(ca); - break; - } - } - } - } - } - } - - private void RenameProperties() - { - Debug.Log("Rename properties begin"); - var refPropertyMetasMap = new Dictionary(); - BuildRefPropertyMetasMap(refPropertyMetasMap); - foreach (ModuleDef mod in _toObfuscatedModules) - { - foreach (TypeDef type in mod.GetTypes()) - { - foreach (PropertyDef property in type.Properties) - { - if (_renamePolicy.NeedRename(property)) - { - Rename(property, refPropertyMetasMap.GetValueOrDefault(property)); - } - } - } - } - Debug.Log("Rename properties end"); - } - - private void RenameEvents() - { - Debug.Log("Rename events begin"); - foreach (ModuleDef mod in _toObfuscatedModules) - { - foreach (TypeDef type in mod.GetTypes()) - { - foreach (EventDef eventDef in type.Events) - { - if (_renamePolicy.NeedRename(eventDef)) - { - Rename(eventDef); - } - } - } - } - Debug.Log("Rename events begin"); - } - - //private void Rename(ModuleDef mod) - //{ - // string oldName = mod.Assembly.Name; - // string newName = _renameRecordMap.TryGetExistRenameMapping(mod, out var n) ? n : _nameMaker.GetNewName(mod, oldName); - // _renameRecordMap.AddRename(mod, newName); - // mod.Assembly.Name = newName; - // mod.Name = $"{newName}.dll"; - // //Debug.Log($"rename module. oldName:{oldName} newName:{newName}"); - // foreach (AssemblyReferenceInfo ass in GetReferenceMeAssemblies(mod)) - // { - // foreach (AssemblyRef assRef in ass.module.GetAssemblyRefs()) - // { - // if (assRef.Name == oldName) - // { - // _renameRecordMap.AddRename(mod, newName); - // assRef.Name = newName; - // // Debug.Log($"rename assembly:{ass.name} ref oldName:{oldName} newName:{newName}"); - // } - // } - // } - //} - - private void Rename(TypeDef type, RefTypeDefMetas refTypeDefMeta) - { - string moduleName = MetaUtil.GetModuleNameWithoutExt(type.Module.Name); - string oldFullName = type.FullName; - string oldNamespace = type.Namespace; - - string oldName = type.Name; - - string newNamespace; - string newName; - if (_renameRecordMap.TryGetExistRenameMapping(type, out var nns, out var nn)) - { - newNamespace = nns; - newName = nn; - } - else - { - newNamespace = _nameMaker.GetNewNamespace(type, oldNamespace, _useConsistentNamespaceObfuscation); - newName = _nameMaker.GetNewName(type, oldName); - } - - if (refTypeDefMeta != null) - { - foreach (TypeRef typeRef in refTypeDefMeta.typeRefs) - { - Assert.AreEqual(typeRef.FullName, oldFullName); - Assert.IsTrue(typeRef.DefinitionAssembly.Name == moduleName); - if (!string.IsNullOrEmpty(oldNamespace)) - { - typeRef.Namespace = newNamespace; - } - typeRef.Name = newName; - //Debug.Log($"rename assembly:{typeRef.Module.Name} reference {oldFullName} => {typeRef.FullName}"); - } - } - type.Name = newName; - type.Namespace = newNamespace; - string newFullName = type.FullName; - _renameRecordMap.AddRename(type, newFullName); - //Debug.Log($"rename typedef. assembly:{type.Module.Name} oldName:{oldFullName} => newName:{newFullName}"); - } - - private void Rename(FieldDef field, RefFieldMetas fieldMetas) - { - string oldName = field.Name; - string newName = _renameRecordMap.TryGetExistRenameMapping(field, out var nn) ? nn : _nameMaker.GetNewName(field, oldName); - if (fieldMetas != null) - { - foreach (var memberRef in fieldMetas.fieldRefs) - { - memberRef.Name = newName; - //Debug.Log($"rename assembly:{memberRef.Module.Name} reference {field.FullName} => {memberRef.FullName}"); - } - foreach (var ca in fieldMetas.customAttributes) - { - foreach (var arg in ca.NamedArguments) - { - if (arg.Name == oldName) - { - arg.Name = newName; - } - } - } - } - //Debug.Log($"rename field. {field} => {newName}"); - _renameRecordMap.AddRename(field, newName); - field.Name = newName; - - } - - private void Rename(MethodDef method, RefMethodMetas refMethodMetas) - { - string oldName = method.Name; - string newName = _renameRecordMap.TryGetExistRenameMapping(method, out var nn) ? nn : _nameMaker.GetNewName(method, oldName); - Rename(method, refMethodMetas, newName); - } - - private void Rename(MethodDef method, RefMethodMetas refMethodMetas, string newName) - { - ModuleDefMD mod = (ModuleDefMD)method.DeclaringType.Module; - RenameMethodParams(method); - RenameMethodBody(method); - if (refMethodMetas != null) - { - foreach (MemberRef memberRef in refMethodMetas.memberRefs) - { - string oldMethodFullName = memberRef.ToString(); - memberRef.Name = newName; - //Debug.Log($"rename assembly:{memberRef.Module.Name} method:{oldMethodFullName} => {memberRef}"); - } - } - _renameRecordMap.AddRename(method, newName); - method.Name = newName; - } - - private void RenameMethodBody(MethodDef method) - { - if (method.Body == null) - { - return; - } - } - - private void RenameMethodParams(MethodDef method) - { - foreach (Parameter param in method.Parameters) - { - if (param.ParamDef != null) - { - Rename(param.ParamDef); - } - } - } - - private void Rename(ParamDef param) - { - string newName = _nameMaker.GetNewName(param, param.Name); - param.Name = newName; - } - - private void Rename(EventDef eventDef) - { - string oldName = eventDef.Name; - string newName = _renameRecordMap.TryGetExistRenameMapping(eventDef, out var nn) ? nn : _nameMaker.GetNewName(eventDef, eventDef.Name); - _renameRecordMap.AddRename(eventDef, newName); - eventDef.Name = newName; - } - - private void Rename(PropertyDef property, RefPropertyMetas refPropertyMetas) - { - string oldName = property.Name; - string newName = _renameRecordMap.TryGetExistRenameMapping(property, out var nn) ? nn : _nameMaker.GetNewName(property, oldName); - - if (refPropertyMetas != null) - { - foreach (var ca in refPropertyMetas.customAttributes) - { - foreach (var arg in ca.NamedArguments) - { - if (arg.Name == oldName) - { - arg.Name = newName; - } - } - } - } - _renameRecordMap.AddRename(property, newName); - property.Name = newName; - } - - public void Save() - { - Directory.CreateDirectory(Path.GetDirectoryName(_mappingXmlPath)); - _renameRecordMap.WriteXmlMappingFile(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs.meta deleted file mode 100644 index 739a842..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ec29be12f08e90741a59970f029c2eec -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs deleted file mode 100644 index 03cb1b3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs +++ /dev/null @@ -1,100 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.ObfusPasses.SymbolObfus -{ - - public class VirtualMethodGroup - { - public List methods; - } - - public class VirtualMethodGroupCalculator - { - - private class TypeFlatMethods - { - public HashSet flatMethods = new HashSet(); - - - public bool TryFindMatchVirtualMethod(MethodDef method, out MethodDef matchMethodDef) - { - foreach (var parentOrInterfaceMethod in flatMethods) - { - if (parentOrInterfaceMethod.Name == method.Name && parentOrInterfaceMethod.GetParamCount() == method.GetParamCount()) - { - matchMethodDef = parentOrInterfaceMethod; - return true; - } - } - matchMethodDef = null; - return false; - } - } - - - private readonly Dictionary _methodGroups = new Dictionary(); - private readonly Dictionary _visitedTypes = new Dictionary(); - - - - public VirtualMethodGroup GetMethodGroup(MethodDef methodDef) - { - if (_methodGroups.TryGetValue(methodDef, out var group)) - { - return group; - } - return null; - } - - public void CalculateType(TypeDef typeDef) - { - if (_visitedTypes.ContainsKey(typeDef)) - { - return; - } - - var typeMethods = new TypeFlatMethods(); - - if (typeDef.BaseType != null) - { - TypeDef baseTypeDef = MetaUtil.GetTypeDefOrGenericTypeBaseThrowException(typeDef.BaseType); - CalculateType(baseTypeDef); - typeMethods.flatMethods.AddRange(_visitedTypes[baseTypeDef].flatMethods); - foreach (var intfType in typeDef.Interfaces) - { - TypeDef intfTypeDef = MetaUtil.GetTypeDefOrGenericTypeBaseThrowException(intfType.Interface); - CalculateType(intfTypeDef); - typeMethods.flatMethods.AddRange(_visitedTypes[intfTypeDef].flatMethods); - } - } - foreach (var method in typeDef.Methods) - { - if (!method.IsVirtual) - { - continue; - } - if (typeMethods.TryFindMatchVirtualMethod(method, out var matchMethodDef)) - { - var group = _methodGroups[matchMethodDef]; - group.methods.Add(method); - _methodGroups.Add(method, group); - } - else - { - _methodGroups.Add(method, new VirtualMethodGroup() { methods = new List { method } }); - } - if (method.IsNewSlot) - { - typeMethods.flatMethods.Add(method); - } - } - _visitedTypes.Add(typeDef, typeMethods); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs.meta deleted file mode 100644 index 097106a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 649aeb6306500a04f8b7a3e01f5aaf0d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs deleted file mode 100644 index 87ca94f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs +++ /dev/null @@ -1,75 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Editor; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - public class ObfuscationMethodWhitelist - { - private bool ShouldBeIgnoredByCustomAttribute(IHasCustomAttribute obj) - { - return MetaUtil.HasObfuzIgnoreAttribute(obj); - } - - public bool IsInWhiteList(ModuleDef module) - { - string modName = module.Assembly.Name; - if (modName == "Obfuz.Runtime") - { - return true; - } - if (ShouldBeIgnoredByCustomAttribute(module)) - { - return true; - } - return false; - } - - public bool IsInWhiteList(MethodDef method) - { - if (IsInWhiteList(method.DeclaringType)) - { - return true; - } - if (method.Name.StartsWith(ConstValues.ObfuzInternalSymbolNamePrefix)) - { - return true; - } - if (ShouldBeIgnoredByCustomAttribute(method)) - { - return true; - } - return false; - } - - public bool IsInWhiteList(TypeDef type) - { - if (type.Name.StartsWith(ConstValues.ObfuzInternalSymbolNamePrefix)) - { - return true; - } - if (IsInWhiteList(type.Module)) - { - return true; - } - if (MetaUtil.HasObfuzIgnoreAttributeInSelfOrParent(type)) - { - return true; - } - if (type.DeclaringType != null && IsInWhiteList(type.DeclaringType)) - { - return true; - } - if (type.FullName == "Obfuz.EncryptionVM.GeneratedEncryptionVirtualMachine") - { - return true; - } - return false; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs.meta deleted file mode 100644 index 0ef3bf3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8824d47fdc31cef41a899294491c8844 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs deleted file mode 100644 index f4b5c74..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs +++ /dev/null @@ -1,83 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Data; -using Obfuz.Emit; -using Obfuz.ObfusPasses; -using Obfuz.ObfusPasses.SymbolObfus; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - public delegate IRandom RandomCreator(int seed); - - public class EncryptionScopeInfo - { - public readonly IEncryptor encryptor; - public readonly RandomCreator localRandomCreator; - - public EncryptionScopeInfo(IEncryptor encryptor, RandomCreator localRandomCreator) - { - this.encryptor = encryptor; - this.localRandomCreator = localRandomCreator; - } - } - - public class EncryptionScopeProvider - { - private readonly EncryptionScopeInfo _defaultStaticScope; - private readonly EncryptionScopeInfo _defaultDynamicScope; - private readonly HashSet _dynamicSecretAssemblyNames; - - public EncryptionScopeProvider(EncryptionScopeInfo defaultStaticScope, EncryptionScopeInfo defaultDynamicScope, HashSet dynamicSecretAssemblyNames) - { - _defaultStaticScope = defaultStaticScope; - _defaultDynamicScope = defaultDynamicScope; - _dynamicSecretAssemblyNames = dynamicSecretAssemblyNames; - } - - public EncryptionScopeInfo GetScope(ModuleDef module) - { - if (_dynamicSecretAssemblyNames.Contains(module.Assembly.Name)) - { - return _defaultDynamicScope; - } - else - { - return _defaultStaticScope; - } - } - - public bool IsDynamicSecretAssembly(ModuleDef module) - { - return _dynamicSecretAssemblyNames.Contains(module.Assembly.Name); - } - } - - public class ObfuscationPassContext - { - public static ObfuscationPassContext Current { get; set; } - - - public GroupByModuleEntityManager moduleEntityManager; - - public AssemblyCache assemblyCache; - - public List modulesToObfuscate; - public List allObfuscationRelativeModules; - - public List assembliesToObfuscate; - public List nonObfuscatedButReferencingObfuscatedAssemblies; - - public string obfuscatedAssemblyOutputPath; - - public EncryptionScopeProvider encryptionScopeProvider; - public ConstFieldAllocator constFieldAllocator; - public RvaDataAllocator rvaDataAllocator; - public ObfuscationMethodWhitelist whiteList; - public ConfigurablePassPolicy passPolicy; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs.meta deleted file mode 100644 index 827ddc4..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 196d07f0366ce4b46bf0333fa4918d40 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs deleted file mode 100644 index 6b7bcb8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs +++ /dev/null @@ -1,339 +0,0 @@ -using dnlib.DotNet; -using Obfuz.Data; -using Obfuz.Emit; -using Obfuz.EncryptionVM; -using Obfuz.ObfusPasses; -using Obfuz.ObfusPasses.CleanUp; -using Obfuz.ObfusPasses.SymbolObfus; -using Obfuz.Utils; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz -{ - - public class Obfuscator - { - private readonly string _obfuscatedAssemblyOutputPath; - - private readonly List _assembliesToObfuscate; - private readonly List _nonObfuscatedButReferencingObfuscatedAssemblies; - private readonly List _assemblySearchPaths; - - private readonly ConfigurablePassPolicy _passPolicy; - - private readonly Pipeline _pipeline1 = new Pipeline(); - private readonly Pipeline _pipeline2 = new Pipeline(); - - private readonly byte[] _defaultStaticByteSecretKey; - private readonly byte[] _defaultDynamicByteSecret; - private readonly HashSet _assembliesUsingDynamicSecretKeys; - - private readonly int _randomSeed; - private readonly string _encryptionVmGenerationSecretKey; - private readonly int _encryptionVmOpCodeCount; - private readonly string _encryptionVmCodeFile; - - private ObfuscationPassContext _ctx; - - public Obfuscator(ObfuscatorBuilder builder) - { - _defaultStaticByteSecretKey = KeyGenerator.GenerateKey(builder.DefaultStaticSecretKey, VirtualMachine.SecretKeyLength); - _defaultDynamicByteSecret = KeyGenerator.GenerateKey(builder.DefaultDynamicSecretKey, VirtualMachine.SecretKeyLength); - _assembliesUsingDynamicSecretKeys = new HashSet(builder.AssembliesUsingDynamicSecretKeys); - - - _randomSeed = builder.RandomSeed; - _encryptionVmGenerationSecretKey = builder.EncryptionVmGenerationSecretKey; - _encryptionVmOpCodeCount = builder.EncryptionVmOpCodeCount; - _encryptionVmCodeFile = builder.EncryptionVmCodeFile; - - _assembliesToObfuscate = builder.AssembliesToObfuscate; - _nonObfuscatedButReferencingObfuscatedAssemblies = builder.NonObfuscatedButReferencingObfuscatedAssemblies; - _obfuscatedAssemblyOutputPath = builder.ObfuscatedAssemblyOutputPath; - _assemblySearchPaths = builder.AssemblySearchPaths; - - _passPolicy = new ConfigurablePassPolicy(_assembliesToObfuscate, builder.EnableObfuscationPasses, builder.ObfuscationPassRuleConfigFiles); - - foreach (var pass in builder.ObfuscationPasses) - { - if (pass is SymbolObfusPass symbolObfusPass) - { - _pipeline2.AddPass(pass); - } - else - { - _pipeline1.AddPass(pass); - } - } - _pipeline1.AddPass(new CleanUpInstructionPass()); - _pipeline2.AddPass(new RemoveObfuzAttributesPass()); - } - - public void Run() - { - Debug.Log($"Obfuscator Run. begin"); - FileUtil.RecreateDir(_obfuscatedAssemblyOutputPath); - RunPipeline(_pipeline1); - _assemblySearchPaths.Insert(0, _obfuscatedAssemblyOutputPath); - RunPipeline(_pipeline2); - Debug.Log($"Obfuscator Run. end"); - } - - private void RunPipeline(Pipeline pipeline) - { - if (pipeline.Empty) - { - return; - } - OnPreObfuscation(pipeline); - DoObfuscation(pipeline); - OnPostObfuscation(pipeline); - } - - private IEncryptor CreateEncryptionVirtualMachine(byte[] secretKey) - { - var vmCreator = new VirtualMachineCreator(_encryptionVmGenerationSecretKey); - var vm = vmCreator.CreateVirtualMachine(_encryptionVmOpCodeCount); - var vmGenerator = new VirtualMachineCodeGenerator(vm); - - if (!File.Exists(_encryptionVmCodeFile)) - { - throw new Exception($"EncryptionVm CodeFile:`{_encryptionVmCodeFile}` not exists! Please run `Obfuz/GenerateVm` to generate it!"); - } - if (!vmGenerator.ValidateMatch(_encryptionVmCodeFile)) - { - throw new Exception($"EncryptionVm CodeFile:`{_encryptionVmCodeFile}` not match with encryptionVM settings! Please run `Obfuz/GenerateVm` to update it!"); - } - var vms = new VirtualMachineSimulator(vm, secretKey); - - var generatedVmTypes = AppDomain.CurrentDomain.GetAssemblies() - .Select(assembly => assembly.GetType("Obfuz.EncryptionVM.GeneratedEncryptionVirtualMachine")) - .Where(type => type != null) - .ToList(); - if (generatedVmTypes.Count == 0) - { - throw new Exception($"class Obfuz.EncryptionVM.GeneratedEncryptionVirtualMachine not found in any assembly! Please run `Obfuz/GenerateVm` to generate it!"); - } - if (generatedVmTypes.Count > 1) - { - throw new Exception($"class Obfuz.EncryptionVM.GeneratedEncryptionVirtualMachine found in multiple assemblies! Please retain only one!"); - } - - var gvmInstance = (IEncryptor)Activator.CreateInstance(generatedVmTypes[0], new object[] { secretKey } ); - - VerifyVm(vm, vms, gvmInstance); - - return vms; - } - - private void VerifyVm(VirtualMachine vm, VirtualMachineSimulator vms, IEncryptor gvm) - { - int testInt = 11223344; - long testLong = 1122334455667788L; - float testFloat = 1234f; - double testDouble = 1122334455.0; - string testString = "hello,world"; - for (int i = 0; i < vm.opCodes.Length; i++) - { - int ops = i * vm.opCodes.Length + i; - //int salt = i; - //int ops = -1135538782; - int salt = -879409147; - { - int encryptedIntOfVms = vms.Encrypt(testInt, ops, salt); - int decryptedIntOfVms = vms.Decrypt(encryptedIntOfVms, ops, salt); - if (decryptedIntOfVms != testInt) - { - throw new Exception($"VirtualMachineSimulator decrypt failed! opCode:{i}, originalValue:{testInt} decryptedValue:{decryptedIntOfVms}"); - } - int encryptedValueOfGvm = gvm.Encrypt(testInt, ops, salt); - int decryptedValueOfGvm = gvm.Decrypt(encryptedValueOfGvm, ops, salt); - if (encryptedValueOfGvm != encryptedIntOfVms) - { - throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testInt} encryptedValue VirtualMachineSimulator:{encryptedIntOfVms} GeneratedEncryptionVirtualMachine:{encryptedValueOfGvm}"); - } - if (decryptedValueOfGvm != testInt) - { - throw new Exception($"GeneratedEncryptionVirtualMachine decrypt failed! opCode:{i}, originalValue:{testInt} decryptedValue:{decryptedValueOfGvm}"); - } - } - { - long encryptedLongOfVms = vms.Encrypt(testLong, ops, salt); - long decryptedLongOfVms = vms.Decrypt(encryptedLongOfVms, ops, salt); - if (decryptedLongOfVms != testLong) - { - throw new Exception($"VirtualMachineSimulator decrypt long failed! opCode:{i}, originalValue:{testLong} decryptedValue:{decryptedLongOfVms}"); - } - long encryptedValueOfGvm = gvm.Encrypt(testLong, ops, salt); - long decryptedValueOfGvm = gvm.Decrypt(encryptedValueOfGvm, ops, salt); - if (encryptedValueOfGvm != encryptedLongOfVms) - { - throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testLong} encryptedValue VirtualMachineSimulator:{encryptedLongOfVms} GeneratedEncryptionVirtualMachine:{encryptedValueOfGvm}"); - } - if (decryptedValueOfGvm != testLong) - { - throw new Exception($"GeneratedEncryptionVirtualMachine decrypt long failed! opCode:{i}, originalValue:{testLong} decryptedValue:{decryptedValueOfGvm}"); - } - } - { - float encryptedFloatOfVms = vms.Encrypt(testFloat, ops, salt); - float decryptedFloatOfVms = vms.Decrypt(encryptedFloatOfVms, ops, salt); - if (decryptedFloatOfVms != testFloat) - { - throw new Exception("encryptedFloat not match"); - } - float encryptedValueOfGvm = gvm.Encrypt(testFloat, ops, salt); - float decryptedValueOfGvm = gvm.Decrypt(encryptedFloatOfVms, ops, salt); - if (encryptedFloatOfVms != encryptedValueOfGvm) - { - throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testFloat} encryptedValue"); - } - if (decryptedValueOfGvm != testFloat) - { - throw new Exception($"GeneratedEncryptionVirtualMachine decrypt float failed! opCode:{i}, originalValue:{testFloat}"); - } - } - { - double encryptedFloatOfVms = vms.Encrypt(testDouble, ops, salt); - double decryptedFloatOfVms = vms.Decrypt(encryptedFloatOfVms, ops, salt); - if (decryptedFloatOfVms != testDouble) - { - throw new Exception("encryptedFloat not match"); - } - double encryptedValueOfGvm = gvm.Encrypt(testDouble, ops, salt); - double decryptedValueOfGvm = gvm.Decrypt(encryptedFloatOfVms, ops, salt); - if (encryptedFloatOfVms != encryptedValueOfGvm) - { - throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testDouble} encryptedValue"); - } - if (decryptedValueOfGvm != testDouble) - { - throw new Exception($"GeneratedEncryptionVirtualMachine decrypt float failed! opCode:{i}, originalValue:{testDouble}"); - } - } - - { - byte[] encryptedStrOfVms = vms.Encrypt(testString, ops, salt); - string decryptedStrOfVms = vms.DecryptString(encryptedStrOfVms, 0, encryptedStrOfVms.Length, ops, salt); - if (decryptedStrOfVms != testString) - { - throw new Exception($"VirtualMachineSimulator decrypt string failed! opCode:{i}, originalValue:{testString} decryptedValue:{decryptedStrOfVms}"); - } - byte[] encryptedStrOfGvm = gvm.Encrypt(testString, ops, salt); - string decryptedStrOfGvm = gvm.DecryptString(encryptedStrOfGvm, 0, encryptedStrOfGvm.Length, ops, salt); - if (!encryptedStrOfGvm.SequenceEqual(encryptedStrOfVms)) - { - throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testString} encryptedValue VirtualMachineSimulator:{encryptedStrOfVms} GeneratedEncryptionVirtualMachine:{encryptedStrOfGvm}"); - } - if (decryptedStrOfGvm != testString) - { - throw new Exception($"GeneratedEncryptionVirtualMachine decrypt string failed! opCode:{i}, originalValue:{testString} decryptedValue:{decryptedStrOfGvm}"); - } - } - } - } - - private EncryptionScopeInfo CreateEncryptionScope(byte[] byteSecret) - { - int[] intSecretKey = KeyGenerator.ConvertToIntKey(byteSecret); - IEncryptor encryption = CreateEncryptionVirtualMachine(byteSecret); - RandomCreator localRandomCreator = (seed) => new RandomWithKey(intSecretKey, _randomSeed ^ seed); - return new EncryptionScopeInfo(encryption, localRandomCreator); - } - - private EncryptionScopeProvider CreateEncryptionScopeProvider() - { - var defaultStaticScope = CreateEncryptionScope(_defaultStaticByteSecretKey); - var defaultDynamicScope = CreateEncryptionScope(_defaultDynamicByteSecret); - foreach (string dynamicAssName in _assembliesUsingDynamicSecretKeys) - { - if (!_assembliesToObfuscate.Contains(dynamicAssName)) - { - throw new Exception($"Dynamic secret assembly `{dynamicAssName}` should be in the toObfuscatedAssemblyNames list!"); - } - } - return new EncryptionScopeProvider(defaultStaticScope, defaultDynamicScope, _assembliesUsingDynamicSecretKeys); - } - - private void OnPreObfuscation(Pipeline pipeline) - { - AssemblyCache assemblyCache = new AssemblyCache(new PathAssemblyResolver(_assemblySearchPaths.ToArray())); - List modulesToObfuscate = new List(); - List allObfuscationRelativeModules = new List(); - LoadAssemblies(assemblyCache, modulesToObfuscate, allObfuscationRelativeModules); - - EncryptionScopeProvider encryptionScopeProvider = CreateEncryptionScopeProvider(); - var moduleEntityManager = new GroupByModuleEntityManager(); - var rvaDataAllocator = new RvaDataAllocator(encryptionScopeProvider, moduleEntityManager); - var constFieldAllocator = new ConstFieldAllocator(encryptionScopeProvider, rvaDataAllocator, moduleEntityManager); - _ctx = new ObfuscationPassContext - { - assemblyCache = assemblyCache, - modulesToObfuscate = modulesToObfuscate, - allObfuscationRelativeModules = allObfuscationRelativeModules, - assembliesToObfuscate = _assembliesToObfuscate, - nonObfuscatedButReferencingObfuscatedAssemblies = _nonObfuscatedButReferencingObfuscatedAssemblies, - obfuscatedAssemblyOutputPath = _obfuscatedAssemblyOutputPath, - moduleEntityManager = moduleEntityManager, - - encryptionScopeProvider = encryptionScopeProvider, - - rvaDataAllocator = rvaDataAllocator, - constFieldAllocator = constFieldAllocator, - whiteList = new ObfuscationMethodWhitelist(), - passPolicy = _passPolicy, - }; - ObfuscationPassContext.Current = _ctx; - pipeline.Start(); - } - - private void LoadAssemblies(AssemblyCache assemblyCache, List modulesToObfuscate, List allObfuscationRelativeModules) - { - foreach (string assName in _assembliesToObfuscate.Concat(_nonObfuscatedButReferencingObfuscatedAssemblies)) - { - ModuleDefMD mod = assemblyCache.TryLoadModule(assName); - if (mod == null) - { - Debug.Log($"assembly: {assName} not found! ignore."); - continue; - } - if (_assembliesToObfuscate.Contains(assName)) - { - modulesToObfuscate.Add(mod); - } - allObfuscationRelativeModules.Add(mod); - } - } - - private void WriteAssemblies() - { - foreach (ModuleDef mod in _ctx.allObfuscationRelativeModules) - { - string assNameWithExt = mod.Name; - string outputFile = $"{_obfuscatedAssemblyOutputPath}/{assNameWithExt}"; - mod.Write(outputFile); - Debug.Log($"save module. name:{mod.Assembly.Name} output:{outputFile}"); - } - } - - private void DoObfuscation(Pipeline pipeline) - { - pipeline.Run(); - } - - private void OnPostObfuscation(Pipeline pipeline) - { - pipeline.Stop(); - - _ctx.constFieldAllocator.Done(); - _ctx.rvaDataAllocator.Done(); - WriteAssemblies(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs.meta deleted file mode 100644 index 08291f3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ca9c4e108bde2184885e599f2bd19a00 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs deleted file mode 100644 index 3a3943c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs +++ /dev/null @@ -1,216 +0,0 @@ -using Obfuz.EncryptionVM; -using Obfuz.ObfusPasses; -using Obfuz.ObfusPasses.CallObfus; -using Obfuz.ObfusPasses.ConstEncrypt; -using Obfuz.ObfusPasses.ExprObfus; -using Obfuz.ObfusPasses.FieldEncrypt; -using Obfuz.ObfusPasses.SymbolObfus; -using Obfuz.Settings; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEditor; - -namespace Obfuz -{ - public class ObfuscatorBuilder - { - private string _defaultStaticSecretKey; - private string _defaultStaticSecretKeyOutputPath; - private string _defaultDynamicSecretKey; - private string _defaultDynamicSecretKeyOutputPath; - private List _assembliesUsingDynamicSecretKeys = new List(); - - private int _randomSeed; - private string _encryptionVmGenerationSecretKey; - private int _encryptionVmOpCodeCount; - private string _encryptionVmCodeFile; - - private List _assembliesToObfuscate = new List(); - private List _nonObfuscatedButReferencingObfuscatedAssemblies = new List(); - private List _assemblySearchPaths = new List(); - - private string _obfuscatedAssemblyOutputPath; - private List _obfuscationPassRuleConfigFiles; - - private ObfuscationPassType _enabledObfuscationPasses; - private List _obfuscationPasses = new List(); - - public string DefaultStaticSecretKey - { - get => _defaultStaticSecretKey; - set => _defaultStaticSecretKey = value; - } - - public string DefaultStaticSecretKeyOutputPath - { - get => _defaultStaticSecretKeyOutputPath; - set => _defaultStaticSecretKeyOutputPath = value; - } - - public string DefaultDynamicSecretKey - { - get => _defaultDynamicSecretKey; - set => _defaultDynamicSecretKey = value; - } - - public string DefaultDynamicSecretKeyOutputPath - { - get => _defaultDynamicSecretKeyOutputPath; - set => _defaultDynamicSecretKeyOutputPath = value; - } - - public List AssembliesUsingDynamicSecretKeys - { - get => _assembliesUsingDynamicSecretKeys; - set => _assembliesUsingDynamicSecretKeys = value; - } - - public int RandomSeed - { - get => _randomSeed; - set => _randomSeed = value; - } - - public string EncryptionVmGenerationSecretKey - { - get => _encryptionVmGenerationSecretKey; - set => _encryptionVmGenerationSecretKey = value; - } - - public int EncryptionVmOpCodeCount - { - get => _encryptionVmOpCodeCount; - set => _encryptionVmOpCodeCount = value; - } - - public string EncryptionVmCodeFile - { - get => _encryptionVmCodeFile; - set => _encryptionVmCodeFile = value; - } - - public List AssembliesToObfuscate - { - get => _assembliesToObfuscate; - set => _assembliesToObfuscate = value; - } - - public List NonObfuscatedButReferencingObfuscatedAssemblies - { - get => _nonObfuscatedButReferencingObfuscatedAssemblies; - set => _nonObfuscatedButReferencingObfuscatedAssemblies = value; - } - - public List AssemblySearchPaths - { - get => _assemblySearchPaths; - set => _assemblySearchPaths = value; - } - - public string ObfuscatedAssemblyOutputPath - { - get => _obfuscatedAssemblyOutputPath; - set => _obfuscatedAssemblyOutputPath = value; - } - - public ObfuscationPassType EnableObfuscationPasses - { - get => _enabledObfuscationPasses; - set => _enabledObfuscationPasses = value; - } - - public List ObfuscationPassRuleConfigFiles - { - get => _obfuscationPassRuleConfigFiles; - set => _obfuscationPassRuleConfigFiles = value; - } - - public List ObfuscationPasses - { - get => _obfuscationPasses; - set => _obfuscationPasses = value; - } - - public void InsertTopPriorityAssemblySearchPaths(List assemblySearchPaths) - { - _assemblySearchPaths.InsertRange(0, assemblySearchPaths); - } - - public ObfuscatorBuilder AddPass(IObfuscationPass pass) - { - _obfuscationPasses.Add(pass); - return this; - } - - public Obfuscator Build() - { - return new Obfuscator(this); - } - - public static List BuildUnityAssemblySearchPaths() - { - string applicationContentsPath = EditorApplication.applicationContentsPath; - return new List - { -#if UNITY_2021_1_OR_NEWER - Path.Combine(applicationContentsPath, "UnityReferenceAssemblies/unity-4.8-api/Facades"), - Path.Combine(applicationContentsPath, "UnityReferenceAssemblies/unity-4.8-api"), -#elif UNITY_2020 || UNITY_2019 - Path.Combine(applicationContentsPath, "MonoBleedingEdge/lib/mono/4.7.1-api/Facades"), - Path.Combine(applicationContentsPath, "MonoBleedingEdge/lib/mono/4.7.1-api"), -#else -#error "Unsupported Unity version" -#endif - Path.Combine(applicationContentsPath, "Managed/UnityEngine"), - }; - } - - public static ObfuscatorBuilder FromObfuzSettings(ObfuzSettings settings, BuildTarget target, bool searchPathIncludeUnityEditorInstallLocation) - { - List searchPaths = searchPathIncludeUnityEditorInstallLocation ? - BuildUnityAssemblySearchPaths().Concat(settings.assemblySettings.additionalAssemblySearchPaths).ToList() - : settings.assemblySettings.additionalAssemblySearchPaths.ToList(); - var builder = new ObfuscatorBuilder - { - _defaultStaticSecretKey = settings.secretSettings.defaultStaticSecretKey, - _defaultStaticSecretKeyOutputPath = settings.secretSettings.DefaultStaticSecretKeyOutputPath, - _defaultDynamicSecretKey = settings.secretSettings.defaultDynamicSecretKey, - _defaultDynamicSecretKeyOutputPath = settings.secretSettings.DefaultDynamicSecretKeyOutputPath, - _assembliesUsingDynamicSecretKeys = settings.secretSettings.assembliesUsingDynamicSecretKeys.ToList(), - _randomSeed = settings.secretSettings.randomSeed, - _encryptionVmGenerationSecretKey = settings.encryptionVMSettings.codeGenerationSecretKey, - _encryptionVmOpCodeCount = settings.encryptionVMSettings.encryptionOpCodeCount, - _encryptionVmCodeFile = settings.encryptionVMSettings.codeOutputPath, - _assembliesToObfuscate = settings.assemblySettings.assembliesToObfuscate.ToList(), - _nonObfuscatedButReferencingObfuscatedAssemblies = settings.assemblySettings.nonObfuscatedButReferencingObfuscatedAssemblies.ToList(), - _assemblySearchPaths = searchPaths, - _obfuscatedAssemblyOutputPath = settings.GetObfuscatedAssemblyOutputPath(target), - _enabledObfuscationPasses = settings.obfuscationPassSettings.enabledPasses, - _obfuscationPassRuleConfigFiles = settings.obfuscationPassSettings.ruleFiles.ToList(), - }; - ObfuscationPassType obfuscationPasses = settings.obfuscationPassSettings.enabledPasses; - if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncrypt)) - { - builder.AddPass(new ConstEncryptPass(settings.constEncryptSettings)); - } - if (obfuscationPasses.HasFlag(ObfuscationPassType.FieldEncrypt)) - { - builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings)); - } - if (obfuscationPasses.HasFlag(ObfuscationPassType.CallObfus)) - { - builder.AddPass(new CallObfusPass(settings.callObfusSettings)); - } - if (obfuscationPasses.HasFlag(ObfuscationPassType.ExprObfus)) - { - builder.AddPass(new ExprObfusPass()); - } - if (obfuscationPasses.HasFlag(ObfuscationPassType.SymbolObfus)) - { - builder.AddPass(new SymbolObfusPass(settings.symbolObfusSettings)); - } - return builder; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs.meta deleted file mode 100644 index 261993b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 77e279242d764ed4d996db96f35e8570 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef deleted file mode 100644 index e1b3933..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "Obfuz.Editor", - "rootNamespace": "", - "references": [ - "GUID:4140bd2e2764f1f47ab93125ecb61942" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": true, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef.meta deleted file mode 100644 index d010c09..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 66e09fc524ec6594b8d6ca1d91aa1a41 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs deleted file mode 100644 index 9e92d46..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Obfuz.ObfusPasses; -using System.Collections.Generic; - -namespace Obfuz -{ - public class Pipeline - { - private readonly List _passes = new List(); - - public bool Empty => _passes.Count == 0; - - public Pipeline AddPass(IObfuscationPass pass) - { - _passes.Add(pass); - return this; - } - - public void Start() - { - foreach (var pass in _passes) - { - pass.Start(); - } - } - - public void Stop() - { - - foreach (var pass in _passes) - { - pass.Stop(); - } - } - - public void Run() - { - foreach (var pass in _passes) - { - pass.Process(); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs.meta deleted file mode 100644 index fd3558c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0915452219e923d428b9a408cf413844 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings.meta deleted file mode 100644 index 64d3c0a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 4939d1f80df50b34c85ffc8fbe530887 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs deleted file mode 100644 index ec4898d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Linq; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class AssemblySettings - { - - [Tooltip("name of assemblies to obfuscate")] - public string[] assembliesToObfuscate; - - [Tooltip("name of assemblies not obfuscated but reference assemblies to obfuscated ")] - public string[] nonObfuscatedButReferencingObfuscatedAssemblies; - - [Tooltip("additional assembly search paths")] - public string[] additionalAssemblySearchPaths; - - public string[] GetObfuscationRelativeAssemblyNames() - { - return assembliesToObfuscate - .Concat(nonObfuscatedButReferencingObfuscatedAssemblies) - .ToArray(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs.meta deleted file mode 100644 index 8a13940..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 735c01fddc6f0c54a83e1feb9a60e13a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs deleted file mode 100644 index 3ea3a1f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class CallObfuscationSettings - { - [Tooltip("The obfuscation level for the obfuscation. Higher levels provide more security but may impact performance.")] - [Range(1, 4)] - public int obfuscationLevel = 1; - - [Tooltip("rule config xml files")] - public string[] ruleFiles; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs.meta deleted file mode 100644 index ce268f1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ae4ddc19ecf8d9940b444f5b66c23efa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs deleted file mode 100644 index 794d685..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class ConstEncryptionSettings - { - [Tooltip("The encryption level for the obfuscation. Higher levels provide more security but may impact performance.")] - [Range(1, 4)] - public int encryptionLevel = 1; - - [Tooltip("config xml files")] - public string[] ruleFiles; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs.meta deleted file mode 100644 index d5cef40..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2b189f76d7da58e4b9403b4fe87265b4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs deleted file mode 100644 index 04a7a22..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class EncryptionVMSettings - { - [Tooltip("secret key for generating encryption virtual machine source code")] - public string codeGenerationSecretKey = "Obfuz"; - - [Tooltip("encryption OpCode count, should be power of 2 and >= 64")] - public int encryptionOpCodeCount = 256; - - [Tooltip("encryption virtual machine source code output path")] - public string codeOutputPath = "Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs"; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs.meta deleted file mode 100644 index 0257381..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f0e626d510710c540bdc36b4dca93340 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs deleted file mode 100644 index 0b41afe..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class FieldEncryptionSettings - { - [Tooltip("The encryption level for the obfuscation. Higher levels provide more security but may impact performance.")] - [Range(1, 4)] - public int encryptionLevel = 1; - - [Tooltip("rule config xml files")] - public string[] ruleFiles; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs.meta deleted file mode 100644 index fbc0e2e..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 56cff1f5683d9114e8f13cee917ea582 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs deleted file mode 100644 index 837c8b0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Obfuz.ObfusPasses; -using System; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class ObfuscationPassSettings - { - [Tooltip("enable obfuscation pass")] - public ObfuscationPassType enabledPasses = ObfuscationPassType.All; - - [Tooltip("rule config xml files")] - public string[] ruleFiles; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs.meta deleted file mode 100644 index 147fed6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9cb41a6fb7293ce47807e432d80f2b2a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs deleted file mode 100644 index 70fb15d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Runtime.Remoting.Messaging; -using UnityEditor; -using UnityEditorInternal; -using UnityEngine; - -namespace Obfuz.Settings -{ - - - public class ObfuzSettings : ScriptableObject - { - [Tooltip("enable Obfuz")] - public bool enable = true; - - [Tooltip("assembly settings")] - public AssemblySettings assemblySettings; - - [Tooltip("obfuscation pass settings")] - public ObfuscationPassSettings obfuscationPassSettings; - - [Tooltip("secret settings")] - public SecretSettings secretSettings; - - [Tooltip("encryption virtual machine settings")] - public EncryptionVMSettings encryptionVMSettings; - - [Tooltip("symbol obfuscation settings")] - public SymbolObfuscationSettings symbolObfusSettings; - - [Tooltip("const encryption settings")] - public ConstEncryptionSettings constEncryptSettings; - - [Tooltip("field encryption settings")] - public FieldEncryptionSettings fieldEncryptSettings; - - [Tooltip("call obfuscation settings")] - public CallObfuscationSettings callObfusSettings; - - public string ObfuzRootDir => $"Library/Obfuz"; - - public string GetObfuscatedAssemblyOutputPath(BuildTarget target) - { - return $"{ObfuzRootDir}/{target}/ObfuscatedAssemblies"; - } - - public string GetOriginalAssemblyBackupDir(BuildTarget target) - { - return $"{ObfuzRootDir}/{target}/OriginalAssemblies"; - } - - private static ObfuzSettings s_Instance; - - public static ObfuzSettings Instance - { - get - { - if (!s_Instance) - { - LoadOrCreate(); - } - return s_Instance; - } - } - - protected static string SettingsPath => "ProjectSettings/Obfuz.asset"; - - private static ObfuzSettings LoadOrCreate() - { - string filePath = SettingsPath; - var arr = InternalEditorUtility.LoadSerializedFileAndForget(filePath); - //Debug.Log($"typeof arr:{arr?.GetType()} arr[0]:{(arr != null && arr.Length > 0 ? arr[0].GetType(): null)}"); - - if (arr != null && arr.Length > 0 && arr[0] is ObfuzSettings obfuzSettings) - { - s_Instance = obfuzSettings; - } - else - { - s_Instance ??= CreateInstance(); - } - return s_Instance; - } - - public static void Save() - { - if (!s_Instance) - { - Debug.LogError("Cannot save ScriptableSingleton: no instance!"); - return; - } - - string filePath = SettingsPath; - string directoryName = Path.GetDirectoryName(filePath); - Directory.CreateDirectory(directoryName); - UnityEngine.Object[] obj = new ObfuzSettings[1] { s_Instance }; - InternalEditorUtility.SaveToSerializedFileAndForget(obj, filePath, true); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs.meta deleted file mode 100644 index 8bad58f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c414eef017e565c4db1442ec64ec52fe -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs deleted file mode 100644 index 3a5c9e2..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Reflection; -using UnityEditor; -using UnityEditor.Presets; -using UnityEngine; -using UnityEngine.UIElements; - -namespace Obfuz.Settings -{ - public class ObfuzSettingsProvider : SettingsProvider - { - - private static ObfuzSettingsProvider s_provider; - - [SettingsProvider] - public static SettingsProvider CreateMyCustomSettingsProvider() - { - if (s_provider == null) - { - s_provider = new ObfuzSettingsProvider(); - using (var so = new SerializedObject(ObfuzSettings.Instance)) - { - s_provider.keywords = GetSearchKeywordsFromSerializedObject(so); - } - } - return s_provider; - } - - - private SerializedObject _serializedObject; - private SerializedProperty _enable; - private SerializedProperty _assemblySettings; - private SerializedProperty _obfuscationPassSettings; - private SerializedProperty _secretSettings; - private SerializedProperty _encryptionVMSettings; - - private SerializedProperty _symbolObfusSettings; - private SerializedProperty _constEncryptSettings; - private SerializedProperty _fieldEncryptSettings; - private SerializedProperty _callObfusSettings; - - public ObfuzSettingsProvider() : base("Project/Obfuz", SettingsScope.Project) - { - } - - public override void OnActivate(string searchContext, VisualElement rootElement) - { - InitGUI(); - } - - public override void OnDeactivate() - { - base.OnDeactivate(); - ObfuzSettings.Save(); - } - - private void InitGUI() - { - var setting = ObfuzSettings.Instance; - _serializedObject?.Dispose(); - _serializedObject = new SerializedObject(setting); - _enable = _serializedObject.FindProperty("enable"); - _assemblySettings = _serializedObject.FindProperty("assemblySettings"); - _obfuscationPassSettings = _serializedObject.FindProperty("obfuscationPassSettings"); - _secretSettings = _serializedObject.FindProperty("secretSettings"); - - _encryptionVMSettings = _serializedObject.FindProperty("encryptionVMSettings"); - - _symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings"); - _constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings"); - _fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings"); - _callObfusSettings = _serializedObject.FindProperty("callObfusSettings"); - } - - public override void OnGUI(string searchContext) - { - if (_serializedObject == null||!_serializedObject.targetObject) - { - InitGUI(); - } - _serializedObject.Update(); - EditorGUI.BeginChangeCheck(); - - EditorGUILayout.PropertyField(_enable); - EditorGUILayout.PropertyField(_assemblySettings); - EditorGUILayout.PropertyField(_obfuscationPassSettings); - EditorGUILayout.PropertyField(_secretSettings); - - EditorGUILayout.PropertyField(_encryptionVMSettings); - - EditorGUILayout.PropertyField(_symbolObfusSettings); - EditorGUILayout.PropertyField(_constEncryptSettings); - EditorGUILayout.PropertyField(_fieldEncryptSettings); - EditorGUILayout.PropertyField(_callObfusSettings); - - - if (EditorGUI.EndChangeCheck()) - { - _serializedObject.ApplyModifiedProperties(); - ObfuzSettings.Save(); - } - } - } -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs.meta deleted file mode 100644 index 471477b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 9f020d09993a1aa41bae3258ec33d5fc -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs deleted file mode 100644 index 09c2143..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.IO; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class SecretSettings - { - - [Tooltip("default static secret key")] - public string defaultStaticSecretKey = "Code Philosophy-Static"; - - [Tooltip("default dynamic secret key")] - public string defaultDynamicSecretKey = "Code Philosophy-Dynamic"; - - [Tooltip("secret key output path")] - public string secretKeyOutputPath = $"Assets/Resources/Obfuz"; - - [Tooltip("random seed")] - public int randomSeed = 0; - - [Tooltip("name of assemblies those use dynamic secret key")] - public string[] assembliesUsingDynamicSecretKeys; - - public string DefaultStaticSecretKeyOutputPath => Path.Combine(secretKeyOutputPath, "defaultStaticSecretKey.bytes"); - - public string DefaultDynamicSecretKeyOutputPath => Path.Combine(secretKeyOutputPath, "defaultDynamicSecretKey.bytes"); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs.meta deleted file mode 100644 index 7e26a78..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7ac4fe2a6df113444b67412254452a00 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs deleted file mode 100644 index 6e1d765..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Settings -{ - [Serializable] - public class SymbolObfuscationSettings - { - public bool debug; - - [Tooltip("prefix for obfuscated name to avoid name confliction with original name")] - public string obfuscatedNamePrefix = "$"; - - [Tooltip("obfuscate same namespace to one name")] - public bool useConsistentNamespaceObfuscation = true; - - [Tooltip("symbol mapping file path")] - public string symbolMappingFile = "Assets/Obfuz/SymbolObfus/symbol-mapping.xml"; - - [Tooltip("rule files")] - public string[] ruleFiles; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs.meta deleted file mode 100644 index 58779d6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2484a8a12a689df46b5eb7fc4ccac81f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity.meta deleted file mode 100644 index 8456b1d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: bc9b206fbf6a69f4c99a6ec9b0b27c69 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs deleted file mode 100644 index b8f2397..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Obfuz.Unity -{ - public class ObfuscationBeginEventArgs - { - public string scriptAssembliesPath; - public string obfuscatedScriptAssembliesPath; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs.meta deleted file mode 100644 index a2d5e11..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 8e3d38018839d4844bf1e15631946e65 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs deleted file mode 100644 index ac2fa76..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Obfuz.Unity -{ - public class ObfuscationEndEventArgs - { - public bool success; - public string originalScriptAssembliesPath; - public string obfuscatedScriptAssembliesPath; - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs.meta deleted file mode 100644 index fe37681..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6b198ad99d0a9c145b1bc2b29b25b8ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs deleted file mode 100644 index 4770a57..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEditor.Build; -using UnityEditor; -using UnityEditor.Build.Reporting; -using UnityEngine; -using UnityEditor.Compilation; -using Obfuz.Utils; -using FileUtil = Obfuz.Utils.FileUtil; -using Obfuz.Settings; - -namespace Obfuz.Unity -{ - -#if UNITY_2019_1_OR_NEWER - public class ObfuscationProcess : IPostBuildPlayerScriptDLLs - { - public int callbackOrder => 10000; - - public static event Action OnObfuscationBegin; - - public static event Action OnObfuscationEnd; - - public void OnPostBuildPlayerScriptDLLs(BuildReport report) - { -#if !UNITY_2022_1_OR_NEWER - RunObfuscate(report.files); -#else - RunObfuscate(report.GetFiles()); -#endif - } - - private static void BackupOriginalDlls(string srcDir, string dstDir, HashSet dllNames) - { - FileUtil.RecreateDir(dstDir); - foreach (string dllName in dllNames) - { - string srcFile = Path.Combine(srcDir, dllName + ".dll"); - string dstFile = Path.Combine(dstDir, dllName + ".dll"); - if (File.Exists(srcFile)) - { - File.Copy(srcFile, dstFile, true); - Debug.Log($"BackupOriginalDll {srcFile} -> {dstFile}"); - } - } - } - - private static void RunObfuscate(BuildFile[] files) - { - ObfuzSettings settings = ObfuzSettings.Instance; - if (!settings.enable) - { - Debug.Log("Obfuscation is disabled."); - return; - } - - Debug.Log("Obfuscation begin..."); - var buildTarget = EditorUserBuildSettings.activeBuildTarget; - - var obfuscationRelativeAssemblyNames = new HashSet(settings.assemblySettings.GetObfuscationRelativeAssemblyNames()); - string stagingAreaTempManagedDllDir = Path.GetDirectoryName(files.First(file => file.path.EndsWith(".dll")).path); - string backupPlayerScriptAssembliesPath = settings.GetOriginalAssemblyBackupDir(buildTarget); - BackupOriginalDlls(stagingAreaTempManagedDllDir, backupPlayerScriptAssembliesPath, obfuscationRelativeAssemblyNames); - - string applicationContentsPath = EditorApplication.applicationContentsPath; - - var obfuscatorBuilder = ObfuscatorBuilder.FromObfuzSettings(settings, buildTarget, false); - - var assemblySearchDirs = new List - { - stagingAreaTempManagedDllDir, - }; - obfuscatorBuilder.InsertTopPriorityAssemblySearchPaths(assemblySearchDirs); - - - OnObfuscationBegin?.Invoke(new ObfuscationBeginEventArgs - { - scriptAssembliesPath = stagingAreaTempManagedDllDir, - obfuscatedScriptAssembliesPath = obfuscatorBuilder.ObfuscatedAssemblyOutputPath, - }); - bool succ = false; - - try - { - Obfuscator obfuz = obfuscatorBuilder.Build(); - obfuz.Run(); - - foreach (var dllName in obfuscationRelativeAssemblyNames) - { - string src = $"{obfuscatorBuilder.ObfuscatedAssemblyOutputPath}/{dllName}.dll"; - string dst = $"{stagingAreaTempManagedDllDir}/{dllName}.dll"; - - if (!File.Exists(src)) - { - Debug.LogWarning($"obfuscation assembly not found! skip copy. path:{src}"); - continue; - } - File.Copy(src, dst, true); - Debug.Log($"obfuscate dll:{dst}"); - } - succ = true; - } - catch (Exception e) - { - succ = false; - Debug.LogException(e); - Debug.LogError($"Obfuscation failed."); - } - OnObfuscationEnd?.Invoke(new ObfuscationEndEventArgs - { - success = succ, - originalScriptAssembliesPath = backupPlayerScriptAssembliesPath, - obfuscatedScriptAssembliesPath = stagingAreaTempManagedDllDir, - }); - - Debug.Log("Obfuscation end."); - } - } -#endif - } diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs.meta deleted file mode 100644 index de6b391..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fc7a8b1e20c66164699de44d0a302cb7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs deleted file mode 100644 index d0162c3..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Obfuz.EncryptionVM; -using Obfuz.Settings; -using Obfuz.Utils; -using System.IO; -using UnityEditor; -using UnityEngine; -using FileUtil = Obfuz.Utils.FileUtil; - -namespace Obfuz.Unity -{ - public static class ObfuzMenu - { - - [MenuItem("Obfuz/Settings...", priority = 1)] - public static void OpenSettings() => SettingsService.OpenProjectSettings("Project/Obfuz"); - - [MenuItem("Obfuz/GenerateEncryptionVM", priority = 62)] - public static void GenerateEncryptionVM() - { - EncryptionVMSettings settings = ObfuzSettings.Instance.encryptionVMSettings; - var generator = new VirtualMachineCodeGenerator(settings.codeGenerationSecretKey, settings.encryptionOpCodeCount); - generator.Generate(settings.codeOutputPath); - } - - [MenuItem("Obfuz/GenerateSecretKeyFile", priority = 63)] - public static void SaveSecretFile() - { - SecretSettings settings = ObfuzSettings.Instance.secretSettings; - - var staticSecretBytes = KeyGenerator.GenerateKey(settings.defaultStaticSecretKey, VirtualMachine.SecretKeyLength); - SaveKey(staticSecretBytes, settings.DefaultStaticSecretKeyOutputPath); - Debug.Log($"Save static secret key to {settings.DefaultStaticSecretKeyOutputPath}"); - var dynamicSecretBytes = KeyGenerator.GenerateKey(settings.defaultDynamicSecretKey, VirtualMachine.SecretKeyLength); - SaveKey(dynamicSecretBytes, settings.DefaultDynamicSecretKeyOutputPath); - Debug.Log($"Save dynamic secret key to {settings.DefaultDynamicSecretKeyOutputPath}"); - AssetDatabase.Refresh(); - } - - private static void SaveKey(byte[] secret, string secretOutputPath) - { - FileUtil.CreateParentDir(secretOutputPath); - File.WriteAllBytes(secretOutputPath, secret); - } - - [MenuItem("Obfuz/Documents/Quick Start")] - public static void OpenQuickStart() => Application.OpenURL("https://obfuz.doc.code-philosophy.com/docs/beginner/quickstart"); - - [MenuItem("Obfuz/Documents/FAQ")] - public static void OpenFAQ() => Application.OpenURL("https://obfuz.doc.code-philosophy.com/docs/help/faq"); - - [MenuItem("Obfuz/Documents/Common Errors")] - public static void OpenCommonErrors() => Application.OpenURL("https://obfuz.doc.code-philosophy.com/docs/help/commonerrors"); - - [MenuItem("Obfuz/Documents/Bug Report")] - public static void OpenBugReport() => Application.OpenURL("https://obfuz.doc.code-philosophy.com/docs/help/issue"); - - [MenuItem("Obfuz/Documents/GitHub")] - public static void OpenGitHub() => Application.OpenURL("https://github.com/focus-creative-games/obfuz"); - - [MenuItem("Obfuz/Documents/About")] - public static void OpenAbout() => Application.OpenURL("https://obfuz.doc.code-philosophy.com/docs/intro"); - } - -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs.meta deleted file mode 100644 index ae1f6f8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ce8d804a6c4640e45a3d5c98b30c0c31 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils.meta deleted file mode 100644 index 8a3e253..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ade28aaad1116b143a4027071e71010f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs deleted file mode 100644 index ecaa587..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs +++ /dev/null @@ -1,91 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public class AssemblyCache - { - private readonly IAssemblyResolver _assemblyPathResolver; - private readonly ModuleContext _modCtx; - private readonly AssemblyResolver _asmResolver; - private bool _enableTypeDefCache; - - - public ModuleContext ModCtx => _modCtx; - - public Dictionary LoadedModules { get; } = new Dictionary(); - - public AssemblyCache(IAssemblyResolver assemblyResolver) - { - _enableTypeDefCache = true; - _assemblyPathResolver = assemblyResolver; - _modCtx = ModuleDef.CreateModuleContext(); - _asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver; - _asmResolver.EnableTypeDefCache = _enableTypeDefCache; - _asmResolver.UseGAC = false; - } - - public bool EnableTypeDefCache - { - get => _enableTypeDefCache; - set - { - _enableTypeDefCache = value; - _asmResolver.EnableTypeDefCache = value; - foreach (var mod in LoadedModules.Values) - { - mod.EnableTypeDefFindCache = value; - } - } - } - - - public ModuleDefMD TryLoadModule(string moduleName) - { - string dllPath = _assemblyPathResolver.ResolveAssembly(moduleName); - if (string.IsNullOrEmpty(dllPath)) - { - return null; - } - return LoadModule(moduleName); - } - - public ModuleDefMD LoadModule(string moduleName) - { - // Debug.Log($"load module:{moduleName}"); - if (LoadedModules.TryGetValue(moduleName, out var mod)) - { - return mod; - } - string assemblyPath = _assemblyPathResolver.ResolveAssembly(moduleName); - if (string.IsNullOrEmpty(assemblyPath)) - { - throw new FileNotFoundException($"Assembly {moduleName} not found"); - } - mod = DoLoadModule(assemblyPath); - LoadedModules.Add(moduleName, mod); - - - foreach (var refAsm in mod.GetAssemblyRefs()) - { - LoadModule(refAsm.Name); - } - - return mod; - } - - private ModuleDefMD DoLoadModule(string dllPath) - { - //Debug.Log($"do load module:{dllPath}"); - ModuleDefMD mod = ModuleDefMD.Load(File.ReadAllBytes(dllPath), _modCtx); - mod.EnableTypeDefFindCache = _enableTypeDefCache; - _asmResolver.AddToCache(mod); - return mod; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs.meta deleted file mode 100644 index bb92229..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ce64ad992f9807d4994d4f41a54b170b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs deleted file mode 100644 index 7eb9491..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public abstract class AssemblyResolverBase : IAssemblyResolver - { - public abstract string ResolveAssembly(string assemblyName); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs.meta deleted file mode 100644 index 4a7f4a0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c7332848ca18498459e6248d06bc5b31 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs deleted file mode 100644 index f7165ab..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public static class CollectionExtensions - { - public static void AddRange(this HashSet values, IEnumerable newValues) - { - foreach (var value in newValues) - { - values.Add(value); - } - } - - public static V GetValueOrDefault(this Dictionary dic, K key) - { - return dic.TryGetValue(key, out V v) ? v : default(V); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs.meta deleted file mode 100644 index ba4aa2a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 58fc4438f86bc174aba662f1d7058f45 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs deleted file mode 100644 index 3dc39fe..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public static class ConfigUtil - { - - public static bool ParseBool(string str) - { - switch (str.ToLowerInvariant()) - { - case "1": - case "true": return true; - case "0": - case "false": return false; - default: throw new Exception($"Invalid bool value {str}"); - } - } - - public static bool? ParseNullableBool(string str) - { - if (string.IsNullOrEmpty(str)) - { - return null; - } - switch (str.ToLowerInvariant()) - { - case "1": - case "true": return true; - case "0": - case "false": return false; - default: throw new Exception($"Invalid bool value {str}"); - } - } - - public static int? ParseNullableInt(string str) - { - if (string.IsNullOrEmpty(str)) - { - return null; - } - return int.Parse(str); - } - - public static long? ParseNullableLong(string str) - { - if (string.IsNullOrEmpty(str)) - { - return null; - } - return long.Parse(str); - } - - public static float? ParseNullableFloat(string str) - { - if (string.IsNullOrEmpty(str)) - { - return null; - } - return float.Parse(str); - } - - public static double? ParseNullableDouble(string str) - { - if (string.IsNullOrEmpty(str)) - { - return null; - } - return double.Parse(str); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs.meta deleted file mode 100644 index bba160a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ff35a8e07f37adf4483eaf5cc5da5c78 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs deleted file mode 100644 index 5785800..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Utils -{ - public static class EncryptionUtil - { - public static int GetBitCount(int value) - { - int count = 0; - while (value > 0) - { - count++; - value >>= 1; - } - return count; - } - - public static int GenerateEncryptionOpCodes(IRandom random, IEncryptor encryptor, int encryptionLevel) - { - if (encryptionLevel <= 0 || encryptionLevel > 4) - { - throw new ArgumentException($"Invalid encryption level: {encryptionLevel}, should be in range [1,4]"); - } - int vmOpCodeCount = encryptor.OpCodeCount; - long ops = 0; - for (int i = 0; i < encryptionLevel; i++) - { - long newOps = ops * vmOpCodeCount; - // don't use 0 - int op = random.NextInt(1, vmOpCodeCount); - newOps |= (uint)op; - if (newOps > uint.MaxValue) - { - Debug.LogWarning($"OpCode overflow. encryptionLevel:{encryptionLevel}, vmOpCodeCount:{vmOpCodeCount}"); - } - else - { - ops = newOps; - } - } - return (int)ops; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs.meta deleted file mode 100644 index 5c82b2b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0b8fc4c92fa6f0b40a9734b347cd265c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs deleted file mode 100644 index ccd210d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public static class FileUtil - { - public static void CreateParentDir(string path) - { - Directory.CreateDirectory(Path.GetDirectoryName(path)); - } - - public static void RemoveDir(string dir, bool log = false) - { - if (log) - { - UnityEngine.Debug.Log($"removeDir dir:{dir}"); - } - - int maxTryCount = 5; - for (int i = 0; i < maxTryCount; ++i) - { - try - { - if (!Directory.Exists(dir)) - { - return; - } - foreach (var file in Directory.GetFiles(dir)) - { - File.SetAttributes(file, FileAttributes.Normal); - File.Delete(file); - } - foreach (var subDir in Directory.GetDirectories(dir)) - { - RemoveDir(subDir); - } - Directory.Delete(dir, true); - break; - } - catch (Exception e) - { - UnityEngine.Debug.LogError($"removeDir:{dir} with exception:{e}. try count:{i}"); - Thread.Sleep(100); - } - } - } - - public static void RecreateDir(string dir) - { - if (Directory.Exists(dir)) - { - RemoveDir(dir, true); - } - Directory.CreateDirectory(dir); - } - - private static void CopyWithCheckLongFile(string srcFile, string dstFile) - { - var maxPathLength = 255; -#if UNITY_EDITOR_OSX - maxPathLength = 1024; -#endif - if (srcFile.Length > maxPathLength) - { - UnityEngine.Debug.LogError($"srcFile:{srcFile} path is too long. skip copy!"); - return; - } - if (dstFile.Length > maxPathLength) - { - UnityEngine.Debug.LogError($"dstFile:{dstFile} path is too long. skip copy!"); - return; - } - File.Copy(srcFile, dstFile); - } - - public static void CopyDir(string src, string dst, bool log = false) - { - if (log) - { - UnityEngine.Debug.Log($"copyDir {src} => {dst}"); - } - RemoveDir(dst); - Directory.CreateDirectory(dst); - foreach (var file in Directory.GetFiles(src)) - { - CopyWithCheckLongFile(file, $"{dst}/{Path.GetFileName(file)}"); - } - foreach (var subDir in Directory.GetDirectories(src)) - { - CopyDir(subDir, $"{dst}/{Path.GetFileName(subDir)}"); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs.meta deleted file mode 100644 index c8523ce..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b6385af8bd061b142a3d7dcf41ab7e79 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs deleted file mode 100644 index a9f89be..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs +++ /dev/null @@ -1,126 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - /// - /// Replaces generic type/method var with its generic argument - /// - public sealed class GenericArgumentContext - { - List typeArgsStack; - List methodArgsStack; - - public GenericArgumentContext(IList typeArgsStack, IList methodArgsStack) - { - this.typeArgsStack = typeArgsStack?.ToList(); - this.methodArgsStack = methodArgsStack?.ToList(); - } - - - - /// - /// Replaces a generic type/method var with its generic argument (if any). If - /// isn't a generic type/method var or if it can't - /// be resolved, it itself is returned. Else the resolved type is returned. - /// - /// Type signature - /// New which is never null unless - /// is null - public TypeSig Resolve(TypeSig typeSig) - { - if (!typeSig.ContainsGenericParameter) - { - return typeSig; - } - typeSig = typeSig.RemovePinnedAndModifiers(); - switch (typeSig.ElementType) - { - case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next)); - case ElementType.ByRef: return new PtrSig(Resolve(typeSig.Next)); - - case ElementType.SZArray: return new PtrSig(Resolve(typeSig.Next)); - case ElementType.Array: - { - var ara = (ArraySig)typeSig; - return new ArraySig(Resolve(typeSig.Next), ara.Rank, ara.Sizes, ara.LowerBounds); - } - - case ElementType.Var: - { - GenericVar genericVar = (GenericVar)typeSig; - var newSig = Resolve(typeArgsStack, genericVar.Number, true); - if (newSig == null) - { - throw new Exception(); - } - return newSig; - } - - case ElementType.MVar: - { - GenericMVar genericVar = (GenericMVar)typeSig; - var newSig = Resolve(methodArgsStack, genericVar.Number, true); - if (newSig == null) - { - throw new Exception(); - } - return newSig; - } - case ElementType.GenericInst: - { - var gia = (GenericInstSig)typeSig; - return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => Resolve(ga)).ToList()); - } - - case ElementType.FnPtr: - { - var fptr = (FnPtrSig)typeSig; - var cs = fptr.Signature; - CallingConventionSig ccs; - switch (cs) - { - case MethodSig ms: - { - ccs = new MethodSig(ms.GetCallingConvention(), ms.GenParamCount, Resolve(ms.RetType), ms.Params.Select(p => Resolve(p)).ToList()); - break; - } - case PropertySig ps: - { - ccs = new PropertySig(ps.HasThis, Resolve(ps.RetType)); - break; - } - case GenericInstMethodSig gims: - { - ccs = new GenericInstMethodSig(gims.GenericArguments.Select(ga => Resolve(ga)).ToArray()); - break; - } - default: throw new NotSupportedException(cs.ToString()); - } - return new FnPtrSig(ccs); - } - - case ElementType.ValueArray: - { - var vas = (ValueArraySig)typeSig; - return new ValueArraySig(Resolve(vas.Next), vas.Size); - } - default: return typeSig; - } - } - - private TypeSig Resolve(List args, uint number, bool isTypeVar) - { - var typeSig = args[(int)number]; - var gvar = typeSig as GenericSig; - if (gvar is null || gvar.IsTypeVar != isTypeVar) - return typeSig; - return gvar; - } - } - -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs.meta deleted file mode 100644 index fd13834..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cdefb4e144f6a98418c7bd02eab51039 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs deleted file mode 100644 index 5b0d823..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs +++ /dev/null @@ -1,67 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine.UIElements; - -namespace Obfuz.Utils -{ - public static class HashUtil - { - public static int CombineHash(int hash1, int hash2) - { - return hash1 * 1566083941 + hash2; - } - - public static int ComputeHash(List sigs) - { - int hash = 135781321; - TypeEqualityComparer tc = TypeEqualityComparer.Instance; - foreach (var sig in sigs) - { - hash = hash * 1566083941 + tc.GetHashCode(sig); - } - return hash; - } - - public static unsafe int ComputeHash(string s) - { - fixed (char* ptr = s) - { - int num = 352654597; - int num2 = num; - int* ptr2 = (int*)ptr; - int num3; - for (num3 = s.Length; num3 > 2; num3 -= 4) - { - num = ((num << 5) + num + (num >> 27)) ^ *ptr2; - num2 = ((num2 << 5) + num2 + (num2 >> 27)) ^ ptr2[1]; - ptr2 += 2; - } - - if (num3 > 0) - { - num = ((num << 5) + num + (num >> 27)) ^ *ptr2; - } - - return num + num2 * 1566083941; - } - } - - public static int ComputePrimitiveOrStringOrBytesHashCode(object obj) - { - if (obj is byte[] bytes) - { - return StructuralComparisons.StructuralEqualityComparer.GetHashCode(bytes); - } - if (obj is string s) - { - return HashUtil.ComputeHash(s); - } - return obj.GetHashCode(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs.meta deleted file mode 100644 index d89f8f0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 0b4cd05dd413bfa4ebb9fcbe591b1486 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs deleted file mode 100644 index 4a7578a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public interface IAssemblyResolver - { - string ResolveAssembly(string assemblyName); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs.meta deleted file mode 100644 index 917a107..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: e0254d9726a78e146af99a61641b47d3 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs deleted file mode 100644 index e3a68b8..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Obfuz.Utils -{ - public interface IRandom - { - int NextInt(int min, int max); - - int NextInt(int max); - - int NextInt(); - - long NextLong(); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs.meta deleted file mode 100644 index 086b073..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 959c821ff51056c4ebca3f89aeeff03d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs deleted file mode 100644 index 31aa40c..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs +++ /dev/null @@ -1,41 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public static class KeyGenerator - { - public static byte[] GenerateKey(string initialString, int keyLength) - { - byte[] initialBytes = Encoding.UTF8.GetBytes(initialString); - using (var sha512 = SHA512.Create()) - { - byte[] hash = sha512.ComputeHash(initialBytes); - byte[] key = new byte[keyLength]; - int bytesCopied = 0; - while (bytesCopied < key.Length) - { - if (bytesCopied > 0) - { - // 再次哈希之前的哈希值以生成更多数据 - hash = sha512.ComputeHash(hash); - } - int bytesToCopy = Math.Min(hash.Length, key.Length - bytesCopied); - Buffer.BlockCopy(hash, 0, key, bytesCopied, bytesToCopy); - bytesCopied += bytesToCopy; - } - return key; - } - } - - public static int[] ConvertToIntKey(byte[] key) - { - return EncryptorBase.ConvertToIntKey(key); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs.meta deleted file mode 100644 index 7d11ff0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5441ac16fd88a8848af862be23bd2ecb -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs deleted file mode 100644 index 711e957..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs +++ /dev/null @@ -1,813 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using UnityEngine.Assertions; -using UnityEngine.UIElements; - -namespace Obfuz.Utils -{ - - public static class MetaUtil - { - public static string GetModuleNameWithoutExt(string moduleName) - { - return Path.GetFileNameWithoutExtension(moduleName); - } - - public static (string, string) SplitNamespaceAndName(string fullName) - { - int index = fullName.LastIndexOf('/'); - if (index == -1) - { - int index2 = fullName.IndexOf('.'); - return index2 >= 0 ? (fullName.Substring(0, index2), fullName.Substring(index2 + 1)) : ("", fullName); - } - return ("", fullName.Substring(index + 1)); - } - - - public static TypeDef GetBaseTypeDef(TypeDef type) - { - ITypeDefOrRef baseType = type.BaseType; - if (baseType == null) - { - return null; - } - TypeDef baseTypeDef = baseType.ResolveTypeDef(); - if (baseTypeDef != null) - { - return baseTypeDef; - } - if (baseType is TypeSpec baseTypeSpec) - { - GenericInstSig genericIns = baseTypeSpec.TypeSig.ToGenericInstSig(); - return genericIns.GenericType.TypeDefOrRef.ResolveTypeDefThrow(); - } - else - { - throw new Exception($"GetBaseTypeDef: {type} fail"); - } - } - - public static TypeDef GetTypeDefOrGenericTypeBaseThrowException(ITypeDefOrRef type) - { - if (type.IsTypeDef) - { - return (TypeDef)type; - } - if (type.IsTypeRef) - { - return type.ResolveTypeDefThrow(); - } - if (type.IsTypeSpec) - { - GenericInstSig gis = type.TryGetGenericInstSig(); - return gis.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow(); - } - throw new NotSupportedException($"{type}"); - } - - public static TypeDef GetTypeDefOrGenericTypeBaseOrNull(ITypeDefOrRef type) - { - if (type.IsTypeDef) - { - return (TypeDef)type; - } - if (type.IsTypeRef) - { - return type.ResolveTypeDefThrow(); - } - if (type.IsTypeSpec) - { - GenericInstSig gis = type.TryGetGenericInstSig(); - return gis.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow(); - } - return null; - } - - public static TypeDef GetMemberRefTypeDefParentOrNull(IMemberRefParent parent) - { - if (parent is TypeDef typeDef) - { - return typeDef; - } - if (parent is TypeRef typeRef) - { - return typeRef.ResolveTypeDefThrow(); - } - if (parent is TypeSpec typeSpec) - { - GenericInstSig genericIns = typeSpec.TypeSig.ToGenericInstSig(); - return genericIns.GenericType.TypeDefOrRef.ResolveTypeDefThrow(); - } - return null; - } - - public static bool IsInheritFromUnityObject(TypeDef typeDef) - { - TypeDef cur = typeDef; - while (true) - { - cur = GetBaseTypeDef(cur); - if (cur == null) - { - return false; - } - if (cur.Name == "Object" && cur.Namespace == "UnityEngine" && cur.Module.Name == "UnityEngine.CoreModule.dll") - { - return true; - } - } - } - - - - public static bool IsScriptOrSerializableType(TypeDef type) - { - if (type.ContainsGenericParameter) - { - return false; - } - if (type.IsSerializable) - { - return true; - } - - for (TypeDef parentType = GetBaseTypeDef(type); parentType != null; parentType = GetBaseTypeDef(parentType)) - { - if ((parentType.Name == "MonoBehaviour" || parentType.Name == "ScriptableObject") - && parentType.Namespace == "UnityEngine" - && parentType.Module.Assembly.Name == "UnityEngine.CoreModule") - { - return true; - } - } - - return false; - } - - public static bool IsSerializableTypeSig(TypeSig typeSig) - { - typeSig = typeSig.RemovePinnedAndModifiers(); - switch (typeSig.ElementType) - { - case ElementType.Boolean: - case ElementType.Char: - case ElementType.I1: - case ElementType.U1: - case ElementType.I2: - case ElementType.U2: - case ElementType.I4: - case ElementType.U4: - case ElementType.I8: - case ElementType.U8: - case ElementType.R4: - case ElementType.R8: - case ElementType.String: - return true; - case ElementType.Class: - return IsScriptOrSerializableType(typeSig.ToTypeDefOrRef().ResolveTypeDefThrow()); - case ElementType.ValueType: - { - TypeDef typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDefThrow(); - if (typeDef.IsEnum) - { - return true; - } - return typeDef.IsSerializable; - } - case ElementType.GenericInst: - { - GenericInstSig genericIns = typeSig.ToGenericInstSig(); - TypeDef typeDef = genericIns.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow(); - return typeDef.FullName == "System.Collections.Generic.List`1" && IsSerializableTypeSig(genericIns.GenericArguments[0]); - } - case ElementType.SZArray: - { - return IsSerializableTypeSig(typeSig.RemovePinnedAndModifiers().Next); - } - default: - return false; - } - } - - public static bool IsSerializableField(FieldDef field) - { - if (field.IsStatic) - { - return false; - } - var fieldSig = field.FieldSig.Type; - if (field.IsPublic) - { - return IsSerializableTypeSig(fieldSig); - } - if (field.CustomAttributes.Any(c => c.TypeFullName == "UnityEngine.SerializeField")) - { - //UnityEngine.Debug.Assert(IsSerializableTypeSig(fieldSig)); - return true; - } - return false; - } - - public static bool MayRenameCustomDataType(ElementType type) - { - return type == ElementType.Class || type == ElementType.ValueType || type == ElementType.Object || type == ElementType.SZArray; - } - - public static TypeSig RetargetTypeRefInTypeSig(TypeSig type) - { - TypeSig next = type.Next; - TypeSig newNext = next != null ? RetargetTypeRefInTypeSig(next) : null; - if (type.IsModifier || type.IsPinned) - { - if (next == newNext) - { - return type; - } - if (type is CModReqdSig cmrs) - { - return new CModReqdSig(cmrs.Modifier, newNext); - } - if (type is CModOptSig cmos) - { - return new CModOptSig(cmos.Modifier, newNext); - } - if (type is PinnedSig ps) - { - return new PinnedSig(newNext); - } - throw new System.NotSupportedException(type.ToString()); - } - switch (type.ElementType) - { - case ElementType.Ptr: - { - if (next == newNext) - { - return type; - } - return new PtrSig(newNext); - } - case ElementType.ValueType: - case ElementType.Class: - { - var vts = type as ClassOrValueTypeSig; - TypeDef typeDef = vts.TypeDefOrRef.ResolveTypeDefThrow(); - if (typeDef == vts.TypeDefOrRef) - { - return type; - } - return type.IsClassSig ? (TypeSig)new ClassSig(typeDef) : new ValueTypeSig(typeDef); - } - case ElementType.Array: - { - if (next == newNext) - { - return type; - } - return new ArraySig(newNext); - } - case ElementType.SZArray: - { - if (next == newNext) - { - return type; - } - return new SZArraySig(newNext); - } - case ElementType.GenericInst: - { - var gis = type as GenericInstSig; - ClassOrValueTypeSig genericType = gis.GenericType; - ClassOrValueTypeSig newGenericType = (ClassOrValueTypeSig)RetargetTypeRefInTypeSig(genericType); - bool anyChange = genericType != newGenericType; - var genericArgs = new List(); - foreach (var arg in gis.GenericArguments) - { - TypeSig newArg = RetargetTypeRefInTypeSig(arg); - anyChange |= newArg != genericType; - genericArgs.Add(newArg); - } - if (!anyChange) - { - return type; - } - return new GenericInstSig(newGenericType, genericArgs); - } - case ElementType.FnPtr: - { - var fp = type as FnPtrSig; - MethodSig methodSig = fp.MethodSig; - TypeSig newReturnType = RetargetTypeRefInTypeSig(methodSig.RetType); - bool anyChange = newReturnType != methodSig.RetType; - var newArgs = new List(); - foreach (TypeSig arg in methodSig.Params) - { - TypeSig newArg = RetargetTypeRefInTypeSig(arg); - anyChange |= newArg != newReturnType; - } - if (!anyChange) - { - return type; - } - var newParamsAfterSentinel = new List(); - foreach (TypeSig arg in methodSig.ParamsAfterSentinel) - { - TypeSig newArg = RetargetTypeRefInTypeSig(arg); - anyChange |= newArg != arg; - newParamsAfterSentinel.Add(newArg); - } - - var newMethodSig = new MethodSig(methodSig.CallingConvention, methodSig.GenParamCount, newReturnType, newArgs, newParamsAfterSentinel); - return new FnPtrSig(newMethodSig); - } - case ElementType.ByRef: - { - if (next == newNext) - { - return type; - } - return new ByRefSig(newNext); - } - default: - { - return type; - } - } - } - - - public static object RetargetTypeRefInTypeSigOfValue(object oldValue) - { - if (oldValue == null) - { - return null; - } - string typeName = oldValue.GetType().FullName; - if (oldValue.GetType().IsPrimitive) - { - return oldValue; - } - if (oldValue is string || oldValue is UTF8String) - { - return oldValue; - } - if (oldValue is TypeSig typeSig) - { - return RetargetTypeRefInTypeSig(typeSig); - } - if (oldValue is CAArgument caValue) - { - TypeSig newType = RetargetTypeRefInTypeSig(caValue.Type); - object newValue = RetargetTypeRefInTypeSigOfValue(caValue.Value); - if (newType != caValue.Type || newValue != caValue.Value) - { - return new CAArgument(newType, newValue); - } - return oldValue; - } - if (oldValue is List oldArr) - { - bool anyChange = false; - var newArr = new List(); - foreach (CAArgument oldArg in oldArr) - { - if (TryRetargetTypeRefInArgument(oldArg, out var newArg)) - { - anyChange = true; - newArr.Add(newArg); - } - else - { - newArr.Add(oldArg); - } - } - return anyChange ? newArr : oldArr; - } - throw new NotSupportedException($"type:{oldValue.GetType()} value:{oldValue}"); - } - - - - public static bool TryRetargetTypeRefInArgument(CAArgument oldArg, out CAArgument newArg) - { - TypeSig newType = RetargetTypeRefInTypeSig(oldArg.Type); - object newValue = RetargetTypeRefInTypeSigOfValue(oldArg.Value); - if (newType != oldArg.Type || oldArg.Value != newValue) - { - newArg = new CAArgument(newType, newValue); - return true; - } - newArg = default; - return false; - } - - public static bool TryRetargetTypeRefInNamedArgument(CANamedArgument arg) - { - bool anyChange = false; - TypeSig newType = RetargetTypeRefInTypeSig(arg.Type); - if (newType != arg.Type) - { - anyChange = true; - arg.Type = newType; - } - if (TryRetargetTypeRefInArgument(arg.Argument, out var newArg)) - { - arg.Argument = newArg; - anyChange = true; - } - return anyChange; - } - - //public static bool ContainsContainsGenericParameter1(MethodDef method) - //{ - // Assert.IsTrue(!(method.DeclaringType.ContainsGenericParameter || method.MethodSig.ContainsGenericParameter)); - // return false; - //} - - public static bool ContainsContainsGenericParameter1(MethodSpec methodSpec) - { - if (methodSpec.GenericInstMethodSig.ContainsGenericParameter) - { - return true; - } - IMethodDefOrRef method = methodSpec.Method; - if (method.IsMethodDef) - { - return false;// ContainsContainsGenericParameter1((MethodDef)method); - } - if (method.IsMemberRef) - { - return ContainsContainsGenericParameter1((MemberRef)method); - } - throw new Exception($"unknown method: {method}"); - } - - public static bool ContainsContainsGenericParameter1(MemberRef memberRef) - { - IMemberRefParent parent = memberRef.Class; - if (parent is TypeSpec typeSpec) - { - return typeSpec.ContainsGenericParameter; - } - return false; - } - - public static bool ContainsContainsGenericParameter(IMethod method) - { - Assert.IsTrue(method.IsMethod); - if (method is MethodDef methodDef) - { - return false; - } - - if (method is MethodSpec methodSpec) - { - return ContainsContainsGenericParameter1(methodSpec); - } - if (method is MemberRef memberRef) - { - return ContainsContainsGenericParameter1(memberRef); - } - throw new Exception($"unknown method: {method}"); - } - - - - public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx) - { - if (!sig.ContainsGenericParameter) - { - return sig; - } - return ctx.Resolve(sig); - } - - - public static MethodSig InflateMethodSig(MethodSig methodSig, GenericArgumentContext genericArgumentContext) - { - var newReturnType = Inflate(methodSig.RetType, genericArgumentContext); - var newParams = new List(); - foreach (var param in methodSig.Params) - { - newParams.Add(Inflate(param, genericArgumentContext)); - } - var newParamsAfterSentinel = new List(); - if (methodSig.ParamsAfterSentinel != null) - { - throw new NotSupportedException($"methodSig.ParamsAfterSentinel is not supported: {methodSig}"); - //foreach (var param in methodSig.ParamsAfterSentinel) - //{ - // newParamsAfterSentinel.Add(Inflate(param, genericArgumentContext)); - //} - } - return new MethodSig(methodSig.CallingConvention, methodSig.GenParamCount, newReturnType, newParams, null); - } - - public static IList GetGenericArguments(IMemberRefParent type) - { - if (type is TypeDef typeDef) - { - return null; - } - if (type is TypeRef typeRef) - { - return null; - } - if (type is TypeSpec typeSpec) - { - GenericInstSig genericInstSig = typeSpec.TypeSig.ToGenericInstSig(); - return genericInstSig?.GenericArguments; - } - throw new NotSupportedException($"type:{type}"); - } - - public static MethodSig GetInflatedMethodSig(IMethod method) - { - if (method is MethodDef methodDef) - { - return methodDef.MethodSig; - } - if (method is MemberRef memberRef) - { - return InflateMethodSig(memberRef.MethodSig, new GenericArgumentContext(GetGenericArguments(memberRef.Class), null)); - } - if (method is MethodSpec methodSpec) - { - var genericInstMethodSig = methodSpec.GenericInstMethodSig; - if (methodSpec.Method is MethodDef methodDef2) - { - return InflateMethodSig(methodDef2.MethodSig, new GenericArgumentContext(null, genericInstMethodSig.GenericArguments)); - } - if (methodSpec.Method is MemberRef memberRef2) - { - return InflateMethodSig(memberRef2.MethodSig, new GenericArgumentContext(GetGenericArguments(memberRef2.Class), genericInstMethodSig.GenericArguments)); - } - - } - throw new NotSupportedException($" method: {method}"); - } - - public static ThisArgType GetThisArgType(IMethod method) - { - if (!method.MethodSig.HasThis) - { - return ThisArgType.None; - } - if (method is MethodDef methodDef) - { - return methodDef.DeclaringType.IsValueType ? ThisArgType.ValueType : ThisArgType.Class; - } - if (method is MemberRef memberRef) - { - TypeDef typeDef = MetaUtil.GetMemberRefTypeDefParentOrNull(memberRef.Class); - if (typeDef == null) - { - return ThisArgType.Class; - } - return typeDef.IsValueType ? ThisArgType.ValueType : ThisArgType.Class; - } - if (method is MethodSpec methodSpec) - { - return GetThisArgType(methodSpec.Method); - } - throw new NotSupportedException($" method: {method}"); - } - - public static MethodSig ToSharedMethodSig(ICorLibTypes corTypes, MethodSig methodSig) - { - var newReturnType = methodSig.RetType; - var newParams = new List(); - foreach (var param in methodSig.Params) - { - newParams.Add(ToShareTypeSig(corTypes, param)); - } - if (methodSig.ParamsAfterSentinel != null) - { - //foreach (var param in methodSig.ParamsAfterSentinel) - //{ - // newParamsAfterSentinel.Add(ToShareTypeSig(corTypes, param)); - //} - throw new NotSupportedException($"methodSig.ParamsAfterSentinel is not supported: {methodSig}"); - } - return new MethodSig(methodSig.CallingConvention, methodSig.GenParamCount, newReturnType, newParams, null); - } - - public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig) - { - var a = typeSig.RemovePinnedAndModifiers(); - switch (a.ElementType) - { - case ElementType.Void: return corTypes.Void; - case ElementType.Boolean: return corTypes.Byte; - case ElementType.Char: return corTypes.UInt16; - case ElementType.I1: return corTypes.SByte; - case ElementType.U1: return corTypes.Byte; - case ElementType.I2: return corTypes.Int16; - case ElementType.U2: return corTypes.UInt16; - case ElementType.I4: return corTypes.Int32; - case ElementType.U4: return corTypes.UInt32; - case ElementType.I8: return corTypes.Int64; - case ElementType.U8: return corTypes.UInt64; - case ElementType.R4: return corTypes.Single; - case ElementType.R8: return corTypes.Double; - case ElementType.String: return corTypes.Object; - case ElementType.TypedByRef: return corTypes.TypedReference; - case ElementType.I: return corTypes.IntPtr; - case ElementType.U: return corTypes.UIntPtr; - case ElementType.Object: return corTypes.Object; - case ElementType.Sentinel: return typeSig; - case ElementType.Ptr: return corTypes.UIntPtr; - case ElementType.ByRef: return corTypes.UIntPtr; - case ElementType.SZArray: return typeSig; - case ElementType.Array: return typeSig; - case ElementType.ValueType: - { - TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef(); - if (typeDef == null) - { - throw new Exception($"type:{a} definition could not be found"); - } - if (typeDef.IsEnum) - { - return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType()); - } - return typeSig; - } - case ElementType.Var: - case ElementType.MVar: - case ElementType.Class: return corTypes.Object; - case ElementType.GenericInst: - { - var gia = (GenericInstSig)a; - TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef(); - if (typeDef == null) - { - throw new Exception($"type:{a} definition could not be found"); - } - if (typeDef.IsEnum) - { - return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType()); - } - if (!typeDef.IsValueType) - { - return corTypes.Object; - } - // il2cpp will raise error when try to share generic value type - return typeSig; - //return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(corTypes, ga)).ToList()); - } - case ElementType.FnPtr: return corTypes.UIntPtr; - case ElementType.ValueArray: return typeSig; - case ElementType.Module: return typeSig; - default: - throw new NotSupportedException(typeSig.ToString()); - } - } - - - public static void AppendIl2CppStackTraceNameOfTypeSig(StringBuilder sb, TypeSig typeSig) - { - typeSig = typeSig.RemovePinnedAndModifiers(); - - switch (typeSig.ElementType) - { - case ElementType.Void: sb.Append("Void"); break; - case ElementType.Boolean: sb.Append("Boolean"); break; - case ElementType.Char: sb.Append("Char"); break; - case ElementType.I1: sb.Append("SByte"); break; - case ElementType.U1: sb.Append("Byte"); break; - case ElementType.I2: sb.Append("Int16"); break; - case ElementType.U2: sb.Append("UInt16"); break; - case ElementType.I4: sb.Append("Int32"); break; - case ElementType.U4: sb.Append("UInt32"); break; - case ElementType.I8: sb.Append("Int64"); break; - case ElementType.U8: sb.Append("UInt64"); break; - case ElementType.R4: sb.Append("Single"); break; - case ElementType.R8: sb.Append("Double"); break; - case ElementType.String: sb.Append("String"); break; - case ElementType.Ptr: AppendIl2CppStackTraceNameOfTypeSig(sb, typeSig.Next); sb.Append("*"); break; - case ElementType.ByRef: AppendIl2CppStackTraceNameOfTypeSig(sb, typeSig.Next); sb.Append("&"); break; - case ElementType.ValueType: - case ElementType.Class: - { - var classOrValueTypeSig = (ClassOrValueTypeSig)typeSig; - TypeDef typeDef = classOrValueTypeSig.TypeDefOrRef.ResolveTypeDef(); - if (typeDef == null) - { - throw new Exception($"type:{classOrValueTypeSig} definition could not be found"); - } - sb.Append(typeDef.Name); - break; - } - case ElementType.GenericInst: - { - var genericInstSig = (GenericInstSig)typeSig; - AppendIl2CppStackTraceNameOfTypeSig(sb, genericInstSig.GenericType); - break; - } - case ElementType.Var: - case ElementType.MVar: - { - var varSig = (GenericSig)typeSig; - sb.Append(varSig.GenericParam.Name); - break; - } - case ElementType.I: sb.Append("IntPtr"); break; - case ElementType.U: sb.Append("UIntPtr"); break; - case ElementType.FnPtr: sb.Append("IntPtr"); break; - case ElementType.Object: sb.Append("Object"); break; - case ElementType.SZArray: - { - var szArraySig = (SZArraySig)typeSig; - AppendIl2CppStackTraceNameOfTypeSig(sb, szArraySig.Next); - sb.Append("[]"); - break; - } - default: - throw new NotSupportedException(typeSig.ToString()); - } - } - - public static TypeDef GetRootDeclaringType(TypeDef type) - { - TypeDef cur = type; - while (true) - { - TypeDef declaringType = cur.DeclaringType; - if (declaringType == null) - { - return cur; - } - cur = declaringType; - } - } - - public static string CreateMethodDefIl2CppStackTraceSignature(MethodDef method) - { - var result = new StringBuilder(); - TypeDef declaringType = method.DeclaringType; - - string namespaze = GetRootDeclaringType(declaringType).Namespace; - if (!string.IsNullOrEmpty(namespaze)) - { - result.Append(namespaze); - result.Append("."); - } - result.Append(declaringType.Name); - result.Append(":"); - result.Append(method.Name); - result.Append("("); - - int index = 0; - foreach (TypeSig p in method.GetParams()) - { - if (index > 0) - { - result.Append(", "); - } - AppendIl2CppStackTraceNameOfTypeSig(result, p); - ++index; - } - result.Append(")"); - return result.ToString(); - } - - public static bool HasObfuzIgnoreAttribute(IHasCustomAttribute obj) - { - return obj.CustomAttributes.Any(ca => ca.AttributeType.FullName == "Obfuz.ObfuzIgnoreAttribute"); - } - - public static bool HasCompilerGeneratedAttribute(IHasCustomAttribute obj) - { - return obj.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute"); - } - - public static bool HasEncryptFieldAttribute(IHasCustomAttribute obj) - { - return obj.CustomAttributes.Any(ca => ca.AttributeType.FullName == "Obfuz.EncryptFieldAttribute"); - } - - public static bool HasObfuzIgnoreAttributeInSelfOrParent(TypeDef typeDef) - { - while (true) - { - if (HasObfuzIgnoreAttribute(typeDef)) - { - return true; - } - typeDef = typeDef.DeclaringType; - if (typeDef == null) - { - return false; - } - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs.meta deleted file mode 100644 index 9ebbd42..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ded544371a7eb524caa1ccef3daebe55 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs deleted file mode 100644 index ea06a66..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Text.RegularExpressions; - -namespace Obfuz.Utils -{ - public class NameMatcher - { - private readonly string _str; - private readonly Regex _regex; - - public string NameOrPattern => _str; - - public NameMatcher(string nameOrPattern) - { - if (string.IsNullOrEmpty(nameOrPattern)) - { - nameOrPattern = "*"; - } - _str = nameOrPattern; - _regex = nameOrPattern.Contains("*") || nameOrPattern.Contains("?") ? new Regex(WildcardToRegex(nameOrPattern)) : null; - } - - public static string WildcardToRegex(string pattern) - { - return "^" + Regex.Escape(pattern). - Replace("\\*", ".*"). - Replace("\\?", ".") + "$"; - } - - public bool IsMatch(string name) - { - if (_regex != null) - { - return _regex.IsMatch(name); - } - else - { - return _str == name; - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs.meta deleted file mode 100644 index 6abe4e1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c3a646fe086ecbd4a8dbf36a395ada71 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs deleted file mode 100644 index 90d55e0..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Obfuz.Utils -{ - public class NumberRange where T : struct - { - public readonly T? min; - public readonly T? max; - - public NumberRange(T? min, T? max) - { - this.min = min; - this.max = max; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs.meta deleted file mode 100644 index f1b17e1..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4d147a6853ce57c4d88529fb73823435 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs deleted file mode 100644 index 11c0f47..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; - -namespace Obfuz.Utils -{ - public class PathAssemblyResolver : AssemblyResolverBase - { - private readonly string[] _searchPaths; - - public PathAssemblyResolver(params string[] searchPaths) - { - _searchPaths = searchPaths; - } - - public override string ResolveAssembly(string assemblyName) - { - foreach(var path in _searchPaths) - { - string assPath = Path.Combine(path, assemblyName + ".dll"); - if (File.Exists(assPath)) - { - //Debug.Log($"resolve {assemblyName} at {assPath}"); - return assPath; - } - } - return null; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs.meta deleted file mode 100644 index 1ae9c58..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5a7681737885f604e885ee39d0bedd74 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs deleted file mode 100644 index 3a38d23..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEditor; - -namespace Obfuz.Utils -{ - public static class PlatformUtil - { - public static bool IsMonoBackend() - { - return PlayerSettings.GetScriptingBackend(EditorUserBuildSettings.selectedBuildTargetGroup) - == ScriptingImplementation.Mono2x; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs.meta deleted file mode 100644 index ec195e6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PlatformUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 85d01014c084c56498d292d3b16351d2 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs deleted file mode 100644 index 27d1001..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Obfuz.Emit; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public class RandomWithKey : IRandom - { - private const long a = 1664525; - private const long c = 1013904223; - private const long m = 4294967296; // 2^32 - - private readonly int[] _key; - - private int _nextIndex; - - private int _seed; - - public RandomWithKey(int[] key, int seed) - { - _key = key; - _seed = seed; - } - - public int NextInt(int min, int max) - { - return min + NextInt(max - min); - } - - public int NextInt(int max) - { - return (int)((uint)NextInt() % (uint)max); - } - - private int GetNextSalt() - { - if (_nextIndex >= _key.Length) - { - _nextIndex = 0; - } - return _key[_nextIndex++]; - } - - public int NextInt() - { - _seed = (int)((a * _seed + c) % m); - return _seed ^ GetNextSalt(); - } - - public long NextLong() - { - return ((long)NextInt() << 32) | (uint)NextInt(); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs.meta deleted file mode 100644 index 41b7f75..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6e16d7eb75fe2354d96eca5bb01358a4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs deleted file mode 100644 index 3f008cc..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Obfuz.Utils -{ - public enum ThisArgType - { - None, - ValueType, - Class, - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs.meta deleted file mode 100644 index c73587a..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 5d5a6303cdb66374f95187ca31b5e82f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs deleted file mode 100644 index 11c722f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs +++ /dev/null @@ -1,198 +0,0 @@ -using dnlib.DotNet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz.Utils -{ - public static class TypeSigUtil - { - public static string ComputeTypeDefSignature(TypeDef type) - { - return type.FullName; - } - - public static string ComputeMethodDefSignature(MethodDef method) - { - var result = new StringBuilder(); - ComputeTypeSigName(method.MethodSig.RetType, result); - result.Append(" "); - result.Append(method.DeclaringType.FullName); - result.Append("::"); - result.Append(method.Name); - if (method.HasGenericParameters) - { - result.Append($"`{method.GenericParameters.Count}"); - } - result.Append("("); - for (int i = 0; i < method.Parameters.Count; i++) - { - if (i > 0) - { - result.Append(", "); - } - ComputeTypeSigName(method.Parameters[i].Type, result); - } - result.Append(")"); - return result.ToString(); - } - - public static string ComputeFieldDefSignature(FieldDef field) - { - var result = new StringBuilder(); - ComputeTypeSigName(field.FieldSig.Type, result); - result.Append(" "); - result.Append(field.Name); - return result.ToString(); - } - - public static string ComputePropertyDefSignature(PropertyDef property) - { - var result = new StringBuilder(); - ComputeTypeSigName(property.PropertySig.RetType, result); - result.Append(" "); - result.Append(property.Name); - return result.ToString(); - } - - public static string ComputeEventDefSignature(EventDef eventDef) - { - var result = new StringBuilder(); - ComputeTypeSigName(eventDef.EventType.ToTypeSig(), result); - result.Append(" "); - result.Append(eventDef.Name); - return result.ToString(); - } - - public static string ComputeMethodSpecSignature(TypeSig type) - { - var sb = new StringBuilder(); - ComputeTypeSigName(type, sb); - return sb.ToString(); - } - - public static void ComputeTypeSigName(TypeSig type, StringBuilder result) - { - type = type.RemovePinnedAndModifiers(); - switch (type.ElementType) - { - case ElementType.Void: result.Append("void"); break; - case ElementType.Boolean: result.Append("bool"); break; - case ElementType.Char: result.Append("char"); break; - case ElementType.I1: result.Append("sbyte"); break; - case ElementType.U1: result.Append("byte"); break; - case ElementType.I2: result.Append("short"); break; - case ElementType.U2: result.Append("ushort"); break; - case ElementType.I4: result.Append("int"); break; - case ElementType.U4: result.Append("uint"); break; - case ElementType.I8: result.Append("long"); break; - case ElementType.U8: result.Append("ulong"); break; - case ElementType.R4: result.Append("float"); break; - case ElementType.R8: result.Append("double"); break; - case ElementType.String: result.Append("string"); break; - case ElementType.Ptr: - ComputeTypeSigName(((PtrSig)type).Next, result); - result.Append("*"); - break; - case ElementType.ByRef: - ComputeTypeSigName(((ByRefSig)type).Next, result); - result.Append("&"); - break; - case ElementType.ValueType: - case ElementType.Class: - { - var valueOrClassType = type.ToClassOrValueTypeSig(); - var typeDef = valueOrClassType.ToTypeDefOrRef().ResolveTypeDefThrow(); - if (typeDef.Module.IsCoreLibraryModule != true) - { - result.Append($"[{typeDef.Module.Assembly.Name}]"); - } - result.Append(typeDef.FullName); - break; - } - case ElementType.GenericInst: - { - var genInst = (GenericInstSig)type; - ComputeTypeSigName(genInst.GenericType, result); - result.Append("<"); - for (int i = 0; i < genInst.GenericArguments.Count; i++) - { - if (i > 0) - { - result.Append(","); - } - ComputeTypeSigName(genInst.GenericArguments[i], result); - } - result.Append(">"); - break; - } - case ElementType.SZArray: - ComputeTypeSigName(((SZArraySig)type).Next, result); - result.Append("[]"); - break; - case ElementType.Array: - { - var arraySig = (ArraySig)type; - ComputeTypeSigName(arraySig.Next, result); - result.Append("["); - for (int i = 0; i < arraySig.Rank; i++) - { - if (i > 0) - { - result.Append(","); - } - //result.Append(arraySig.Sizes[i]); - } - result.Append("]"); - break; - } - case ElementType.FnPtr: - { - var fnPtr = (FnPtrSig)type; - result.Append("("); - MethodSig ms = fnPtr.MethodSig; - ComputeTypeSigName(ms.RetType, result); - result.Append("("); - for (int i = 0; i < ms.Params.Count; i++) - { - if (i > 0) - { - result.Append(","); - } - ComputeTypeSigName(ms.Params[i], result); - } - result.Append(")*"); - break; - } - case ElementType.TypedByRef: - result.Append("typedref"); - break; - case ElementType.I: - result.Append("nint"); - break; - case ElementType.U: - result.Append("nuint"); - break; - case ElementType.Object: - result.Append("object"); - break; - case ElementType.Var: - { - var var = (GenericVar)type; - result.Append($"!{var.Number}"); - break; - } - case ElementType.MVar: - { - var mvar = (GenericMVar)type; - result.Append($"!!{mvar.Number}"); - break; - } - default: throw new NotSupportedException($"[ComputeTypeSigName] not support :{type}"); - - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs.meta deleted file mode 100644 index fd92512..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 83e1214102577b449a933438c41c97bf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE b/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE deleted file mode 100644 index 093e599..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Code Philosophy(代码哲学) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE.meta b/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE.meta deleted file mode 100644 index 3bb31e6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4431597180c05fb46839ded925d40a19 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Plugins.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Plugins.meta deleted file mode 100644 index c04aee9..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Plugins.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f98a5dd310a82a64c9cc45cc139773dc -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll b/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll deleted file mode 100644 index ba1f36de278074a797876eae5deaed5ca7714856..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1175040 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

o(gBe*%CPwbI*X=Yy`R^;tu9d`B^j= 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%0AdyR-vmfN=Kg+or0dwOANA*7h?#`{k<}Sfa#MTyl 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

ImsUP$Xv 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∈e$weJ1aKKJ+5_wFC8gYJXYQTLD5FYd$EaraT{ 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

{$I|}n3l{o813ib68J6}94*Jy(DDAoE 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

e;$dDTQfSl%=A;Tc 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 M#sBd4|341=pM;M;RsaA1 diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll.meta deleted file mode 100644 index 5bde396..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: 355f9a0beb9535e4792b15e532d17460 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 1 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime.meta deleted file mode 100644 index a93405f..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: cd1451b864839ad41b5463274b1d171c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs deleted file mode 100644 index 467cc2b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using Unity.Collections.LowLevel.Unsafe; -using UnityEngine; -using UnityEngine.Assertions; - -namespace Obfuz -{ - public static class ConstUtility - { - public static int GetInt(byte[] data, int offset) - { - return BitConverter.ToInt32(data, offset); - } - - public static long GetLong(byte[] data, int offset) - { - return BitConverter.ToInt64(data, offset); - } - - public static float GetFloat(byte[] data, int offset) - { - return BitConverter.ToSingle(data, offset); - } - - public static double GetDouble(byte[] data, int offset) - { - return BitConverter.ToDouble(data, offset); - } - - public static string GetString(byte[] data, int offset, int length) - { - return Encoding.UTF8.GetString(data, offset, length); - } - - public static byte[] GetBytes(byte[] data, int offset, int length) - { - byte[] result = new byte[length]; - Array.Copy(data, offset, result, 0, length); - return result; - } - - public static int[] GetInts(byte[] data, int offset, int byteLength) - { - Assert.IsTrue(byteLength % 4 == 0); - int[] result = new int[byteLength >> 2]; - Buffer.BlockCopy(data, offset, result, 0, byteLength); - return result; - } - - public static void InitializeArray(Array array, byte[] data, int offset, int length) - { - Buffer.BlockCopy(data, offset, array, 0, length); - } - - public static unsafe int CastFloatAsInt(float value) - { - int* intValue = (int*)&value; - return *intValue; - } - - public static unsafe float CastIntAsFloat(int value) - { - float* floatValue = (float*)&value; - return *floatValue; - } - - public static unsafe long CastDoubleAsLong(double value) - { - long* longValue = (long*)&value; - return *longValue; - } - - public static unsafe double CastLongAsDouble(long value) - { - double* doubleValue = (double*)&value; - return *doubleValue; - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs.meta deleted file mode 100644 index f474205..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 48bd592d1a1339643be1fafe4b97c941 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs deleted file mode 100644 index cf8eecb..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] - public class EncryptFieldAttribute : Attribute - { - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs.meta deleted file mode 100644 index a76ea9d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptFieldAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 30f22110938816d4cb7e9cc9a176fd1e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs deleted file mode 100644 index fe215ef..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Obfuz -{ - public interface IEncryptionScope - { - - } - - public abstract class EncryptionScopeBase : IEncryptionScope - { - public void ForcePreserveAOT() - { - EncryptionService.Encrypt(0, 0, 0); - } - } - - public struct DefaultDynamicEncryptionScope : IEncryptionScope - { - public void ForcePreserveAOT() - { - EncryptionService.Encrypt(0, 0, 0); - } - } - - public struct DefaultStaticEncryptionScope: IEncryptionScope - { - public void ForcePreserveAOT() - { - EncryptionService.Encrypt(0, 0, 0); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs.meta deleted file mode 100644 index 064f875..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1d729fe7cb7d0bc43a69f1ba09f99061 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs deleted file mode 100644 index ccd0cea..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - - public static class EncryptionService where T : IEncryptionScope - { - // for compatibility with Mono because Mono will raise FieldAccessException when try access private field - public static IEncryptor _encryptor; - - public static IEncryptor Encryptor - { - get => _encryptor; - set { _encryptor = value; } - } - - public static void EncryptBlock(byte[] data, int ops, int salt) - { - _encryptor.EncryptBlock(data, ops, salt); - } - - public static void DecryptBlock(byte[] data, int ops, int salt) - { - _encryptor.DecryptBlock(data, ops, salt); - } - - public static int Encrypt(int value, int opts, int salt) - { - return _encryptor.Encrypt(value, opts, salt); - } - - public static int Decrypt(int value, int opts, int salt) - { - return _encryptor.Decrypt(value, opts, salt); - } - - public static long Encrypt(long value, int opts, int salt) - { - return _encryptor.Encrypt(value, opts, salt); - } - - public static long Decrypt(long value, int opts, int salt) - { - return _encryptor.Decrypt(value, opts, salt); - } - - public static float Encrypt(float value, int opts, int salt) - { - return _encryptor.Encrypt(value, opts, salt); - } - - public static float Decrypt(float value, int opts, int salt) - { - return _encryptor.Decrypt(value, opts, salt); - } - - public static double Encrypt(double value, int opts, int salt) - { - return _encryptor.Encrypt(value, opts, salt); - } - - public static double Decrypt(double value, int opts, int salt) - { - return _encryptor.Decrypt(value, opts, salt); - } - - public static byte[] Encrypt(byte[] value, int offset, int length, int opts, int salt) - { - return _encryptor.Encrypt(value, offset, length, opts, salt); - } - - public static byte[] Decrypt(byte[] value, int offset, int byteLength, int ops, int salt) - { - return _encryptor.Decrypt(value, offset, byteLength, ops, salt); - } - - public static byte[] Encrypt(string value, int ops, int salt) - { - return _encryptor.Encrypt(value, ops, salt); - } - - public static string DecryptString(byte[] value, int offset, int stringBytesLength, int ops, int salt) - { - return _encryptor.DecryptString(value, offset, stringBytesLength, ops, salt); - } - - - public static int DecryptFromRvaInt(byte[] data, int offset, int ops, int salt) - { - int encryptedValue = ConstUtility.GetInt(data, offset); - return Decrypt(encryptedValue, ops, salt); - } - - public static long DecryptFromRvaLong(byte[] data, int offset, int ops, int salt) - { - long encryptedValue = ConstUtility.GetLong(data, offset); - return Decrypt(encryptedValue, ops, salt); - } - - public static float DecryptFromRvaFloat(byte[] data, int offset, int ops, int salt) - { - float encryptedValue = ConstUtility.GetFloat(data, offset); - return Decrypt(encryptedValue, ops, salt); - } - - public static double DecryptFromRvaDouble(byte[] data, int offset, int ops, int salt) - { - double encryptedValue = ConstUtility.GetDouble(data, offset); - return Decrypt(encryptedValue, ops, salt); - } - - public static string DecryptFromRvaString(byte[] data, int offset, int length, int ops, int salt) - { - return DecryptString(data, offset, length, ops, salt); - } - - public static byte[] DecryptFromRvaBytes(byte[] data, int offset, int bytesLength, int ops, int salt) - { - return Decrypt(data, offset, bytesLength, ops, salt); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs.meta deleted file mode 100644 index d7364ef..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: bbbeb7501a0d84542828cb1aa7103d1b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs deleted file mode 100644 index 007e4b9..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs +++ /dev/null @@ -1,258 +0,0 @@ -using JetBrains.Annotations; -using System; -using System.Text; -using Unity.Collections.LowLevel.Unsafe; -using UnityEngine.Assertions; - -namespace Obfuz -{ - public abstract class EncryptorBase : IEncryptor - { - public abstract int OpCodeCount { get; } - - public static int[] ConvertToIntKey(byte[] key) - { - Assert.AreEqual(0, key.Length % 4); - int align4Length = key.Length / 4; - int[] intKey = new int[align4Length]; - Buffer.BlockCopy(key, 0, intKey, 0, key.Length); - return intKey; - } - - public abstract int Encrypt(int value, int opts, int salt); - public abstract int Decrypt(int value, int opts, int salt); - - public virtual long Encrypt(long value, int opts, int salt) - { - int low = (int)value; - int high = (int)(value >> 32); - int encryptedLow = Encrypt(low, opts, salt); - int encryptedHigh = Encrypt(high, opts, salt); - return ((long)encryptedHigh << 32) | (uint)encryptedLow; - } - - public virtual long Decrypt(long value, int opts, int salt) - { - int low = (int)value; - int high = (int)(value >> 32); - int decryptedLow = Decrypt(low, opts, salt); - int decryptedHigh = Decrypt(high, opts, salt); - return ((long)decryptedHigh << 32) | (uint)decryptedLow; - } - - public virtual unsafe float Encrypt(float value, int opts, int salt) - { - if (float.IsNaN(value) || float.IsInfinity(value)) - { - return value; - } - ref int intValue = ref *(int*)&value; - int xorValue = ((1 << 23) - 1) & Decrypt(0xABCD, opts, salt); - intValue ^= xorValue; - return value; - } - - public virtual unsafe float Decrypt(float value, int opts, int salt) - { - if (float.IsNaN(value) || float.IsInfinity(value)) - { - return value; - } - ref int intValue = ref *(int*)&value; - int xorValue = ((1 << 23) - 1) & Decrypt(0xABCD, opts, salt); - intValue ^= xorValue; - return value; - } - - public virtual unsafe double Encrypt(double value, int opts, int salt) - { - if (double.IsNaN(value) || double.IsInfinity(value)) - { - return value; - } - ref long longValue = ref *(long*)&value; - long xorValue = ((1L << 52) - 1) & Decrypt(0xAABBCCDDL, opts, salt); - longValue ^= xorValue; - return value; - } - - public virtual unsafe double Decrypt(double value, int opts, int salt) - { - if (double.IsNaN(value) || double.IsInfinity(value)) - { - return value; - } - ref long longValue = ref *(long*)&value; - long xorValue = ((1L << 52) - 1) & Decrypt(0xAABBCCDDL, opts, salt); - longValue ^= xorValue; - return value; - } - - public virtual unsafe byte[] Encrypt(byte[] value, int offset, int length, int ops, int salt) - { - if (length == 0) - { - return Array.Empty(); - } - - var encryptedBytes = new byte[length]; - int intArrLength = length >> 2; - - // align to 4 - if ((offset & 0x3) != 0) - { - Buffer.BlockCopy(value, offset, encryptedBytes, 0, length); - - // encrypt int - - fixed (byte* dstBytePtr = &encryptedBytes[0]) - { - int* dstIntPtr = (int*)dstBytePtr; - int last = 0; - for (int i = 0; i < intArrLength; i++) - { - last ^= Encrypt(dstIntPtr[i], ops, salt); - dstIntPtr[i] = last; - } - } - for (int i = intArrLength * 4; i < length; i++) - { - encryptedBytes[i] = (byte)(encryptedBytes[i] ^ salt); - } - } - else - { - // encrypt int - fixed (byte* srcBytePtr = &value[offset]) - { - fixed (byte* dstBytePtr = &encryptedBytes[0]) - { - int* srcIntPtr = (int*)srcBytePtr; - int* dstIntPtr = (int*)dstBytePtr; - - int last = 0; - for (int i = 0; i < intArrLength; i++) - { - last ^= Encrypt(srcIntPtr[i], ops, salt); - dstIntPtr[i] = last; - } - } - } - for (int i = intArrLength * 4; i < length; i++) - { - encryptedBytes[i] = (byte)(value[offset + i] ^ salt); - } - } - return encryptedBytes; - } - - public unsafe virtual byte[] Decrypt(byte[] value, int offset, int length, int ops, int salt) - { - var decryptedBytes = new byte[length]; - int intArrLength = length >> 2; - - // align to 4 - if ((offset & 0x3) != 0) - { - Buffer.BlockCopy(value, offset, decryptedBytes, 0, length); - - // encrypt int - - fixed (byte* dstBytePtr = &decryptedBytes[0]) - { - int* dstIntPtr = (int*)dstBytePtr; - int last = 0; - for (int i = 0; i < intArrLength; i++) - { - int oldLast = last; - last = dstIntPtr[i]; - dstIntPtr[i] = Decrypt(last ^ oldLast, ops, salt); - } - } - for (int i = intArrLength * 4; i < length; i++) - { - decryptedBytes[i] = (byte)(decryptedBytes[i] ^ salt); - } - } - else - { - // encrypt int - fixed (byte* srcBytePtr = &value[offset]) - { - fixed (byte* dstBytePtr = &decryptedBytes[0]) - { - int* srcIntPtr = (int*)srcBytePtr; - int* dstIntPtr = (int*)dstBytePtr; - int last = 0; - for (int i = 0; i < intArrLength; i++) - { - int oldLast = last; - last = srcIntPtr[i]; - dstIntPtr[i] = Decrypt(last ^ oldLast, ops, salt); - } - } - } - for (int i = intArrLength * 4; i < length; i++) - { - decryptedBytes[i] = (byte)(value[offset + i] ^ salt); - } - } - return decryptedBytes; - } - - public virtual byte[] Encrypt(string value, int ops, int salt) - { - byte[] bytes = Encoding.UTF8.GetBytes(value); - return Encrypt(bytes, 0, bytes.Length, ops, salt); - } - - public virtual string DecryptString(byte[] value, int offset, int length, int ops, int salt) - { - byte[] bytes = Decrypt(value, offset, length, ops, salt); - return Encoding.UTF8.GetString(bytes); - } - - public virtual unsafe void EncryptBlock(byte[] data, int ops, int salt) - { - int length = data.Length; - int intArrLength = length >> 2; - - fixed (byte* dstBytePtr = &data[0]) - { - int* dstIntPtr = (int*)dstBytePtr; - int last = 0; - for (int i = 0; i < intArrLength; i++) - { - last ^= Encrypt(dstIntPtr[i], ops, salt); - dstIntPtr[i] = last; - } - } - for (int i = intArrLength * 4; i < length; i++) - { - data[i] = (byte)(data[i] ^ salt); - } - } - - public virtual unsafe void DecryptBlock(byte[] data, int ops, int salt) - { - int length = data.Length; - int intArrLength = length >> 2; - - fixed (byte* dstBytePtr = &data[0]) - { - int* dstIntPtr = (int*)dstBytePtr; - int last = 0; - for (int i = 0; i < intArrLength; i++) - { - int oldLast = last; - last = dstIntPtr[i]; - dstIntPtr[i] = Decrypt(oldLast ^ last, ops, salt); - } - } - for (int i = intArrLength * 4; i < length; i++) - { - data[i] = (byte)(data[i] ^ salt); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs.meta deleted file mode 100644 index e81d521..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d1d4c5725e7ad624ba8e55ecb63bb440 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs deleted file mode 100644 index 0d8fdaa..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Obfuz -{ - public interface IEncryptor - { - int OpCodeCount { get; } - - void EncryptBlock(byte[] data, int ops, int salt); - void DecryptBlock(byte[] data, int ops, int salt); - - int Encrypt(int value, int opts, int salt); - int Decrypt(int value, int opts, int salt); - - long Encrypt(long value, int opts, int salt); - long Decrypt(long value, int opts, int salt); - - float Encrypt(float value, int opts, int salt); - float Decrypt(float value, int opts, int salt); - - double Encrypt(double value, int opts, int salt); - double Decrypt(double value, int opts, int salt); - - byte[] Encrypt(byte[] value, int offset, int length, int opts, int salt); - byte[] Decrypt(byte[] value, int offset, int byteLength, int ops, int salt); - - byte[] Encrypt(string value, int ops, int salt); - string DecryptString(byte[] value, int offset, int stringBytesLength, int ops, int salt); - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs.meta deleted file mode 100644 index 4141821..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3078fa59ff0af6b4cbbee25e20bc41c1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs deleted file mode 100644 index ec28f36..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - public class NullEncryptor : EncryptorBase - { - private readonly byte[] _key; - - public override int OpCodeCount => 256; - - public NullEncryptor(byte[] key) - { - _key = key; - } - - public override int Encrypt(int value, int opts, int salt) - { - return value; - } - - public override int Decrypt(int value, int opts, int salt) - { - return value; - } - - public override long Encrypt(long value, int opts, int salt) - { - return value; - } - - public override long Decrypt(long value, int opts, int salt) - { - return value; - } - - public override float Encrypt(float value, int opts, int salt) - { - return value; - } - - public override float Decrypt(float value, int opts, int salt) - { - return value; - } - - public override double Encrypt(double value, int opts, int salt) - { - return value; - } - - public override double Decrypt(double value, int opts, int salt) - { - return value; - } - - public override byte[] Encrypt(byte[] value, int offset, int length, int opts, int salt) - { - if (length == 0) - { - return Array.Empty(); - } - var encryptedBytes = new byte[length]; - Buffer.BlockCopy(value, offset, encryptedBytes, 0, length); - return encryptedBytes; - } - - public override byte[] Decrypt(byte[] value, int offset, int length, int ops, int salt) - { - if (length == 0) - { - return Array.Empty(); - } - byte[] byteArr = new byte[length]; - Buffer.BlockCopy(value, 0, byteArr, 0, length); - return byteArr; - } - - public override byte[] Encrypt(string value, int ops, int salt) - { - return Encoding.UTF8.GetBytes(value); - } - - public override string DecryptString(byte[] value, int offset, int length, int ops, int salt) - { - return Encoding.UTF8.GetString(value, offset, length); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs.meta deleted file mode 100644 index b490d29..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c53481f2ec513be4783a5ae2f76dc6e7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef deleted file mode 100644 index 4ee1d16..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "Obfuz.Runtime", - "rootNamespace": "", - "references": [], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": true, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef.meta deleted file mode 100644 index 4868da2..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4140bd2e2764f1f47ab93125ecb61942 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs deleted file mode 100644 index 90d2b17..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Obfuz -{ - [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)] - public class ObfuzIgnoreAttribute : Attribute - { - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs.meta deleted file mode 100644 index bc8fb89..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c2b4cf04729157b4dab504167ab5f703 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/package.json b/Obfuz/Packages/com.code-philosophy.obfuz/package.json deleted file mode 100644 index 6af9393..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "com.code-philosophy.obfuz", - "version": "1.0.0-alpha", - "displayName": "Obfuz", - "description": "Obfuz is an open-source Unity code obfuscation tool designed to provide Unity developers with a powerful, secure, and user-friendly code protection solution.", - "category": "Editor", - "documentationUrl": "https://www.obfuz.com", - "changelogUrl": "https://github.com/focus-creative-games/obfuz/commits/main/", - "licensesUrl": "https://github.com/focus-creative-games/obfuz/blob/main/LICENSE", - "keywords": [ - "obfuscation", - "obfuscator", - "confuser", - "code-philosophy" - ], - "author": { - "name": "Code Philosophy", - "email": "obfuz@code-philosophy.com", - "url": "https://code-philosophy.com" - } -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/package.json.meta b/Obfuz/Packages/com.code-philosophy.obfuz/package.json.meta deleted file mode 100644 index 74168f7..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz/package.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 63433d029d2e08c46abd56175e308a15 -PackageManifestImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor.meta b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor.meta deleted file mode 100644 index ec94239..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 067341936b8cb2242be3bdc83f3ca3cd -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs deleted file mode 100644 index ea52e32..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs +++ /dev/null @@ -1,82 +0,0 @@ -using HybridCLR.Editor; -using Obfuz.Settings; -using Obfuz; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEditor; -using HybridCLR.Editor.Commands; -using HybridCLR.Editor.Installer; -using System.IO; -using HybridCLR.Editor.ABI; -using UnityEngine; - -namespace Obfuz4HybridCLR -{ - public static class ObfuscateUtil - { - public static bool AreSameDirectory(string path1, string path2) - { - try - { - var dir1 = new DirectoryInfo(path1); - var dir2 = new DirectoryInfo(path2); - - // 比较完整路径(考虑符号链接) - return dir1.FullName.TrimEnd('\\') == dir2.FullName.TrimEnd('\\'); - } - catch - { - return false; - } - } - - public static void CompileAndObfuscateHotUpdateAssemblies(BuildTarget target) - { - string hotUpdateDllPath = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target); - BashUtil.RemoveDir(hotUpdateDllPath); - CompileDllCommand.CompileDll(target); - var assemblySearchPaths = new List - { - SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), - }; - Obfuscate(target, assemblySearchPaths, hotUpdateDllPath); - } - - public static void Obfuscate(BuildTarget target, List assemblySearchPaths, string outputPath) - { - var obfuzSettings = ObfuzSettings.Instance; - - var assemblySearchDirs = assemblySearchPaths; - ObfuscatorBuilder builder = ObfuscatorBuilder.FromObfuzSettings(obfuzSettings, target, true); - builder.InsertTopPriorityAssemblySearchPaths(assemblySearchDirs); - - string obfuscatedAssemblyOutputPath = obfuzSettings.GetObfuscatedAssemblyOutputPath(target); - if (AreSameDirectory(outputPath, obfuscatedAssemblyOutputPath)) - { - throw new Exception($"outputPath:{outputPath} can't be same to ObfuscatedAssemblyOutputPath:{obfuscatedAssemblyOutputPath}"); - } - foreach (var assemblySearchDir in builder.AssemblySearchPaths) - { - if (AreSameDirectory(assemblySearchDir, obfuscatedAssemblyOutputPath)) - { - throw new Exception($"assemblySearchDir:{assemblySearchDir} can't be same to ObfuscatedAssemblyOutputPath:{obfuscatedAssemblyOutputPath}"); - } - } - - Obfuscator obfuz = builder.Build(); - obfuz.Run(); - - Directory.CreateDirectory(outputPath); - foreach (string srcFile in Directory.GetFiles(obfuscatedAssemblyOutputPath, "*.dll")) - { - string fileName = Path.GetFileName(srcFile); - string destFile = $"{outputPath}/{fileName}"; - File.Copy(srcFile, destFile, true); - Debug.Log($"Copy {srcFile} to {destFile}"); - } - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs.meta deleted file mode 100644 index 3702fdd..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/ObfuscateUtil.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b7f5fe18513bcdd4c8960d908e88402e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef deleted file mode 100644 index 2af5cd5..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "Obfuz4HybridCLR.Editor", - "rootNamespace": "", - "references": [ - "GUID:2373f786d14518f44b0f475db77ba4de", - "GUID:66e09fc524ec6594b8d6ca1d91aa1a41" - ], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef.meta b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef.meta deleted file mode 100644 index cc375a6..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/Obfuz4HybridCLR.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 3743e71edcd5bd8499007797ef02cbfb -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs deleted file mode 100644 index 95a115d..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs +++ /dev/null @@ -1,38 +0,0 @@ -using HybridCLR.Editor.Commands; -using HybridCLR.Editor; -using Obfuz.Settings; -using Obfuz; -using System.Collections; -using System.Collections.Generic; -using UnityEditor; -using UnityEngine; -using System.Reflection; -using System; -using System.IO; -using HybridCLR.Editor.Link; -using HybridCLR.Editor.Meta; -using UnityEditor.Build; -using HybridCLR.Editor.Installer; - -namespace Obfuz4HybridCLR -{ - public static class PrebuildCommandExt - { - [MenuItem("HybridCLR/ObfuzExtension/GenerateAll")] - public static void GenerateAll() - { - var installer = new InstallerController(); - if (!installer.HasInstalledHybridCLR()) - { - throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'"); - } - BuildTarget target = EditorUserBuildSettings.activeBuildTarget; - ObfuscateUtil.CompileAndObfuscateHotUpdateAssemblies(target); - Il2CppDefGeneratorCommand.GenerateIl2CppDef(); - LinkGeneratorCommand.GenerateLinkXml(target); - StripAOTDllCommand.GenerateStripedAOTDlls(target); - MethodBridgeGeneratorCommand.GenerateMethodBridgeAndReversePInvokeWrapper(target); - AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target); - } - } -} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs.meta b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs.meta deleted file mode 100644 index 2bcd1c7..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/Editor/PrebuildCommandExt.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: afc965e1afdfc8e47b8a70be7a93cf25 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE deleted file mode 100644 index 093e599..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 Code Philosophy(代码哲学) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE.meta b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE.meta deleted file mode 100644 index dd09461..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/LICENSE.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 3036602f815e31341b4445f0e331b58e -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json deleted file mode 100644 index 76fed77..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "com.code-philosophy.obfuz4hybridclr", - "version": "1.0.0-alpha", - "displayName": "Obfuz4HybridCLR", - "description": "Obfuz Extension for HybridCLR", - "category": "Editor", - "documentationUrl": "https://www.obfuz.com", - "changelogUrl": "https://github.com/focus-creative-games/obfuz/commits/main/", - "licensesUrl": "https://github.com/focus-creative-games/obfuz/blob/main/LICENSE", - "keywords": [ - "obfuscation", - "obfuscator", - "confuser", - "code-philosophy" - ], - "author": { - "name": "Code Philosophy", - "email": "obfuz@code-philosophy.com", - "url": "https://code-philosophy.com" - } -} \ No newline at end of file diff --git a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json.meta b/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json.meta deleted file mode 100644 index 5577b3b..0000000 --- a/Obfuz/Packages/com.code-philosophy.obfuz4hybridclr/package.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 9ac66e213a764b840b2533ee30123717 -PackageManifestImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Obfuz/Packages/manifest.json b/Obfuz/Packages/manifest.json deleted file mode 100644 index 3a34c71..0000000 --- a/Obfuz/Packages/manifest.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "dependencies": { - "com.code-philosophy.hybridclr": "https://github.com/focus-creative-games/hybridclr_unity.git", - "com.unity.ide.visualstudio": "2.0.23", - "com.unity.toolchain.win-x86_64-linux-x86_64": "2.0.10", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestwww": "1.0.0" - } -} diff --git a/Obfuz/Packages/packages-lock.json b/Obfuz/Packages/packages-lock.json deleted file mode 100644 index db27b13..0000000 --- a/Obfuz/Packages/packages-lock.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "dependencies": { - "com.code-philosophy.hybridclr": { - "version": "https://github.com/focus-creative-games/hybridclr_unity.git", - "depth": 0, - "source": "git", - "dependencies": {}, - "hash": "7a0032934b438ad20a4a691f8093ce1865824c42" - }, - "com.code-philosophy.obfuz": { - "version": "file:com.code-philosophy.obfuz", - "depth": 0, - "source": "embedded", - "dependencies": {} - }, - "com.code-philosophy.obfuz4hybridclr": { - "version": "file:com.code-philosophy.obfuz4hybridclr", - "depth": 0, - "source": "embedded", - "dependencies": {} - }, - "com.unity.ext.nunit": { - "version": "1.0.6", - "depth": 2, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.ide.visualstudio": { - "version": "2.0.23", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.test-framework": "1.1.9" - }, - "url": "https://packages.unity.com" - }, - "com.unity.sysroot": { - "version": "2.0.10", - "depth": 1, - "source": "registry", - "dependencies": {}, - "url": "https://packages.unity.com" - }, - "com.unity.sysroot.linux-x86_64": { - "version": "2.0.9", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.sysroot": "2.0.10" - }, - "url": "https://packages.unity.com" - }, - "com.unity.test-framework": { - "version": "1.1.33", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.ext.nunit": "1.0.6", - "com.unity.modules.imgui": "1.0.0", - "com.unity.modules.jsonserialize": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.toolchain.win-x86_64-linux-x86_64": { - "version": "2.0.10", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.sysroot": "2.0.10", - "com.unity.sysroot.linux-x86_64": "2.0.9" - }, - "url": "https://packages.unity.com" - }, - "com.unity.modules.assetbundle": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.audio": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.imageconversion": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.imgui": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.jsonserialize": { - "version": "1.0.0", - "depth": 2, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.unitywebrequest": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": {} - }, - "com.unity.modules.unitywebrequestassetbundle": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.unitywebrequest": "1.0.0" - } - }, - "com.unity.modules.unitywebrequestaudio": { - "version": "1.0.0", - "depth": 1, - "source": "builtin", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.audio": "1.0.0" - } - }, - "com.unity.modules.unitywebrequestwww": { - "version": "1.0.0", - "depth": 0, - "source": "builtin", - "dependencies": { - "com.unity.modules.unitywebrequest": "1.0.0", - "com.unity.modules.unitywebrequestassetbundle": "1.0.0", - "com.unity.modules.unitywebrequestaudio": "1.0.0", - "com.unity.modules.audio": "1.0.0", - "com.unity.modules.assetbundle": "1.0.0", - "com.unity.modules.imageconversion": "1.0.0" - } - } - } -} diff --git a/Obfuz/ProjectSettings/AudioManager.asset b/Obfuz/ProjectSettings/AudioManager.asset deleted file mode 100644 index 07ebfb0..0000000 --- a/Obfuz/ProjectSettings/AudioManager.asset +++ /dev/null @@ -1,19 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!11 &1 -AudioManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Volume: 1 - Rolloff Scale: 1 - Doppler Factor: 1 - Default Speaker Mode: 2 - m_SampleRate: 0 - m_DSPBufferSize: 1024 - m_VirtualVoiceCount: 512 - m_RealVoiceCount: 32 - m_SpatializerPlugin: - m_AmbisonicDecoderPlugin: - m_DisableAudio: 0 - m_VirtualizeEffects: 1 - m_RequestedDSPBufferSize: 1024 diff --git a/Obfuz/ProjectSettings/ClusterInputManager.asset b/Obfuz/ProjectSettings/ClusterInputManager.asset deleted file mode 100644 index e7886b2..0000000 --- a/Obfuz/ProjectSettings/ClusterInputManager.asset +++ /dev/null @@ -1,6 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!236 &1 -ClusterInputManager: - m_ObjectHideFlags: 0 - m_Inputs: [] diff --git a/Obfuz/ProjectSettings/DynamicsManager.asset b/Obfuz/ProjectSettings/DynamicsManager.asset deleted file mode 100644 index cdc1f3e..0000000 --- a/Obfuz/ProjectSettings/DynamicsManager.asset +++ /dev/null @@ -1,34 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!55 &1 -PhysicsManager: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_Gravity: {x: 0, y: -9.81, z: 0} - m_DefaultMaterial: {fileID: 0} - m_BounceThreshold: 2 - m_SleepThreshold: 0.005 - m_DefaultContactOffset: 0.01 - m_DefaultSolverIterations: 6 - m_DefaultSolverVelocityIterations: 1 - m_QueriesHitBackfaces: 0 - m_QueriesHitTriggers: 1 - m_EnableAdaptiveForce: 0 - m_ClothInterCollisionDistance: 0 - m_ClothInterCollisionStiffness: 0 - m_ContactsGeneration: 1 - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - m_AutoSimulation: 1 - m_AutoSyncTransforms: 0 - m_ReuseCollisionCallbacks: 1 - m_ClothInterCollisionSettingsToggle: 0 - m_ContactPairsMode: 0 - m_BroadphaseType: 0 - m_WorldBounds: - m_Center: {x: 0, y: 0, z: 0} - m_Extent: {x: 250, y: 250, z: 250} - m_WorldSubdivisions: 8 - m_FrictionType: 0 - m_EnableEnhancedDeterminism: 0 - m_EnableUnifiedHeightmaps: 1 - m_DefaultMaxAngluarSpeed: 7 diff --git a/Obfuz/ProjectSettings/EditorBuildSettings.asset b/Obfuz/ProjectSettings/EditorBuildSettings.asset deleted file mode 100644 index 2a164fd..0000000 --- a/Obfuz/ProjectSettings/EditorBuildSettings.asset +++ /dev/null @@ -1,11 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1045 &1 -EditorBuildSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Scenes: - - enabled: 1 - path: Assets/main.unity - guid: 528018d8add4a724bb1e36008449a904 - m_configObjects: {} diff --git a/Obfuz/ProjectSettings/EditorSettings.asset b/Obfuz/ProjectSettings/EditorSettings.asset deleted file mode 100644 index 1e44a0a..0000000 --- a/Obfuz/ProjectSettings/EditorSettings.asset +++ /dev/null @@ -1,30 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!159 &1 -EditorSettings: - m_ObjectHideFlags: 0 - serializedVersion: 11 - m_ExternalVersionControlSupport: Visible Meta Files - m_SerializationMode: 2 - m_LineEndingsForNewScripts: 0 - m_DefaultBehaviorMode: 0 - m_PrefabRegularEnvironment: {fileID: 0} - m_PrefabUIEnvironment: {fileID: 0} - m_SpritePackerMode: 0 - m_SpritePackerPaddingPower: 1 - m_EtcTextureCompressorBehavior: 1 - m_EtcTextureFastCompressor: 1 - m_EtcTextureNormalCompressor: 2 - m_EtcTextureBestCompressor: 4 - m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref - m_ProjectGenerationRootNamespace: - m_CollabEditorSettings: - inProgressEnabled: 1 - m_EnableTextureStreamingInEditMode: 1 - m_EnableTextureStreamingInPlayMode: 1 - m_AsyncShaderCompilation: 1 - m_EnterPlayModeOptionsEnabled: 0 - m_EnterPlayModeOptions: 3 - m_ShowLightmapResolutionOverlay: 1 - m_UseLegacyProbeSampleCount: 0 - m_SerializeInlineMappingsOnOneLine: 1 diff --git a/Obfuz/ProjectSettings/GraphicsSettings.asset b/Obfuz/ProjectSettings/GraphicsSettings.asset deleted file mode 100644 index 4706883..0000000 --- a/Obfuz/ProjectSettings/GraphicsSettings.asset +++ /dev/null @@ -1,66 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!30 &1 -GraphicsSettings: - m_ObjectHideFlags: 0 - serializedVersion: 13 - m_Deferred: - m_Mode: 1 - m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} - m_DeferredReflections: - m_Mode: 1 - m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} - m_ScreenSpaceShadows: - m_Mode: 1 - m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} - m_LegacyDeferred: - m_Mode: 1 - m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} - m_DepthNormals: - m_Mode: 1 - m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} - m_MotionVectors: - m_Mode: 1 - m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} - m_LightHalo: - m_Mode: 1 - m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} - m_LensFlare: - m_Mode: 1 - m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} - m_AlwaysIncludedShaders: - - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} - m_PreloadedShaders: [] - m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, - type: 0} - m_CustomRenderPipeline: {fileID: 0} - m_TransparencySortMode: 0 - m_TransparencySortAxis: {x: 0, y: 0, z: 1} - m_DefaultRenderingPath: 1 - m_DefaultMobileRenderingPath: 1 - m_TierSettings: [] - m_LightmapStripping: 0 - m_FogStripping: 0 - m_InstancingStripping: 0 - m_LightmapKeepPlain: 1 - m_LightmapKeepDirCombined: 1 - m_LightmapKeepDynamicPlain: 1 - m_LightmapKeepDynamicDirCombined: 1 - m_LightmapKeepShadowMask: 1 - m_LightmapKeepSubtractive: 1 - m_FogKeepLinear: 1 - m_FogKeepExp: 1 - m_FogKeepExp2: 1 - m_AlbedoSwatchInfos: [] - m_LightsUseLinearIntensity: 0 - m_LightsUseColorTemperature: 0 - m_LogWhenShaderIsCompiled: 0 - m_AllowEnlightenSupportForUpgradedProject: 0 diff --git a/Obfuz/ProjectSettings/HybridCLRSettings.asset b/Obfuz/ProjectSettings/HybridCLRSettings.asset deleted file mode 100644 index 8c743fe..0000000 --- a/Obfuz/ProjectSettings/HybridCLRSettings.asset +++ /dev/null @@ -1,32 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e189374413a3f00468e49d51d8b27a09, type: 3} - m_Name: - m_EditorClassIdentifier: - enable: 1 - useGlobalIl2cpp: 0 - hybridclrRepoURL: https://gitee.com/focus-creative-games/hybridclr - il2cppPlusRepoURL: https://gitee.com/focus-creative-games/il2cpp_plus - hotUpdateAssemblyDefinitions: - - {fileID: 5897886265953266890, guid: bb51ff56468259445b7d23b3d0e0f128, type: 3} - - {fileID: 5897886265953266890, guid: e486716a437ebda49bd80ffa906243cc, type: 3} - - {fileID: 5897886265953266890, guid: b34fdb1dadcceaf4893904ced3c8e655, type: 3} - hotUpdateAssemblies: [] - preserveHotUpdateAssemblies: [] - hotUpdateDllCompileOutputRootDir: HybridCLRData/HotUpdateDlls - externalHotUpdateAssembliyDirs: [] - strippedAOTDllOutputRootDir: HybridCLRData/AssembliesPostIl2CppStrip - patchAOTAssemblies: [] - outputLinkFile: HybridCLRGenerate/link.xml - outputAOTGenericReferenceFile: Main/AOTGenericReferences.cs - maxGenericReferenceIteration: 10 - maxMethodBridgeGenericIteration: 10 diff --git a/Obfuz/ProjectSettings/InputManager.asset b/Obfuz/ProjectSettings/InputManager.asset deleted file mode 100644 index 17c8f53..0000000 --- a/Obfuz/ProjectSettings/InputManager.asset +++ /dev/null @@ -1,295 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!13 &1 -InputManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_Axes: - - serializedVersion: 3 - m_Name: Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: left - positiveButton: right - altNegativeButton: a - altPositiveButton: d - gravity: 3 - dead: 0.001 - sensitivity: 3 - snap: 1 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: down - positiveButton: up - altNegativeButton: s - altPositiveButton: w - gravity: 3 - dead: 0.001 - sensitivity: 3 - snap: 1 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left ctrl - altNegativeButton: - altPositiveButton: mouse 0 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left alt - altNegativeButton: - altPositiveButton: mouse 1 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire3 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: left shift - altNegativeButton: - altPositiveButton: mouse 2 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Jump - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: space - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse X - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse Y - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 1 - joyNum: 0 - - serializedVersion: 3 - m_Name: Mouse ScrollWheel - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0 - sensitivity: 0.1 - snap: 0 - invert: 0 - type: 1 - axis: 2 - joyNum: 0 - - serializedVersion: 3 - m_Name: Horizontal - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0.19 - sensitivity: 1 - snap: 0 - invert: 0 - type: 2 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Vertical - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: - altNegativeButton: - altPositiveButton: - gravity: 0 - dead: 0.19 - sensitivity: 1 - snap: 0 - invert: 1 - type: 2 - axis: 1 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire1 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 0 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire2 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 1 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Fire3 - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 2 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Jump - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: joystick button 3 - altNegativeButton: - altPositiveButton: - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Submit - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: return - altNegativeButton: - altPositiveButton: joystick button 0 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Submit - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: enter - altNegativeButton: - altPositiveButton: space - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 - - serializedVersion: 3 - m_Name: Cancel - descriptiveName: - descriptiveNegativeName: - negativeButton: - positiveButton: escape - altNegativeButton: - altPositiveButton: joystick button 1 - gravity: 1000 - dead: 0.001 - sensitivity: 1000 - snap: 0 - invert: 0 - type: 0 - axis: 0 - joyNum: 0 diff --git a/Obfuz/ProjectSettings/MemorySettings.asset b/Obfuz/ProjectSettings/MemorySettings.asset deleted file mode 100644 index 5b5face..0000000 --- a/Obfuz/ProjectSettings/MemorySettings.asset +++ /dev/null @@ -1,35 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!387306366 &1 -MemorySettings: - m_ObjectHideFlags: 0 - m_EditorMemorySettings: - m_MainAllocatorBlockSize: -1 - m_ThreadAllocatorBlockSize: -1 - m_MainGfxBlockSize: -1 - m_ThreadGfxBlockSize: -1 - m_CacheBlockSize: -1 - m_TypetreeBlockSize: -1 - m_ProfilerBlockSize: -1 - m_ProfilerEditorBlockSize: -1 - m_BucketAllocatorGranularity: -1 - m_BucketAllocatorBucketsCount: -1 - m_BucketAllocatorBlockSize: -1 - m_BucketAllocatorBlockCount: -1 - m_ProfilerBucketAllocatorGranularity: -1 - m_ProfilerBucketAllocatorBucketsCount: -1 - m_ProfilerBucketAllocatorBlockSize: -1 - m_ProfilerBucketAllocatorBlockCount: -1 - m_TempAllocatorSizeMain: -1 - m_JobTempAllocatorBlockSize: -1 - m_BackgroundJobTempAllocatorBlockSize: -1 - m_JobTempAllocatorReducedBlockSize: -1 - m_TempAllocatorSizeGIBakingWorker: -1 - m_TempAllocatorSizeNavMeshWorker: -1 - m_TempAllocatorSizeAudioWorker: -1 - m_TempAllocatorSizeCloudWorker: -1 - m_TempAllocatorSizeGfx: -1 - m_TempAllocatorSizeJobWorker: -1 - m_TempAllocatorSizeBackgroundWorker: -1 - m_TempAllocatorSizePreloadManager: -1 - m_PlatformMemorySettings: {} diff --git a/Obfuz/ProjectSettings/MultiplayerManager.asset b/Obfuz/ProjectSettings/MultiplayerManager.asset deleted file mode 100644 index 2a93664..0000000 --- a/Obfuz/ProjectSettings/MultiplayerManager.asset +++ /dev/null @@ -1,7 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!655991488 &1 -MultiplayerManager: - m_ObjectHideFlags: 0 - m_EnableMultiplayerRoles: 0 - m_StrippingTypes: {} diff --git a/Obfuz/ProjectSettings/NavMeshAreas.asset b/Obfuz/ProjectSettings/NavMeshAreas.asset deleted file mode 100644 index 3b0b7c3..0000000 --- a/Obfuz/ProjectSettings/NavMeshAreas.asset +++ /dev/null @@ -1,91 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!126 &1 -NavMeshProjectSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - areas: - - name: Walkable - cost: 1 - - name: Not Walkable - cost: 1 - - name: Jump - cost: 2 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - - name: - cost: 1 - m_LastAgentTypeID: -887442657 - m_Settings: - - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.75 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - debug: - m_Flags: 0 - m_SettingNames: - - Humanoid diff --git a/Obfuz/ProjectSettings/Obfuz.asset b/Obfuz/ProjectSettings/Obfuz.asset deleted file mode 100644 index c4f658e..0000000 --- a/Obfuz/ProjectSettings/Obfuz.asset +++ /dev/null @@ -1,49 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: c414eef017e565c4db1442ec64ec52fe, type: 3} - m_Name: - m_EditorClassIdentifier: - enable: 1 - assemblySettings: - assembliesToObfuscate: - - Assembly-CSharp - - Obfuz.Runtime - nonObfuscatedButReferencingObfuscatedAssemblies: [] - additionalAssemblySearchPaths: [] - obfuscationPassSettings: - enabledPasses: -1 - ruleFiles: [] - secretSettings: - defaultStaticSecretKey: Code Philosophy-Static - defaultDynamicSecretKey: Code Philosophy-Dynamic - secretKeyOutputPath: Assets/Resources/Obfuz - randomSeed: 0 - assembliesUsingDynamicSecretKeys: [] - encryptionVMSettings: - codeGenerationSecretKey: Obfuz - encryptionOpCodeCount: 256 - codeOutputPath: Assets/Obfuz/GeneratedEncryptionVirtualMachine.cs - symbolObfusSettings: - debug: 0 - obfuscatedNamePrefix: $ - useConsistentNamespaceObfuscation: 1 - symbolMappingFile: Assets/Obfuz/SymbolObfus/symbol-mapping.xml - ruleFiles: [] - constEncryptSettings: - encryptionLevel: 1 - ruleFiles: [] - fieldEncryptSettings: - encryptionLevel: 1 - ruleFiles: [] - callObfusSettings: - obfuscationLevel: 1 - ruleFiles: [] diff --git a/Obfuz/ProjectSettings/PackageManagerSettings.asset b/Obfuz/ProjectSettings/PackageManagerSettings.asset deleted file mode 100644 index 112a053..0000000 --- a/Obfuz/ProjectSettings/PackageManagerSettings.asset +++ /dev/null @@ -1,35 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &1 -MonoBehaviour: - m_ObjectHideFlags: 61 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} - m_Name: - m_EditorClassIdentifier: - m_EnablePreReleasePackages: 0 - m_EnablePackageDependencies: 0 - m_AdvancedSettingsExpanded: 1 - m_ScopedRegistriesSettingsExpanded: 1 - m_SeeAllPackageVersions: 0 - oneTimeWarningShown: 0 - m_Registries: - - m_Id: main - m_Name: - m_Url: https://packages.unity.com - m_Scopes: [] - m_IsDefault: 1 - m_Capabilities: 7 - m_UserSelectedRegistryName: - m_UserAddingNewScopedRegistry: 0 - m_RegistryInfoDraft: - m_Modified: 0 - m_ErrorMessage: - m_UserModificationsInstanceId: -830 - m_OriginalInstanceId: -832 - m_LoadAssets: 0 diff --git a/Obfuz/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/Obfuz/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json deleted file mode 100644 index 3c7b4c1..0000000 --- a/Obfuz/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "m_Dictionary": { - "m_DictionaryValues": [] - } -} \ No newline at end of file diff --git a/Obfuz/ProjectSettings/Physics2DSettings.asset b/Obfuz/ProjectSettings/Physics2DSettings.asset deleted file mode 100644 index 47880b1..0000000 --- a/Obfuz/ProjectSettings/Physics2DSettings.asset +++ /dev/null @@ -1,56 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!19 &1 -Physics2DSettings: - m_ObjectHideFlags: 0 - serializedVersion: 4 - m_Gravity: {x: 0, y: -9.81} - m_DefaultMaterial: {fileID: 0} - m_VelocityIterations: 8 - m_PositionIterations: 3 - m_VelocityThreshold: 1 - m_MaxLinearCorrection: 0.2 - m_MaxAngularCorrection: 8 - m_MaxTranslationSpeed: 100 - m_MaxRotationSpeed: 360 - m_BaumgarteScale: 0.2 - m_BaumgarteTimeOfImpactScale: 0.75 - m_TimeToSleep: 0.5 - m_LinearSleepTolerance: 0.01 - m_AngularSleepTolerance: 2 - m_DefaultContactOffset: 0.01 - m_JobOptions: - serializedVersion: 2 - useMultithreading: 0 - useConsistencySorting: 0 - m_InterpolationPosesPerJob: 100 - m_NewContactsPerJob: 30 - m_CollideContactsPerJob: 100 - m_ClearFlagsPerJob: 200 - m_ClearBodyForcesPerJob: 200 - m_SyncDiscreteFixturesPerJob: 50 - m_SyncContinuousFixturesPerJob: 50 - m_FindNearestContactsPerJob: 100 - m_UpdateTriggerContactsPerJob: 100 - m_IslandSolverCostThreshold: 100 - m_IslandSolverBodyCostScale: 1 - m_IslandSolverContactCostScale: 10 - m_IslandSolverJointCostScale: 10 - m_IslandSolverBodiesPerJob: 50 - m_IslandSolverContactsPerJob: 50 - m_AutoSimulation: 1 - m_QueriesHitTriggers: 1 - m_QueriesStartInColliders: 1 - m_CallbacksOnDisable: 1 - m_ReuseCollisionCallbacks: 1 - m_AutoSyncTransforms: 0 - m_AlwaysShowColliders: 0 - m_ShowColliderSleep: 1 - m_ShowColliderContacts: 0 - m_ShowColliderAABB: 0 - m_ContactArrowScale: 0.2 - m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} - m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} - m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} - m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} - m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/Obfuz/ProjectSettings/PresetManager.asset b/Obfuz/ProjectSettings/PresetManager.asset deleted file mode 100644 index 67a94da..0000000 --- a/Obfuz/ProjectSettings/PresetManager.asset +++ /dev/null @@ -1,7 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!1386491679 &1 -PresetManager: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_DefaultPresets: {} diff --git a/Obfuz/ProjectSettings/ProjectSettings.asset b/Obfuz/ProjectSettings/ProjectSettings.asset deleted file mode 100644 index 9398732..0000000 --- a/Obfuz/ProjectSettings/ProjectSettings.asset +++ /dev/null @@ -1,994 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!129 &1 -PlayerSettings: - m_ObjectHideFlags: 0 - serializedVersion: 26 - productGUID: e7f1e2f620eaec64485a63083a6d4cd8 - AndroidProfiler: 0 - AndroidFilterTouchesWhenObscured: 0 - AndroidEnableSustainedPerformanceMode: 0 - defaultScreenOrientation: 4 - targetDevice: 2 - useOnDemandResources: 0 - accelerometerFrequency: 60 - companyName: DefaultCompany - productName: ObfuzDemo - defaultCursor: {fileID: 0} - cursorHotspot: {x: 0, y: 0} - m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} - m_ShowUnitySplashScreen: 1 - m_ShowUnitySplashLogo: 1 - m_SplashScreenOverlayOpacity: 1 - m_SplashScreenAnimation: 1 - m_SplashScreenLogoStyle: 1 - m_SplashScreenDrawMode: 0 - m_SplashScreenBackgroundAnimationZoom: 1 - m_SplashScreenLogoAnimationZoom: 1 - m_SplashScreenBackgroundLandscapeAspect: 1 - m_SplashScreenBackgroundPortraitAspect: 1 - m_SplashScreenBackgroundLandscapeUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenBackgroundPortraitUvs: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - m_SplashScreenLogos: [] - m_VirtualRealitySplashScreen: {fileID: 0} - m_HolographicTrackingLossScreen: {fileID: 0} - defaultScreenWidth: 800 - defaultScreenHeight: 600 - defaultScreenWidthWeb: 960 - defaultScreenHeightWeb: 600 - m_StereoRenderingPath: 0 - m_ActiveColorSpace: 1 - m_SpriteBatchVertexThreshold: 300 - m_MTRendering: 1 - mipStripping: 0 - numberOfMipsStripped: 0 - numberOfMipsStrippedPerMipmapLimitGroup: {} - m_StackTraceTypes: 010000000100000001000000010000000100000001000000 - iosShowActivityIndicatorOnLoading: -1 - androidShowActivityIndicatorOnLoading: -1 - iosUseCustomAppBackgroundBehavior: 0 - allowedAutorotateToPortrait: 1 - allowedAutorotateToPortraitUpsideDown: 1 - allowedAutorotateToLandscapeRight: 1 - allowedAutorotateToLandscapeLeft: 1 - useOSAutorotation: 1 - use32BitDisplayBuffer: 1 - preserveFramebufferAlpha: 0 - disableDepthAndStencilBuffers: 0 - androidStartInFullscreen: 1 - androidRenderOutsideSafeArea: 1 - androidUseSwappy: 1 - androidBlitType: 0 - androidResizableWindow: 0 - androidDefaultWindowWidth: 1920 - androidDefaultWindowHeight: 1080 - androidMinimumWindowWidth: 400 - androidMinimumWindowHeight: 300 - androidFullscreenMode: 1 - defaultIsNativeResolution: 1 - macRetinaSupport: 1 - runInBackground: 1 - captureSingleScreen: 0 - muteOtherAudioSources: 0 - Prepare IOS For Recording: 0 - Force IOS Speakers When Recording: 0 - deferSystemGesturesMode: 0 - hideHomeButton: 0 - submitAnalytics: 1 - usePlayerLog: 1 - dedicatedServerOptimizations: 0 - bakeCollisionMeshes: 0 - forceSingleInstance: 0 - useFlipModelSwapchain: 1 - resizableWindow: 0 - useMacAppStoreValidation: 0 - macAppStoreCategory: public.app-category.games - gpuSkinning: 1 - xboxPIXTextureCapture: 0 - xboxEnableAvatar: 0 - xboxEnableKinect: 0 - xboxEnableKinectAutoTracking: 0 - xboxEnableFitness: 0 - visibleInBackground: 1 - allowFullscreenSwitch: 1 - fullscreenMode: 3 - xboxSpeechDB: 0 - xboxEnableHeadOrientation: 0 - xboxEnableGuest: 0 - xboxEnablePIXSampling: 0 - metalFramebufferOnly: 0 - xboxOneResolution: 0 - xboxOneSResolution: 0 - xboxOneXResolution: 3 - xboxOneMonoLoggingLevel: 0 - xboxOneLoggingLevel: 1 - xboxOneDisableEsram: 0 - xboxOneEnableTypeOptimization: 0 - xboxOnePresentImmediateThreshold: 0 - switchQueueCommandMemory: 0 - switchQueueControlMemory: 16384 - switchQueueComputeMemory: 262144 - switchNVNShaderPoolsGranularity: 33554432 - switchNVNDefaultPoolsGranularity: 16777216 - switchNVNOtherPoolsGranularity: 16777216 - switchGpuScratchPoolGranularity: 2097152 - switchAllowGpuScratchShrinking: 0 - switchNVNMaxPublicTextureIDCount: 0 - switchNVNMaxPublicSamplerIDCount: 0 - switchNVNGraphicsFirmwareMemory: 32 - switchMaxWorkerMultiple: 8 - stadiaPresentMode: 0 - stadiaTargetFramerate: 0 - vulkanNumSwapchainBuffers: 3 - vulkanEnableSetSRGBWrite: 0 - vulkanEnablePreTransform: 1 - vulkanEnableLateAcquireNextImage: 0 - vulkanEnableCommandBufferRecycling: 1 - loadStoreDebugModeEnabled: 0 - bundleVersion: 0.1 - preloadedAssets: [] - metroInputSource: 0 - wsaTransparentSwapchain: 0 - m_HolographicPauseOnTrackingLoss: 1 - xboxOneDisableKinectGpuReservation: 1 - xboxOneEnable7thCore: 1 - vrSettings: - enable360StereoCapture: 0 - isWsaHolographicRemotingEnabled: 0 - enableFrameTimingStats: 0 - enableOpenGLProfilerGPURecorders: 1 - allowHDRDisplaySupport: 0 - useHDRDisplay: 0 - hdrBitDepth: 0 - m_ColorGamuts: 00000000 - targetPixelDensity: 30 - resolutionScalingMode: 0 - resetResolutionOnWindowResize: 0 - androidSupportedAspectRatio: 1 - androidMaxAspectRatio: 2.1 - applicationIdentifier: - Android: com.DefaultCompany.ObfuzDemo - Standalone: com.DefaultCompany.ObfuzDemo - buildNumber: - Standalone: 0 - VisionOS: 0 - iPhone: 0 - tvOS: 0 - overrideDefaultApplicationIdentifier: 0 - AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 22 - AndroidTargetSdkVersion: 0 - AndroidPreferredInstallLocation: 1 - aotOptions: - stripEngineCode: 1 - iPhoneStrippingLevel: 0 - iPhoneScriptCallOptimization: 0 - ForceInternetPermission: 0 - ForceSDCardPermission: 0 - CreateWallpaper: 0 - APKExpansionFiles: 0 - keepLoadedShadersAlive: 0 - StripUnusedMeshComponents: 1 - strictShaderVariantMatching: 0 - VertexChannelCompressionMask: 4054 - iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 12.0 - tvOSSdkVersion: 0 - tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 12.0 - VisionOSSdkVersion: 0 - VisionOSTargetOSVersionString: 1.0 - uIPrerenderedIcon: 0 - uIRequiresPersistentWiFi: 0 - uIRequiresFullScreen: 1 - uIStatusBarHidden: 1 - uIExitOnSuspend: 0 - uIStatusBarStyle: 0 - appleTVSplashScreen: {fileID: 0} - appleTVSplashScreen2x: {fileID: 0} - tvOSSmallIconLayers: [] - tvOSSmallIconLayers2x: [] - tvOSLargeIconLayers: [] - tvOSLargeIconLayers2x: [] - tvOSTopShelfImageLayers: [] - tvOSTopShelfImageLayers2x: [] - tvOSTopShelfImageWideLayers: [] - tvOSTopShelfImageWideLayers2x: [] - iOSLaunchScreenType: 0 - iOSLaunchScreenPortrait: {fileID: 0} - iOSLaunchScreenLandscape: {fileID: 0} - iOSLaunchScreenBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreenFillPct: 100 - iOSLaunchScreenSize: 100 - iOSLaunchScreenCustomXibPath: - iOSLaunchScreeniPadType: 0 - iOSLaunchScreeniPadImage: {fileID: 0} - iOSLaunchScreeniPadBackgroundColor: - serializedVersion: 2 - rgba: 0 - iOSLaunchScreeniPadFillPct: 100 - iOSLaunchScreeniPadSize: 100 - iOSLaunchScreeniPadCustomXibPath: - iOSLaunchScreenCustomStoryboardPath: - iOSLaunchScreeniPadCustomStoryboardPath: - iOSDeviceRequirements: [] - iOSURLSchemes: [] - macOSURLSchemes: [] - iOSBackgroundModes: 0 - iOSMetalForceHardShadows: 0 - metalEditorSupport: 1 - metalAPIValidation: 1 - iOSRenderExtraFrameOnPause: 0 - iosCopyPluginsCodeInsteadOfSymlink: 0 - appleDeveloperTeamID: - iOSManualSigningProvisioningProfileID: - tvOSManualSigningProvisioningProfileID: - VisionOSManualSigningProvisioningProfileID: - iOSManualSigningProvisioningProfileType: 0 - tvOSManualSigningProvisioningProfileType: 0 - VisionOSManualSigningProvisioningProfileType: 0 - appleEnableAutomaticSigning: 0 - iOSRequireARKit: 0 - iOSAutomaticallyDetectAndAddCapabilities: 1 - appleEnableProMotion: 0 - shaderPrecisionModel: 0 - clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea - templatePackageId: com.unity.template.3d@8.1.3 - templateDefaultScene: Assets/Scenes/SampleScene.unity - useCustomMainManifest: 0 - useCustomLauncherManifest: 0 - useCustomMainGradleTemplate: 0 - useCustomLauncherGradleManifest: 0 - useCustomBaseGradleTemplate: 0 - useCustomGradlePropertiesTemplate: 0 - useCustomGradleSettingsTemplate: 0 - useCustomProguardFile: 0 - AndroidTargetArchitectures: 1 - AndroidTargetDevices: 0 - AndroidSplashScreenScale: 0 - androidSplashScreen: {fileID: 0} - AndroidKeystoreName: - AndroidKeyaliasName: - AndroidEnableArmv9SecurityFeatures: 0 - AndroidBuildApkPerCpuArchitecture: 0 - AndroidTVCompatibility: 0 - AndroidIsGame: 1 - AndroidEnableTango: 0 - androidEnableBanner: 1 - androidUseLowAccuracyLocation: 0 - androidUseCustomKeystore: 0 - m_AndroidBanners: - - width: 320 - height: 180 - banner: {fileID: 0} - androidGamepadSupportLevel: 0 - chromeosInputEmulation: 1 - AndroidMinifyRelease: 0 - AndroidMinifyDebug: 0 - AndroidValidateAppBundleSize: 1 - AndroidAppBundleSizeToValidate: 150 - m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: - - m_BuildTarget: tvOS - m_Icons: - - m_Textures: [] - m_Width: 1280 - m_Height: 768 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 800 - m_Height: 480 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 400 - m_Height: 240 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 4640 - m_Height: 1440 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 2320 - m_Height: 720 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 3840 - m_Height: 1440 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 1920 - m_Height: 720 - m_Kind: 1 - m_SubKind: - - m_BuildTarget: iPhone - m_Icons: - - m_Textures: [] - m_Width: 180 - m_Height: 180 - m_Kind: 0 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 120 - m_Height: 120 - m_Kind: 0 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 167 - m_Height: 167 - m_Kind: 0 - m_SubKind: iPad - - m_Textures: [] - m_Width: 152 - m_Height: 152 - m_Kind: 0 - m_SubKind: iPad - - m_Textures: [] - m_Width: 76 - m_Height: 76 - m_Kind: 0 - m_SubKind: iPad - - m_Textures: [] - m_Width: 120 - m_Height: 120 - m_Kind: 3 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 80 - m_Height: 80 - m_Kind: 3 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 80 - m_Height: 80 - m_Kind: 3 - m_SubKind: iPad - - m_Textures: [] - m_Width: 40 - m_Height: 40 - m_Kind: 3 - m_SubKind: iPad - - m_Textures: [] - m_Width: 87 - m_Height: 87 - m_Kind: 1 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 58 - m_Height: 58 - m_Kind: 1 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 29 - m_Height: 29 - m_Kind: 1 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 58 - m_Height: 58 - m_Kind: 1 - m_SubKind: iPad - - m_Textures: [] - m_Width: 29 - m_Height: 29 - m_Kind: 1 - m_SubKind: iPad - - m_Textures: [] - m_Width: 60 - m_Height: 60 - m_Kind: 2 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 40 - m_Height: 40 - m_Kind: 2 - m_SubKind: iPhone - - m_Textures: [] - m_Width: 40 - m_Height: 40 - m_Kind: 2 - m_SubKind: iPad - - m_Textures: [] - m_Width: 20 - m_Height: 20 - m_Kind: 2 - m_SubKind: iPad - - m_Textures: [] - m_Width: 1024 - m_Height: 1024 - m_Kind: 4 - m_SubKind: App Store - - m_BuildTarget: Android - m_Icons: - - m_Textures: [] - m_Width: 432 - m_Height: 432 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 324 - m_Height: 324 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 216 - m_Height: 216 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 162 - m_Height: 162 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 108 - m_Height: 108 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 81 - m_Height: 81 - m_Kind: 2 - m_SubKind: - - m_Textures: [] - m_Width: 192 - m_Height: 192 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 144 - m_Height: 144 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 96 - m_Height: 96 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 72 - m_Height: 72 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 48 - m_Height: 48 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 36 - m_Height: 36 - m_Kind: 1 - m_SubKind: - - m_Textures: [] - m_Width: 192 - m_Height: 192 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 144 - m_Height: 144 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 96 - m_Height: 96 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 72 - m_Height: 72 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 48 - m_Height: 48 - m_Kind: 0 - m_SubKind: - - m_Textures: [] - m_Width: 36 - m_Height: 36 - m_Kind: 0 - m_SubKind: - m_BuildTargetBatching: - - m_BuildTarget: Standalone - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: tvOS - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: Android - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: iPhone - m_StaticBatching: 1 - m_DynamicBatching: 0 - - m_BuildTarget: WebGL - m_StaticBatching: 0 - m_DynamicBatching: 0 - m_BuildTargetShaderSettings: [] - m_BuildTargetGraphicsJobs: - - m_BuildTarget: MacStandaloneSupport - m_GraphicsJobs: 0 - - m_BuildTarget: Switch - m_GraphicsJobs: 1 - - m_BuildTarget: MetroSupport - m_GraphicsJobs: 1 - - m_BuildTarget: AppleTVSupport - m_GraphicsJobs: 0 - - m_BuildTarget: BJMSupport - m_GraphicsJobs: 1 - - m_BuildTarget: LinuxStandaloneSupport - m_GraphicsJobs: 1 - - m_BuildTarget: PS4Player - m_GraphicsJobs: 1 - - m_BuildTarget: iOSSupport - m_GraphicsJobs: 0 - - m_BuildTarget: WindowsStandaloneSupport - m_GraphicsJobs: 1 - - m_BuildTarget: XboxOnePlayer - m_GraphicsJobs: 1 - - m_BuildTarget: LuminSupport - m_GraphicsJobs: 0 - - m_BuildTarget: AndroidPlayer - m_GraphicsJobs: 0 - - m_BuildTarget: WebGLSupport - m_GraphicsJobs: 0 - m_BuildTargetGraphicsJobMode: - - m_BuildTarget: PS4Player - m_GraphicsJobMode: 0 - - m_BuildTarget: XboxOnePlayer - m_GraphicsJobMode: 0 - m_BuildTargetGraphicsAPIs: - - m_BuildTarget: AndroidPlayer - m_APIs: 150000000b000000 - m_Automatic: 1 - - m_BuildTarget: iOSSupport - m_APIs: 10000000 - m_Automatic: 1 - - m_BuildTarget: AppleTVSupport - m_APIs: 10000000 - m_Automatic: 1 - - m_BuildTarget: WebGLSupport - m_APIs: 0b000000 - m_Automatic: 1 - m_BuildTargetVRSettings: - - m_BuildTarget: Standalone - m_Enabled: 0 - m_Devices: - - Oculus - - OpenVR - m_DefaultShaderChunkSizeInMB: 16 - m_DefaultShaderChunkCount: 0 - openGLRequireES31: 0 - openGLRequireES31AEP: 0 - openGLRequireES32: 0 - m_TemplateCustomTags: {} - mobileMTRendering: - Android: 1 - iPhone: 1 - tvOS: 1 - m_BuildTargetGroupLightmapEncodingQuality: - - m_BuildTarget: Android - m_EncodingQuality: 1 - - m_BuildTarget: iPhone - m_EncodingQuality: 1 - - m_BuildTarget: tvOS - m_EncodingQuality: 1 - m_BuildTargetGroupHDRCubemapEncodingQuality: - - m_BuildTarget: Android - m_EncodingQuality: 1 - - m_BuildTarget: iPhone - m_EncodingQuality: 1 - - m_BuildTarget: tvOS - m_EncodingQuality: 1 - m_BuildTargetGroupLightmapSettings: [] - m_BuildTargetGroupLoadStoreDebugModeSettings: [] - m_BuildTargetNormalMapEncoding: - - m_BuildTarget: Android - m_Encoding: 1 - - m_BuildTarget: iPhone - m_Encoding: 1 - - m_BuildTarget: tvOS - m_Encoding: 1 - m_BuildTargetDefaultTextureCompressionFormat: - - m_BuildTarget: Android - m_Format: 3 - playModeTestRunnerEnabled: 0 - runPlayModeTestAsEditModeTest: 0 - actionOnDotNetUnhandledException: 1 - enableInternalProfiler: 0 - logObjCUncaughtExceptions: 1 - enableCrashReportAPI: 0 - cameraUsageDescription: - locationUsageDescription: - microphoneUsageDescription: - bluetoothUsageDescription: - macOSTargetOSVersion: 10.13.0 - switchNMETAOverride: - switchNetLibKey: - switchSocketMemoryPoolSize: 6144 - switchSocketAllocatorPoolSize: 128 - switchSocketConcurrencyLimit: 14 - switchScreenResolutionBehavior: 2 - switchUseCPUProfiler: 0 - switchEnableFileSystemTrace: 0 - switchUseGOLDLinker: 0 - switchLTOSetting: 0 - switchApplicationID: 0x01004b9000490000 - switchNSODependencies: - switchCompilerFlags: - switchTitleNames_0: - switchTitleNames_1: - switchTitleNames_2: - switchTitleNames_3: - switchTitleNames_4: - switchTitleNames_5: - switchTitleNames_6: - switchTitleNames_7: - switchTitleNames_8: - switchTitleNames_9: - switchTitleNames_10: - switchTitleNames_11: - switchTitleNames_12: - switchTitleNames_13: - switchTitleNames_14: - switchTitleNames_15: - switchPublisherNames_0: - switchPublisherNames_1: - switchPublisherNames_2: - switchPublisherNames_3: - switchPublisherNames_4: - switchPublisherNames_5: - switchPublisherNames_6: - switchPublisherNames_7: - switchPublisherNames_8: - switchPublisherNames_9: - switchPublisherNames_10: - switchPublisherNames_11: - switchPublisherNames_12: - switchPublisherNames_13: - switchPublisherNames_14: - switchPublisherNames_15: - switchIcons_0: {fileID: 0} - switchIcons_1: {fileID: 0} - switchIcons_2: {fileID: 0} - switchIcons_3: {fileID: 0} - switchIcons_4: {fileID: 0} - switchIcons_5: {fileID: 0} - switchIcons_6: {fileID: 0} - switchIcons_7: {fileID: 0} - switchIcons_8: {fileID: 0} - switchIcons_9: {fileID: 0} - switchIcons_10: {fileID: 0} - switchIcons_11: {fileID: 0} - switchIcons_12: {fileID: 0} - switchIcons_13: {fileID: 0} - switchIcons_14: {fileID: 0} - switchIcons_15: {fileID: 0} - switchSmallIcons_0: {fileID: 0} - switchSmallIcons_1: {fileID: 0} - switchSmallIcons_2: {fileID: 0} - switchSmallIcons_3: {fileID: 0} - switchSmallIcons_4: {fileID: 0} - switchSmallIcons_5: {fileID: 0} - switchSmallIcons_6: {fileID: 0} - switchSmallIcons_7: {fileID: 0} - switchSmallIcons_8: {fileID: 0} - switchSmallIcons_9: {fileID: 0} - switchSmallIcons_10: {fileID: 0} - switchSmallIcons_11: {fileID: 0} - switchSmallIcons_12: {fileID: 0} - switchSmallIcons_13: {fileID: 0} - switchSmallIcons_14: {fileID: 0} - switchSmallIcons_15: {fileID: 0} - switchManualHTML: - switchAccessibleURLs: - switchLegalInformation: - switchMainThreadStackSize: 1048576 - switchPresenceGroupId: - switchLogoHandling: 0 - switchReleaseVersion: 0 - switchDisplayVersion: 1.0.0 - switchStartupUserAccount: 0 - switchSupportedLanguagesMask: 0 - switchLogoType: 0 - switchApplicationErrorCodeCategory: - switchUserAccountSaveDataSize: 0 - switchUserAccountSaveDataJournalSize: 0 - switchApplicationAttribute: 0 - switchCardSpecSize: -1 - switchCardSpecClock: -1 - switchRatingsMask: 0 - switchRatingsInt_0: 0 - switchRatingsInt_1: 0 - switchRatingsInt_2: 0 - switchRatingsInt_3: 0 - switchRatingsInt_4: 0 - switchRatingsInt_5: 0 - switchRatingsInt_6: 0 - switchRatingsInt_7: 0 - switchRatingsInt_8: 0 - switchRatingsInt_9: 0 - switchRatingsInt_10: 0 - switchRatingsInt_11: 0 - switchRatingsInt_12: 0 - switchLocalCommunicationIds_0: - switchLocalCommunicationIds_1: - switchLocalCommunicationIds_2: - switchLocalCommunicationIds_3: - switchLocalCommunicationIds_4: - switchLocalCommunicationIds_5: - switchLocalCommunicationIds_6: - switchLocalCommunicationIds_7: - switchParentalControl: 0 - switchAllowsScreenshot: 1 - switchAllowsVideoCapturing: 1 - switchAllowsRuntimeAddOnContentInstall: 0 - switchDataLossConfirmation: 0 - switchUserAccountLockEnabled: 0 - switchSystemResourceMemory: 16777216 - switchSupportedNpadStyles: 22 - switchNativeFsCacheSize: 32 - switchIsHoldTypeHorizontal: 0 - switchSupportedNpadCount: 8 - switchEnableTouchScreen: 1 - switchSocketConfigEnabled: 0 - switchTcpInitialSendBufferSize: 32 - switchTcpInitialReceiveBufferSize: 64 - switchTcpAutoSendBufferSizeMax: 256 - switchTcpAutoReceiveBufferSizeMax: 256 - switchUdpSendBufferSize: 9 - switchUdpReceiveBufferSize: 42 - switchSocketBufferEfficiency: 4 - switchSocketInitializeEnabled: 1 - switchNetworkInterfaceManagerInitializeEnabled: 1 - switchUseNewStyleFilepaths: 1 - switchUseLegacyFmodPriorities: 0 - switchUseMicroSleepForYield: 1 - switchEnableRamDiskSupport: 0 - switchMicroSleepForYieldTime: 25 - switchRamDiskSpaceSize: 12 - ps4NPAgeRating: 12 - ps4NPTitleSecret: - ps4NPTrophyPackPath: - ps4ParentalLevel: 11 - ps4ContentID: ED1633-NPXX51362_00-0000000000000000 - ps4Category: 0 - ps4MasterVersion: 01.00 - ps4AppVersion: 01.00 - ps4AppType: 0 - ps4ParamSfxPath: - ps4VideoOutPixelFormat: 0 - ps4VideoOutInitialWidth: 1920 - ps4VideoOutBaseModeInitialWidth: 1920 - ps4VideoOutReprojectionRate: 60 - ps4PronunciationXMLPath: - ps4PronunciationSIGPath: - ps4BackgroundImagePath: - ps4StartupImagePath: - ps4StartupImagesFolder: - ps4IconImagesFolder: - ps4SaveDataImagePath: - ps4SdkOverride: - ps4BGMPath: - ps4ShareFilePath: - ps4ShareOverlayImagePath: - ps4PrivacyGuardImagePath: - ps4ExtraSceSysFile: - ps4NPtitleDatPath: - ps4RemotePlayKeyAssignment: -1 - ps4RemotePlayKeyMappingDir: - ps4PlayTogetherPlayerCount: 0 - ps4EnterButtonAssignment: 1 - ps4ApplicationParam1: 0 - ps4ApplicationParam2: 0 - ps4ApplicationParam3: 0 - ps4ApplicationParam4: 0 - ps4DownloadDataSize: 0 - ps4GarlicHeapSize: 2048 - ps4ProGarlicHeapSize: 2560 - playerPrefsMaxSize: 32768 - ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ - ps4pnSessions: 1 - ps4pnPresence: 1 - ps4pnFriends: 1 - ps4pnGameCustomData: 1 - playerPrefsSupport: 0 - enableApplicationExit: 0 - resetTempFolder: 1 - restrictedAudioUsageRights: 0 - ps4UseResolutionFallback: 0 - ps4ReprojectionSupport: 0 - ps4UseAudio3dBackend: 0 - ps4UseLowGarlicFragmentationMode: 1 - ps4SocialScreenEnabled: 0 - ps4ScriptOptimizationLevel: 0 - ps4Audio3dVirtualSpeakerCount: 14 - ps4attribCpuUsage: 0 - ps4PatchPkgPath: - ps4PatchLatestPkgPath: - ps4PatchChangeinfoPath: - ps4PatchDayOne: 0 - ps4attribUserManagement: 0 - ps4attribMoveSupport: 0 - ps4attrib3DSupport: 0 - ps4attribShareSupport: 0 - ps4attribExclusiveVR: 0 - ps4disableAutoHideSplash: 0 - ps4videoRecordingFeaturesUsed: 0 - ps4contentSearchFeaturesUsed: 0 - ps4CompatibilityPS5: 0 - ps4AllowPS5Detection: 0 - ps4GPU800MHz: 1 - ps4attribEyeToEyeDistanceSettingVR: 0 - ps4IncludedModules: [] - ps4attribVROutputEnabled: 0 - monoEnv: - splashScreenBackgroundSourceLandscape: {fileID: 0} - splashScreenBackgroundSourcePortrait: {fileID: 0} - blurSplashScreenBackground: 1 - spritePackerPolicy: - webGLMemorySize: 16 - webGLExceptionSupport: 1 - webGLNameFilesAsHashes: 0 - webGLShowDiagnostics: 0 - webGLDataCaching: 1 - webGLDebugSymbols: 0 - webGLEmscriptenArgs: - webGLModulesDirectory: - webGLTemplate: APPLICATION:Default - webGLAnalyzeBuildSize: 0 - webGLUseEmbeddedResources: 0 - webGLCompressionFormat: 1 - webGLWasmArithmeticExceptions: 0 - webGLLinkerTarget: 1 - webGLThreadsSupport: 0 - webGLDecompressionFallback: 0 - webGLInitialMemorySize: 32 - webGLMaximumMemorySize: 2048 - webGLMemoryGrowthMode: 2 - webGLMemoryLinearGrowthStep: 16 - webGLMemoryGeometricGrowthStep: 0.2 - webGLMemoryGeometricGrowthCap: 96 - webGLPowerPreference: 2 - scriptingDefineSymbols: {} - additionalCompilerArguments: {} - platformArchitecture: {} - scriptingBackend: - Android: 1 - Standalone: 1 - il2cppCompilerConfiguration: - Android: 0 - Standalone: 0 - il2cppCodeGeneration: {} - managedStrippingLevel: - EmbeddedLinux: 1 - GameCoreScarlett: 1 - GameCoreXboxOne: 1 - Nintendo Switch: 1 - PS4: 1 - PS5: 1 - QNX: 1 - Stadia: 1 - VisionOS: 1 - WebGL: 1 - Windows Store Apps: 1 - XboxOne: 1 - iPhone: 1 - tvOS: 1 - incrementalIl2cppBuild: {} - suppressCommonWarnings: 1 - allowUnsafeCode: 0 - useDeterministicCompilation: 1 - additionalIl2CppArgs: - scriptingRuntimeVersion: 1 - gcIncremental: 1 - gcWBarrierValidation: 0 - apiCompatibilityLevelPerPlatform: {} - m_RenderingPath: 1 - m_MobileRenderingPath: 1 - metroPackageName: ObfuzDemo - metroPackageVersion: - metroCertificatePath: - metroCertificatePassword: - metroCertificateSubject: - metroCertificateIssuer: - metroCertificateNotAfter: 0000000000000000 - metroApplicationDescription: ObfuzDemo - wsaImages: {} - metroTileShortName: - metroTileShowName: 0 - metroMediumTileShowName: 0 - metroLargeTileShowName: 0 - metroWideTileShowName: 0 - metroSupportStreamingInstall: 0 - metroLastRequiredScene: 0 - metroDefaultTileSize: 1 - metroTileForegroundText: 2 - metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} - metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} - metroSplashScreenUseBackgroundColor: 0 - platformCapabilities: {} - metroTargetDeviceFamilies: {} - metroFTAName: - metroFTAFileTypes: [] - metroProtocolName: - vcxProjDefaultLanguage: - XboxOneProductId: - XboxOneUpdateKey: - XboxOneSandboxId: - XboxOneContentId: - XboxOneTitleId: - XboxOneSCId: - XboxOneGameOsOverridePath: - XboxOnePackagingOverridePath: - XboxOneAppManifestOverridePath: - XboxOneVersion: 1.0.0.0 - XboxOnePackageEncryption: 0 - XboxOnePackageUpdateGranularity: 2 - XboxOneDescription: - XboxOneLanguage: - - enus - XboxOneCapability: [] - XboxOneGameRating: {} - XboxOneIsContentPackage: 0 - XboxOneEnhancedXboxCompatibilityMode: 0 - XboxOneEnableGPUVariability: 1 - XboxOneSockets: {} - XboxOneSplashScreen: {fileID: 0} - XboxOneAllowedProductIds: [] - XboxOnePersistentLocalStorageSize: 0 - XboxOneXTitleMemory: 8 - XboxOneOverrideIdentityName: - XboxOneOverrideIdentityPublisher: - vrEditorSettings: {} - cloudServicesEnabled: - UNet: 1 - luminIcon: - m_Name: - m_ModelFolderPath: - m_PortalFolderPath: - luminCert: - m_CertPath: - m_SignPackage: 1 - luminIsChannelApp: 0 - luminVersion: - m_VersionCode: 1 - m_VersionName: - hmiPlayerDataPath: - hmiForceSRGBBlit: 1 - embeddedLinuxEnableGamepadInput: 1 - hmiLogStartupTiming: 0 - hmiCpuConfiguration: - apiCompatibilityLevel: 3 - activeInputHandler: 0 - windowsGamepadBackendHint: 0 - cloudProjectId: - framebufferDepthMemorylessMode: 0 - qualitySettingsNames: [] - projectName: - organizationId: - cloudEnabled: 0 - legacyClampBlendShapeWeights: 0 - hmiLoadingImage: {fileID: 0} - platformRequiresReadableAssets: 0 - virtualTexturingSupportEnabled: 0 - insecureHttpOption: 0 diff --git a/Obfuz/ProjectSettings/ProjectVersion.txt b/Obfuz/ProjectSettings/ProjectVersion.txt deleted file mode 100644 index 37f39b7..0000000 --- a/Obfuz/ProjectSettings/ProjectVersion.txt +++ /dev/null @@ -1,2 +0,0 @@ -m_EditorVersion: 2022.3.11f1 -m_EditorVersionWithRevision: 2022.3.11f1 (d00248457e15) diff --git a/Obfuz/ProjectSettings/QualitySettings.asset b/Obfuz/ProjectSettings/QualitySettings.asset deleted file mode 100644 index 36c0dad..0000000 --- a/Obfuz/ProjectSettings/QualitySettings.asset +++ /dev/null @@ -1,234 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!47 &1 -QualitySettings: - m_ObjectHideFlags: 0 - serializedVersion: 5 - m_CurrentQuality: 5 - m_QualitySettings: - - serializedVersion: 2 - name: Very Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 15 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 1 - textureQuality: 1 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.3 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 4 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Low - pixelLightCount: 0 - shadows: 0 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 0 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 0 - lodBias: 0.4 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 16 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Medium - pixelLightCount: 1 - shadows: 1 - shadowResolution: 0 - shadowProjection: 1 - shadowCascades: 1 - shadowDistance: 20 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 0 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 0 - realtimeReflectionProbes: 0 - billboardsFaceCameraPosition: 0 - vSyncCount: 1 - lodBias: 0.7 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 64 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: High - pixelLightCount: 2 - shadows: 2 - shadowResolution: 1 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 40 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 2 - textureQuality: 0 - anisotropicTextures: 1 - antiAliasing: 0 - softParticles: 0 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 256 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Very High - pixelLightCount: 3 - shadows: 2 - shadowResolution: 2 - shadowProjection: 1 - shadowCascades: 2 - shadowDistance: 70 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 4 - textureQuality: 0 - anisotropicTextures: 2 - antiAliasing: 2 - softParticles: 1 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 1.5 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 1024 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - - serializedVersion: 2 - name: Ultra - pixelLightCount: 4 - shadows: 2 - shadowResolution: 2 - shadowProjection: 1 - shadowCascades: 4 - shadowDistance: 150 - shadowNearPlaneOffset: 3 - shadowCascade2Split: 0.33333334 - shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} - shadowmaskMode: 1 - blendWeights: 4 - textureQuality: 0 - anisotropicTextures: 2 - antiAliasing: 2 - softParticles: 1 - softVegetation: 1 - realtimeReflectionProbes: 1 - billboardsFaceCameraPosition: 1 - vSyncCount: 1 - lodBias: 2 - maximumLODLevel: 0 - streamingMipmapsActive: 0 - streamingMipmapsAddAllCameras: 1 - streamingMipmapsMemoryBudget: 512 - streamingMipmapsRenderersPerFrame: 512 - streamingMipmapsMaxLevelReduction: 2 - streamingMipmapsMaxFileIORequests: 1024 - particleRaycastBudget: 4096 - asyncUploadTimeSlice: 2 - asyncUploadBufferSize: 16 - asyncUploadPersistentBuffer: 1 - resolutionScalingFixedDPIFactor: 1 - excludedTargetPlatforms: [] - m_PerPlatformDefaultQuality: - Android: 2 - Lumin: 5 - GameCoreScarlett: 5 - GameCoreXboxOne: 5 - Nintendo 3DS: 5 - Nintendo Switch: 5 - PS4: 5 - PS5: 5 - Stadia: 5 - Standalone: 5 - WebGL: 3 - Windows Store Apps: 5 - XboxOne: 5 - iPhone: 2 - tvOS: 2 diff --git a/Obfuz/ProjectSettings/SceneTemplateSettings.json b/Obfuz/ProjectSettings/SceneTemplateSettings.json deleted file mode 100644 index 5e97f83..0000000 --- a/Obfuz/ProjectSettings/SceneTemplateSettings.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "templatePinStates": [], - "dependencyTypeInfos": [ - { - "userAdded": false, - "type": "UnityEngine.AnimationClip", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.Animations.AnimatorController", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.AnimatorOverrideController", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.Audio.AudioMixerController", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.ComputeShader", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.Cubemap", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.GameObject", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.LightingDataAsset", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.LightingSettings", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Material", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.MonoScript", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.PhysicMaterial", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.PhysicsMaterial2D", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Rendering.VolumeProfile", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEditor.SceneAsset", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.Shader", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.ShaderVariantCollection", - "defaultInstantiationMode": 1 - }, - { - "userAdded": false, - "type": "UnityEngine.Texture", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Texture2D", - "defaultInstantiationMode": 0 - }, - { - "userAdded": false, - "type": "UnityEngine.Timeline.TimelineAsset", - "defaultInstantiationMode": 0 - } - ], - "defaultDependencyTypeInfo": { - "userAdded": false, - "type": "", - "defaultInstantiationMode": 1 - }, - "newSceneOverride": 0 -} \ No newline at end of file diff --git a/Obfuz/ProjectSettings/TagManager.asset b/Obfuz/ProjectSettings/TagManager.asset deleted file mode 100644 index 1c92a78..0000000 --- a/Obfuz/ProjectSettings/TagManager.asset +++ /dev/null @@ -1,43 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!78 &1 -TagManager: - serializedVersion: 2 - tags: [] - layers: - - Default - - TransparentFX - - Ignore Raycast - - - - Water - - UI - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - m_SortingLayers: - - name: Default - uniqueID: 0 - locked: 0 diff --git a/Obfuz/ProjectSettings/TimeManager.asset b/Obfuz/ProjectSettings/TimeManager.asset deleted file mode 100644 index 558a017..0000000 --- a/Obfuz/ProjectSettings/TimeManager.asset +++ /dev/null @@ -1,9 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!5 &1 -TimeManager: - m_ObjectHideFlags: 0 - Fixed Timestep: 0.02 - Maximum Allowed Timestep: 0.33333334 - m_TimeScale: 1 - Maximum Particle Timestep: 0.03 diff --git a/Obfuz/ProjectSettings/UnityConnectSettings.asset b/Obfuz/ProjectSettings/UnityConnectSettings.asset deleted file mode 100644 index a88bee0..0000000 --- a/Obfuz/ProjectSettings/UnityConnectSettings.asset +++ /dev/null @@ -1,36 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!310 &1 -UnityConnectSettings: - m_ObjectHideFlags: 0 - serializedVersion: 1 - m_Enabled: 0 - m_TestMode: 0 - m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events - m_EventUrl: https://cdp.cloud.unity3d.com/v1/events - m_ConfigUrl: https://config.uca.cloud.unity3d.com - m_DashboardUrl: https://dashboard.unity3d.com - m_TestInitMode: 0 - CrashReportingSettings: - m_EventUrl: https://perf-events.cloud.unity3d.com - m_Enabled: 0 - m_LogBufferSize: 10 - m_CaptureEditorExceptions: 1 - UnityPurchasingSettings: - m_Enabled: 0 - m_TestMode: 0 - UnityAnalyticsSettings: - m_Enabled: 0 - m_TestMode: 0 - m_InitializeOnStartup: 1 - m_PackageRequiringCoreStatsPresent: 0 - UnityAdsSettings: - m_Enabled: 0 - m_InitializeOnStartup: 1 - m_TestMode: 0 - m_IosGameId: - m_AndroidGameId: - m_GameIds: {} - m_GameId: - PerformanceReportingSettings: - m_Enabled: 0 diff --git a/Obfuz/ProjectSettings/VFXManager.asset b/Obfuz/ProjectSettings/VFXManager.asset deleted file mode 100644 index 3a95c98..0000000 --- a/Obfuz/ProjectSettings/VFXManager.asset +++ /dev/null @@ -1,12 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!937362698 &1 -VFXManager: - m_ObjectHideFlags: 0 - m_IndirectShader: {fileID: 0} - m_CopyBufferShader: {fileID: 0} - m_SortShader: {fileID: 0} - m_StripUpdateShader: {fileID: 0} - m_RenderPipeSettingsPath: - m_FixedTimeStep: 0.016666668 - m_MaxDeltaTime: 0.05 diff --git a/Obfuz/ProjectSettings/VersionControlSettings.asset b/Obfuz/ProjectSettings/VersionControlSettings.asset deleted file mode 100644 index dca2881..0000000 --- a/Obfuz/ProjectSettings/VersionControlSettings.asset +++ /dev/null @@ -1,8 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!890905787 &1 -VersionControlSettings: - m_ObjectHideFlags: 0 - m_Mode: Visible Meta Files - m_CollabEditorSettings: - inProgressEnabled: 1 diff --git a/Obfuz/ProjectSettings/XRSettings.asset b/Obfuz/ProjectSettings/XRSettings.asset deleted file mode 100644 index 482590c..0000000 --- a/Obfuz/ProjectSettings/XRSettings.asset +++ /dev/null @@ -1,10 +0,0 @@ -{ - "m_SettingKeys": [ - "VR Device Disabled", - "VR Device User Alert" - ], - "m_SettingValues": [ - "False", - "False" - ] -} \ No newline at end of file diff --git a/Obfuz/README.md b/Obfuz/README.md deleted file mode 100644 index 952c515..0000000 --- a/Obfuz/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Obfuz - -这是一个极简的Obfuz示例项目。 - -## 配置 - -点击 `Obfuz/Settings...`菜单打开ObfuzSettings页面。 -可以看到`Assembly Settings`里已经添加了两个混淆程序集:Assembly-CSharp和Obfuz.Runtime(没错,Obfuz自身也是可混淆的)。 - -## 构建 - -打开`Build Settings`,运行`Build`或`Build and Run`即可。 - -## 查看混淆文件 - -混淆后的文件在`Library/Obfuz/{buildTarget}/ObfuscatedAssemblies目录下。 - -使用IlSpy打开`Assembly-CSharp.dll`,混淆后的Bootstrap类代码变成这样: - -```csharp - -using System; -using $a; -using $A; -using UnityEngine; - -// Token: 0x02000002 RID: 2 -public class Bootstrap : MonoBehaviour -{ - // Token: 0x06000001 RID: 1 RVA: 0x000030F0 File Offset: 0x000012F0 - [RuntimeInitializeOnLoadMethod(2)] - private static void SetUpStaticSecret() - { - Debug.Log("SetUpStaticSecret begin"); - global::$A.$C<$c>.$L = new $a.$A(Resources.Load("Obfuz/defaultStaticSecretKey").bytes); - Debug.Log("SetUpStaticSecret end"); - } - - // Token: 0x06000002 RID: 2 RVA: 0x0000311F File Offset: 0x0000131F - public int $a(int 1, int 1) - { - return 1 + 1; - } - - // Token: 0x06000003 RID: 3 RVA: 0x00003204 File Offset: 0x00001404 - private void Start() - { - int num = global::$e.$A(this, global::$e.$a(global::$d.$A, 0, 117, -2060908889, global::$A.$C<$c>.$d(-1139589574, 85, -452785586)), global::$e.$a(global::$d.$A, 4, 138, -1222258517, global::$A.$C<$c>.$d(-1139589574, 85, -452785586)), global::$A.$C<$c>.$d(1757957431, 242, 760404455)); - global::$e.$b(string.Format(global::$D.$a, num), global::$A.$C<$c>.$d(1718597184, 154, 2114032877)); - } -} - - - -```