diff --git a/.gitignore b/.gitignore index a4fe18b..60816c3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,398 +3,14 @@ ## ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates +**/Library/ +**/Logs/ +**/Temp/ -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs +**/.vs/ +**/bin/ +**/obj/ -# Mono auto generated files -mono_crash.* -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -# but not Directory.Build.rsp, as it configures directory-level build defaults -!Directory.Build.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - -# Visual Studio 6 workspace and project file (working project files containing files to include in project) -*.dsw -*.dsp - -# Visual Studio 6 technical files -*.ncb -*.aps - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# Visual Studio History (VSHistory) files -.vshistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -# VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -# Local History for Visual Studio Code -.history/ - -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp - -# JetBrains Rider -*.sln.iml +*.vsconfig +**/UserSettings/ diff --git a/DeobfuscateStackTrace/deobfuscated.log b/DeobfuscateStackTrace/deobfuscated.log new file mode 100644 index 0000000..1803a9e --- /dev/null +++ b/DeobfuscateStackTrace/deobfuscated.log @@ -0,0 +1,17 @@ +test stack trace +UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object) +UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) +UnityEngine.Logger:Log(LogType, Object) +UnityEngine.Debug:Log(Object) +Obfus2.TestStackTrace:Stack3() +Obfus2.NestedClass`1:Stack2(TestStackTrace, Int32[], List`1, Banana) +Obfus2.TestStackTrace:Stack1(Int64, UInt64, Single, Double, String, Object) +Obfus2.TestStackTrace:Stack0(Byte, SByte, Int16, UInt16, Int32, UInt32) +Tests.TC_StackTrace:PrintStackTrace() +System.Reflection.RuntimeMethodInfo:InternalInvoke(Object, Object[], Exception&) +System.Reflection.RuntimeMethodInfo:Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) +System.Reflection.MethodBase:Invoke(Object, Object[]) +SharpUnit.TestCase:Run(TestResult) +SharpUnit.TestSuite:Run(TestResult) +TestRunner:Run() +Bootstrap:Start() diff --git a/DeobfuscateStackTrace/obfuscated.log b/DeobfuscateStackTrace/obfuscated.log new file mode 100644 index 0000000..d772f37 --- /dev/null +++ b/DeobfuscateStackTrace/obfuscated.log @@ -0,0 +1,17 @@ +test stack trace +UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object) +UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) +UnityEngine.Logger:Log(LogType, Object) +UnityEngine.Debug:Log(Object) +F.g:A() +F.G:a(g, Int32[], List`1, Banana) +F.g:a(Int64, UInt64, Single, Double, String, Object) +F.g:b(Byte, SByte, Int16, UInt16, Int32, UInt32) +Tests.TC_StackTrace:PrintStackTrace() +System.Reflection.RuntimeMethodInfo:InternalInvoke(Object, Object[], Exception&) +System.Reflection.RuntimeMethodInfo:Invoke(Object, BindingFlags, Binder, Object[], CultureInfo) +System.Reflection.MethodBase:Invoke(Object, Object[]) +SharpUnit.TestCase:Run(TestResult) +SharpUnit.TestSuite:Run(TestResult) +TestRunner:Run() +Bootstrap:Start() \ No newline at end of file diff --git a/Obfuz/Obfuz.Editor.csproj b/Obfuz/Obfuz.Editor.csproj new file mode 100644 index 0000000..3e60133 --- /dev/null +++ b/Obfuz/Obfuz.Editor.csproj @@ -0,0 +1,1095 @@ + + + + + 9.0 + + + Debug + AnyCPU + 10.0.20506 + 2.0 + + {61F9FC55-17B9-1093-9FB3-FCD0720BA981} + Library + Properties + Obfuz.Editor + v4.7.1 + 512 + . + + + 0169;USG0001 + UNITY_2022_3_11;UNITY_2022_3;UNITY_2022;UNITY_5_3_OR_NEWER;UNITY_5_4_OR_NEWER;UNITY_5_5_OR_NEWER;UNITY_5_6_OR_NEWER;UNITY_2017_1_OR_NEWER;UNITY_2017_2_OR_NEWER;UNITY_2017_3_OR_NEWER;UNITY_2017_4_OR_NEWER;UNITY_2018_1_OR_NEWER;UNITY_2018_2_OR_NEWER;UNITY_2018_3_OR_NEWER;UNITY_2018_4_OR_NEWER;UNITY_2019_1_OR_NEWER;UNITY_2019_2_OR_NEWER;UNITY_2019_3_OR_NEWER;UNITY_2019_4_OR_NEWER;UNITY_2020_1_OR_NEWER;UNITY_2020_2_OR_NEWER;UNITY_2020_3_OR_NEWER;UNITY_2021_1_OR_NEWER;UNITY_2021_2_OR_NEWER;UNITY_2021_3_OR_NEWER;UNITY_2022_1_OR_NEWER;UNITY_2022_2_OR_NEWER;UNITY_2022_3_OR_NEWER;PLATFORM_ARCH_64;UNITY_64;UNITY_INCLUDE_TESTS;ENABLE_AR;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_EVENT_QUEUE;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_TEXTURE_STREAMING;ENABLE_VIRTUALTEXTURING;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_VR;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_EDITOR_GAME_SERVICES;ENABLE_UNITY_GAME_SERVICES_ANALYTICS_SUPPORT;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_GENERATE_NATIVE_PLUGINS_FOR_ASSEMBLIES_API;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;ENABLE_MANAGED_ANIMATION_JOBS;ENABLE_MANAGED_AUDIO_JOBS;ENABLE_MANAGED_UNITYTLS;INCLUDE_DYNAMIC_GI;ENABLE_SCRIPTING_GC_WBARRIERS;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;ENABLE_VIDEO;ENABLE_ACCELERATOR_CLIENT_DEBUGGING;ENABLE_NAVIGATION_PACKAGE_DEBUG_VISUALIZATION;ENABLE_NAVIGATION_HEIGHTMESH_RUNTIME_SUPPORT;ENABLE_NAVIGATION_UI_REQUIRES_PACKAGE;PLATFORM_STANDALONE;TEXTCORE_1_0_OR_NEWER;PLATFORM_STANDALONE_WIN;UNITY_STANDALONE_WIN;UNITY_STANDALONE;ENABLE_RUNTIME_GI;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_NVIDIA;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_OUT_OF_PROCESS_CRASH_HANDLER;ENABLE_CLUSTER_SYNC;ENABLE_CLUSTERINPUT;PLATFORM_UPDATES_TIME_OUTSIDE_OF_PLAYER_LOOP;GFXDEVICE_WAITFOREVENT_MESSAGEPUMP;PLATFORM_INITIALIZES_MEMORY_MANAGER_EXPLICITLY;ENABLE_MONO;NET_4_6;NET_UNITY_4_8;ENABLE_PROFILER;DEBUG;TRACE;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_WIN;ENABLE_UNITY_COLLECTIONS_CHECKS;ENABLE_BURST_AOT;UNITY_TEAM_LICENSE;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_DIRECTOR;ENABLE_LOCALIZATION;ENABLE_SPRITES;ENABLE_TERRAIN;ENABLE_TILEMAP;ENABLE_TIMELINE;ENABLE_LEGACY_INPUT_MANAGER;TEXTCORE_FONT_ENGINE_1_5_OR_NEWER;CSHARP_7_OR_LATER;CSHARP_7_3_OR_NEWER;UNITY_EDITOR_ONLY_COMPILATION + True + + + true + full + false + Temp\bin\Debug\ + prompt + 4 + + + pdbonly + true + Temp\bin\Release\ + prompt + 4 + + + true + true + false + false + false + + + {E097FAD1-6243-4DAD-9C02-E9B9EFC3FFC1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Package + 2.0.23 + Legacy + Editor:5 + StandaloneWindows64:19 + 2022.3.11f1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ARModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AccessibilityModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AndroidJNIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AnimationModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AssetBundleModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AudioModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ClothModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ClusterInputModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ClusterRendererModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ContentLoadModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.CrashReportingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.DSPGraphModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.DirectorModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.GIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.GameCenterModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.GridModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.HotReloadModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.IMGUIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ImageConversionModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.InputModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.InputLegacyModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.JSONSerializeModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.LocalizationModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.NVIDIAModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ParticleSystemModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.PerformanceReportingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.PhysicsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.Physics2DModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ProfilerModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.PropertiesModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ScreenCaptureModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SharedInternalsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SpriteMaskModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SpriteShapeModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.StreamingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SubstanceModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SubsystemsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TLSModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TerrainModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TerrainPhysicsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextCoreFontEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextCoreTextEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextRenderingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TilemapModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UIElementsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UmbraModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityAnalyticsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityAnalyticsCommonModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityConnectModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityCurlModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityTestProtocolModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestAssetBundleModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestAudioModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestTextureModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestWWWModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VFXModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VRModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VehiclesModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VideoModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VirtualTexturingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.WindModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.XRModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.CoreModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.DeviceSimulatorModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.DiagnosticsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.EditorToolbarModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.GraphViewModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.PresetsUIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.QuickSearchModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.SceneTemplateModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.SceneViewModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.TextCoreFontEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.TextCoreTextEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UIBuilderModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UIElementsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UIElementsSamplesModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UnityConnectModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEditor.Graphs.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\WebGLSupport\UnityEditor.WebGL.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\UnityEditor.Android.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\iOSSupport\UnityEditor.iOS.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AppleTVSupport\UnityEditor.AppleTV.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\WindowsStandaloneSupport\UnityEditor.WindowsStandalone.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\LinuxStandaloneSupport\UnityEditor.LinuxStandalone.Extensions.dll + False + + + Packages\com.code-philosophy.obfuz\Plugins\dnlib.dll + False + + + Library\PackageCache\com.unity.ext.nunit@1.0.6\net35\unity-custom\nunit.framework.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AppleTVSupport\UnityEditor.iOS.Extensions.Xcode.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\iOSSupport\UnityEditor.iOS.Extensions.Xcode.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\iOSSupport\UnityEditor.iOS.Extensions.Common.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\Unity.Android.Types.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\Unity.Android.Gradle.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\Unity.Android.GradleProject.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\mscorlib.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Core.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Runtime.Serialization.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Xml.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Xml.Linq.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Numerics.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Numerics.Vectors.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Net.Http.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.IO.Compression.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Microsoft.CSharp.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Data.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Data.DataSetExtensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Drawing.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.IO.Compression.FileSystem.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.ComponentModel.Composition.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Transactions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\Microsoft.Win32.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\netstandard.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.AppContext.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Buffers.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.Concurrent.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.NonGeneric.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.Specialized.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.Annotations.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.EventBasedAsync.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.TypeConverter.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Console.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Data.Common.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Contracts.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Debug.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.FileVersionInfo.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Process.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.StackTrace.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.TextWriterTraceListener.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Tools.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.TraceSource.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Drawing.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Dynamic.Runtime.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Globalization.Calendars.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Globalization.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Globalization.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.Compression.ZipFile.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.DriveInfo.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.Watcher.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.IsolatedStorage.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.MemoryMappedFiles.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.Pipes.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.UnmanagedMemoryStream.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.Expressions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.Parallel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.Queryable.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Memory.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Http.Rtc.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.NameResolution.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.NetworkInformation.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Ping.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Requests.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Security.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Sockets.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.WebHeaderCollection.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.WebSockets.Client.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.WebSockets.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ObjectModel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.DispatchProxy.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Emit.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Emit.ILGeneration.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Emit.Lightweight.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Resources.Reader.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Resources.ResourceManager.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Resources.Writer.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.CompilerServices.VisualC.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Handles.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.InteropServices.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.InteropServices.RuntimeInformation.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.InteropServices.WindowsRuntime.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Numerics.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Formatters.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Json.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Xml.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Claims.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Algorithms.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Csp.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Encoding.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.X509Certificates.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Principal.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.SecureString.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Duplex.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Http.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.NetTcp.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Security.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Text.Encoding.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Text.Encoding.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Text.RegularExpressions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Overlapped.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Tasks.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Tasks.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Tasks.Parallel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Thread.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.ThreadPool.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Timer.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ValueTuple.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.ReaderWriter.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XDocument.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XmlDocument.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XmlSerializer.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XPath.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XPath.XDocument.dll + False + + + Library\ScriptAssemblies\UnityEngine.TestRunner.dll + False + + + Library\ScriptAssemblies\UnityEditor.TestRunner.dll + False + + + + + {1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6} + Obfuz.Runtime + + + + + + diff --git a/Obfuz/Obfuz.Runtime.csproj b/Obfuz/Obfuz.Runtime.csproj new file mode 100644 index 0000000..6a495f8 --- /dev/null +++ b/Obfuz/Obfuz.Runtime.csproj @@ -0,0 +1,881 @@ + + + + + 9.0 + + + Debug + AnyCPU + 10.0.20506 + 2.0 + + {1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6} + Library + Properties + Obfuz.Runtime + v4.7.1 + 512 + . + + + 0169;USG0001 + UNITY_2022_3_11;UNITY_2022_3;UNITY_2022;UNITY_5_3_OR_NEWER;UNITY_5_4_OR_NEWER;UNITY_5_5_OR_NEWER;UNITY_5_6_OR_NEWER;UNITY_2017_1_OR_NEWER;UNITY_2017_2_OR_NEWER;UNITY_2017_3_OR_NEWER;UNITY_2017_4_OR_NEWER;UNITY_2018_1_OR_NEWER;UNITY_2018_2_OR_NEWER;UNITY_2018_3_OR_NEWER;UNITY_2018_4_OR_NEWER;UNITY_2019_1_OR_NEWER;UNITY_2019_2_OR_NEWER;UNITY_2019_3_OR_NEWER;UNITY_2019_4_OR_NEWER;UNITY_2020_1_OR_NEWER;UNITY_2020_2_OR_NEWER;UNITY_2020_3_OR_NEWER;UNITY_2021_1_OR_NEWER;UNITY_2021_2_OR_NEWER;UNITY_2021_3_OR_NEWER;UNITY_2022_1_OR_NEWER;UNITY_2022_2_OR_NEWER;UNITY_2022_3_OR_NEWER;PLATFORM_ARCH_64;UNITY_64;UNITY_INCLUDE_TESTS;ENABLE_AR;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_EVENT_QUEUE;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_PHYSICS;ENABLE_TEXTURE_STREAMING;ENABLE_VIRTUALTEXTURING;ENABLE_LZMA;ENABLE_UNITYEVENTS;ENABLE_VR;ENABLE_WEBCAM;ENABLE_UNITYWEBREQUEST;ENABLE_WWW;ENABLE_CLOUD_SERVICES;ENABLE_CLOUD_SERVICES_ADS;ENABLE_CLOUD_SERVICES_USE_WEBREQUEST;ENABLE_CLOUD_SERVICES_CRASH_REPORTING;ENABLE_CLOUD_SERVICES_PURCHASING;ENABLE_CLOUD_SERVICES_ANALYTICS;ENABLE_CLOUD_SERVICES_BUILD;ENABLE_EDITOR_GAME_SERVICES;ENABLE_UNITY_GAME_SERVICES_ANALYTICS_SUPPORT;ENABLE_CLOUD_LICENSE;ENABLE_EDITOR_HUB_LICENSE;ENABLE_WEBSOCKET_CLIENT;ENABLE_GENERATE_NATIVE_PLUGINS_FOR_ASSEMBLIES_API;ENABLE_DIRECTOR_AUDIO;ENABLE_DIRECTOR_TEXTURE;ENABLE_MANAGED_JOBS;ENABLE_MANAGED_TRANSFORM_JOBS;ENABLE_MANAGED_ANIMATION_JOBS;ENABLE_MANAGED_AUDIO_JOBS;ENABLE_MANAGED_UNITYTLS;INCLUDE_DYNAMIC_GI;ENABLE_SCRIPTING_GC_WBARRIERS;PLATFORM_SUPPORTS_MONO;RENDER_SOFTWARE_CURSOR;ENABLE_VIDEO;ENABLE_ACCELERATOR_CLIENT_DEBUGGING;ENABLE_NAVIGATION_PACKAGE_DEBUG_VISUALIZATION;ENABLE_NAVIGATION_HEIGHTMESH_RUNTIME_SUPPORT;ENABLE_NAVIGATION_UI_REQUIRES_PACKAGE;PLATFORM_STANDALONE;TEXTCORE_1_0_OR_NEWER;PLATFORM_STANDALONE_WIN;UNITY_STANDALONE_WIN;UNITY_STANDALONE;ENABLE_RUNTIME_GI;ENABLE_MOVIES;ENABLE_NETWORK;ENABLE_NVIDIA;ENABLE_CRUNCH_TEXTURE_COMPRESSION;ENABLE_OUT_OF_PROCESS_CRASH_HANDLER;ENABLE_CLUSTER_SYNC;ENABLE_CLUSTERINPUT;PLATFORM_UPDATES_TIME_OUTSIDE_OF_PLAYER_LOOP;GFXDEVICE_WAITFOREVENT_MESSAGEPUMP;PLATFORM_INITIALIZES_MEMORY_MANAGER_EXPLICITLY;ENABLE_MONO;NET_4_6;NET_UNITY_4_8;ENABLE_PROFILER;DEBUG;TRACE;UNITY_ASSERTIONS;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_WIN;ENABLE_UNITY_COLLECTIONS_CHECKS;ENABLE_BURST_AOT;UNITY_TEAM_LICENSE;ENABLE_CUSTOM_RENDER_TEXTURE;ENABLE_DIRECTOR;ENABLE_LOCALIZATION;ENABLE_SPRITES;ENABLE_TERRAIN;ENABLE_TILEMAP;ENABLE_TIMELINE;ENABLE_LEGACY_INPUT_MANAGER;TEXTCORE_FONT_ENGINE_1_5_OR_NEWER;CSHARP_7_OR_LATER;CSHARP_7_3_OR_NEWER + True + + + true + full + false + Temp\bin\Debug\ + prompt + 4 + + + pdbonly + true + Temp\bin\Release\ + prompt + 4 + + + true + true + false + false + false + + + {E097FAD1-6243-4DAD-9C02-E9B9EFC3FFC1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Package + 2.0.23 + Legacy + Game:1 + StandaloneWindows64:19 + 2022.3.11f1 + + + + + + + + + + + + + + + + + + + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ARModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AccessibilityModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AssetBundleModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.AudioModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ClusterInputModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ClusterRendererModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ContentLoadModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.CrashReportingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.DSPGraphModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.GIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.GameCenterModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.GridModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.HotReloadModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.IMGUIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ImageConversionModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.InputModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.InputLegacyModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.JSONSerializeModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.LocalizationModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.PerformanceReportingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.ProfilerModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.PropertiesModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SharedInternalsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SpriteMaskModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SpriteShapeModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.StreamingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.SubstanceModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TLSModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextCoreFontEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextCoreTextEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.TextRenderingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityAnalyticsCommonModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityConnectModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityCurlModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityTestProtocolModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestAssetBundleModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestAudioModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.UnityWebRequestWWWModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VFXModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEngine.VirtualTexturingModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.CoreModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.DeviceSimulatorModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.DiagnosticsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.EditorToolbarModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.GraphViewModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.PresetsUIModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.QuickSearchModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.SceneTemplateModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.SceneViewModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.TextCoreFontEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.TextCoreTextEngineModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UIBuilderModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UIElementsModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UIElementsSamplesModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEngine\UnityEditor.UnityConnectModule.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\Managed\UnityEditor.Graphs.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\WebGLSupport\UnityEditor.WebGL.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\UnityEditor.Android.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\iOSSupport\UnityEditor.iOS.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AppleTVSupport\UnityEditor.AppleTV.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\WindowsStandaloneSupport\UnityEditor.WindowsStandalone.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\LinuxStandaloneSupport\UnityEditor.LinuxStandalone.Extensions.dll + False + + + Packages\com.code-philosophy.obfuz\Plugins\dnlib.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AppleTVSupport\UnityEditor.iOS.Extensions.Xcode.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\iOSSupport\UnityEditor.iOS.Extensions.Xcode.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\iOSSupport\UnityEditor.iOS.Extensions.Common.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\Unity.Android.Types.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\Unity.Android.Gradle.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\PlaybackEngines\AndroidPlayer\Unity.Android.GradleProject.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\mscorlib.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Core.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Runtime.Serialization.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Xml.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Xml.Linq.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Numerics.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Numerics.Vectors.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Net.Http.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.IO.Compression.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Microsoft.CSharp.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Data.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Data.DataSetExtensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Drawing.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.IO.Compression.FileSystem.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.ComponentModel.Composition.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\System.Transactions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\Microsoft.Win32.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\netstandard.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.AppContext.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Buffers.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.Concurrent.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.NonGeneric.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Collections.Specialized.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.Annotations.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.EventBasedAsync.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ComponentModel.TypeConverter.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Console.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Data.Common.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Contracts.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Debug.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.FileVersionInfo.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Process.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.StackTrace.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.TextWriterTraceListener.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.Tools.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Diagnostics.TraceSource.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Drawing.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Dynamic.Runtime.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Globalization.Calendars.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Globalization.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Globalization.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.Compression.ZipFile.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.DriveInfo.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.FileSystem.Watcher.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.IsolatedStorage.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.MemoryMappedFiles.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.Pipes.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.IO.UnmanagedMemoryStream.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.Expressions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.Parallel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Linq.Queryable.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Memory.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Http.Rtc.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.NameResolution.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.NetworkInformation.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Ping.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Requests.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Security.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.Sockets.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.WebHeaderCollection.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.WebSockets.Client.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Net.WebSockets.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ObjectModel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.DispatchProxy.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Emit.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Emit.ILGeneration.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Emit.Lightweight.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Reflection.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Resources.Reader.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Resources.ResourceManager.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Resources.Writer.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.CompilerServices.VisualC.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Handles.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.InteropServices.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.InteropServices.RuntimeInformation.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.InteropServices.WindowsRuntime.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Numerics.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Formatters.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Json.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Runtime.Serialization.Xml.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Claims.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Algorithms.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Csp.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Encoding.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Cryptography.X509Certificates.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.Principal.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Security.SecureString.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Duplex.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Http.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.NetTcp.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Primitives.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ServiceModel.Security.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Text.Encoding.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Text.Encoding.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Text.RegularExpressions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Overlapped.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Tasks.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Tasks.Extensions.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Tasks.Parallel.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Thread.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.ThreadPool.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Threading.Timer.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.ValueTuple.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.ReaderWriter.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XDocument.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XmlDocument.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XmlSerializer.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XPath.dll + False + + + D:\UnityHubs\2022.3.11f1\Editor\Data\UnityReferenceAssemblies\unity-4.8-api\Facades\System.Xml.XPath.XDocument.dll + False + + + + + + diff --git a/Obfuz/Obfuz.sln b/Obfuz/Obfuz.sln new file mode 100644 index 0000000..c019123 --- /dev/null +++ b/Obfuz/Obfuz.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Obfuz.Editor", "Obfuz.Editor.csproj", "{61F9FC55-17B9-1093-9FB3-FCD0720BA981}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Obfuz.Runtime", "Obfuz.Runtime.csproj", "{1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {61F9FC55-17B9-1093-9FB3-FCD0720BA981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61F9FC55-17B9-1093-9FB3-FCD0720BA981}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61F9FC55-17B9-1093-9FB3-FCD0720BA981}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61F9FC55-17B9-1093-9FB3-FCD0720BA981}.Release|Any CPU.Build.0 = Release|Any CPU + {1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FE2F0BF-BDED-ACA3-1B41-08AC3002B1B6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/.gitignore b/Obfuz/Packages/com.code-philosophy.obfuz/.gitignore new file mode 100644 index 0000000..a4fe18b --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/.gitignore @@ -0,0 +1,400 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs new file mode 100644 index 0000000..aac0a66 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlAssemblyTypeMethodRuleParser.cs @@ -0,0 +1,267 @@ +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 interface IRule + { + 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/XmlFieldRuleParser.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs new file mode 100644 index 0000000..591271e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Conf/XmlFieldRuleParser.cs @@ -0,0 +1,208 @@ +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/ConfigurablePassPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs new file mode 100644 index 0000000..6d0fc7e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConfigurablePassPolicy.cs @@ -0,0 +1,547 @@ +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/ConstValues.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs new file mode 100644 index 0000000..2792a00 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ConstValues.cs @@ -0,0 +1,13 @@ +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/Data/ConstFieldAllocator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs new file mode 100644 index 0000000..7d90f8f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/ConstFieldAllocator.cs @@ -0,0 +1,344 @@ +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.Private | 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/RvaDataAllocator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs new file mode 100644 index 0000000..ed8e748 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Data/RvaDataAllocator.cs @@ -0,0 +1,354 @@ +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); + 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.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/Emit/BasicBlockCollection.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs new file mode 100644 index 0000000..acd80a7 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/BasicBlockCollection.cs @@ -0,0 +1,295 @@ +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/DefaultMetadataImporter.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs new file mode 100644 index 0000000..8a3c30d --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/DefaultMetadataImporter.cs @@ -0,0 +1,193 @@ +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/GroupByModuleEntityManager.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs new file mode 100644 index 0000000..860bdf8 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Emit/GroupByModuleEntityManager.cs @@ -0,0 +1,66 @@ +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/EncryptionVM/EncryptionInstructionWithOpCode.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs new file mode 100644 index 0000000..19ded45 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/EncryptionInstructionWithOpCode.cs @@ -0,0 +1,25 @@ +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/IEncryptionInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs new file mode 100644 index 0000000..49808c4 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/IEncryptionInstruction.cs @@ -0,0 +1,24 @@ +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/Instructions/AddInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs new file mode 100644 index 0000000..2681fff --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddInstruction.cs @@ -0,0 +1,35 @@ +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/AddRotateXorInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs new file mode 100644 index 0000000..099a566 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddRotateXorInstruction.cs @@ -0,0 +1,66 @@ +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/AddXorRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs new file mode 100644 index 0000000..cc453a7 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/AddXorRotateInstruction.cs @@ -0,0 +1,66 @@ +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/BitRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs new file mode 100644 index 0000000..2d9dcd1 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/BitRotateInstruction.cs @@ -0,0 +1,46 @@ +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/EncryptFunction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs new file mode 100644 index 0000000..ed59848 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/EncryptFunction.cs @@ -0,0 +1,47 @@ +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/MultipleInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs new file mode 100644 index 0000000..2635f5e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleInstruction.cs @@ -0,0 +1,64 @@ +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/MultipleRotateXorInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs new file mode 100644 index 0000000..75e4c5c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleRotateXorInstruction.cs @@ -0,0 +1,68 @@ +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/MultipleXorRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs new file mode 100644 index 0000000..9733776 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/MultipleXorRotateInstruction.cs @@ -0,0 +1,68 @@ +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/XorAddRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs new file mode 100644 index 0000000..10a9226 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorAddRotateInstruction.cs @@ -0,0 +1,66 @@ +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/XorInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs new file mode 100644 index 0000000..ec5fb9f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorInstruction.cs @@ -0,0 +1,36 @@ +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/XorMultipleRotateInstruction.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs new file mode 100644 index 0000000..7a10395 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/Instructions/XorMultipleRotateInstruction.cs @@ -0,0 +1,68 @@ +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/VirtualMachine.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs new file mode 100644 index 0000000..1ca1a59 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachine.cs @@ -0,0 +1,17 @@ +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/VirtualMachineCodeGenerator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs new file mode 100644 index 0000000..b05f000 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs @@ -0,0 +1,207 @@ +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/VirtualMachineCreator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs new file mode 100644 index 0000000..8035ad0 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineCreator.cs @@ -0,0 +1,71 @@ +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/VirtualMachineSimulator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs new file mode 100644 index 0000000..a8e25c8 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/EncryptionVM/VirtualMachineSimulator.cs @@ -0,0 +1,96 @@ +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/IObfuscationPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs new file mode 100644 index 0000000..16d875f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/IObfuscationPass.cs @@ -0,0 +1,20 @@ +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/ObfusPasses/BasicBlockObfuscationPassBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs new file mode 100644 index 0000000..916a9ef --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/BasicBlockObfuscationPassBase.cs @@ -0,0 +1,87 @@ +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/CallObfus/CallObfusPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs new file mode 100644 index 0000000..9b32359 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallObfusPass.cs @@ -0,0 +1,92 @@ +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/CallProxyAllocator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs new file mode 100644 index 0000000..da44d86 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs @@ -0,0 +1,293 @@ +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.Private); + 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/ConfigurableObfuscationPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs new file mode 100644 index 0000000..f336721 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/ConfigurableObfuscationPolicy.cs @@ -0,0 +1,372 @@ +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? obfuscateNone; + public List types = new List(); + } + + class WhiteListType + { + public string name; + public NameMatcher nameMatcher; + public bool? obfuscateNone; + public List methods = new List(); + } + + class WhiteListMethod + { + public string name; + public NameMatcher nameMatcher; + } + + 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); + } + + 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); + if (element.HasAttribute("obfuscateNone")) + { + ass.obfuscateNone = ConfigUtil.ParseBool(element.GetAttribute("obfuscateNone")); + } + 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); + if (element.HasAttribute("obfuscateNone")) + { + type.obfuscateNone = ConfigUtil.ParseBool(element.GetAttribute("obfuscateNone")); + } + + 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); + 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; + } + // 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; + } + if (ass.obfuscateNone == true) + { + return true; + } + foreach (var type in ass.types) + { + if (!type.nameMatcher.IsMatch(typeFullName)) + { + continue; + } + if (type.obfuscateNone == true) + { + return true; + } + foreach (var method in type.methods) + { + if (method.nameMatcher.IsMatch(methodName)) + { + return true; + } + } + } + } + return false; + } + + private bool IsInWhiteList(IMethod method) + { + if (!_whiteListMethodCache.TryGetValue(method, out var isWhiteList)) + { + isWhiteList = ComputeIsInWhiteList(method); + _whiteListMethodCache.Add(method, isWhiteList); + } + return isWhiteList; + } + + public override bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir, bool currentInLoop) + { + if (IsInWhiteList(calledMethod)) + { + 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/DefaultCallProxyObfuscator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs new file mode 100644 index 0000000..e171909 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs @@ -0,0 +1,53 @@ +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/IObfuscationPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs new file mode 100644 index 0000000..43c505f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscationPolicy.cs @@ -0,0 +1,34 @@ +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/IObfuscator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs new file mode 100644 index 0000000..4135b0d --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CallObfus/IObfuscator.cs @@ -0,0 +1,23 @@ +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/CleanUp/CleanUpInstructionPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs new file mode 100644 index 0000000..1a526eb --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/CleanUpInstructionPass.cs @@ -0,0 +1,46 @@ +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/RemoveObfuzAttributesPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs new file mode 100644 index 0000000..c9e72a9 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/CleanUp/RemoveObfuzAttributesPass.cs @@ -0,0 +1,70 @@ +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"); + } + + 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/ConstEncrypt/ConfigurableEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs new file mode 100644 index 0000000..3b3445c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConfigurableEncryptPolicy.cs @@ -0,0 +1,489 @@ +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/ConstEncryptPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs new file mode 100644 index 0000000..1356255 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs @@ -0,0 +1,166 @@ +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); + switch (inst.OpCode.OperandType) + { + case OperandType.InlineI: + case OperandType.InlineI8: + case OperandType.ShortInlineI: + case OperandType.ShortInlineR: + case OperandType.InlineR: + { + bool needCache = currentInLoop ? constCachePolicy.cacheConstInLoop : constCachePolicy.cacheConstNotInLoop; + object operand = inst.Operand; + if (operand is int) + { + int value = (int)operand; + if (_dataObfuscatorPolicy.NeedObfuscateInt(method, currentInLoop, value)) + { + _dataObfuscator.ObfuscateInt(method, needCache, value, outputInstructions); + return true; + } + } + else if (operand is sbyte) + { + int value = (sbyte)operand; + if (_dataObfuscatorPolicy.NeedObfuscateInt(method, currentInLoop, value)) + { + _dataObfuscator.ObfuscateInt(method, needCache, value, outputInstructions); + return true; + } + } + else if (operand is byte) + { + int value = (byte)operand; + if (_dataObfuscatorPolicy.NeedObfuscateInt(method, currentInLoop, value)) + { + _dataObfuscator.ObfuscateInt(method, needCache, value, outputInstructions); + return true; + } + } + else if (operand is long) + { + long value = (long)operand; + if (_dataObfuscatorPolicy.NeedObfuscateLong(method, currentInLoop, value)) + { + _dataObfuscator.ObfuscateLong(method, needCache, value, outputInstructions); + return true; + } + } + else if (operand is float) + { + float value = (float)operand; + if (_dataObfuscatorPolicy.NeedObfuscateFloat(method, currentInLoop, value)) + { + _dataObfuscator.ObfuscateFloat(method, needCache, value, outputInstructions); + return true; + } + } + else if (operand is double) + { + double value = (double)operand; + if (_dataObfuscatorPolicy.NeedObfuscateDouble(method, currentInLoop, value)) + { + _dataObfuscator.ObfuscateDouble(method, needCache, value, outputInstructions); + return true; + } + } + return false; + } + case OperandType.InlineString: + { + //RuntimeHelpers.InitializeArray + string value = (string)inst.Operand; + if (_dataObfuscatorPolicy.NeedObfuscateString(method, currentInLoop, value)) + { + bool needCache = currentInLoop ? constCachePolicy.cacheStringInLoop : constCachePolicy.cacheStringNotInLoop; + _dataObfuscator.ObfuscateString(method, needCache, value, outputInstructions); + return true; + } + return false; + } + case OperandType.InlineMethod: + { + //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/DefaultConstEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs new file mode 100644 index 0000000..52d686a --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs @@ -0,0 +1,204 @@ +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.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 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/IConstEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs new file mode 100644 index 0000000..7043aec --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IConstEncryptor.cs @@ -0,0 +1,32 @@ +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/IEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs new file mode 100644 index 0000000..1db7f0e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ConstEncrypt/IEncryptPolicy.cs @@ -0,0 +1,48 @@ +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/ExprObfus/ExprObfusPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs new file mode 100644 index 0000000..468bfce --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ExprObfus/ExprObfusPass.cs @@ -0,0 +1,35 @@ +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/FieldEncrypt/ConfigurableEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs new file mode 100644 index 0000000..9f09832 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/ConfigurableEncryptPolicy.cs @@ -0,0 +1,36 @@ +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) + { + var rule = _configParser.GetFieldRule(field); + return rule != null; + } + } +} 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 new file mode 100644 index 0000000..05c9c63 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs @@ -0,0 +1,182 @@ +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/FieldEncryptPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs new file mode 100644 index 0000000..054044e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs @@ -0,0 +1,108 @@ +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/IEncryptPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs new file mode 100644 index 0000000..a1a7705 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IEncryptPolicy.cs @@ -0,0 +1,19 @@ +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/IFieldEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs new file mode 100644 index 0000000..7c9f7c3 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/FieldEncrypt/IFieldEncryptor.cs @@ -0,0 +1,29 @@ +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/InstructionObfuscationPassBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs new file mode 100644 index 0000000..4028c41 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/InstructionObfuscationPassBase.cs @@ -0,0 +1,85 @@ +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/ObfuscationPassBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs new file mode 100644 index 0000000..b3aaf0c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassBase.cs @@ -0,0 +1,20 @@ +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/ObfuscationPassType.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs new file mode 100644 index 0000000..ec28ad3 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/ObfuscationPassType.cs @@ -0,0 +1,25 @@ +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/SymbolObfus/INameMaker.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs new file mode 100644 index 0000000..4028edc --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/INameMaker.cs @@ -0,0 +1,35 @@ +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(ParamDef paramDef, 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/IObfuscationPolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs new file mode 100644 index 0000000..34f9e99 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/IObfuscationPolicy.cs @@ -0,0 +1,19 @@ +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); + + bool NeedRename(ParamDef paramDef); + } +} 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 new file mode 100644 index 0000000..b7b4e3f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/DebugNameMaker.cs @@ -0,0 +1,29 @@ +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/INameScope.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs new file mode 100644 index 0000000..9fb5a98 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/INameScope.cs @@ -0,0 +1,9 @@ +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/NameMakerBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs new file mode 100644 index 0000000..a103757 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerBase.cs @@ -0,0 +1,108 @@ +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(ParamDef paramDef, string 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 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/NameMakerFactory.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs new file mode 100644 index 0000000..b0ba913 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameMakerFactory.cs @@ -0,0 +1,28 @@ +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/NameScope.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs new file mode 100644 index 0000000..610f845 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScope.cs @@ -0,0 +1,35 @@ +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/NameScopeBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs new file mode 100644 index 0000000..4f3d213 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/NameScopeBase.cs @@ -0,0 +1,57 @@ +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/WordSetNameMaker.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs new file mode 100644 index 0000000..8e8b5db --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/NameMakers/WordSetNameMaker.cs @@ -0,0 +1,26 @@ +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/Policies/CacheRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs new file mode 100644 index 0000000..937ff66 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CacheRenamePolicy.cs @@ -0,0 +1,78 @@ +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; + } + + public override bool NeedRename(ParamDef paramDef) + { + if (!_computeCache.TryGetValue(paramDef, out var value)) + { + value = _underlyingPolicy.NeedRename(paramDef); + _computeCache[paramDef] = value; + } + return value; + } + } +} 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 new file mode 100644 index 0000000..53ca0c9 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/CombineRenamePolicy.cs @@ -0,0 +1,45 @@ +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)); + } + + public bool NeedRename(ParamDef paramDef) + { + return _policies.All(policy => policy.NeedRename(paramDef)); + } + } +} 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 new file mode 100644 index 0000000..101f0db --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ConfigurableRenamePolicy.cs @@ -0,0 +1,895 @@ +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 System.Xml.Linq; +using UnityEngine; + +namespace Obfuz.ObfusPasses.SymbolObfus.Policies +{ + + public class ConfigurableRenamePolicy : ObfuscationPolicyBase + { + enum ObfuscationType + { + Name = 1, + Namespace = 2, + NestType = 3, + Method = 4, + Field = 5, + Property = 6, + Event = 7, + Param = 8, + MethodBody = 9, + Getter = 10, + Setter = 11, + Add = 12, + Remove = 13, + Fire = 14, + } + + enum RuleType + { + Assembly = 1, + Type = 2, + Method = 3, + Field = 4, + Property = 5, + Event = 6, + } + + enum ModifierType + { + Private = 0, + Protected = 1, + Public = 2, + } + + interface IRule + { + + } + + class MethodRuleSpec + { + public NameMatcher nameMatcher; + public ModifierType modifierType; + public MethodRule rule; + } + + class MethodRule : IRule + { + public string ruleName; + public bool obfuscateName; + public bool obfuscateParam; + public bool obfuscateBody; + } + + class FieldRuleSpec + { + public NameMatcher nameMatcher; + public ModifierType modifierType; + public FieldRule rule; + } + + class FieldRule : IRule + { + public string ruleName; + public bool obfuscateName; + } + + class PropertyRuleSpec + { + public NameMatcher nameMatcher; + public PropertyRule rule; + } + + class PropertyRule : IRule + { + public string ruleName; + public bool obfuscateName; + public MethodRuleSpec getter; + public MethodRuleSpec setter; + } + + class EventRuleSpec + { + public NameMatcher nameMatcher; + public EventRule rule; + } + + class EventRule : IRule + { + public string ruleName; + public bool obfuscateName; + public MethodRuleSpec add; + public MethodRuleSpec remove; + public MethodRuleSpec fire; + } + + class TypeRuleSpec + { + public NameMatcher nameMatcher; + public ModifierType modifierType; + public TypeRule rule; + } + + class TypeRule : IRule + { + public string ruleName; + + public bool obfuscateName; + public bool obfuscateNamespace; + + //public List nestTypeRuleSpecs; + public List fieldRuleSpecs; + public List methodRuleSpecs; + public List propertyRuleSpecs; + public List eventRuleSpecs; + } + + class AssemblyRule : IRule + { + public string ruleName; + + public bool obfuscateName; + + public List typeRuleSpecs; + } + + class AssemblyRuleSpec + { + public string assemblyName; + public AssemblyRule rule; + } + + //class DefaultRule : IRule + //{ + + //} + + //private readonly static IRule _defaultRule = new DefaultRule(); + //private readonly static IRule _noneRule = new DefaultRule(); + + private readonly Dictionary<(string, RuleType), IRule> _rules = new Dictionary<(string, RuleType), IRule>(); + + private readonly Dictionary<(string, RuleType), XmlElement> _rawRuleElements = new Dictionary<(string, RuleType), XmlElement>(); + + private readonly Dictionary _assemblyRuleSpecs = new Dictionary(); + + + private static readonly MethodRule s_noneMethodRule = new MethodRule + { + ruleName = "none", + obfuscateName = false, + obfuscateParam = false, + obfuscateBody = false, + }; + + private static readonly EventRule s_noneEventRule = new EventRule + { + ruleName = "none", + obfuscateName = false, + add = new MethodRuleSpec { rule = s_noneMethodRule}, + remove = new MethodRuleSpec { rule = s_noneMethodRule }, + fire = new MethodRuleSpec { rule = s_noneMethodRule }, + }; + + private static readonly PropertyRule s_nonePropertyRule = new PropertyRule + { + ruleName = "none", + obfuscateName = false, + getter = new MethodRuleSpec { rule = s_noneMethodRule }, + setter = new MethodRuleSpec { rule = s_noneMethodRule }, + }; + + private static readonly FieldRule s_noneFieldRule = new FieldRule + { + ruleName = "none", + obfuscateName = false, + }; + + private static readonly TypeRule s_noneTypeRule = new TypeRule + { + ruleName = "none", + obfuscateName = false, + obfuscateNamespace = false, + //nestTypeRuleSpecs = new List(), + fieldRuleSpecs = new List { new FieldRuleSpec { rule = s_noneFieldRule} }, + methodRuleSpecs = new List { new MethodRuleSpec { rule = s_noneMethodRule} }, + propertyRuleSpecs = new List { new PropertyRuleSpec { rule = s_nonePropertyRule} }, + eventRuleSpecs = new List { new EventRuleSpec { rule = s_noneEventRule} }, + }; + + private static readonly AssemblyRule s_noneAssemblyRule = new AssemblyRule + { + ruleName = "none", + obfuscateName = false, + typeRuleSpecs = new List { new TypeRuleSpec { rule = s_noneTypeRule } }, + }; + + //static ObfuscateRuleConfig() + //{ + // s_noneTypeRule.nestTypeRuleSpecs.Add(new TypeRuleSpec + // { + // rule = s_noneTypeRule, + // }); + //} + + private IRule GetOrParseRule(string ruleName, RuleType ruleType, XmlElement ele) + { + IRule rule = null; + XmlElement element; + if (!string.IsNullOrEmpty(ruleName)) + { + if (ruleName == "none") + { + switch (ruleType) + { + case RuleType.Assembly: return s_noneAssemblyRule; + case RuleType.Type: return s_noneTypeRule; + case RuleType.Method: return s_noneMethodRule; + case RuleType.Field: return s_noneFieldRule; + case RuleType.Property: return s_nonePropertyRule; + case RuleType.Event: return s_noneEventRule; + default: throw new Exception($"Invalid rule type {ruleType}"); + } + } + if (_rules.TryGetValue((ruleName, ruleType), out rule)) + { + return rule; + } + if (!_rawRuleElements.TryGetValue((ruleName, ruleType), out element)) + { + throw new Exception($"Invalid xml file, rule {ruleName} type {ruleType} not found"); + } + } + else + { + element = ele; + } + switch (ruleType) + { + case RuleType.Assembly: + rule = ParseAssemblyRule(ruleName, element); + break; + case RuleType.Type: + rule = ParseTypeRule(ruleName, element); + break; + case RuleType.Method: + rule = ParseMethodRule(ruleName, element); + break; + case RuleType.Field: + rule = ParseFieldRule(ruleName, element); + break; + case RuleType.Property: + rule = ParsePropertyRule(ruleName, element); + break; + case RuleType.Event: + rule = ParseEventRule(ruleName, element); + break; + default: + throw new Exception($"Invalid rule type {ruleType}"); + } + if (!string.IsNullOrEmpty(ruleName)) + { + _rules.Add((ruleName, ruleType), rule); + } + return rule; + } + + private static bool ParseBoolNoneOrFalse(string str) + { + if (string.IsNullOrEmpty(str)) + { + return true; + } + switch (str.ToLowerInvariant()) + { + case "1": + case "true": throw new Exception($"Invalid bool value '{str}', only accept '0' or 'false' because default is true"); // true is default + case "0": + case "false": return false; + default: throw new Exception($"Invalid bool value {str}"); + } + } + + private AssemblyRule ParseAssemblyRule(string ruleName, XmlElement element) + { + var rule = new AssemblyRule(); + rule.ruleName = ruleName; + rule.obfuscateName = ParseBoolNoneOrFalse(element.GetAttribute("ob-name")); + rule.typeRuleSpecs = new List(); + foreach (XmlNode node in element.ChildNodes) + { + if (!(node is XmlElement childElement)) + { + continue; + } + if (childElement.Name != "type") + { + throw new Exception($"Invalid xml file, unknown node {childElement.Name}"); + } + var typeRuleSpec = new TypeRuleSpec(); + typeRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); + typeRuleSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); + typeRuleSpec.rule = (TypeRule)GetOrParseRule(childElement.GetAttribute("rule"), RuleType.Type, childElement); + rule.typeRuleSpecs.Add(typeRuleSpec); + } + return rule; + } + + private TypeRule ParseTypeRule(string ruleName, XmlElement element) + { + var rule = new TypeRule(); + rule.ruleName = ruleName; + rule.obfuscateName = ParseBoolNoneOrFalse(element.GetAttribute("ob-name")); + rule.obfuscateNamespace = ParseBoolNoneOrFalse(element.GetAttribute("ob-namespace")); + //rule.nestTypeRuleSpecs = new List(); + rule.fieldRuleSpecs = new List(); + rule.methodRuleSpecs = new List(); + rule.propertyRuleSpecs = new List(); + rule.eventRuleSpecs = new List(); + foreach (XmlNode node in element.ChildNodes) + { + if (!(node is XmlElement childElement)) + { + continue; + } + switch (childElement.Name) + { + //case "nesttype": + //{ + // var typeRuleSpec = new TypeRuleSpec(); + // typeRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); + // typeRuleSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); + // typeRuleSpec.rule = (TypeRule)GetOrParseRule(childElement.GetAttribute("rule"), RuleType.Type, childElement); + // rule.nestTypeRuleSpecs.Add(typeRuleSpec); + // break; + //} + case "field": + { + var fieldRuleSpec = new FieldRuleSpec(); + fieldRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); + fieldRuleSpec.modifierType = ParseModifierType(childElement.GetAttribute("modifier")); + fieldRuleSpec.rule = (FieldRule)GetOrParseRule(childElement.GetAttribute("rule"), RuleType.Field, childElement); + rule.fieldRuleSpecs.Add(fieldRuleSpec); + break; + } + case "method": + { + rule.methodRuleSpecs.Add(ParseMethodRuleSpec(childElement)); + break; + } + case "property": + { + var propertyRulerSpec = new PropertyRuleSpec(); + propertyRulerSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); + propertyRulerSpec.rule = (PropertyRule)GetOrParseRule(childElement.GetAttribute("rule"), RuleType.Property, childElement); + rule.propertyRuleSpecs.Add(propertyRulerSpec); + break; + } + case "event": + { + var eventRuleSpec = new EventRuleSpec(); + eventRuleSpec.nameMatcher = new NameMatcher(childElement.GetAttribute("name")); + eventRuleSpec.rule = (EventRule)GetOrParseRule(childElement.GetAttribute("rule"), RuleType.Event, childElement); + rule.eventRuleSpecs.Add(eventRuleSpec); + break; + } + default: throw new Exception($"Invalid xml file, unknown node {childElement.Name} in type rule {ruleName}"); + } + } + return rule; + } + + private MethodRuleSpec ParseMethodRuleSpec(XmlElement el) + { + var methodRuleSpec = new MethodRuleSpec(); + methodRuleSpec.nameMatcher = new NameMatcher(el.GetAttribute("name")); + methodRuleSpec.modifierType = ParseModifierType(el.GetAttribute("modifier")); + methodRuleSpec.rule = (MethodRule)GetOrParseRule(el.GetAttribute("rule"), RuleType.Method, el); + return methodRuleSpec; + } + + private MethodRule ParseMethodRule(string ruleName, XmlElement element) + { + var rule = new MethodRule(); + rule.ruleName = ruleName; + rule.obfuscateName = ParseBoolNoneOrFalse(element.GetAttribute("ob-name")); + rule.obfuscateParam = ParseBoolNoneOrFalse(element.GetAttribute("ob-param")); + rule.obfuscateBody = ParseBoolNoneOrFalse(element.GetAttribute("ob-body")); + return rule; + } + + private FieldRule ParseFieldRule(string ruleName, XmlElement element) + { + var rule = new FieldRule(); + rule.ruleName = ruleName; + rule.obfuscateName = ParseBoolNoneOrFalse(element.GetAttribute("ob-name")); + return rule; + } + + private PropertyRule ParsePropertyRule(string ruleName, XmlElement element) + { + var rule = new PropertyRule(); + rule.ruleName = ruleName; + rule.obfuscateName = ParseBoolNoneOrFalse(element.GetAttribute("ob-name")); + + foreach (XmlNode node in element.ChildNodes) + { + if (!(node is XmlElement childElement)) + { + continue; + } + switch (node.Name) + { + case "getter": + { + if (rule.getter != null) + { + throw new Exception($"Invalid xml file, duplicate getter rule in property rule {ruleName}"); + } + rule.getter = ParseMethodRuleSpec(childElement); + break; + } + case "setter": + { + if (rule.setter != null) + { + throw new Exception($"Invalid xml file, duplicate setter rule in property rule {ruleName}"); + } + rule.setter = ParseMethodRuleSpec(childElement); + break; + } + default: throw new Exception($"Invalid xml file, unknown node {childElement.Name} in property rule {ruleName}"); + } + } + return rule; + } + + private EventRule ParseEventRule(string ruleName, XmlElement element) + { + var rule = new EventRule(); + rule.ruleName = ruleName; + rule.obfuscateName = ParseBoolNoneOrFalse(element.GetAttribute("ob-name")); + + foreach (XmlNode node in element.ChildNodes) + { + if (!(node is XmlElement childElement)) + { + continue; + } + switch (node.Name) + { + case "add": + { + if (rule.add != null) + { + throw new Exception($"Invalid xml file, duplicate getter rule in property rule {ruleName}"); + } + rule.add = ParseMethodRuleSpec(childElement); + break; + } + case "remove": + { + if (rule.remove != null) + { + throw new Exception($"Invalid xml file, duplicate setter rule in property rule {ruleName}"); + } + rule.remove = ParseMethodRuleSpec(childElement); + break; + } + case "fire": + { + if (rule.fire != null) + { + throw new Exception($"Invalid xml file, duplicate fire rule in property rule {ruleName}"); + } + rule.fire = ParseMethodRuleSpec(childElement); + break; + } + default: throw new Exception($"Invalid xml file, unknown node {childElement.Name} in event rule {ruleName}"); + } + } + + 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) + { + 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 assemblyRule = new AssemblyRuleSpec() + { + assemblyName = assemblyName, + rule = (AssemblyRule)GetOrParseRule(ele.GetAttribute("rule"), RuleType.Assembly, ele), + }; + _assemblyRuleSpecs.Add(assemblyName, assemblyRule); + } + } + + + private RuleType ParseRuleType(string ruleType) + { + switch (ruleType) + { + case "assembly": return RuleType.Assembly; + case "type": return RuleType.Type; + case "method": return RuleType.Method; + case "field": return RuleType.Field; + case "property": return RuleType.Property; + case "event": return RuleType.Event; + default: throw new Exception($"Invalid rule type {ruleType}"); + } + } + + private ModifierType ParseModifierType(string modifierType) + { + if (string.IsNullOrEmpty(modifierType)) + { + return ModifierType.Private; + } + switch (modifierType) + { + case "public": return ModifierType.Public; + case "protected": return ModifierType.Protected; + case "private": return ModifierType.Private; + default: throw new Exception($"Invalid modifier type {modifierType}"); + } + } + + private void LoadRawXml(string xmlFile, List rawAssemblyElements) + { + Debug.Log($"ObfuscateRule::LoadXml {xmlFile}"); + var doc = new XmlDocument(); + //var nsManager = new XmlNamespaceManager(doc.NameTable); + //nsManager.AddNamespace("ob", "https://github.com/focus-creative-games/Obfuz"); // 绑定前缀到 URI + 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 "rules": + { + ParseRules(xmlFile, element); + break; + } + case "assembly": + { + rawAssemblyElements.Add(element); + break; + } + default: + { + throw new Exception($"Invalid xml file {xmlFile}, unknown node {element.Name}"); + } + } + } + } + + void ParseRules(string xmlFile, XmlElement rulesNode) + { + foreach (XmlNode node in rulesNode) + { + if (!(node is XmlElement ruleEle)) + { + continue; + } + string ruleName = ruleEle.GetAttribute("name"); + string ruleTypeName = ruleEle.Name; + RuleType ruleType = ParseRuleType(ruleTypeName); + var key = (ruleName, ruleType); + if (_rawRuleElements.ContainsKey(key)) + { + throw new Exception($"Invalid xml file {xmlFile}, duplicate rule name:{ruleName} type:{ruleType}"); + } + _rawRuleElements.Add(key, ruleEle); + } + + } + + 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 <= ComputeModifierType(typeDef.Visibility); + } + + private bool MatchModifier(ModifierType modifierType, FieldDef fieldDef) + { + return modifierType <= ComputeModifierType(fieldDef.Access); + } + + private bool MatchModifier(ModifierType modifierType, MethodDef methodDef) + { + return modifierType <= ComputeModifierType((FieldAttributes)methodDef.Access); + } + + //private bool MatchModifier(ModifierType modifierType, PropertyDef propertyDef) + //{ + // return modifierType <= ComputeModifierType((FieldAttributes)propertyDef.Attributes); + //} + + 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 _typeRenameCache = new Dictionary(); + + private readonly HashSet _obfuscationAssemblyNames; + + public ConfigurableRenamePolicy(List obfuscationAssemblyNames, List xmlFiles) + { + _obfuscationAssemblyNames = new HashSet(obfuscationAssemblyNames); + LoadXmls(xmlFiles); + } + + private TypeDefComputeCache GetOrCreateTypeDefRenameComputeCache(TypeDef typeDef) + { + if (_typeRenameCache.TryGetValue(typeDef, out var cache)) + { + return cache; + } + cache = new TypeDefComputeCache(); + _typeRenameCache.Add(typeDef, cache); + + if (!_assemblyRuleSpecs.TryGetValue(typeDef.Module.Assembly.Name, out var assemblyRuleSpec) || assemblyRuleSpec.rule == null) + { + return cache; + } + string typeName = typeDef.FullName; + var totalMethodSpecs = new List(); + var totalMethodSpecFromPropertyAndEvents = new List<(MethodDef, MethodRuleSpec)>(); + foreach (var typeRule in assemblyRuleSpec.rule.typeRuleSpecs) + { + if ((typeRule.nameMatcher != null && !typeRule.nameMatcher.IsMatch(typeName)) || !MatchModifier(typeRule.modifierType, typeDef)) + { + continue; + } + cache.obfuscateNamespace &= typeRule.rule.obfuscateNamespace; + cache.obfuscateName &= typeRule.rule.obfuscateName; + + totalMethodSpecs.AddRange(typeRule.rule.methodRuleSpecs); + + foreach (var eventDef in typeDef.Events) + { + foreach (var eventSpec in typeRule.rule.eventRuleSpecs) + { + if (eventSpec.nameMatcher != null && !eventSpec.nameMatcher.IsMatch(eventDef.Name)) + { + continue; + } + EventRule eventRule = eventSpec.rule; + if (!eventRule.obfuscateName) + { + cache.notObfuscatedEvents.Add(eventDef); + } + if (eventDef.AddMethod != null && eventRule.add != null && MatchModifier(eventRule.add.modifierType, eventDef.AddMethod)) + { + totalMethodSpecFromPropertyAndEvents.Add((eventDef.AddMethod,eventRule.add)); + } + if (eventDef.RemoveMethod != null && eventRule.remove != null && MatchModifier(eventRule.remove.modifierType, eventDef.RemoveMethod)) + { + totalMethodSpecFromPropertyAndEvents.Add((eventDef.RemoveMethod, eventRule.remove)); + } + if (eventDef.InvokeMethod != null && eventRule.fire != null && MatchModifier(eventRule.fire.modifierType, eventDef.InvokeMethod)) + { + totalMethodSpecFromPropertyAndEvents.Add((eventDef.InvokeMethod, eventRule.fire)); + } + } + } + foreach (var propertyDef in typeDef.Properties) + { + foreach (var propertySpec in typeRule.rule.propertyRuleSpecs) + { + if (propertySpec.nameMatcher != null && !propertySpec.nameMatcher.IsMatch(propertyDef.Name)) + { + continue; + } + PropertyRule propertyRule = propertySpec.rule; + if (!propertyRule.obfuscateName) + { + cache.notObfuscatedProperties.Add(propertyDef); + } + if (propertyDef.GetMethod != null && propertyRule.getter != null && MatchModifier(propertyRule.getter.modifierType, propertyDef.GetMethod)) + { + totalMethodSpecFromPropertyAndEvents.Add((propertyDef.GetMethod, propertyRule.getter)); + } + if (propertyDef.SetMethod != null && propertyRule.setter != null && MatchModifier(propertyRule.setter.modifierType, propertyDef.SetMethod)) + { + totalMethodSpecFromPropertyAndEvents.Add((propertyDef.SetMethod, propertyRule.setter)); + } + } + } + + foreach (var fieldDef in typeDef.Fields) + { + foreach (var fieldRule in typeRule.rule.fieldRuleSpecs) + { + if ((fieldRule.nameMatcher == null || fieldRule.nameMatcher.IsMatch(fieldDef.Name)) && MatchModifier(fieldRule.modifierType, fieldDef) && !fieldRule.rule.obfuscateName) + { + cache.notObfuscatedFields.Add(fieldDef); + } + } + } + foreach (MethodDef methodDef in typeDef.Methods) + { + foreach (var e in totalMethodSpecFromPropertyAndEvents) + { + if (e.Item1 != methodDef) + { + continue; + } + if (!cache.methods.TryGetValue(methodDef, out var methodCache)) + { + methodCache = new MethodComputeCache(); + cache.methods.Add(methodDef, methodCache); + } + MethodRule methodRule = e.Item2.rule; + methodCache.obfuscateName &= methodRule.obfuscateName; + methodCache.obfuscateParam &= methodRule.obfuscateParam; + methodCache.obfuscateBody &= methodRule.obfuscateBody; + } + foreach (MethodRuleSpec methodSpec in totalMethodSpecs) + { + if ((methodSpec.nameMatcher != null && !methodSpec.nameMatcher.IsMatch(methodDef.Name)) || !MatchModifier(methodSpec.modifierType, methodDef)) + { + continue; + } + if (!cache.methods.TryGetValue(methodDef, out var methodCache)) + { + methodCache = new MethodComputeCache(); + cache.methods.Add(methodDef, methodCache); + } + MethodRule methodRule = methodSpec.rule; + methodCache.obfuscateName &= methodRule.obfuscateName; + methodCache.obfuscateParam &= methodRule.obfuscateParam; + methodCache.obfuscateBody &= methodRule.obfuscateBody; + } + } + } + return cache; + } + + public override bool NeedRename(TypeDef typeDef) + { + TypeDefComputeCache cache = GetOrCreateTypeDefRenameComputeCache(typeDef); + return cache.obfuscateName; + } + + public override bool NeedRename(MethodDef methodDef) + { + TypeDef typeDef = methodDef.DeclaringType; + TypeDefComputeCache cache = GetOrCreateTypeDefRenameComputeCache(typeDef); + if (!cache.methods.TryGetValue(methodDef, out var methodCache)) + { + return true; + } + return methodCache.obfuscateName; + } + + public override bool NeedRename(FieldDef fieldDef) + { + TypeDef typeDef = fieldDef.DeclaringType; + TypeDefComputeCache cache = GetOrCreateTypeDefRenameComputeCache(typeDef); + return !cache.notObfuscatedFields.Contains(fieldDef); + } + + public override bool NeedRename(PropertyDef propertyDef) + { + TypeDef typeDef = propertyDef.DeclaringType; + TypeDefComputeCache cache = GetOrCreateTypeDefRenameComputeCache(typeDef); + return !cache.notObfuscatedProperties.Contains(propertyDef); + } + + public override bool NeedRename(EventDef eventDef) + { + TypeDef typeDef = eventDef.DeclaringType; + TypeDefComputeCache cache = GetOrCreateTypeDefRenameComputeCache(typeDef); + return !cache.notObfuscatedEvents.Contains(eventDef); + } + + public override bool NeedRename(ParamDef paramDef) + { + MethodDef methodDef = paramDef.DeclaringMethod; + TypeDef typeDef = methodDef.DeclaringType; + TypeDefComputeCache cache = GetOrCreateTypeDefRenameComputeCache(typeDef); + if (!cache.methods.TryGetValue(methodDef, out var methodCache)) + { + return true; + } + return methodCache.obfuscateParam; + } + } +} 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 new file mode 100644 index 0000000..96cfcce --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/ObfuscationPolicyBase.cs @@ -0,0 +1,38 @@ +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; + } + + public virtual bool NeedRename(ParamDef paramDef) + { + return true; + } + } +} 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 new file mode 100644 index 0000000..1d0cb6b --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SupportPassPolicy.cs @@ -0,0 +1,50 @@ +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/SystemRenamePolicy.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs new file mode 100644 index 0000000..bda6302 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/SystemRenamePolicy.cs @@ -0,0 +1,67 @@ +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.HasObfuzIgnoreAttribute(typeDef)) + { + return false; + } + return true; + } + + public override bool NeedRename(MethodDef methodDef) + { + if (methodDef.Name == ".ctor" || methodDef.Name == ".cctor") + { + return false; + } + + if (MetaUtil.HasObfuzIgnoreAttribute(methodDef) || MetaUtil.HasObfuzIgnoreAttribute(methodDef.DeclaringType)) + { + return false; + } + return true; + } + + public override bool NeedRename(FieldDef fieldDef) + { + if (MetaUtil.HasObfuzIgnoreAttribute(fieldDef) || MetaUtil.HasObfuzIgnoreAttribute(fieldDef.DeclaringType)) + { + return false; + } + if (fieldDef.DeclaringType.IsEnum && fieldDef.Name == "value__") + { + return false; + } + return true; + } + + public override bool NeedRename(PropertyDef propertyDef) + { + if (MetaUtil.HasObfuzIgnoreAttribute(propertyDef) || MetaUtil.HasObfuzIgnoreAttribute(propertyDef.DeclaringType)) + { + return false; + } + return true; + } + + public override bool NeedRename(EventDef eventDef) + { + if (MetaUtil.HasObfuzIgnoreAttribute(eventDef) || MetaUtil.HasObfuzIgnoreAttribute(eventDef.DeclaringType)) + { + return false; + } + return true; + } + } +} 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 new file mode 100644 index 0000000..9878973 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/Policies/UnityRenamePolicy.cs @@ -0,0 +1,97 @@ +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/RenameRecordMap.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs new file mode 100644 index 0000000..de5b13e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/RenameRecordMap.cs @@ -0,0 +1,739 @@ +using dnlib.DotNet; +using Obfuz.Utils; +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; + + public List parameters = new List(); + } + + 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, + }; + foreach (XmlNode node in ele.ChildNodes) + { + if (!(node is XmlElement c)) + { + continue; + } + switch (node.Name) + { + case "param": LoadMethodParamMapping(c, rmm); break; + default: throw new System.Exception($"unknown node name:{node.Name}, expect 'param'"); + } + } + type.methods.Add(signature, rmm); + } + + private void LoadMethodParamMapping(XmlElement ele, RenameMappingMethod method) + { + string index = ele.Attributes["index"].Value; + string newName = ele.Attributes["newName"].Value; + var rmp = new RenameMappingMethodParam + { + index = int.Parse(index), + newName = newName, + status = RenameStatus.Renamed, + }; + method.parameters.Add(rmp); + } + + 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); + } + + public void WriteXmlMappingFile() + { + if (string.IsNullOrEmpty(_mappingFile)) + { + return; + } + var doc = new XmlDocument(); + var root = doc.CreateElement("mapping"); + doc.AppendChild(root); + foreach (var kvp in _modRenames) + { + 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); + } + foreach (RenameMappingAssembly ass in _assemblies.Values) + { + if (_modRenames.Keys.Any(m => m.Assembly.Name == ass.assName)) + { + continue; + } + var assemblyNode = doc.CreateElement("assembly"); + assemblyNode.SetAttribute("name", ass.assName); + foreach (var e in ass.types) + { + WriteTypeMapping(assemblyNode, e.Key, e.Value); + } + 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); + //methodNode.SetAttribute("status", record != null ? record.status.ToString() : RenameStatus.NotRenamed.ToString()); + foreach (RenameMappingMethodParam param in method.parameters) + { + WriteMethodParamMapping(methodNode, param); + } + 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); + } + + private void WriteMethodParamMapping(XmlElement methodEle, RenameMappingMethodParam param) + { + var paramNode = methodEle.OwnerDocument.CreateElement("param"); + paramNode.SetAttribute("index", param.index.ToString()); + paramNode.SetAttribute("newName", param.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 AddRename(ParamDef paramDef, string newName) + { + RenameRecord record = _paramRenames[paramDef]; + 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/SymbolObfusPass.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs new file mode 100644 index 0000000..2501f1d --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolObfusPass.cs @@ -0,0 +1,36 @@ +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/SymbolRename.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs new file mode 100644 index 0000000..d7f8525 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/SymbolRename.cs @@ -0,0 +1,774 @@ +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 + { + class AssemblyReferenceInfo + { + public string name; + + public bool needObfuscated; + + public ModuleDef module; + + public List referenceMeAssemblies; + } + + 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) + { + if (_renamePolicy.NeedRename(param)) + { + string newName = _nameMaker.GetNewName(param, param.Name); + _renameRecordMap.AddRename(param, newName); + 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/VirtualMethodGroupCalculator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs new file mode 100644 index 0000000..03cb1b3 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfusPasses/SymbolObfus/VirtualMethodGroupCalculator.cs @@ -0,0 +1,100 @@ +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/ObfuscationMethodWhitelist.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs new file mode 100644 index 0000000..f07b22a --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationMethodWhitelist.cs @@ -0,0 +1,71 @@ +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) || MetaUtil.HasCompilerGeneratedAttribute(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 (ShouldBeIgnoredByCustomAttribute(type)) + { + return true; + } + if (type.FullName == "Obfuz.EncryptionVM.GeneratedEncryptionVirtualMachine") + { + return true; + } + return false; + } + } +} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs new file mode 100644 index 0000000..f4b5c74 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscationPassContext.cs @@ -0,0 +1,83 @@ +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/Obfuscator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs new file mode 100644 index 0000000..e79f62c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuscator.cs @@ -0,0 +1,337 @@ +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() + { + FileUtil.RecreateDir(_obfuscatedAssemblyOutputPath); + RunPipeline(_pipeline1); + _assemblySearchPaths.Insert(0, _obfuscatedAssemblyOutputPath); + RunPipeline(_pipeline2); + } + + 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/ObfuscatorBuilder.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs new file mode 100644 index 0000000..3a3943c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/ObfuscatorBuilder.cs @@ -0,0 +1,216 @@ +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/Obfuz.Editor.asmdef b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef new file mode 100644 index 0000000..e1b3933 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Obfuz.Editor.asmdef @@ -0,0 +1,18 @@ +{ + "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/Pipeline.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs new file mode 100644 index 0000000..9e92d46 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Pipeline.cs @@ -0,0 +1,43 @@ +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/Settings/AssemblySettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs new file mode 100644 index 0000000..ec4898d --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/AssemblySettings.cs @@ -0,0 +1,27 @@ +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/CallObfuscationSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs new file mode 100644 index 0000000..3ea3a1f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/CallObfuscationSettings.cs @@ -0,0 +1,20 @@ +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/ConstEncryptionSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs new file mode 100644 index 0000000..794d685 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ConstEncryptionSettings.cs @@ -0,0 +1,20 @@ +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/EncryptionVMSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs new file mode 100644 index 0000000..04a7a22 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/EncryptionVMSettings.cs @@ -0,0 +1,23 @@ +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/FieldEncryptionSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs new file mode 100644 index 0000000..0b41afe --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/FieldEncryptionSettings.cs @@ -0,0 +1,20 @@ +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/ObfuscationPassSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs new file mode 100644 index 0000000..837c8b0 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuscationPassSettings.cs @@ -0,0 +1,16 @@ +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/ObfuzSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs new file mode 100644 index 0000000..d79ebe2 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettings.cs @@ -0,0 +1,94 @@ +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)}"); + + s_Instance = arr != null && arr.Length > 0 ? (ObfuzSettings)arr[0] : (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/ObfuzSettingsProvider.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs new file mode 100644 index 0000000..3a5c9e2 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/ObfuzSettingsProvider.cs @@ -0,0 +1,104 @@ +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/SecretSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs new file mode 100644 index 0000000..1a53d7e --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SecretSettings.cs @@ -0,0 +1,30 @@ +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, "defaultStaticSecret.bytes"); + + public string DefaultDynamicSecretKeyOutputPath => Path.Combine(secretKeyOutputPath, "defaultDynamicSecret.bytes"); + } +} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs new file mode 100644 index 0000000..6e1d765 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Settings/SymbolObfuscationSettings.cs @@ -0,0 +1,27 @@ +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/Unity/ObfuscationBeginEventArgs.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs new file mode 100644 index 0000000..b8f2397 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationBeginEventArgs.cs @@ -0,0 +1,8 @@ +namespace Obfuz.Unity +{ + public class ObfuscationBeginEventArgs + { + public string scriptAssembliesPath; + public string obfuscatedScriptAssembliesPath; + } +} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs new file mode 100644 index 0000000..ac2fa76 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationEndEventArgs.cs @@ -0,0 +1,9 @@ +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/ObfuscationProcess.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs new file mode 100644 index 0000000..0ff9f4b --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuscationProcess.cs @@ -0,0 +1,124 @@ +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); + string dstFile = Path.Combine(dstDir, dllName); + 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/ObfuzMenu.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs new file mode 100644 index 0000000..dcfc409 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Unity/ObfuzMenu.cs @@ -0,0 +1,63 @@ +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/GenerateVM", 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/SaveSecretFile", 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}"); + } + + 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/Utils/AssemblyCache.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs new file mode 100644 index 0000000..ecaa587 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyCache.cs @@ -0,0 +1,91 @@ +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/AssemblyResolverBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs new file mode 100644 index 0000000..7eb9491 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/AssemblyResolverBase.cs @@ -0,0 +1,13 @@ +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/CollectionExtensions.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs new file mode 100644 index 0000000..f7165ab --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/CollectionExtensions.cs @@ -0,0 +1,24 @@ +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/ConfigUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs new file mode 100644 index 0000000..93ac5d0 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ConfigUtil.cs @@ -0,0 +1,60 @@ +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 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/EncryptionUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs new file mode 100644 index 0000000..5199a6a --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/EncryptionUtil.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +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++) + { + ops *= vmOpCodeCount; + // don't use 0 + int op = random.NextInt(1, vmOpCodeCount); + ops |= (uint)op; + if (ops > uint.MaxValue) + { + throw new Exception($"OpCode overflow. encryptionLevel:{encryptionLevel}, vmOpCodeCount:{vmOpCodeCount}"); + } + } + return (int)ops; + } + } +} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs new file mode 100644 index 0000000..ccd210d --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/FileUtil.cs @@ -0,0 +1,100 @@ +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/GenericArgumentContext.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs new file mode 100644 index 0000000..a9f89be --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/GenericArgumentContext.cs @@ -0,0 +1,126 @@ +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/HashUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs new file mode 100644 index 0000000..5b0d823 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/HashUtil.cs @@ -0,0 +1,67 @@ +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/IAssemblyResolver.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs new file mode 100644 index 0000000..4a7578a --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IAssemblyResolver.cs @@ -0,0 +1,13 @@ +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/IRandom.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs new file mode 100644 index 0000000..e3a68b8 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/IRandom.cs @@ -0,0 +1,13 @@ +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/KeyGenerator.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs new file mode 100644 index 0000000..31aa40c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/KeyGenerator.cs @@ -0,0 +1,41 @@ +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/MetaUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs new file mode 100644 index 0000000..c77ff86 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/MetaUtil.cs @@ -0,0 +1,792 @@ +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 = ToShareTypeSig(corTypes, 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 corTypes.Object; + case ElementType.Array: return corTypes.Object; + 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"); + } + } +} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs new file mode 100644 index 0000000..ea06a66 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NameMatcher.cs @@ -0,0 +1,41 @@ +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/NumberRange.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs new file mode 100644 index 0000000..90d55e0 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/NumberRange.cs @@ -0,0 +1,14 @@ +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/PathAssemblyResolver.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs new file mode 100644 index 0000000..11c0f47 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/PathAssemblyResolver.cs @@ -0,0 +1,34 @@ +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/RandomWithKey.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs new file mode 100644 index 0000000..27d1001 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/RandomWithKey.cs @@ -0,0 +1,58 @@ +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/ThisArgType.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs new file mode 100644 index 0000000..3f008cc --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/ThisArgType.cs @@ -0,0 +1,9 @@ +namespace Obfuz.Utils +{ + public enum ThisArgType + { + None, + ValueType, + Class, + } +} diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs new file mode 100644 index 0000000..e016d8c --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Editor/Utils/TypeSigUtil.cs @@ -0,0 +1,194 @@ +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); + 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/LICENSE b/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE new file mode 100644 index 0000000..093e599 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/LICENSE @@ -0,0 +1,21 @@ +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/Plugins/dnlib.dll b/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll new file mode 100644 index 0000000..ba1f36d Binary files /dev/null and b/Obfuz/Packages/com.code-philosophy.obfuz/Plugins/dnlib.dll differ diff --git a/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs new file mode 100644 index 0000000..467cc2b --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ConstUtility.cs @@ -0,0 +1,82 @@ +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/EncryptionScope.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs new file mode 100644 index 0000000..fe215ef --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionScope.cs @@ -0,0 +1,31 @@ +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/EncryptionService.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs new file mode 100644 index 0000000..bd6cd98 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptionService.cs @@ -0,0 +1,125 @@ +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 + { + private 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/EncryptorBase.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs new file mode 100644 index 0000000..007e4b9 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/EncryptorBase.cs @@ -0,0 +1,258 @@ +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/IEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs new file mode 100644 index 0000000..0d8fdaa --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/IEncryptor.cs @@ -0,0 +1,32 @@ +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/NullEncryptor.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs new file mode 100644 index 0000000..ec28f36 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/NullEncryptor.cs @@ -0,0 +1,92 @@ +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/Obfuz.Runtime.asmdef b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef new file mode 100644 index 0000000..4ee1d16 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/Obfuz.Runtime.asmdef @@ -0,0 +1,14 @@ +{ + "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/ObfuzIgnoreAttribute.cs b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs new file mode 100644 index 0000000..90d2b17 --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/Runtime/ObfuzIgnoreAttribute.cs @@ -0,0 +1,13 @@ +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/package.json b/Obfuz/Packages/com.code-philosophy.obfuz/package.json new file mode 100644 index 0000000..27f3d9f --- /dev/null +++ b/Obfuz/Packages/com.code-philosophy.obfuz/package.json @@ -0,0 +1,20 @@ +{ + "name": "com.code-philosophy.obfuz", + "version": "1.0.0-alpha", + "displayName": "Obfuz", + "description": "Obfuz is a powerful code obfuscation tool designed specifically for Unity projects.", + "category": "Editor", + "documentationUrl": "https://obfuz.doc.code-philosophy.com/#/", + "changelogUrl": "https://obfuz.doc.code-philosophy.com/RELEASELOG.MD", + "licensesUrl": "https://github.com/focus-creative-games/obfuz/blob/main/LICENSE", + "keywords": [ + "obfuscation", + "obfuscator", + "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/manifest.json b/Obfuz/Packages/manifest.json new file mode 100644 index 0000000..778eb57 --- /dev/null +++ b/Obfuz/Packages/manifest.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "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 new file mode 100644 index 0000000..0dd06dc --- /dev/null +++ b/Obfuz/Packages/packages-lock.json @@ -0,0 +1,130 @@ +{ + "dependencies": { + "com.code-philosophy.obfuz": { + "version": "file:com.code-philosophy.obfuz", + "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 new file mode 100644 index 0000000..07ebfb0 --- /dev/null +++ b/Obfuz/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%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 new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/Obfuz/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%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 new file mode 100644 index 0000000..cdc1f3e --- /dev/null +++ b/Obfuz/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,34 @@ +%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 new file mode 100644 index 0000000..40917b0 --- /dev/null +++ b/Obfuz/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,11 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: + - enabled: 1 + path: Assets/Scenes/SampleScene.unity + guid: 9fc0d4010bbf28b4594072e72b8655ab + m_configObjects: {} diff --git a/Obfuz/ProjectSettings/EditorSettings.asset b/Obfuz/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..1e44a0a --- /dev/null +++ b/Obfuz/ProjectSettings/EditorSettings.asset @@ -0,0 +1,30 @@ +%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 new file mode 100644 index 0000000..4706883 --- /dev/null +++ b/Obfuz/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,66 @@ +%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 new file mode 100644 index 0000000..8c743fe --- /dev/null +++ b/Obfuz/ProjectSettings/HybridCLRSettings.asset @@ -0,0 +1,32 @@ +%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 new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/Obfuz/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%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 new file mode 100644 index 0000000..5b5face --- /dev/null +++ b/Obfuz/ProjectSettings/MemorySettings.asset @@ -0,0 +1,35 @@ +%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 new file mode 100644 index 0000000..2a93664 --- /dev/null +++ b/Obfuz/ProjectSettings/MultiplayerManager.asset @@ -0,0 +1,7 @@ +%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 new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/Obfuz/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%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 new file mode 100644 index 0000000..c631591 --- /dev/null +++ b/Obfuz/ProjectSettings/Obfuz.asset @@ -0,0 +1,47 @@ +%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: [] + 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 new file mode 100644 index 0000000..112a053 --- /dev/null +++ b/Obfuz/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,35 @@ +%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 new file mode 100644 index 0000000..3c7b4c1 --- /dev/null +++ b/Obfuz/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -0,0 +1,5 @@ +{ + "m_Dictionary": { + "m_DictionaryValues": [] + } +} \ No newline at end of file diff --git a/Obfuz/ProjectSettings/Physics2DSettings.asset b/Obfuz/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..47880b1 --- /dev/null +++ b/Obfuz/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%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 new file mode 100644 index 0000000..67a94da --- /dev/null +++ b/Obfuz/ProjectSettings/PresetManager.asset @@ -0,0 +1,7 @@ +%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 new file mode 100644 index 0000000..32f7fb5 --- /dev/null +++ b/Obfuz/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,993 @@ +%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 + 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 new file mode 100644 index 0000000..37f39b7 --- /dev/null +++ b/Obfuz/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2022.3.11f1 +m_EditorVersionWithRevision: 2022.3.11f1 (d00248457e15) diff --git a/Obfuz/ProjectSettings/QualitySettings.asset b/Obfuz/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..36c0dad --- /dev/null +++ b/Obfuz/ProjectSettings/QualitySettings.asset @@ -0,0 +1,234 @@ +%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 new file mode 100644 index 0000000..5e97f83 --- /dev/null +++ b/Obfuz/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,121 @@ +{ + "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 new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/Obfuz/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%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 new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/Obfuz/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%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 new file mode 100644 index 0000000..a88bee0 --- /dev/null +++ b/Obfuz/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,36 @@ +%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 new file mode 100644 index 0000000..3a95c98 --- /dev/null +++ b/Obfuz/ProjectSettings/VFXManager.asset @@ -0,0 +1,12 @@ +%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 new file mode 100644 index 0000000..dca2881 --- /dev/null +++ b/Obfuz/ProjectSettings/VersionControlSettings.asset @@ -0,0 +1,8 @@ +%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 new file mode 100644 index 0000000..482590c --- /dev/null +++ b/Obfuz/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 6c2b56b..e92f1fe 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,12 @@ Obfuz 是一款开源的 Unity 代码混淆工具,致力于为 Unity 开发者 - **深度 Unity 集成**:与 Unity 工作流无缝衔接,配置简单即可使用。 - **热更新支持**:全面兼容 HybridCLR、xLua、Puerts 等热更新框架,确保动态代码更新顺畅。 +## 支持的Unity版本与平台 + +- 支持Unity 2019+ +- 支持团结引擎 +- 支持Unity支持的所有平台 + ## 未来计划 Obfuz 正在持续开发中,即将推出的功能包括: diff --git a/REAME-EN.md b/REAME-EN.md index 117155f..bdc3476 100644 --- a/REAME-EN.md +++ b/REAME-EN.md @@ -21,6 +21,12 @@ - **Seamless Unity Integration**: Deeply integrated with Unity workflows, requiring minimal configuration to get started. - **Hot Update Compatibility**: Fully supports hot update frameworks like HybridCLR, xLua, and Puerts, ensuring compatibility with dynamic code updates. +## Supported Unity Versions & Platforms + +- Unity 2019 and later versions +- Tuanjie 1.0.0 and later versions +- All platforms supported by Unity and Tuanjie + ## Planned Features Obfuz is actively evolving. Upcoming features include: