Compare commits
No commits in common. "backup" and "main" have entirely different histories.
|
|
@ -1,400 +0,0 @@
|
|||
## 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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2326b426d539e084dbddf7f7c23ed1bd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 241df8eaf3a34dc47a0873c37ddb2695
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,12 +1,28 @@
|
|||
// Copyright 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.
|
||||
|
||||
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
|
||||
|
|
@ -17,7 +33,7 @@ namespace Obfuz.Conf
|
|||
}
|
||||
|
||||
|
||||
public interface IMethodRule<R> where R: IRule<R>
|
||||
public interface IMethodRule<R> where R : IRule<R>
|
||||
{
|
||||
string Name { get; set; }
|
||||
NameMatcher NameMatcher { get; set; }
|
||||
|
|
@ -33,7 +49,7 @@ namespace Obfuz.Conf
|
|||
public R Rule { get; set; }
|
||||
}
|
||||
|
||||
public interface ITypeRule<T, R> where T: IMethodRule<R> where R : IRule<R>
|
||||
public interface ITypeRule<T, R> where T : IMethodRule<R> where R : IRule<R>
|
||||
{
|
||||
string Name { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 36a3e142db81f6d4bb54938525e31973
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,13 +1,28 @@
|
|||
// Copyright 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.
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1578270b9b81e1e4dba84d562c91090f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,11 +1,28 @@
|
|||
// Copyright 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.
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -189,7 +206,7 @@ namespace Obfuz
|
|||
ObfuscationPassType passType = ObfuscationPassType.None;
|
||||
foreach (var passName in obfuscationPassTypesStr.Split('|'))
|
||||
{
|
||||
if (Enum.TryParse< ObfuscationPassType>(passName, out var pass))
|
||||
if (Enum.TryParse<ObfuscationPassType>(passName, out var pass))
|
||||
{
|
||||
passType |= pass;
|
||||
}
|
||||
|
|
@ -389,7 +406,7 @@ namespace Obfuz
|
|||
{
|
||||
if (ass.nameMatcher.IsMatch(assName))
|
||||
{
|
||||
result = (ass, _defaultPassRule);
|
||||
result = (ass, ass.rule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 41044699810a34f4780e14de084bf7d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,13 +1,52 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
// Copyright 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.
|
||||
|
||||
namespace Obfuz.Editor
|
||||
namespace Obfuz.Editor
|
||||
{
|
||||
public static class ConstValues
|
||||
{
|
||||
public const string ObfuzInternalSymbolNamePrefix = "$Obfuz$";
|
||||
|
||||
public const string ObfuzRuntimeAssemblyName = "Obfuz.Runtime";
|
||||
|
||||
public const string ObfuzIgnoreAttributeFullName = "Obfuz.ObfuzIgnoreAttribute";
|
||||
|
||||
public const string ObfuzScopeFullName = "Obfuz.ObfuzScope";
|
||||
|
||||
public const string EncryptFieldAttributeFullName = "Obfuz.EncryptFieldAttribute";
|
||||
public const string GeneratedEncryptionVirtualMachineFullName = "Obfuz.EncryptionVM.GeneratedEncryptionVirtualMachine";
|
||||
|
||||
public const string EmbeddedAttributeFullName = "Microsoft.CodeAnalysis.EmbeddedAttribute";
|
||||
|
||||
public const string MonoPInvokeCallbackAttributeName = "MonoPInvokeCallbackAttribute";
|
||||
|
||||
public const string ZluaLuaInvokeAttributeFullName = "Zlua.LuaInvokeAttribute";
|
||||
public const string ZluaLuaCallbackAttributeFullName = "Zlua.LuaCallbackAttribute";
|
||||
public const string ZluaLuaMarshalAsAttributeFullName = "Zlua.LuaMarshalAsAttribute";
|
||||
|
||||
public const string BurstCompileFullName = "Unity.Burst.BurstCompileAttribute";
|
||||
public const string DOTSCompilerGeneratedAttributeFullName = "Unity.Jobs.DOTSCompilerGeneratedAttribute";
|
||||
|
||||
public const string RuntimeInitializedOnLoadMethodAttributeFullName = "UnityEngine.RuntimeInitializeOnLoadMethodAttribute";
|
||||
public const string BlackboardEnumAttributeFullName = "Unity.Behavior.BlackboardEnumAttribute";
|
||||
|
||||
public const string CompilerGeneratedAttributeFullName = "System.Runtime.CompilerServices.CompilerGeneratedAttribute";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aee7817ed523a5e4ea42104013e8a775
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3319ebe75a42f3d4d996846ca09ed099
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Editor;
|
||||
|
|
@ -6,22 +26,12 @@ 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
|
||||
public class ConstFieldAllocator : GroupByModuleEntityBase
|
||||
{
|
||||
private ModuleDef _module;
|
||||
private readonly EncryptionScopeProvider _encryptionScopeProvider;
|
||||
private readonly RvaDataAllocator _rvaDataAllocator;
|
||||
private readonly GroupByModuleEntityManager _moduleEntityManager;
|
||||
private EncryptionScopeInfo _encryptionScope;
|
||||
private RandomCreator _randomCreator;
|
||||
private IEncryptor _encryptor;
|
||||
|
||||
|
|
@ -62,19 +72,14 @@ namespace Obfuz.Data
|
|||
private bool _done;
|
||||
|
||||
|
||||
public ModuleConstFieldAllocator(EncryptionScopeProvider encryptionScopeProvider, RvaDataAllocator rvaDataAllocator, GroupByModuleEntityManager moduleEntityManager)
|
||||
public ConstFieldAllocator()
|
||||
{
|
||||
_encryptionScopeProvider = encryptionScopeProvider;
|
||||
_rvaDataAllocator = rvaDataAllocator;
|
||||
_moduleEntityManager = moduleEntityManager;
|
||||
}
|
||||
|
||||
public void Init(ModuleDef mod)
|
||||
public override void Init()
|
||||
{
|
||||
_module = mod;
|
||||
_encryptionScope = _encryptionScopeProvider.GetScope(mod);
|
||||
_randomCreator = _encryptionScope.localRandomCreator;
|
||||
_encryptor = _encryptionScope.encryptor;
|
||||
_randomCreator = EncryptionScope.localRandomCreator;
|
||||
_encryptor = EncryptionScope.encryptor;
|
||||
}
|
||||
|
||||
const int maxFieldCount = 1000;
|
||||
|
|
@ -82,34 +87,37 @@ namespace Obfuz.Data
|
|||
|
||||
private TypeSig GetTypeSigOfValue(object value)
|
||||
{
|
||||
ModuleDef mod = Module;
|
||||
if (value is int)
|
||||
return _module.CorLibTypes.Int32;
|
||||
return mod.CorLibTypes.Int32;
|
||||
if (value is long)
|
||||
return _module.CorLibTypes.Int64;
|
||||
return mod.CorLibTypes.Int64;
|
||||
if (value is float)
|
||||
return _module.CorLibTypes.Single;
|
||||
return mod.CorLibTypes.Single;
|
||||
if (value is double)
|
||||
return _module.CorLibTypes.Double;
|
||||
return mod.CorLibTypes.Double;
|
||||
if (value is string)
|
||||
return _module.CorLibTypes.String;
|
||||
return mod.CorLibTypes.String;
|
||||
if (value is byte[])
|
||||
return new SZArraySig(_module.CorLibTypes.Byte);
|
||||
return new SZArraySig(mod.CorLibTypes.Byte);
|
||||
throw new NotSupportedException($"Unsupported type: {value.GetType()}");
|
||||
}
|
||||
|
||||
private ConstFieldInfo CreateConstFieldInfo(object value)
|
||||
{
|
||||
ModuleDef mod = Module;
|
||||
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;
|
||||
using (var scope = new DisableTypeDefFindCacheScope(mod))
|
||||
{
|
||||
ITypeDefOrRef objectTypeRef = mod.Import(typeof(object));
|
||||
_holderTypeDef = new TypeDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}ConstFieldHolder${_holderTypeDefs.Count}", objectTypeRef);
|
||||
mod.Types.Add(_holderTypeDef);
|
||||
_holderTypeDefs.Add(_holderTypeDef);
|
||||
}
|
||||
}
|
||||
|
||||
var field = new FieldDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}RVA_Value{_holderTypeDef.Fields.Count}", new FieldSig(GetTypeSigOfValue(value)), FieldAttributes.Static | FieldAttributes.Private | FieldAttributes.InitOnly);
|
||||
var field = new FieldDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}RVA_Value{_holderTypeDef.Fields.Count}", new FieldSig(GetTypeSigOfValue(value)), FieldAttributes.Static | FieldAttributes.Public);
|
||||
field.DeclaringType = _holderTypeDef;
|
||||
return new ConstFieldInfo
|
||||
{
|
||||
|
|
@ -163,41 +171,35 @@ namespace Obfuz.Data
|
|||
return AllocateAny(value);
|
||||
}
|
||||
|
||||
private DefaultMetadataImporter GetModuleMetadataImporter()
|
||||
{
|
||||
return _moduleEntityManager.GetDefaultModuleMetadataImporter(_module, _encryptionScopeProvider);
|
||||
}
|
||||
|
||||
private void CreateCCtorOfRvaTypeDef(TypeDef type)
|
||||
{
|
||||
ModuleDef mod = Module;
|
||||
var cctor = new MethodDefUser(".cctor",
|
||||
MethodSig.CreateStatic(_module.CorLibTypes.Void),
|
||||
MethodSig.CreateStatic(mod.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();
|
||||
DefaultMetadataImporter importer = this.GetDefaultModuleMetadataImporter();
|
||||
RvaDataAllocator rvaDataAllocator = GetEntity<RvaDataAllocator>();
|
||||
// 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 ops = EncryptionUtil.GenerateEncryptionOpCodes(localRandom, _encryptor, EncryptionScopeInfo.MaxEncryptionLevel, false);
|
||||
int salt = localRandom.NextInt();
|
||||
switch (constInfo.value)
|
||||
{
|
||||
case int i:
|
||||
{
|
||||
int encryptedValue = _encryptor.Encrypt(i, ops, salt);
|
||||
RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(encryptedValue);
|
||||
ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
||||
ins.Add(Instruction.CreateLdcI4(rvaData.offset));
|
||||
ins.Add(Instruction.CreateLdcI4(ops));
|
||||
|
|
@ -208,7 +210,7 @@ namespace Obfuz.Data
|
|||
case long l:
|
||||
{
|
||||
long encryptedValue = _encryptor.Encrypt(l, ops, salt);
|
||||
RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(encryptedValue);
|
||||
ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
||||
ins.Add(Instruction.CreateLdcI4(rvaData.offset));
|
||||
ins.Add(Instruction.CreateLdcI4(ops));
|
||||
|
|
@ -219,7 +221,7 @@ namespace Obfuz.Data
|
|||
case float f:
|
||||
{
|
||||
float encryptedValue = _encryptor.Encrypt(f, ops, salt);
|
||||
RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(encryptedValue);
|
||||
ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
||||
ins.Add(Instruction.CreateLdcI4(rvaData.offset));
|
||||
ins.Add(Instruction.CreateLdcI4(ops));
|
||||
|
|
@ -230,7 +232,7 @@ namespace Obfuz.Data
|
|||
case double d:
|
||||
{
|
||||
double encryptedValue = _encryptor.Encrypt(d, ops, salt);
|
||||
RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(encryptedValue);
|
||||
ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
||||
ins.Add(Instruction.CreateLdcI4(rvaData.offset));
|
||||
ins.Add(Instruction.CreateLdcI4(ops));
|
||||
|
|
@ -241,7 +243,7 @@ namespace Obfuz.Data
|
|||
case string s:
|
||||
{
|
||||
byte[] encryptedValue = _encryptor.Encrypt(s, ops, salt);
|
||||
RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(encryptedValue);
|
||||
ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
||||
ins.Add(Instruction.CreateLdcI4(rvaData.offset));
|
||||
Assert.AreEqual(encryptedValue.Length, rvaData.size);
|
||||
|
|
@ -255,7 +257,7 @@ namespace Obfuz.Data
|
|||
{
|
||||
byte[] encryptedValue = _encryptor.Encrypt(bs, 0, bs.Length, ops, salt);
|
||||
Assert.AreEqual(encryptedValue.Length, bs.Length);
|
||||
RvaData rvaData = _rvaDataAllocator.Allocate(_module, encryptedValue);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(encryptedValue);
|
||||
ins.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
||||
ins.Add(Instruction.CreateLdcI4(rvaData.offset));
|
||||
ins.Add(Instruction.CreateLdcI4(bs.Length));
|
||||
|
|
@ -271,7 +273,7 @@ namespace Obfuz.Data
|
|||
ins.Add(Instruction.Create(OpCodes.Ret));
|
||||
}
|
||||
|
||||
public void Done()
|
||||
public override void Done()
|
||||
{
|
||||
if (_done)
|
||||
{
|
||||
|
|
@ -284,61 +286,4 @@ namespace Obfuz.Data
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<ModuleConstFieldAllocator>(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<ModuleConstFieldAllocator>())
|
||||
{
|
||||
moduleAllocator.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e75f5cdfd47370d4ea6c4dee7e55a881
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Emit;
|
||||
|
|
@ -6,7 +26,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace Obfuz.Data
|
||||
|
|
@ -25,16 +44,13 @@ namespace Obfuz.Data
|
|||
}
|
||||
}
|
||||
|
||||
public class ModuleRvaDataAllocator : GroupByModuleEntityBase
|
||||
public class RvaDataAllocator : GroupByModuleEntityBase
|
||||
{
|
||||
// randomized
|
||||
const int maxRvaDataSize = 0x1000;
|
||||
const int maxRvaDataSize = 2 * 1024;
|
||||
|
||||
private ModuleDef _module;
|
||||
private readonly EncryptionScopeProvider _encryptionScopeProvider;
|
||||
private readonly GroupByModuleEntityManager _moduleEntityManager;
|
||||
// in HybridCLR version below 8.3.0, the max total static field size of a type is 16KB, so we limit the total size of RVA data to 16KB
|
||||
const int maxTotalRvaDataFieldSizeInHybridCLR = 16 * 1024;
|
||||
|
||||
private EncryptionScopeInfo _encryptionScope;
|
||||
private IRandom _random;
|
||||
|
||||
class RvaField
|
||||
|
|
@ -64,65 +80,74 @@ namespace Obfuz.Data
|
|||
}
|
||||
}
|
||||
|
||||
private readonly List<RvaField> _rvaFields = new List<RvaField>();
|
||||
private class RvaTypeDefInfo
|
||||
{
|
||||
public readonly TypeDef typeDef;
|
||||
public readonly int index;
|
||||
public readonly List<RvaField> rvaFields = new List<RvaField>();
|
||||
|
||||
public RvaTypeDefInfo(TypeDef typeDef, int index)
|
||||
{
|
||||
this.typeDef = typeDef;
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
|
||||
private RvaField _currentField;
|
||||
|
||||
|
||||
private TypeDef _rvaTypeDef;
|
||||
private RvaTypeDefInfo _currentRvaType;
|
||||
private readonly List<RvaTypeDefInfo> _rvaTypeDefs = new List<RvaTypeDefInfo>();
|
||||
|
||||
private readonly Dictionary<int, TypeDef> _dataHolderTypeBySizes = new Dictionary<int, TypeDef>();
|
||||
private bool _done;
|
||||
|
||||
public ModuleRvaDataAllocator(EncryptionScopeProvider encryptionScopeProvider, GroupByModuleEntityManager moduleEntityManager)
|
||||
public RvaDataAllocator()
|
||||
{
|
||||
_encryptionScopeProvider = encryptionScopeProvider;
|
||||
_moduleEntityManager = moduleEntityManager;
|
||||
}
|
||||
|
||||
public override void Init(ModuleDef mod)
|
||||
public override void Init()
|
||||
{
|
||||
_module = mod;
|
||||
_encryptionScope = _encryptionScopeProvider.GetScope(mod);
|
||||
_random = _encryptionScope.localRandomCreator(HashUtil.ComputeHash(mod.Name));
|
||||
_random = EncryptionScope.localRandomCreator(HashUtil.ComputeHash(Module.Name));
|
||||
}
|
||||
|
||||
private (FieldDef, FieldDef) CreateDataHolderRvaField(TypeDef dataHolderType)
|
||||
{
|
||||
if (_rvaTypeDef == null)
|
||||
if (_currentRvaType == null || _currentRvaType.rvaFields.Count >= maxTotalRvaDataFieldSizeInHybridCLR / maxRvaDataSize - 1)
|
||||
{
|
||||
_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;
|
||||
using (var scope = new DisableTypeDefFindCacheScope(Module))
|
||||
{
|
||||
var rvaTypeDef = new TypeDefUser($"$Obfuz$RVA${_rvaTypeDefs.Count}", Module.CorLibTypes.Object.ToTypeDefOrRef());
|
||||
Module.Types.Add(rvaTypeDef);
|
||||
_currentRvaType = new RvaTypeDefInfo(rvaTypeDef, _rvaTypeDefs.Count);
|
||||
_rvaTypeDefs.Add(_currentRvaType);
|
||||
}
|
||||
}
|
||||
|
||||
var holderField = new FieldDefUser($"$RVA_Data{_currentRvaType.rvaFields.Count}", new FieldSig(dataHolderType.ToTypeSig()), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
|
||||
holderField.DeclaringType = _currentRvaType.typeDef;
|
||||
|
||||
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;
|
||||
var runtimeValueField = new FieldDefUser($"$RVA_Value{_currentRvaType.rvaFields.Count}", new FieldSig(new SZArraySig(Module.CorLibTypes.Byte)), FieldAttributes.Static | FieldAttributes.Public);
|
||||
runtimeValueField.DeclaringType = _currentRvaType.typeDef;
|
||||
return (holderField, runtimeValueField);
|
||||
}
|
||||
|
||||
private TypeDef GetDataHolderType(int size)
|
||||
{
|
||||
size = (size + 15) & ~15; // align to 6 bytes
|
||||
size = (size + 15) & ~15; // align to 16 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;
|
||||
|
||||
using (var scope = new DisableTypeDefFindCacheScope(Module))
|
||||
{
|
||||
var dataHolderType = new TypeDefUser($"$ObfuzRVA$DataHolder{size}", Module.Import(typeof(ValueType)));
|
||||
dataHolderType.Attributes = TypeAttributes.Public | TypeAttributes.Sealed;
|
||||
dataHolderType.Layout = TypeAttributes.ExplicitLayout;
|
||||
dataHolderType.PackingSize = 1;
|
||||
dataHolderType.ClassSize = (uint)size;
|
||||
_dataHolderTypeBySizes.Add(size, dataHolderType);
|
||||
Module.Types.Add(dataHolderType);
|
||||
return dataHolderType;
|
||||
}
|
||||
}
|
||||
|
||||
private static int AlignTo(int size, int alignment)
|
||||
|
|
@ -143,7 +168,7 @@ namespace Obfuz.Data
|
|||
encryptionOps = _random.NextInt(),
|
||||
salt = _random.NextInt(),
|
||||
};
|
||||
_rvaFields.Add(newRvaField);
|
||||
_currentRvaType.rvaFields.Add(newRvaField);
|
||||
return newRvaField;
|
||||
}
|
||||
|
||||
|
|
@ -227,52 +252,71 @@ namespace Obfuz.Data
|
|||
return new RvaData(field.runtimeValueField, offset, value.Length);
|
||||
}
|
||||
|
||||
|
||||
private void AddVerifyCodes(IList<Instruction> insts, DefaultMetadataImporter importer)
|
||||
{
|
||||
int verifyIntValue = 0x12345678;
|
||||
EncryptionScopeInfo encryptionScope = this.EncryptionScope;
|
||||
IRandom verifyRandom = encryptionScope.localRandomCreator(verifyIntValue);
|
||||
int verifyOps = EncryptionUtil.GenerateEncryptionOpCodes(verifyRandom, encryptionScope.encryptor, EncryptionScopeInfo.MaxEncryptionLevel, false);
|
||||
int verifySalt = verifyRandom.NextInt();
|
||||
int encryptedVerifyIntValue = encryptionScope.encryptor.Encrypt(verifyIntValue, verifyOps, verifySalt);
|
||||
|
||||
insts.Add(Instruction.Create(OpCodes.Ldc_I4, verifyIntValue));
|
||||
insts.Add(Instruction.CreateLdcI4(encryptedVerifyIntValue));
|
||||
insts.Add(Instruction.CreateLdcI4(verifyOps));
|
||||
insts.Add(Instruction.CreateLdcI4(verifySalt));
|
||||
insts.Add(Instruction.Create(OpCodes.Call, importer.DecryptInt));
|
||||
insts.Add(Instruction.Create(OpCodes.Call, importer.VerifySecretKey));
|
||||
|
||||
}
|
||||
|
||||
private void CreateCCtorOfRvaTypeDef()
|
||||
{
|
||||
if (_rvaTypeDef == null)
|
||||
foreach (RvaTypeDefInfo rvaTypeDef in _rvaTypeDefs)
|
||||
{
|
||||
return;
|
||||
ModuleDef mod = rvaTypeDef.typeDef.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.typeDef;
|
||||
//_rvaTypeDef.Methods.Add(cctor);
|
||||
var body = new CilBody();
|
||||
cctorMethod.Body = body;
|
||||
var ins = body.Instructions;
|
||||
|
||||
DefaultMetadataImporter importer = this.GetDefaultModuleMetadataImporter();
|
||||
AddVerifyCodes(ins, importer);
|
||||
foreach (var field in rvaTypeDef.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.InitializedArray));
|
||||
|
||||
// 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));
|
||||
}
|
||||
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)
|
||||
foreach (var field in _rvaTypeDefs.SelectMany(t => t.rvaFields))
|
||||
{
|
||||
Assert.IsTrue(field.bytes.Count <= field.size);
|
||||
if (field.bytes.Count < field.size)
|
||||
|
|
@ -280,12 +324,12 @@ namespace Obfuz.Data
|
|||
field.FillPaddingToEnd();
|
||||
}
|
||||
byte[] data = field.bytes.ToArray();
|
||||
_encryptionScope.encryptor.EncryptBlock(data, field.encryptionOps, field.salt);
|
||||
EncryptionScope.encryptor.EncryptBlock(data, field.encryptionOps, field.salt);
|
||||
field.holderDataField.InitialValue = data;
|
||||
}
|
||||
}
|
||||
|
||||
public void Done()
|
||||
public override void Done()
|
||||
{
|
||||
if (_done)
|
||||
{
|
||||
|
|
@ -296,59 +340,4 @@ namespace Obfuz.Data
|
|||
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<ModuleRvaDataAllocator>(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<ModuleRvaDataAllocator>())
|
||||
{
|
||||
allocator.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c00ca514f46605645bf40b0135e7e504
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a513a192808ba5f47b1ef8a3ecf02533
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,11 +1,28 @@
|
|||
// Copyright 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.
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -41,13 +58,20 @@ namespace Obfuz.Emit
|
|||
|
||||
public IList<BasicBlock> Blocks => _blocks;
|
||||
|
||||
public BasicBlockCollection(MethodDef method)
|
||||
public BasicBlockCollection(MethodDef method, bool computeInLoop)
|
||||
{
|
||||
_method = method;
|
||||
HashSet<Instruction> splitPoints = BuildSplitPoint(method);
|
||||
BuildBasicBlocks(method, splitPoints);
|
||||
BuildInOutGraph(method);
|
||||
if (computeInLoop)
|
||||
{
|
||||
ComputeBlocksInLoop();
|
||||
}
|
||||
}
|
||||
|
||||
public void ComputeBlocksInLoop()
|
||||
{
|
||||
var loopBlocks = FindLoopBlocks(_blocks);
|
||||
foreach (var block in loopBlocks)
|
||||
{
|
||||
|
|
@ -100,6 +124,7 @@ namespace Obfuz.Emit
|
|||
{
|
||||
splitPoints.Add(nextInst);
|
||||
}
|
||||
splitPoints.Add((Instruction)curInst.Operand);
|
||||
break;
|
||||
}
|
||||
case FlowControl.Cond_Branch:
|
||||
|
|
@ -141,7 +166,7 @@ namespace Obfuz.Emit
|
|||
}
|
||||
return splitPoints;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void BuildBasicBlocks(MethodDef method, HashSet<Instruction> splitPoints)
|
||||
{
|
||||
|
|
@ -207,11 +232,21 @@ namespace Obfuz.Emit
|
|||
}
|
||||
break;
|
||||
}
|
||||
case FlowControl.Call:
|
||||
case FlowControl.Next:
|
||||
{
|
||||
if (nextBlock != null)
|
||||
{
|
||||
curBlock.AddTargetBasicBlock(nextBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FlowControl.Return:
|
||||
case FlowControl.Throw:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default: throw new NotSupportedException($"Unsupported flow control: {lastInst.OpCode.FlowControl} in method {method.FullName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 77c19c023bb7f77489998d994a3be1bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,5 +1,26 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace Obfuz.Emit
|
||||
|
|
@ -31,6 +52,8 @@ namespace Obfuz.Emit
|
|||
private IMethod _decryptFromRvaString;
|
||||
private IMethod _decryptFromRvaBytes;
|
||||
|
||||
private IMethod _decryptInitializeArray;
|
||||
|
||||
public IMethod EncryptBlock => _encryptBlock;
|
||||
public IMethod DecryptBlock => _decryptBlock;
|
||||
|
||||
|
|
@ -54,6 +77,8 @@ namespace Obfuz.Emit
|
|||
public IMethod DecryptFromRvaBytes => _decryptFromRvaBytes;
|
||||
public IMethod DecryptFromRvaString => _decryptFromRvaString;
|
||||
|
||||
public IMethod DecryptInitializeArray => _decryptInitializeArray;
|
||||
|
||||
public EncryptionServiceMetadataImporter(ModuleDef mod, Type encryptionServiceType)
|
||||
{
|
||||
_module = mod;
|
||||
|
|
@ -99,28 +124,27 @@ namespace Obfuz.Emit
|
|||
Assert.IsNotNull(_decryptFromRvaBytes);
|
||||
_decryptFromRvaString = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaString", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_decryptFromRvaString);
|
||||
_decryptInitializeArray = mod.Import(encryptionServiceType.GetMethod("DecryptInitializeArray", new[] { typeof(System.Array), typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_decryptInitializeArray);
|
||||
}
|
||||
}
|
||||
|
||||
public class DefaultMetadataImporter : GroupByModuleEntityBase
|
||||
{
|
||||
private readonly EncryptionScopeProvider _encryptionScopeProvider;
|
||||
private EncryptionScopeInfo _encryptionScope;
|
||||
private EncryptionServiceMetadataImporter _defaultEncryptionServiceMetadataImporter;
|
||||
|
||||
|
||||
private EncryptionServiceMetadataImporter _staticDefaultEncryptionServiceMetadataImporter;
|
||||
private EncryptionServiceMetadataImporter _dynamicDefaultEncryptionServiceMetadataImporter;
|
||||
|
||||
public DefaultMetadataImporter(EncryptionScopeProvider encryptionScopeProvider)
|
||||
public DefaultMetadataImporter()
|
||||
{
|
||||
_encryptionScopeProvider = encryptionScopeProvider;
|
||||
}
|
||||
|
||||
public override void Init(ModuleDef mod)
|
||||
public override void Init()
|
||||
{
|
||||
_module = mod;
|
||||
_encryptionScope = _encryptionScopeProvider.GetScope(mod);
|
||||
ModuleDef mod = Module;
|
||||
|
||||
var constUtilityType = typeof(ConstUtility);
|
||||
|
||||
_castIntAsFloat = mod.Import(constUtilityType.GetMethod("CastIntAsFloat"));
|
||||
|
|
@ -134,10 +158,119 @@ namespace Obfuz.Emit
|
|||
|
||||
_initializeArray = mod.Import(typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray", new[] { typeof(Array), typeof(RuntimeFieldHandle) }));
|
||||
Assert.IsNotNull(_initializeArray);
|
||||
_verifySecretKey = mod.Import(typeof(AssertUtility).GetMethod("VerifySecretKey", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_verifySecretKey, "VerifySecretKey not found");
|
||||
|
||||
_obfuscationTypeMapperRegisterType = mod.Import(typeof(ObfuscationTypeMapper).GetMethod("RegisterType", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null));
|
||||
Assert.IsNotNull(_obfuscationTypeMapperRegisterType, "ObfuscationTypeMapper.RegisterType not found");
|
||||
|
||||
var exprUtilityType = typeof(ExprUtility);
|
||||
_addInt = mod.Import(exprUtilityType.GetMethod("Add", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_addInt, "ExprUtility.Add(int, int) not found");
|
||||
_addLong = mod.Import(exprUtilityType.GetMethod("Add", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_addLong, "ExprUtility.Add(long, long) not found");
|
||||
_addFloat = mod.Import(exprUtilityType.GetMethod("Add", new[] { typeof(float), typeof(float) }));
|
||||
Assert.IsNotNull(_addFloat, "ExprUtility.Add(float, float) not found");
|
||||
_addDouble = mod.Import(exprUtilityType.GetMethod("Add", new[] { typeof(double), typeof(double) }));
|
||||
Assert.IsNotNull(_addDouble, "ExprUtility.Add(double, double) not found");
|
||||
_addIntPtr = mod.Import(exprUtilityType.GetMethod("Add", new[] { typeof(IntPtr), typeof(IntPtr) }));
|
||||
Assert.IsNotNull(_addIntPtr, "ExprUtility.Add(IntPtr, IntPtr) not found");
|
||||
_addIntPtrInt = mod.Import(exprUtilityType.GetMethod("Add", new[] { typeof(IntPtr), typeof(int) }));
|
||||
Assert.IsNotNull(_addIntPtrInt, "ExprUtility.Add(IntPtr, int) not found");
|
||||
|
||||
_subtractInt = mod.Import(exprUtilityType.GetMethod("Subtract", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_subtractInt, "ExprUtility.Subtract(int, int) not found");
|
||||
_subtractLong = mod.Import(exprUtilityType.GetMethod("Subtract", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_subtractLong, "ExprUtility.Subtract(long, long) not found");
|
||||
_subtractFloat = mod.Import(exprUtilityType.GetMethod("Subtract", new[] { typeof(float), typeof(float) }));
|
||||
Assert.IsNotNull(_subtractFloat, "ExprUtility.Subtract(float, float) not found");
|
||||
_subtractDouble = mod.Import(exprUtilityType.GetMethod("Subtract", new[] { typeof(double), typeof(double) }));
|
||||
Assert.IsNotNull(_subtractDouble, "ExprUtility.Subtract(double, double) not found");
|
||||
_subtractIntPtr = mod.Import(exprUtilityType.GetMethod("Subtract", new[] { typeof(IntPtr), typeof(IntPtr) }));
|
||||
Assert.IsNotNull(_subtractIntPtr, "ExprUtility.Subtract(IntPtr, IntPtr) not found");
|
||||
_subtractIntPtrInt = mod.Import(exprUtilityType.GetMethod("Subtract", new[] { typeof(IntPtr), typeof(int) }));
|
||||
Assert.IsNotNull(_subtractIntPtrInt, "ExprUtility.Subtract(IntPtr, int) not found");
|
||||
|
||||
_multiplyInt = mod.Import(exprUtilityType.GetMethod("Multiply", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_multiplyInt, "ExprUtility.Multiply(int, int) not found");
|
||||
_multiplyLong = mod.Import(exprUtilityType.GetMethod("Multiply", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_multiplyLong, "ExprUtility.Multiply(long, long) not found");
|
||||
_multiplyFloat = mod.Import(exprUtilityType.GetMethod("Multiply", new[] { typeof(float), typeof(float) }));
|
||||
Assert.IsNotNull(_multiplyFloat, "ExprUtility.Multiply(float, float) not found");
|
||||
_multiplyDouble = mod.Import(exprUtilityType.GetMethod("Multiply", new[] { typeof(double), typeof(double) }));
|
||||
Assert.IsNotNull(_multiplyDouble, "ExprUtility.Multiply(double, double) not found");
|
||||
_multiplyIntPtr = mod.Import(exprUtilityType.GetMethod("Multiply", new[] { typeof(IntPtr), typeof(IntPtr) }));
|
||||
Assert.IsNotNull(_multiplyIntPtr, "ExprUtility.Multiply(IntPtr, IntPtr) not found");
|
||||
_multiplyIntPtrInt = mod.Import(exprUtilityType.GetMethod("Multiply", new[] { typeof(IntPtr), typeof(int) }));
|
||||
Assert.IsNotNull(_multiplyIntPtrInt, "ExprUtility.Multiply(IntPtr, int) not found");
|
||||
|
||||
_divideInt = mod.Import(exprUtilityType.GetMethod("Divide", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_divideInt, "ExprUtility.Divide(int, int) not found");
|
||||
_divideLong = mod.Import(exprUtilityType.GetMethod("Divide", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_divideLong);
|
||||
_divideFloat = mod.Import(exprUtilityType.GetMethod("Divide", new[] { typeof(float), typeof(float) }));
|
||||
Assert.IsNotNull(_divideFloat, "ExprUtility.Divide(float, float) not found");
|
||||
_divideDouble = mod.Import(exprUtilityType.GetMethod("Divide", new[] { typeof(double), typeof(double) }));
|
||||
Assert.IsNotNull(_divideDouble, "ExprUtility.Divide(double, double) not found");
|
||||
_divideUnInt = mod.Import(exprUtilityType.GetMethod("DivideUn", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_divideUnInt, "ExprUtility.DivideUn(int, int) not found");
|
||||
_divideUnLong = mod.Import(exprUtilityType.GetMethod("DivideUn", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_divideUnLong, "ExprUtility.DivideUn(long, long) not found");
|
||||
_remInt = mod.Import(exprUtilityType.GetMethod("Rem", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_remInt, "ExprUtility.Rem(int, int) not found");
|
||||
_remLong = mod.Import(exprUtilityType.GetMethod("Rem", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_remLong, "ExprUtility.Rem(long, long) not found");
|
||||
_remFloat = mod.Import(exprUtilityType.GetMethod("Rem", new[] { typeof(float), typeof(float) }));
|
||||
Assert.IsNotNull(_remFloat, "ExprUtility.Rem(float, float) not found");
|
||||
_remDouble = mod.Import(exprUtilityType.GetMethod("Rem", new[] { typeof(double), typeof(double) }));
|
||||
Assert.IsNotNull(_remDouble, "ExprUtility.Rem(double, double) not found");
|
||||
_remUnInt = mod.Import(exprUtilityType.GetMethod("RemUn", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_remUnInt, "ExprUtility.RemUn(int, int) not found");
|
||||
_remUnLong = mod.Import(exprUtilityType.GetMethod("RemUn", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_remUnLong, "ExprUtility.RemUn(long, long) not found");
|
||||
_negInt = mod.Import(exprUtilityType.GetMethod("Negate", new[] { typeof(int) }));
|
||||
Assert.IsNotNull(_negInt, "ExprUtility.Negate(int) not found");
|
||||
_negLong = mod.Import(exprUtilityType.GetMethod("Negate", new[] { typeof(long) }));
|
||||
Assert.IsNotNull(_negLong, "ExprUtility.Negate(long) not found");
|
||||
_negFloat = mod.Import(exprUtilityType.GetMethod("Negate", new[] { typeof(float) }));
|
||||
Assert.IsNotNull(_negFloat, "ExprUtility.Negate(float) not found");
|
||||
_negDouble = mod.Import(exprUtilityType.GetMethod("Negate", new[] { typeof(double) }));
|
||||
Assert.IsNotNull(_negDouble, "ExprUtility.Negate(double) not found");
|
||||
|
||||
_andInt = mod.Import(exprUtilityType.GetMethod("And", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_andInt, "ExprUtility.And(int, int) not found");
|
||||
_andLong = mod.Import(exprUtilityType.GetMethod("And", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_andLong, "ExprUtility.And(long, long) not found");
|
||||
_orInt = mod.Import(exprUtilityType.GetMethod("Or", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_orInt, "ExprUtility.Or(int, int) not found");
|
||||
_orLong = mod.Import(exprUtilityType.GetMethod("Or", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_orLong, "ExprUtility.Or(long, long) not found");
|
||||
_xorInt = mod.Import(exprUtilityType.GetMethod("Xor", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_xorInt, "ExprUtility.Xor(int, int) not found");
|
||||
_xorLong = mod.Import(exprUtilityType.GetMethod("Xor", new[] { typeof(long), typeof(long) }));
|
||||
Assert.IsNotNull(_xorLong, "ExprUtility.Xor(long, long) not found");
|
||||
_notInt = mod.Import(exprUtilityType.GetMethod("Not", new[] { typeof(int) }));
|
||||
Assert.IsNotNull(_notInt, "ExprUtility.Not(int) not found");
|
||||
_notLong = mod.Import(exprUtilityType.GetMethod("Not", new[] { typeof(long) }));
|
||||
Assert.IsNotNull(_notLong, "ExprUtility.Not(long) not found");
|
||||
|
||||
_shlInt = mod.Import(exprUtilityType.GetMethod("ShiftLeft", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_shlInt, "ExprUtility.ShiftLeft(int, int) not found");
|
||||
_shlLong = mod.Import(exprUtilityType.GetMethod("ShiftLeft", new[] { typeof(long), typeof(int) }));
|
||||
Assert.IsNotNull(_shlLong, "ExprUtility.ShiftLeft(long, int) not found");
|
||||
_shrInt = mod.Import(exprUtilityType.GetMethod("ShiftRight", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_shrInt, "ExprUtility.ShiftRight(int, int) not found");
|
||||
_shrLong = mod.Import(exprUtilityType.GetMethod("ShiftRight", new[] { typeof(long), typeof(int) }));
|
||||
Assert.IsNotNull(_shrLong, "ExprUtility.ShiftRight(long, int) not found");
|
||||
_shrUnInt = mod.Import(exprUtilityType.GetMethod("ShiftRightUn", new[] { typeof(int), typeof(int) }));
|
||||
Assert.IsNotNull(_shrUnInt, "ExprUtility.ShiftRightUn(int, int) not found");
|
||||
_shrUnLong = mod.Import(exprUtilityType.GetMethod("ShiftRightUn", new[] { typeof(long), typeof(int) }));
|
||||
Assert.IsNotNull(_shrUnLong, "ExprUtility.ShiftRightUn(long, int) not found");
|
||||
|
||||
|
||||
_staticDefaultEncryptionServiceMetadataImporter = new EncryptionServiceMetadataImporter(mod, typeof(EncryptionService<DefaultStaticEncryptionScope>));
|
||||
_dynamicDefaultEncryptionServiceMetadataImporter = new EncryptionServiceMetadataImporter(mod, typeof(EncryptionService<DefaultDynamicEncryptionScope>));
|
||||
if (_encryptionScopeProvider.IsDynamicSecretAssembly(mod))
|
||||
if (EncryptionScopeProvider.IsDynamicSecretAssembly(mod))
|
||||
{
|
||||
_defaultEncryptionServiceMetadataImporter = _dynamicDefaultEncryptionServiceMetadataImporter;
|
||||
}
|
||||
|
|
@ -147,9 +280,14 @@ namespace Obfuz.Emit
|
|||
}
|
||||
}
|
||||
|
||||
public override void Done()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public EncryptionServiceMetadataImporter GetEncryptionServiceMetadataImporterOfModule(ModuleDef mod)
|
||||
{
|
||||
return _encryptionScopeProvider.IsDynamicSecretAssembly(mod) ? _dynamicDefaultEncryptionServiceMetadataImporter : _staticDefaultEncryptionServiceMetadataImporter;
|
||||
return EncryptionScopeProvider.IsDynamicSecretAssembly(mod) ? _dynamicDefaultEncryptionServiceMetadataImporter : _staticDefaultEncryptionServiceMetadataImporter;
|
||||
}
|
||||
|
||||
private ModuleDef _module;
|
||||
|
|
@ -158,13 +296,71 @@ namespace Obfuz.Emit
|
|||
private IMethod _castFloatAsInt;
|
||||
private IMethod _castDoubleAsLong;
|
||||
private IMethod _initializeArray;
|
||||
private IMethod _verifySecretKey;
|
||||
|
||||
private IMethod _obfuscationTypeMapperRegisterType;
|
||||
|
||||
private IMethod _addInt;
|
||||
private IMethod _addLong;
|
||||
private IMethod _addFloat;
|
||||
private IMethod _addDouble;
|
||||
private IMethod _addIntPtr;
|
||||
private IMethod _addIntPtrInt;
|
||||
private IMethod _subtractInt;
|
||||
private IMethod _subtractLong;
|
||||
private IMethod _subtractFloat;
|
||||
private IMethod _subtractDouble;
|
||||
private IMethod _subtractIntPtr;
|
||||
private IMethod _subtractIntPtrInt;
|
||||
private IMethod _multiplyInt;
|
||||
private IMethod _multiplyLong;
|
||||
private IMethod _multiplyFloat;
|
||||
private IMethod _multiplyDouble;
|
||||
private IMethod _multiplyIntPtr;
|
||||
private IMethod _multiplyIntPtrInt;
|
||||
private IMethod _divideInt;
|
||||
private IMethod _divideLong;
|
||||
private IMethod _divideFloat;
|
||||
private IMethod _divideDouble;
|
||||
private IMethod _divideUnInt;
|
||||
private IMethod _divideUnLong;
|
||||
private IMethod _remInt;
|
||||
private IMethod _remLong;
|
||||
private IMethod _remFloat;
|
||||
private IMethod _remDouble;
|
||||
private IMethod _remUnInt;
|
||||
private IMethod _remUnLong;
|
||||
private IMethod _negInt;
|
||||
private IMethod _negLong;
|
||||
private IMethod _negFloat;
|
||||
private IMethod _negDouble;
|
||||
|
||||
private IMethod _andInt;
|
||||
private IMethod _andLong;
|
||||
private IMethod _orInt;
|
||||
private IMethod _orLong;
|
||||
private IMethod _xorInt;
|
||||
private IMethod _xorLong;
|
||||
private IMethod _notInt;
|
||||
private IMethod _notLong;
|
||||
|
||||
private IMethod _shlInt;
|
||||
private IMethod _shlLong;
|
||||
private IMethod _shrInt;
|
||||
private IMethod _shrLong;
|
||||
private IMethod _shrUnInt;
|
||||
private IMethod _shrUnLong;
|
||||
|
||||
public IMethod CastIntAsFloat => _castIntAsFloat;
|
||||
public IMethod CastLongAsDouble => _castLongAsDouble;
|
||||
public IMethod CastFloatAsInt => _castFloatAsInt;
|
||||
public IMethod CastDoubleAsLong => _castDoubleAsLong;
|
||||
|
||||
public IMethod InitializedArrayMethod => _initializeArray;
|
||||
public IMethod InitializedArray => _initializeArray;
|
||||
|
||||
public IMethod VerifySecretKey => _verifySecretKey;
|
||||
|
||||
public IMethod ObfuscationTypeMapperRegisterType => _obfuscationTypeMapperRegisterType;
|
||||
|
||||
public IMethod EncryptBlock => _defaultEncryptionServiceMetadataImporter.EncryptBlock;
|
||||
public IMethod DecryptBlock => _defaultEncryptionServiceMetadataImporter.DecryptBlock;
|
||||
|
|
@ -189,5 +385,59 @@ namespace Obfuz.Emit
|
|||
public IMethod DecryptFromRvaBytes => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaBytes;
|
||||
public IMethod DecryptFromRvaString => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaString;
|
||||
|
||||
public IMethod DecryptInitializeArray => _defaultEncryptionServiceMetadataImporter.DecryptInitializeArray;
|
||||
|
||||
public IMethod AddInt => _addInt;
|
||||
public IMethod AddLong => _addLong;
|
||||
public IMethod AddFloat => _addFloat;
|
||||
public IMethod AddDouble => _addDouble;
|
||||
public IMethod AddIntPtr => _addIntPtr;
|
||||
public IMethod AddIntPtrInt => _addIntPtrInt;
|
||||
public IMethod SubtractInt => _subtractInt;
|
||||
public IMethod SubtractLong => _subtractLong;
|
||||
public IMethod SubtractFloat => _subtractFloat;
|
||||
public IMethod SubtractDouble => _subtractDouble;
|
||||
public IMethod SubtractIntPtr => _subtractIntPtr;
|
||||
public IMethod SubtractIntPtrInt => _subtractIntPtrInt;
|
||||
|
||||
public IMethod MultiplyInt => _multiplyInt;
|
||||
public IMethod MultiplyLong => _multiplyLong;
|
||||
public IMethod MultiplyFloat => _multiplyFloat;
|
||||
public IMethod MultiplyDouble => _multiplyDouble;
|
||||
public IMethod MultiplyIntPtr => _multiplyIntPtr;
|
||||
public IMethod MultiplyIntPtrInt => _multiplyIntPtrInt;
|
||||
|
||||
public IMethod DivideInt => _divideInt;
|
||||
public IMethod DivideLong => _divideLong;
|
||||
public IMethod DivideFloat => _divideFloat;
|
||||
public IMethod DivideDouble => _divideDouble;
|
||||
public IMethod DivideUnInt => _divideUnInt;
|
||||
public IMethod DivideUnLong => _divideUnLong;
|
||||
public IMethod RemInt => _remInt;
|
||||
public IMethod RemLong => _remLong;
|
||||
public IMethod RemFloat => _remFloat;
|
||||
public IMethod RemDouble => _remDouble;
|
||||
public IMethod RemUnInt => _remUnInt;
|
||||
public IMethod RemUnLong => _remUnLong;
|
||||
public IMethod NegInt => _negInt;
|
||||
public IMethod NegLong => _negLong;
|
||||
public IMethod NegFloat => _negFloat;
|
||||
public IMethod NegDouble => _negDouble;
|
||||
public IMethod AndInt => _andInt;
|
||||
public IMethod AndLong => _andLong;
|
||||
public IMethod OrInt => _orInt;
|
||||
public IMethod OrLong => _orLong;
|
||||
public IMethod XorInt => _xorInt;
|
||||
public IMethod XorLong => _xorLong;
|
||||
public IMethod NotInt => _notInt;
|
||||
public IMethod NotLong => _notLong;
|
||||
public IMethod ShlInt => _shlInt;
|
||||
public IMethod ShlLong => _shlLong;
|
||||
public IMethod ShrInt => _shrInt;
|
||||
public IMethod ShrLong => _shrLong;
|
||||
public IMethod ShrUnInt => _shrUnInt;
|
||||
public IMethod ShrUnLong => _shrUnLong;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 76438ce96146edd469872feada7857ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 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.
|
||||
|
||||
namespace Obfuz.Emit
|
||||
{
|
||||
public static class EntityExtensions
|
||||
{
|
||||
public static T GetEntity<T>(this IGroupByModuleEntity entity) where T : IGroupByModuleEntity, new()
|
||||
{
|
||||
return entity.Manager.GetEntity<T>(entity.Module);
|
||||
}
|
||||
|
||||
public static DefaultMetadataImporter GetDefaultModuleMetadataImporter(this IGroupByModuleEntity entity)
|
||||
{
|
||||
return entity.GetEntity<DefaultMetadataImporter>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6e9557733f180764692756653eb60f88
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f25425a3077f6db41873dee4223d0abc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,27 +1,71 @@
|
|||
// Copyright 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.
|
||||
|
||||
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);
|
||||
GroupByModuleEntityManager Manager { get; set; }
|
||||
|
||||
ModuleDef Module { get; set; }
|
||||
|
||||
EncryptionScopeProvider EncryptionScopeProvider { get; }
|
||||
|
||||
EncryptionScopeInfo EncryptionScope { get; set; }
|
||||
|
||||
void Init();
|
||||
|
||||
void Done();
|
||||
}
|
||||
|
||||
public abstract class GroupByModuleEntityBase : IGroupByModuleEntity
|
||||
{
|
||||
public abstract void Init(ModuleDef mod);
|
||||
public GroupByModuleEntityManager Manager { get; set; }
|
||||
|
||||
public ModuleDef Module { get; set; }
|
||||
|
||||
public EncryptionScopeInfo EncryptionScope { get; set; }
|
||||
|
||||
public EncryptionScopeProvider EncryptionScopeProvider => Manager.EncryptionScopeProvider;
|
||||
|
||||
public T GetEntity<T>() where T : IGroupByModuleEntity, new()
|
||||
{
|
||||
return Manager.GetEntity<T>(Module);
|
||||
}
|
||||
|
||||
public abstract void Init();
|
||||
|
||||
public abstract void Done();
|
||||
}
|
||||
|
||||
public class GroupByModuleEntityManager
|
||||
{
|
||||
private readonly Dictionary<(ModuleDef, Type), IGroupByModuleEntity> _moduleEntityManagers = new Dictionary<(ModuleDef, Type), IGroupByModuleEntity>();
|
||||
|
||||
public T GetEntity<T>(ModuleDef mod, Func<T> creator = null) where T : IGroupByModuleEntity
|
||||
public EncryptionScopeProvider EncryptionScopeProvider { get; set; }
|
||||
|
||||
public T GetEntity<T>(ModuleDef mod) where T : IGroupByModuleEntity, new()
|
||||
{
|
||||
var key = (mod, typeof(T));
|
||||
if (_moduleEntityManagers.TryGetValue(key, out var emitManager))
|
||||
|
|
@ -30,22 +74,17 @@ namespace Obfuz.Emit
|
|||
}
|
||||
else
|
||||
{
|
||||
T newEmitManager;
|
||||
if (creator != null)
|
||||
{
|
||||
newEmitManager = creator();
|
||||
}
|
||||
else
|
||||
{
|
||||
newEmitManager = (T)Activator.CreateInstance(typeof(T));
|
||||
}
|
||||
newEmitManager.Init(mod);
|
||||
T newEmitManager = new T();
|
||||
newEmitManager.Manager = this;
|
||||
newEmitManager.Module = mod;
|
||||
newEmitManager.EncryptionScope = EncryptionScopeProvider.GetScope(mod);
|
||||
newEmitManager.Init();
|
||||
_moduleEntityManagers[key] = newEmitManager;
|
||||
return newEmitManager;
|
||||
}
|
||||
}
|
||||
|
||||
public List<T> GetEntities<T>() where T: IGroupByModuleEntity
|
||||
public List<T> GetEntities<T>() where T : IGroupByModuleEntity, new()
|
||||
{
|
||||
var managers = new List<T>();
|
||||
foreach (var kv in _moduleEntityManagers)
|
||||
|
|
@ -58,9 +97,13 @@ namespace Obfuz.Emit
|
|||
return managers;
|
||||
}
|
||||
|
||||
public DefaultMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module, EncryptionScopeProvider encryptionScopeProvider)
|
||||
public void Done<T>() where T : IGroupByModuleEntity, new()
|
||||
{
|
||||
return GetEntity<DefaultMetadataImporter>(module, () => new DefaultMetadataImporter(encryptionScopeProvider));
|
||||
var managers = GetEntities<T>();
|
||||
foreach (var manager in managers)
|
||||
{
|
||||
manager.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0bfcb2b5a87851f469d201fc8978c109
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.Emit
|
||||
{
|
||||
class ScopeLocalVariables : IDisposable
|
||||
{
|
||||
private readonly LocalVariableAllocator _localVariableAllocator;
|
||||
|
||||
private readonly List<Local> _allocatedVars = new List<Local>();
|
||||
|
||||
public IReadOnlyList<Local> AllocatedLocals => _allocatedVars;
|
||||
|
||||
|
||||
public ScopeLocalVariables(LocalVariableAllocator localVariableAllocator)
|
||||
{
|
||||
_localVariableAllocator = localVariableAllocator;
|
||||
}
|
||||
|
||||
public Local AllocateLocal(TypeSig type)
|
||||
{
|
||||
var local = _localVariableAllocator.AllocateLocal(type);
|
||||
_allocatedVars.Add(local);
|
||||
return local;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var local in _allocatedVars)
|
||||
{
|
||||
_localVariableAllocator.ReturnLocal(local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LocalVariableAllocator
|
||||
{
|
||||
private readonly MethodDef _method;
|
||||
private readonly List<Local> _freeLocals = new List<Local>();
|
||||
|
||||
public LocalVariableAllocator(MethodDef method)
|
||||
{
|
||||
_method = method;
|
||||
}
|
||||
|
||||
public Local AllocateLocal(TypeSig type)
|
||||
{
|
||||
foreach (var local in _freeLocals)
|
||||
{
|
||||
if (TypeEqualityComparer.Instance.Equals(local.Type, type))
|
||||
{
|
||||
_freeLocals.Remove(local);
|
||||
return local;
|
||||
}
|
||||
}
|
||||
var newLocal = new Local(type);
|
||||
// _freeLocals.Add(newLocal);
|
||||
_method.Body.Variables.Add(newLocal);
|
||||
return newLocal;
|
||||
}
|
||||
|
||||
public void ReturnLocal(Local local)
|
||||
{
|
||||
_freeLocals.Add(local);
|
||||
}
|
||||
|
||||
public ScopeLocalVariables CreateScope()
|
||||
{
|
||||
return new ScopeLocalVariables(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 955da34fbde179641a94108ec53405ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fec4187cc1b96d5439ff908bcecd988f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
namespace Obfuz.EncryptionVM
|
||||
{
|
||||
public class EncryptionInstructionWithOpCode
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca9bd232ed2583f4bb5f330886a329e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f7b9d087de770a5488a9069ddf697c2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 981355cf75a9d234883b2a15c446f478
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
|
|
@ -29,7 +49,7 @@ namespace Obfuz.EncryptionVM.Instructions
|
|||
|
||||
public override void GenerateDecryptCode(List<string> lines, string indent)
|
||||
{
|
||||
lines.Add(indent + $"value = ((value - {_addValue}) ^ salt) - _secretKey[{_opKeyIndex}];");
|
||||
lines.Add(indent + $"value = ((value - {_addValue}) ^ salt) - _secretKey[{_opKeyIndex}];");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6bdbdc5fd983f044a87e7b8ab8647aeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cda67c0dd0cadd24ea02c2988e34281a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d806305e627be06469fb2d2c2cf98816
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bccff31b9f07fcf4f821cee671f82caf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,25 @@
|
|||
// Copyright 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: feafdb30f7b6d5143a89c7659bc16171
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,5 +1,24 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
|
|
@ -14,31 +33,14 @@ namespace Obfuz.EncryptionVM.Instructions
|
|||
{
|
||||
_multiValue = addValue;
|
||||
_opKeyIndex = opKeyIndex;
|
||||
_revertMultiValue = (int)ModInverseOdd((uint)addValue);
|
||||
_revertMultiValue = MathUtil.ModInverse32(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
|
||||
UnityEngine.Assertions.Assert.AreEqual(a, a * _multiValue * _revertMultiValue);
|
||||
}
|
||||
|
||||
public override int Encrypt(int value, int[] secretKey, int salt)
|
||||
|
|
@ -53,7 +55,7 @@ namespace Obfuz.EncryptionVM.Instructions
|
|||
|
||||
public override void GenerateEncryptCode(List<string> lines, string indent)
|
||||
{
|
||||
lines.Add(indent + $"value = value * {_multiValue} + _secretKey[{_opKeyIndex}] + salt;");
|
||||
lines.Add(indent + $"value = value * {_multiValue} + _secretKey[{_opKeyIndex}] + salt;");
|
||||
}
|
||||
|
||||
public override void GenerateDecryptCode(List<string> lines, string indent)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd5fdfad694e0ae469bf6ca04c913220
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,25 @@
|
|||
using System;
|
||||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
@ -21,7 +38,7 @@ namespace Obfuz.EncryptionVM.Instructions
|
|||
public MultipleRotateXorInstruction(int multipleValue, int index1, int rotateBitNum, int xorValue)
|
||||
{
|
||||
_multipleValue = multipleValue;
|
||||
_revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue);
|
||||
_revertMultipleValue = MathUtil.ModInverse32(multipleValue);
|
||||
_index1 = index1;
|
||||
_rotateBitNum = rotateBitNum;
|
||||
_xorValue = xorValue;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e3c8b55b35ff1554489fa657a714f485
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,25 @@
|
|||
using System;
|
||||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
@ -21,7 +38,7 @@ namespace Obfuz.EncryptionVM.Instructions
|
|||
public MultipleXorRotateInstruction(int multipleValue, int index1, int xorValue, int rotateBitNum)
|
||||
{
|
||||
_multipleValue = multipleValue;
|
||||
_revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue);
|
||||
_revertMultipleValue = MathUtil.ModInverse32(multipleValue);
|
||||
_index1 = index1;
|
||||
_rotateBitNum = rotateBitNum;
|
||||
_xorValue = xorValue;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: adc3dcde66795744fa4bdc753a2c599f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ad8f4dd724d7ff845b0dd65861054d37
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,28 @@
|
|||
// Copyright 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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
public class XorInstruction : EncryptionInstructionBase
|
||||
public class XorInstruction : EncryptionInstructionBase
|
||||
{
|
||||
private readonly int _xorValue;
|
||||
private readonly int _opKeyIndex;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2f16dd868e4473b45bfa9daaf7fabaf8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,8 +1,25 @@
|
|||
using System;
|
||||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Obfuz.EncryptionVM.Instructions
|
||||
{
|
||||
|
|
@ -21,7 +38,7 @@ namespace Obfuz.EncryptionVM.Instructions
|
|||
public XorMultipleRotateInstruction(int xorValue, int multipleValue, int index1, int rotateBitNum)
|
||||
{
|
||||
_multipleValue = multipleValue;
|
||||
_revertMultipleValue = (int)MultipleInstruction.ModInverseOdd((uint)multipleValue);
|
||||
_revertMultipleValue = MathUtil.ModInverse32(multipleValue);
|
||||
_index1 = index1;
|
||||
_rotateBitNum = rotateBitNum;
|
||||
_xorValue = xorValue;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3eb7e6d475cfc14459d3850c5964ba52
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,3 +1,23 @@
|
|||
// Copyright 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.
|
||||
|
||||
namespace Obfuz.EncryptionVM
|
||||
{
|
||||
public class VirtualMachine
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c6970e037654dcb49912783a40f3e1ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,11 +1,28 @@
|
|||
// Copyright 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.
|
||||
|
||||
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
|
||||
|
|
@ -55,7 +72,6 @@ namespace Obfuz.EncryptionVM
|
|||
|
||||
File.WriteAllText(outputFile, code, Encoding.UTF8);
|
||||
Debug.Log($"Generate EncryptionVM code to {outputFile}");
|
||||
UnityEditor.AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private string GenerateCode()
|
||||
|
|
@ -77,17 +93,16 @@ namespace Obfuz.EncryptionVM
|
|||
{");
|
||||
foreach (var opCode in _vm.opCodes)
|
||||
{
|
||||
lines.Add($@" case {opCode.code}:
|
||||
{{
|
||||
// {opCode.function.GetType().Name}");
|
||||
lines.Add($@" case {opCode.code}:
|
||||
{{
|
||||
// {opCode.function.GetType().Name}");
|
||||
AppendEncryptCode(lines, opCode.function);
|
||||
lines.Add(@" return value;
|
||||
}");
|
||||
lines.Add(@" return value;
|
||||
}");
|
||||
}
|
||||
|
||||
lines.Add(@"
|
||||
default:
|
||||
throw new System.Exception($""Invalid opCode:{opCode}"");
|
||||
default: throw new System.Exception($""Invalid opCode:{opCode}"");
|
||||
}
|
||||
}");
|
||||
}
|
||||
|
|
@ -101,17 +116,16 @@ namespace Obfuz.EncryptionVM
|
|||
{");
|
||||
foreach (var opCode in _vm.opCodes)
|
||||
{
|
||||
lines.Add($@" case {opCode.code}:
|
||||
{{
|
||||
// {opCode.function.GetType().Name}");
|
||||
lines.Add($@" case {opCode.code}:
|
||||
{{
|
||||
// {opCode.function.GetType().Name}");
|
||||
AppendDecryptCode(lines, opCode.function);
|
||||
lines.Add(@" return value;
|
||||
}");
|
||||
lines.Add(@" return value;
|
||||
}");
|
||||
}
|
||||
|
||||
lines.Add(@"
|
||||
default:
|
||||
throw new System.Exception($""Invalid opCode:{opCode}"");
|
||||
default: throw new System.Exception($""Invalid opCode:{opCode}"");
|
||||
}
|
||||
}");
|
||||
}
|
||||
|
|
@ -196,12 +210,12 @@ namespace Obfuz.EncryptionVM
|
|||
|
||||
private void AppendEncryptCode(List<string> lines, IEncryptionInstruction instruction)
|
||||
{
|
||||
instruction.GenerateEncryptCode(lines, " ");
|
||||
instruction.GenerateEncryptCode(lines, " ");
|
||||
}
|
||||
|
||||
private void AppendDecryptCode(List<string> lines, IEncryptionInstruction instruction)
|
||||
{
|
||||
instruction.GenerateDecryptCode(lines, " ");
|
||||
instruction.GenerateDecryptCode(lines, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2246e9d3369eb3c45bc19ae0748d76ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,10 +1,27 @@
|
|||
using NUnit.Framework;
|
||||
using Obfuz.EncryptionVM.Instructions;
|
||||
// Copyright 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.
|
||||
|
||||
using Obfuz.EncryptionVM.Instructions;
|
||||
using Obfuz.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Obfuz.EncryptionVM
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 77d95ff5cf0b3aa4e96a055e37c381ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,12 +1,26 @@
|
|||
// Copyright 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.
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -47,7 +61,7 @@ namespace Obfuz.EncryptionVM
|
|||
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++)
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
{
|
||||
arr[i] = (byte)i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4f86f4d6faf49764a915d5c675091375
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f47f2abd9eb7ba8469ba5cb1bb085d33
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Obfuz.GarbageCodeGeneration
|
||||
{
|
||||
|
||||
public class ConfigGarbageCodeGenerator : SpecificGarbageCodeGeneratorBase
|
||||
{
|
||||
|
||||
private readonly string[] _types = new string[]
|
||||
{
|
||||
"bool",
|
||||
"byte",
|
||||
"short",
|
||||
"int",
|
||||
"long",
|
||||
"float",
|
||||
"double",
|
||||
};
|
||||
|
||||
private string CreateRandomType(IRandom random)
|
||||
{
|
||||
return _types[random.NextInt(_types.Length)];
|
||||
}
|
||||
|
||||
private string GetReadMethodNameOfType(string type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "bool": return "ReadBoolean";
|
||||
case "byte": return "ReadByte";
|
||||
case "short": return "ReadInt16";
|
||||
case "int": return "ReadInt32";
|
||||
case "long": return "ReadInt64";
|
||||
case "float": return "ReadSingle";
|
||||
case "double": return "ReadDouble";
|
||||
default: throw new ArgumentException($"Unsupported type: {type}");
|
||||
}
|
||||
}
|
||||
class FieldGenerationInfo
|
||||
{
|
||||
public int index;
|
||||
public string name;
|
||||
public string type;
|
||||
}
|
||||
|
||||
class MethodGenerationInfo
|
||||
{
|
||||
public int index;
|
||||
public string name;
|
||||
}
|
||||
|
||||
protected override object CreateField(int index, IRandom random, GenerationParameters parameters)
|
||||
{
|
||||
return new FieldGenerationInfo
|
||||
{
|
||||
index = index,
|
||||
name = $"x{index}",
|
||||
type = CreateRandomType(random),
|
||||
};
|
||||
}
|
||||
|
||||
protected override object CreateMethod(int index, IRandom random, GenerationParameters parameters)
|
||||
{
|
||||
return new MethodGenerationInfo
|
||||
{
|
||||
index = index,
|
||||
name = $"Load{index}",
|
||||
};
|
||||
}
|
||||
|
||||
protected override void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent)
|
||||
{
|
||||
var fgi = (FieldGenerationInfo)field;
|
||||
result.AppendLine($"{indent}public {fgi.type} {fgi.name};");
|
||||
}
|
||||
|
||||
protected override void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent)
|
||||
{
|
||||
var mgi = (MethodGenerationInfo)method;
|
||||
result.AppendLine($"{indent}public void {mgi.name}(BinaryReader reader)");
|
||||
result.AppendLine($"{indent}{{");
|
||||
|
||||
string indent2 = indent + " ";
|
||||
result.AppendLine($"{indent2}int a = 0;");
|
||||
result.AppendLine($"{indent2}int b = 0;");
|
||||
int maxN = 100;
|
||||
var shuffledFields = cgi.Fields.ToList();
|
||||
RandomUtil.ShuffleList(shuffledFields, random);
|
||||
foreach (FieldGenerationInfo fgi in shuffledFields)
|
||||
{
|
||||
result.AppendLine($"{indent2}this.{fgi.name} = reader.{GetReadMethodNameOfType(fgi.type)}();");
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}a = b * {random.NextInt(maxN)} + reader.ReadInt32();");
|
||||
result.AppendLine($"{indent2}b = a * reader.ReadInt32() + {random.NextInt(maxN)};");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}a += {random.NextInt(0, 10000)};");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}b += {random.NextInt(0, 10000)};");
|
||||
}
|
||||
}
|
||||
|
||||
result.AppendLine($"{indent}}}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 327cb4a465ff23944a5fea30bf3beeeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 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.
|
||||
|
||||
using Obfuz.Settings;
|
||||
using Obfuz.Utils;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obfuz.GarbageCodeGeneration
|
||||
{
|
||||
|
||||
public class GarbageCodeGenerator
|
||||
{
|
||||
private const int CodeGenerationSecretKeyLength = 1024;
|
||||
|
||||
private readonly GarbageCodeGenerationSettings _settings;
|
||||
private readonly int[] _intGenerationSecretKey;
|
||||
|
||||
public GarbageCodeGenerator(GarbageCodeGenerationSettings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
byte[] byteGenerationSecretKey = KeyGenerator.GenerateKey(settings.codeGenerationSecret, CodeGenerationSecretKeyLength);
|
||||
_intGenerationSecretKey = KeyGenerator.ConvertToIntKey(byteGenerationSecretKey);
|
||||
}
|
||||
|
||||
public void Generate()
|
||||
{
|
||||
GenerateTask(_settings.defaultTask);
|
||||
if (_settings.additionalTasks != null && _settings.additionalTasks.Length > 0)
|
||||
{
|
||||
foreach (var task in _settings.additionalTasks)
|
||||
{
|
||||
GenerateTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanCodes()
|
||||
{
|
||||
Debug.Log($"Cleaning generated garbage codes begin.");
|
||||
if (_settings.defaultTask != null)
|
||||
{
|
||||
FileUtil.RemoveDir(_settings.defaultTask.outputPath, true);
|
||||
}
|
||||
if (_settings.additionalTasks != null && _settings.additionalTasks.Length > 0)
|
||||
{
|
||||
foreach (var task in _settings.additionalTasks)
|
||||
{
|
||||
FileUtil.RemoveDir(task.outputPath, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateTask(GarbageCodeGenerationTask task)
|
||||
{
|
||||
Debug.Log($"Generating garbage code with seed: {task.codeGenerationRandomSeed}, class count: {task.classCount}, method count per class: {task.methodCountPerClass}, types: {task.garbageCodeType}, output path: {task.outputPath}");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(task.outputPath))
|
||||
{
|
||||
throw new Exception("outputPath of GarbageCodeGenerationTask is empty!");
|
||||
}
|
||||
|
||||
var generator = CreateSpecificCodeGenerator(task.garbageCodeType);
|
||||
|
||||
var parameters = new GenerationParameters
|
||||
{
|
||||
random = new RandomWithKey(_intGenerationSecretKey, task.codeGenerationRandomSeed),
|
||||
classNamespace = task.classNamespace,
|
||||
classNamePrefix = task.classNamePrefix,
|
||||
classCount = task.classCount,
|
||||
methodCountPerClass = task.methodCountPerClass,
|
||||
fieldCountPerClass = task.fieldCountPerClass,
|
||||
outputPath = task.outputPath,
|
||||
};
|
||||
generator.Generate(parameters);
|
||||
|
||||
Debug.Log($"Generate garbage code end.");
|
||||
}
|
||||
|
||||
private ISpecificGarbageCodeGenerator CreateSpecificCodeGenerator(GarbageCodeType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GarbageCodeType.Config: return new ConfigGarbageCodeGenerator();
|
||||
case GarbageCodeType.UI: return new UIGarbageCodeGenerator();
|
||||
default: throw new NotSupportedException($"Garbage code type {type} is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ff64fd1e6f7b8874db5a5228fab159f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
|
||||
namespace Obfuz.GarbageCodeGeneration
|
||||
{
|
||||
public class GenerationParameters
|
||||
{
|
||||
public IRandom random;
|
||||
|
||||
public string classNamespace;
|
||||
public string classNamePrefix;
|
||||
public int classCount;
|
||||
public int methodCountPerClass;
|
||||
public int fieldCountPerClass;
|
||||
public string outputPath;
|
||||
}
|
||||
|
||||
public interface ISpecificGarbageCodeGenerator
|
||||
{
|
||||
void Generate(GenerationParameters parameters);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 74a17802b5aab2e40a3c89e0ddbcec0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obfuz.GarbageCodeGeneration
|
||||
{
|
||||
public abstract class SpecificGarbageCodeGeneratorBase : ISpecificGarbageCodeGenerator
|
||||
{
|
||||
protected interface IClassGenerationInfo
|
||||
{
|
||||
string Namespace { get; set; }
|
||||
|
||||
string Name { get; set; }
|
||||
|
||||
IList<object> Fields { get; set; }
|
||||
|
||||
IList<object> Methods { get; set; }
|
||||
}
|
||||
|
||||
protected class ClassGenerationInfo : IClassGenerationInfo
|
||||
{
|
||||
public string Namespace { get; set; }
|
||||
public string Name { get; set; }
|
||||
public IList<object> Fields { get; set; } = new List<object>();
|
||||
public IList<object> Methods { get; set; } = new List<object>();
|
||||
}
|
||||
|
||||
public virtual void Generate(GenerationParameters parameters)
|
||||
{
|
||||
FileUtil.RecreateDir(parameters.outputPath);
|
||||
|
||||
for (int i = 0; i < parameters.classCount; i++)
|
||||
{
|
||||
Debug.Log($"[{GetType().Name}] Generating class {i}");
|
||||
var localRandom = new RandomWithKey(((RandomWithKey)parameters.random).Key, parameters.random.NextInt());
|
||||
string outputFile = $"{parameters.outputPath}/__GeneratedGarbageClass_{i}.cs";
|
||||
var result = new StringBuilder(64 * 1024);
|
||||
GenerateClass(i, localRandom, result, parameters);
|
||||
File.WriteAllText(outputFile, result.ToString(), Encoding.UTF8);
|
||||
Debug.Log($"[{GetType().Name}] Generated class {i} to {outputFile}");
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract object CreateField(int index, IRandom random, GenerationParameters parameters);
|
||||
|
||||
protected abstract object CreateMethod(int index, IRandom random, GenerationParameters parameters);
|
||||
|
||||
protected virtual IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters)
|
||||
{
|
||||
var cgi = new ClassGenerationInfo
|
||||
{
|
||||
Namespace = classNamespace,
|
||||
Name = className,
|
||||
};
|
||||
|
||||
for (int i = 0; i < parameters.fieldCountPerClass; i++)
|
||||
{
|
||||
cgi.Fields.Add(CreateField(i, random, parameters));
|
||||
}
|
||||
|
||||
for (int i = 0; i < parameters.methodCountPerClass; i++)
|
||||
{
|
||||
cgi.Methods.Add(CreateMethod(i, random, parameters));
|
||||
}
|
||||
|
||||
return cgi;
|
||||
}
|
||||
|
||||
protected virtual void GenerateClass(int classIndex, IRandom random, StringBuilder result, GenerationParameters parameters)
|
||||
{
|
||||
IClassGenerationInfo cgi = CreateClassGenerationInfo(parameters.classNamespace, $"{parameters.classNamePrefix}{classIndex}", random, parameters);
|
||||
result.AppendLine("using System;");
|
||||
result.AppendLine("using System.Collections.Generic;");
|
||||
result.AppendLine("using System.Linq;");
|
||||
result.AppendLine("using System.IO;");
|
||||
result.AppendLine("using UnityEngine;");
|
||||
|
||||
GenerateUsings(result, cgi);
|
||||
|
||||
result.AppendLine($"namespace {cgi.Namespace}");
|
||||
result.AppendLine("{");
|
||||
result.AppendLine($" public class {cgi.Name}");
|
||||
result.AppendLine(" {");
|
||||
|
||||
string indent = " ";
|
||||
foreach (object field in cgi.Fields)
|
||||
{
|
||||
GenerateField(result, cgi, random, field, indent);
|
||||
}
|
||||
foreach (object method in cgi.Methods)
|
||||
{
|
||||
GenerateMethod(result, cgi, random, method, indent);
|
||||
}
|
||||
result.AppendLine(" }");
|
||||
result.AppendLine("}");
|
||||
}
|
||||
|
||||
protected abstract void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi);
|
||||
|
||||
protected abstract void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent);
|
||||
|
||||
protected abstract void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: bae18fd49482f00439d37f28a6a78d9b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
// Copyright 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.
|
||||
|
||||
using Obfuz.Utils;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Obfuz.GarbageCodeGeneration
|
||||
{
|
||||
|
||||
public class UIGarbageCodeGenerator : SpecificGarbageCodeGeneratorBase
|
||||
{
|
||||
/*
|
||||
*
|
||||
* public Button b1;
|
||||
public Image b2;
|
||||
public RawImage b30;
|
||||
public Text b3;
|
||||
public Slider b4;
|
||||
public ScrollRect b5;
|
||||
public Scrollbar b6;
|
||||
public Mask b7;
|
||||
public RectMask2D b70;
|
||||
public Canvas b8;
|
||||
public CanvasGroup b9;
|
||||
public RectTransform b10;
|
||||
public Transform b11;
|
||||
public GameObject b12;
|
||||
*/
|
||||
|
||||
private readonly string[] _types = new string[]
|
||||
{
|
||||
"Button",
|
||||
"Image",
|
||||
"RawImage",
|
||||
"Text",
|
||||
"Slider",
|
||||
"ScrollRect",
|
||||
"Scrollbar",
|
||||
"Mask",
|
||||
"RectMask2D",
|
||||
"Canvas",
|
||||
"CanvasGroup",
|
||||
"RectTransform",
|
||||
//"Transform",
|
||||
//"GameObject",
|
||||
};
|
||||
|
||||
private string CreateRandomType(IRandom random)
|
||||
{
|
||||
return _types[random.NextInt(_types.Length)];
|
||||
}
|
||||
|
||||
private string GetReadMethodNameOfType(string type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "bool": return "ReadBoolean";
|
||||
case "byte": return "ReadByte";
|
||||
case "short": return "ReadInt16";
|
||||
case "int": return "ReadInt32";
|
||||
case "long": return "ReadInt64";
|
||||
case "float": return "ReadSingle";
|
||||
case "double": return "ReadDouble";
|
||||
default: throw new ArgumentException($"Unsupported type: {type}");
|
||||
}
|
||||
}
|
||||
class FieldGenerationInfo
|
||||
{
|
||||
public int index;
|
||||
public string name;
|
||||
public string type;
|
||||
}
|
||||
|
||||
class MethodGenerationInfo
|
||||
{
|
||||
public int index;
|
||||
public string name;
|
||||
}
|
||||
|
||||
protected override object CreateField(int index, IRandom random, GenerationParameters parameters)
|
||||
{
|
||||
return new FieldGenerationInfo
|
||||
{
|
||||
index = index,
|
||||
name = $"x{index}",
|
||||
type = CreateRandomType(random),
|
||||
};
|
||||
}
|
||||
|
||||
protected override object CreateMethod(int index, IRandom random, GenerationParameters parameters)
|
||||
{
|
||||
return new MethodGenerationInfo
|
||||
{
|
||||
index = index,
|
||||
name = $"Init{index}",
|
||||
};
|
||||
}
|
||||
|
||||
protected override void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi)
|
||||
{
|
||||
result.AppendLine("using UnityEngine.UI;");
|
||||
}
|
||||
|
||||
protected override void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent)
|
||||
{
|
||||
var fgi = (FieldGenerationInfo)field;
|
||||
result.AppendLine($"{indent}public {fgi.type} {fgi.name};");
|
||||
}
|
||||
|
||||
protected override void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent)
|
||||
{
|
||||
var mgi = (MethodGenerationInfo)method;
|
||||
result.AppendLine($"{indent}public void {mgi.name}(GameObject go)");
|
||||
result.AppendLine($"{indent}{{");
|
||||
|
||||
string indent2 = indent + " ";
|
||||
result.AppendLine($"{indent2}int a = 0;");
|
||||
result.AppendLine($"{indent2}int b = 0;");
|
||||
int maxN = 100;
|
||||
var shuffledFields = cgi.Fields.ToList();
|
||||
RandomUtil.ShuffleList(shuffledFields, random);
|
||||
foreach (FieldGenerationInfo fgi in shuffledFields)
|
||||
{
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}this.{fgi.name} = go.transform.Find(\"ui/{fgi.name}\").GetComponent<{fgi.type}>();");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendLine($"{indent2}this.{fgi.name} = go.GetComponent<{fgi.type}>();");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}a = b * {random.NextInt(maxN)} + go.layer;");
|
||||
result.AppendLine($"{indent2}b = a * go.layer + {random.NextInt(maxN)};");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}a *= {random.NextInt(0, 10000)};");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}b /= {random.NextInt(0, 10000)};");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}a = a * b << {random.NextInt(0, 10000)};");
|
||||
}
|
||||
if (random.NextInPercentage(0.5f))
|
||||
{
|
||||
result.AppendLine($"{indent2}b = a / b & {random.NextInt(0, 10000)};");
|
||||
}
|
||||
}
|
||||
|
||||
result.AppendLine($"{indent}}}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5071c4b9c7f5aef409f3e7fdb45ecd8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,9 +1,24 @@
|
|||
// Copyright 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.
|
||||
|
||||
using Obfuz.ObfusPasses;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Obfuz
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b7003f9503025794b8aa775d9ade335c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 120b2dcffd582e84dbb92003240824d1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,54 +1,40 @@
|
|||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Emit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.ObfusPasses
|
||||
{
|
||||
public abstract class BasicBlockObfuscationPassBase : ObfuscationPassBase
|
||||
public abstract class BasicBlockObfuscationPassBase : ObfuscationMethodPassBase
|
||||
{
|
||||
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 virtual bool ComputeBlockInLoop => true;
|
||||
|
||||
protected abstract bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, BasicBlock block, int instructionIndex,
|
||||
IList<Instruction> globalInstructions, List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions);
|
||||
|
||||
private void ObfuscateData(MethodDef method)
|
||||
protected override void ObfuscateData(MethodDef method)
|
||||
{
|
||||
BasicBlockCollection bbc = new BasicBlockCollection(method);
|
||||
BasicBlockCollection bbc = new BasicBlockCollection(method, ComputeBlockInLoop);
|
||||
|
||||
IList<Instruction> instructions = method.Body.Instructions;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ae83aaf003665614092aabceabff3cf8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: cf68e45551825c547b137f6e5189937e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,31 +1,56 @@
|
|||
// Copyright 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.
|
||||
|
||||
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;
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.ObfusPasses.CallObfus
|
||||
{
|
||||
public class CallObfusPass : BasicBlockObfuscationPassBase
|
||||
class ObfusMethodContext
|
||||
{
|
||||
private readonly List<string> _configFiles;
|
||||
private readonly int _obfuscationLevel;
|
||||
public MethodDef method;
|
||||
public LocalVariableAllocator localVariableAllocator;
|
||||
public IRandom localRandom;
|
||||
public EncryptionScopeInfo encryptionScope;
|
||||
}
|
||||
|
||||
public class CallObfusPass : ObfuscationMethodPassBase
|
||||
{
|
||||
public static CallObfuscationSettingsFacade CurrentSettings { get; private set; }
|
||||
|
||||
private readonly CallObfuscationSettingsFacade _settings;
|
||||
private SpecialWhiteListMethodCalculator _specialWhiteListMethodCache;
|
||||
|
||||
private IObfuscator _dynamicProxyObfuscator;
|
||||
private IObfuscationPolicy _dynamicProxyPolicy;
|
||||
|
||||
public override ObfuscationPassType Type => ObfuscationPassType.CallObfus;
|
||||
|
||||
public CallObfusPass(CallObfuscationSettings settings)
|
||||
public CallObfusPass(CallObfuscationSettingsFacade settings)
|
||||
{
|
||||
_configFiles = settings.ruleFiles.ToList();
|
||||
_obfuscationLevel = settings.obfuscationLevel;
|
||||
_settings = settings;
|
||||
CurrentSettings = settings;
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
|
|
@ -36,8 +61,74 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
public override void Start()
|
||||
{
|
||||
var ctx = ObfuscationPassContext.Current;
|
||||
_dynamicProxyObfuscator = new DefaultCallProxyObfuscator(ctx.encryptionScopeProvider, ctx.constFieldAllocator, ctx.moduleEntityManager, _obfuscationLevel);
|
||||
_dynamicProxyPolicy = new ConfigurableObfuscationPolicy(ctx.assembliesToObfuscate, _configFiles);
|
||||
|
||||
_specialWhiteListMethodCache = new SpecialWhiteListMethodCalculator(ctx.coreSettings.targetRuntime, _settings.obfuscateCallToMethodInMscorlib);
|
||||
_dynamicProxyObfuscator = CreateObfuscator(ctx, _settings.proxyMode);
|
||||
_dynamicProxyPolicy = new ConfigurableObfuscationPolicy(ctx.coreSettings.assembliesToObfuscate, _settings.ruleFiles);
|
||||
}
|
||||
|
||||
private IObfuscator CreateObfuscator(ObfuscationPassContext ctx, ProxyMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case ProxyMode.Dispatch:
|
||||
return new DispatchProxyObfuscator(ctx.moduleEntityManager);
|
||||
case ProxyMode.Delegate:
|
||||
return new DelegateProxyObfuscator(ctx.moduleEntityManager);
|
||||
default:
|
||||
throw new System.NotSupportedException($"Unsupported proxy mode: {mode}");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ObfuscateData(MethodDef method)
|
||||
{
|
||||
BasicBlockCollection bbc = new BasicBlockCollection(method, false);
|
||||
|
||||
IList<Instruction> instructions = method.Body.Instructions;
|
||||
|
||||
var outputInstructions = new List<Instruction>();
|
||||
var totalFinalInstructions = new List<Instruction>();
|
||||
|
||||
ObfuscationPassContext ctx = ObfuscationPassContext.Current;
|
||||
var encryptionScope = ctx.moduleEntityManager.EncryptionScopeProvider.GetScope(method.Module);
|
||||
var localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method));
|
||||
var omc = new ObfusMethodContext
|
||||
{
|
||||
method = method,
|
||||
localVariableAllocator = new LocalVariableAllocator(method),
|
||||
localRandom = localRandom,
|
||||
encryptionScope = encryptionScope,
|
||||
};
|
||||
Instruction lastInst = null;
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
{
|
||||
Instruction inst = instructions[i];
|
||||
BasicBlock block = bbc.GetBasicBlockByInstruction(inst);
|
||||
outputInstructions.Clear();
|
||||
if (TryObfuscateInstruction(method, lastInst, inst, outputInstructions, omc))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
lastInst = inst;
|
||||
}
|
||||
|
||||
instructions.Clear();
|
||||
foreach (var obInst in totalFinalInstructions)
|
||||
{
|
||||
instructions.Add(obInst);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool NeedObfuscateMethod(MethodDef method)
|
||||
|
|
@ -45,8 +136,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
return _dynamicProxyPolicy.NeedObfuscateCallInMethod(method);
|
||||
}
|
||||
|
||||
protected override bool TryObfuscateInstruction(MethodDef callerMethod, Instruction inst, BasicBlock block,
|
||||
int instructionIndex, IList<Instruction> globalInstructions, List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions)
|
||||
private bool TryObfuscateInstruction(MethodDef callerMethod, Instruction lastInst, Instruction inst, List<Instruction> outputInstructions, ObfusMethodContext ctx)
|
||||
{
|
||||
IMethod calledMethod = inst.Operand as IMethod;
|
||||
if (calledMethod == null || !calledMethod.IsMethod)
|
||||
|
|
@ -68,7 +158,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
}
|
||||
case Code.Callvirt:
|
||||
{
|
||||
if (instructionIndex > 0 && globalInstructions[instructionIndex - 1].OpCode.Code == Code.Constrained)
|
||||
if (lastInst != null && lastInst.OpCode.Code == Code.Constrained)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -78,15 +168,19 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
default: return false;
|
||||
}
|
||||
|
||||
if (!_dynamicProxyPolicy.NeedObfuscateCalledMethod(callerMethod, calledMethod, callVir, block.inLoop))
|
||||
|
||||
if (_specialWhiteListMethodCache.IsInWhiteList(calledMethod))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ObfuscationCachePolicy cachePolicy = _dynamicProxyPolicy.GetMethodObfuscationCachePolicy(callerMethod);
|
||||
bool cachedCallIndex = block.inLoop ? cachePolicy.cacheInLoop : cachePolicy.cacheNotInLoop;
|
||||
_dynamicProxyObfuscator.Obfuscate(callerMethod, calledMethod, callVir, cachedCallIndex, outputInstructions);
|
||||
return true;
|
||||
|
||||
if (!_dynamicProxyPolicy.NeedObfuscateCalledMethod(callerMethod, calledMethod, callVir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _dynamicProxyObfuscator.Obfuscate(callerMethod, calledMethod, callVir, outputInstructions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 112178b770868274fb8119a4997a3420
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,13 +1,30 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using Obfuz.Conf;
|
||||
using Obfuz.Settings;
|
||||
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
|
||||
{
|
||||
|
|
@ -17,7 +34,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
{
|
||||
public string name;
|
||||
public NameMatcher nameMatcher;
|
||||
public bool? obfuscateNone;
|
||||
public bool? obfuscate;
|
||||
public List<WhiteListType> types = new List<WhiteListType>();
|
||||
}
|
||||
|
||||
|
|
@ -25,7 +42,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
{
|
||||
public string name;
|
||||
public NameMatcher nameMatcher;
|
||||
public bool? obfuscateNone;
|
||||
public bool? obfuscate;
|
||||
public List<WhiteListMethod> methods = new List<WhiteListMethod>();
|
||||
}
|
||||
|
||||
|
|
@ -33,33 +50,17 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
{
|
||||
public string name;
|
||||
public NameMatcher nameMatcher;
|
||||
public bool? obfuscate;
|
||||
}
|
||||
|
||||
class ObfuscationRule : IRule<ObfuscationRule>
|
||||
{
|
||||
public bool? disableObfuscation;
|
||||
public bool? obfuscateCallInLoop;
|
||||
public bool? cacheCallIndexInLoop;
|
||||
public bool? cacheCallIndexNotLoop;
|
||||
public ObfuscationLevel? obfuscationLevel;
|
||||
|
||||
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;
|
||||
}
|
||||
if (obfuscationLevel == null)
|
||||
obfuscationLevel = parentRule.obfuscationLevel;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,10 +79,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
|
||||
private static readonly ObfuscationRule s_default = new ObfuscationRule()
|
||||
{
|
||||
disableObfuscation = false,
|
||||
obfuscateCallInLoop = true,
|
||||
cacheCallIndexInLoop = true,
|
||||
cacheCallIndexNotLoop = false,
|
||||
obfuscationLevel = ObfuscationLevel.Basic,
|
||||
};
|
||||
|
||||
private readonly XmlAssemblyTypeMethodRuleParser<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule> _configParser;
|
||||
|
|
@ -89,11 +87,12 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
private ObfuscationRule _global;
|
||||
private readonly List<WhiteListAssembly> _whiteListAssemblies = new List<WhiteListAssembly>();
|
||||
|
||||
private readonly Dictionary<IMethod, bool> _whiteListMethodCache = new Dictionary<IMethod, bool>(MethodEqualityComparer.CompareDeclaringTypes);
|
||||
private readonly CachedDictionary<IMethod, bool> _whiteListMethodCache;
|
||||
private readonly Dictionary<MethodDef, ObfuscationRule> _methodRuleCache = new Dictionary<MethodDef, ObfuscationRule>();
|
||||
|
||||
public ConfigurableObfuscationPolicy(List<string> toObfuscatedAssemblyNames, List<string> xmlConfigFiles)
|
||||
{
|
||||
_whiteListMethodCache = new CachedDictionary<IMethod, bool>(MethodEqualityComparer.CompareDeclaringTypes, this.ComputeIsInWhiteList);
|
||||
_configParser = new XmlAssemblyTypeMethodRuleParser<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule>(toObfuscatedAssemblyNames,
|
||||
ParseObfuscationRule, ParseGlobalElement);
|
||||
LoadConfigs(xmlConfigFiles);
|
||||
|
|
@ -112,6 +111,28 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
_global.InheritParent(s_default);
|
||||
}
|
||||
_configParser.InheritParentRules(_global);
|
||||
InheritWhitelistRules();
|
||||
}
|
||||
|
||||
private void InheritWhitelistRules()
|
||||
{
|
||||
foreach (var ass in _whiteListAssemblies)
|
||||
{
|
||||
foreach (var type in ass.types)
|
||||
{
|
||||
if (type.obfuscate == null)
|
||||
{
|
||||
type.obfuscate = ass.obfuscate;
|
||||
}
|
||||
foreach (var method in type.methods)
|
||||
{
|
||||
if (method.obfuscate == null)
|
||||
{
|
||||
method.obfuscate = type.obfuscate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseGlobalElement(string configFile, XmlElement ele)
|
||||
|
|
@ -127,21 +148,9 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele)
|
||||
{
|
||||
var rule = new ObfuscationRule();
|
||||
if (ele.HasAttribute("disableObfuscation"))
|
||||
if (ele.HasAttribute("obfuscationLevel"))
|
||||
{
|
||||
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"));
|
||||
rule.obfuscationLevel = ConfigUtil.ParseObfuscationLevel(ele.GetAttribute("obfuscationLevel"));
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
|
@ -172,10 +181,9 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
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"));
|
||||
}
|
||||
|
||||
ass.obfuscate = ConfigUtil.ParseNullableBool(element.GetAttribute("obfuscate")) ?? false;
|
||||
|
||||
foreach (XmlNode node in element.ChildNodes)
|
||||
{
|
||||
if (!(node is XmlElement ele))
|
||||
|
|
@ -199,10 +207,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
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"));
|
||||
}
|
||||
type.obfuscate = ConfigUtil.ParseNullableBool(element.GetAttribute("obfuscate"));
|
||||
|
||||
foreach (XmlNode node in element.ChildNodes)
|
||||
{
|
||||
|
|
@ -229,6 +234,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
var method = new WhiteListMethod();
|
||||
method.name = element.GetAttribute("name");
|
||||
method.nameMatcher = new NameMatcher(method.name);
|
||||
method.obfuscate = ConfigUtil.ParseNullableBool(element.GetAttribute("obfuscate"));
|
||||
return method;
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +242,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
{
|
||||
if (!_methodRuleCache.TryGetValue(method, out var rule))
|
||||
{
|
||||
rule = _configParser.GetMethodRule(method, s_default);
|
||||
rule = _configParser.GetMethodRule(method, _global);
|
||||
_methodRuleCache[method] = rule;
|
||||
}
|
||||
return rule;
|
||||
|
|
@ -245,39 +251,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
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<T>.Enumerator GetEnumerator()
|
||||
if (methodName == "GetEnumerator")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return rule.obfuscationLevel != null && rule.obfuscationLevel.Value >= ObfuscationLevel.Basic;
|
||||
}
|
||||
|
||||
private bool ComputeIsInWhiteList(IMethod calledMethod)
|
||||
|
|
@ -305,11 +279,6 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
|
||||
TypeDef typeDef = declaringType.ResolveTypeDef();
|
||||
|
||||
if (IsSpecialNotObfuscatedMethod(typeDef, calledMethod))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
string assName = typeDef.Module.Assembly.Name;
|
||||
string typeFullName = typeDef.FullName;
|
||||
string methodName = calledMethod.Name;
|
||||
|
|
@ -319,50 +288,29 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
{
|
||||
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 !method.obfuscate.Value;
|
||||
}
|
||||
}
|
||||
return !type.obfuscate.Value;
|
||||
}
|
||||
return !ass.obfuscate.Value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsInWhiteList(IMethod method)
|
||||
public override bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir)
|
||||
{
|
||||
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)
|
||||
if (_whiteListMethodCache.GetValue(calledMethod))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d9ea12b16c4b296459db8a60fb1615d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using System.Collections.Generic;
|
||||
using Obfuz.Utils;
|
||||
using Obfuz.Emit;
|
||||
using Obfuz.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obfuz.ObfusPasses.CallObfus
|
||||
{
|
||||
public class DefaultCallProxyObfuscator : ObfuscatorBase
|
||||
{
|
||||
private readonly EncryptionScopeProvider _encryptionScopeProvider;
|
||||
private readonly ConstFieldAllocator _constFieldAllocator;
|
||||
private readonly CallProxyAllocator _proxyCallAllocator;
|
||||
private readonly GroupByModuleEntityManager _moduleEntityManager;
|
||||
|
||||
public DefaultCallProxyObfuscator(EncryptionScopeProvider encryptionScopeProvider, ConstFieldAllocator constFieldAllocator, GroupByModuleEntityManager moduleEntityManager, int encryptionLevel)
|
||||
{
|
||||
_encryptionScopeProvider = encryptionScopeProvider;
|
||||
_constFieldAllocator = constFieldAllocator;
|
||||
_moduleEntityManager = moduleEntityManager;
|
||||
_proxyCallAllocator = new CallProxyAllocator(encryptionScopeProvider, moduleEntityManager, encryptionLevel);
|
||||
}
|
||||
|
||||
public override void Done()
|
||||
{
|
||||
_proxyCallAllocator.Done();
|
||||
}
|
||||
|
||||
public override void Obfuscate(MethodDef callerMethod, IMethod calledMethod, bool callVir, bool needCacheCall, List<Instruction> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Data;
|
||||
using Obfuz.Emit;
|
||||
using Obfuz.Settings;
|
||||
using Obfuz.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Obfuz.ObfusPasses.CallObfus
|
||||
{
|
||||
|
||||
struct DelegateProxyMethodData
|
||||
{
|
||||
public readonly FieldDef delegateInstanceField;
|
||||
public readonly MethodDef delegateInvokeMethod;
|
||||
|
||||
public DelegateProxyMethodData(FieldDef delegateInstanceField, MethodDef delegateInvokeMethod)
|
||||
{
|
||||
this.delegateInstanceField = delegateInstanceField;
|
||||
this.delegateInvokeMethod = delegateInvokeMethod;
|
||||
}
|
||||
}
|
||||
|
||||
class DelegateProxyAllocator : GroupByModuleEntityBase
|
||||
{
|
||||
private readonly CachedDictionary<MethodSig, TypeDef> _delegateTypes;
|
||||
private readonly HashSet<string> _allocatedDelegateNames = new HashSet<string>();
|
||||
|
||||
private TypeDef _delegateInstanceHolderType;
|
||||
private bool _done;
|
||||
|
||||
class CallInfo
|
||||
{
|
||||
public string key1;
|
||||
public int key2;
|
||||
public IMethod method;
|
||||
public bool callVir;
|
||||
|
||||
public int index;
|
||||
public TypeDef delegateType;
|
||||
public FieldDef delegateInstanceField;
|
||||
public MethodDef delegateInvokeMethod;
|
||||
public MethodDef proxyMethod;
|
||||
}
|
||||
private readonly Dictionary<MethodKey, CallInfo> _callMethods = new Dictionary<MethodKey, CallInfo>();
|
||||
private CallObfuscationSettingsFacade _settings;
|
||||
|
||||
public DelegateProxyAllocator()
|
||||
{
|
||||
_delegateTypes = new CachedDictionary<MethodSig, TypeDef>(SignatureEqualityComparer.Instance, CreateDelegateForSignature);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
_delegateInstanceHolderType = CreateDelegateInstanceHolderTypeDef();
|
||||
_settings = CallObfusPass.CurrentSettings;
|
||||
}
|
||||
|
||||
private string AllocateDelegateTypeName(MethodSig delegateInvokeSig)
|
||||
{
|
||||
uint hashCode = (uint)SignatureEqualityComparer.Instance.GetHashCode(delegateInvokeSig);
|
||||
string typeName = $"$Obfuz$Delegate_{hashCode}";
|
||||
if (_allocatedDelegateNames.Add(typeName))
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
typeName = $"$Obfuz$Delegate_{hashCode}_{i}";
|
||||
if (_allocatedDelegateNames.Add(typeName))
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TypeDef CreateDelegateForSignature(MethodSig delegateInvokeSig)
|
||||
{
|
||||
ModuleDef mod = Module;
|
||||
using (var scope = new DisableTypeDefFindCacheScope(mod))
|
||||
{
|
||||
|
||||
string typeName = AllocateDelegateTypeName(delegateInvokeSig);
|
||||
mod.Import(typeof(MulticastDelegate));
|
||||
|
||||
TypeDef delegateType = new TypeDefUser("", typeName, mod.CorLibTypes.GetTypeRef("System", "MulticastDelegate"));
|
||||
delegateType.Attributes = TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public;
|
||||
mod.Types.Add(delegateType);
|
||||
|
||||
MethodDef ctor = new MethodDefUser(
|
||||
".ctor",
|
||||
MethodSig.CreateInstance(mod.CorLibTypes.Void, mod.CorLibTypes.Object, mod.CorLibTypes.IntPtr),
|
||||
MethodImplAttributes.Runtime,
|
||||
MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Public
|
||||
);
|
||||
ctor.DeclaringType = delegateType;
|
||||
|
||||
|
||||
MethodDef invokeMethod = new MethodDefUser(
|
||||
"Invoke",
|
||||
MethodSig.CreateInstance(delegateInvokeSig.RetType, delegateInvokeSig.Params.ToArray()),
|
||||
MethodImplAttributes.Runtime,
|
||||
MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.Virtual
|
||||
);
|
||||
invokeMethod.DeclaringType = delegateType;
|
||||
return delegateType;
|
||||
}
|
||||
}
|
||||
|
||||
private TypeDef CreateDelegateInstanceHolderTypeDef()
|
||||
{
|
||||
ModuleDef mod = Module;
|
||||
using (var scope = new DisableTypeDefFindCacheScope(mod))
|
||||
{
|
||||
string typeName = "$Obfuz$DelegateInstanceHolder";
|
||||
TypeDef holderType = new TypeDefUser("", typeName, mod.CorLibTypes.Object.ToTypeDefOrRef());
|
||||
holderType.Attributes = TypeAttributes.Class | TypeAttributes.Public;
|
||||
mod.Types.Add(holderType);
|
||||
return holderType;
|
||||
}
|
||||
}
|
||||
|
||||
private string AllocateFieldName(IMethod method, bool callVir)
|
||||
{
|
||||
uint hashCode = (uint)MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method);
|
||||
string typeName = $"$Obfuz$Delegate$Field_{hashCode}_{callVir}";
|
||||
if (_allocatedDelegateNames.Add(typeName))
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
typeName = $"$Obfuz$Delegate$Field_{hashCode}_{callVir}_{i}";
|
||||
if (_allocatedDelegateNames.Add(typeName))
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MethodDef CreateProxyMethod(string name, IMethod calledMethod, bool callVir, MethodSig delegateInvokeSig)
|
||||
{
|
||||
var proxyMethod = new MethodDefUser(name, delegateInvokeSig, MethodImplAttributes.Managed, MethodAttributes.Public | MethodAttributes.Static);
|
||||
var body = new CilBody();
|
||||
proxyMethod.Body = body;
|
||||
var ins = body.Instructions;
|
||||
|
||||
foreach (Parameter param in proxyMethod.Parameters)
|
||||
{
|
||||
ins.Add(Instruction.Create(OpCodes.Ldarg, param));
|
||||
}
|
||||
|
||||
ins.Add(Instruction.Create(callVir ? OpCodes.Callvirt : OpCodes.Call, calledMethod));
|
||||
ins.Add(Instruction.Create(OpCodes.Ret));
|
||||
return proxyMethod;
|
||||
}
|
||||
|
||||
public DelegateProxyMethodData Allocate(IMethod method, bool callVir, MethodSig delegateInvokeSig)
|
||||
{
|
||||
var key = new MethodKey(method, callVir);
|
||||
if (!_callMethods.TryGetValue(key, out var callInfo))
|
||||
{
|
||||
TypeDef delegateType = _delegateTypes.GetValue(delegateInvokeSig);
|
||||
MethodDef delegateInvokeMethod = delegateType.FindMethod("Invoke");
|
||||
string fieldName = AllocateFieldName(method, callVir);
|
||||
FieldDef delegateInstanceField = new FieldDefUser(fieldName, new FieldSig(delegateType.ToTypeSig()), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly);
|
||||
string key1 = $"{method.FullName}_{callVir}";
|
||||
callInfo = new CallInfo
|
||||
{
|
||||
key1 = key1,
|
||||
key2 = HashUtil.ComputePrimitiveOrStringOrBytesHashCode(key1) * 33445566,
|
||||
method = method,
|
||||
callVir = callVir,
|
||||
delegateType = delegateType,
|
||||
delegateInstanceField = delegateInstanceField,
|
||||
delegateInvokeMethod = delegateInvokeMethod,
|
||||
proxyMethod = CreateProxyMethod($"{fieldName}$Proxy", method, callVir, delegateInvokeSig),
|
||||
};
|
||||
_callMethods.Add(key, callInfo);
|
||||
}
|
||||
return new DelegateProxyMethodData(callInfo.delegateInstanceField, callInfo.delegateInvokeMethod);
|
||||
}
|
||||
|
||||
public override void Done()
|
||||
{
|
||||
if (_done)
|
||||
{
|
||||
throw new Exception("Already done");
|
||||
}
|
||||
_done = true;
|
||||
|
||||
ModuleDef mod = Module;
|
||||
|
||||
// for stable order, we sort methods by name
|
||||
List<CallInfo> callMethodList = _callMethods.Values.ToList();
|
||||
callMethodList.Sort((a, b) => a.key1.CompareTo(b.key1));
|
||||
|
||||
var cctor = new MethodDefUser(".cctor",
|
||||
MethodSig.CreateStatic(mod.CorLibTypes.Void),
|
||||
MethodImplAttributes.IL | MethodImplAttributes.Managed,
|
||||
MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Private);
|
||||
cctor.DeclaringType = _delegateInstanceHolderType;
|
||||
//_rvaTypeDef.Methods.Add(cctor);
|
||||
var body = new CilBody();
|
||||
cctor.Body = body;
|
||||
var ins = body.Instructions;
|
||||
|
||||
// var arr = new array[];
|
||||
// var d = new delegate;
|
||||
// arr[index] = d;
|
||||
int index = 0;
|
||||
ins.Add(Instruction.CreateLdcI4(callMethodList.Count));
|
||||
ins.Add(Instruction.Create(OpCodes.Newarr, mod.CorLibTypes.Object));
|
||||
foreach (CallInfo ci in callMethodList)
|
||||
{
|
||||
ci.index = index;
|
||||
_delegateInstanceHolderType.Methods.Add(ci.proxyMethod);
|
||||
ins.Add(Instruction.Create(OpCodes.Dup));
|
||||
ins.Add(Instruction.CreateLdcI4(index));
|
||||
ins.Add(Instruction.Create(OpCodes.Ldnull));
|
||||
ins.Add(Instruction.Create(OpCodes.Ldftn, ci.proxyMethod));
|
||||
MethodDef ctor = ci.delegateType.FindMethod(".ctor");
|
||||
UnityEngine.Assertions.Assert.IsNotNull(ctor, $"Delegate type {ci.delegateType.FullName} does not have a constructor.");
|
||||
ins.Add(Instruction.Create(OpCodes.Newobj, ctor));
|
||||
ins.Add(Instruction.Create(OpCodes.Stelem_Ref));
|
||||
++index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
List<CallInfo> callMethodList2 = callMethodList.ToList();
|
||||
callMethodList2.Sort((a, b) => a.key2.CompareTo(b.key2));
|
||||
|
||||
EncryptionScopeInfo encryptionScope = EncryptionScope;
|
||||
DefaultMetadataImporter importer = this.GetDefaultModuleMetadataImporter();
|
||||
RvaDataAllocator rvaDataAllocator = this.GetEntity<RvaDataAllocator>();
|
||||
foreach (CallInfo ci in callMethodList2)
|
||||
{
|
||||
_delegateInstanceHolderType.Fields.Add(ci.delegateInstanceField);
|
||||
|
||||
|
||||
ins.Add(Instruction.Create(OpCodes.Dup));
|
||||
|
||||
IRandom localRandom = encryptionScope.localRandomCreator(HashUtil.ComputePrimitiveOrStringOrBytesHashCode(ci.key1));
|
||||
int ops = EncryptionUtil.GenerateEncryptionOpCodes(localRandom, encryptionScope.encryptor, _settings.obfuscationLevel);
|
||||
int salt = localRandom.NextInt();
|
||||
|
||||
int encryptedValue = encryptionScope.encryptor.Encrypt(ci.index, ops, salt);
|
||||
RvaData rvaData = rvaDataAllocator.Allocate(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));
|
||||
ins.Add(Instruction.Create(OpCodes.Ldelem_Ref));
|
||||
ins.Add(Instruction.Create(OpCodes.Stsfld, ci.delegateInstanceField));
|
||||
}
|
||||
|
||||
ins.Add(Instruction.Create(OpCodes.Pop));
|
||||
ins.Add(Instruction.Create(OpCodes.Ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 02761bacbed8a8b489ae3e7f49f0f84a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Emit;
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Obfuz.ObfusPasses.CallObfus
|
||||
{
|
||||
|
||||
public class DelegateProxyObfuscator : ObfuscatorBase
|
||||
{
|
||||
private readonly GroupByModuleEntityManager _entityManager;
|
||||
|
||||
public DelegateProxyObfuscator(GroupByModuleEntityManager moduleEntityManager)
|
||||
{
|
||||
_entityManager = moduleEntityManager;
|
||||
}
|
||||
|
||||
public override void Done()
|
||||
{
|
||||
_entityManager.Done<DelegateProxyAllocator>();
|
||||
}
|
||||
|
||||
private MethodSig CreateProxyMethodSig(ModuleDef module, IMethod method)
|
||||
{
|
||||
MethodSig methodSig = MetaUtil.ToSharedMethodSig(module.CorLibTypes, MetaUtil.GetInflatedMethodSig(method, null));
|
||||
//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;
|
||||
}
|
||||
}
|
||||
return MethodSig.CreateStatic(methodSig.RetType, methodSig.Params.ToArray());
|
||||
}
|
||||
|
||||
public override bool Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, List<Instruction> obfuscatedInstructions)
|
||||
{
|
||||
DelegateProxyAllocator allocator = _entityManager.GetEntity<DelegateProxyAllocator>(callingMethod.Module);
|
||||
LocalVariableAllocator localVarAllocator = new LocalVariableAllocator(callingMethod);
|
||||
MethodSig methodSig = CreateProxyMethodSig(callingMethod.Module, calledMethod);
|
||||
DelegateProxyMethodData proxyData = allocator.Allocate(calledMethod, callVir, methodSig);
|
||||
bool isVoidReturn = MetaUtil.IsVoidType(methodSig.RetType);
|
||||
|
||||
using (var varScope = localVarAllocator.CreateScope())
|
||||
{
|
||||
List<Local> localVars = new List<Local>();
|
||||
if (!isVoidReturn)
|
||||
{
|
||||
varScope.AllocateLocal(methodSig.RetType);
|
||||
}
|
||||
foreach (var p in methodSig.Params)
|
||||
{
|
||||
localVars.Add(varScope.AllocateLocal(p));
|
||||
}
|
||||
// save args
|
||||
for (int i = localVars.Count - 1; i >= 0; i--)
|
||||
{
|
||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Stloc, localVars[i]));
|
||||
}
|
||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, proxyData.delegateInstanceField));
|
||||
foreach (var local in localVars)
|
||||
{
|
||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldloc, local));
|
||||
}
|
||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Callvirt, proxyData.delegateInvokeMethod));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1102cd9f03de27c4b9fde3d6a87277c7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,18 +1,38 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Editor;
|
||||
using Obfuz.Emit;
|
||||
using Obfuz.Settings;
|
||||
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;
|
||||
|
|
@ -31,38 +51,11 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
}
|
||||
}
|
||||
|
||||
class ModuleCallProxyAllocator : IGroupByModuleEntity
|
||||
class ModuleDispatchProxyAllocator : GroupByModuleEntityBase
|
||||
{
|
||||
private ModuleDef _module;
|
||||
private readonly EncryptionScopeProvider _encryptionScopeProvider;
|
||||
private readonly int _encryptionLevel;
|
||||
|
||||
private EncryptionScopeInfo _encryptionScope;
|
||||
private bool _done;
|
||||
private CallObfuscationSettingsFacade _settings;
|
||||
|
||||
class MethodKey : IEquatable<MethodKey>
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
@ -76,11 +69,9 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
|
||||
private readonly Dictionary<MethodKey, MethodProxyInfo> _methodProxys = new Dictionary<MethodKey, MethodProxyInfo>();
|
||||
|
||||
|
||||
const int maxProxyMethodPerDispatchMethod = 1000;
|
||||
|
||||
class CallInfo
|
||||
{
|
||||
public string id;
|
||||
public IMethod method;
|
||||
public bool callVir;
|
||||
}
|
||||
|
|
@ -96,61 +87,87 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
|
||||
private TypeDef _proxyTypeDef;
|
||||
|
||||
public ModuleCallProxyAllocator(EncryptionScopeProvider encryptionScopeProvider, int encryptionLevel)
|
||||
public ModuleDispatchProxyAllocator()
|
||||
{
|
||||
_encryptionScopeProvider = encryptionScopeProvider;
|
||||
_encryptionLevel = encryptionLevel;
|
||||
}
|
||||
|
||||
public void Init(ModuleDef mod)
|
||||
public override void Init()
|
||||
{
|
||||
_module = mod;
|
||||
_encryptionScope = _encryptionScopeProvider.GetScope(mod);
|
||||
_settings = CallObfusPass.CurrentSettings;
|
||||
}
|
||||
|
||||
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;
|
||||
ModuleDef mod = Module;
|
||||
using (var scope = new DisableTypeDefFindCacheScope(mod))
|
||||
{
|
||||
var typeDef = new TypeDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}ProxyCall", mod.CorLibTypes.Object.ToTypeDefOrRef());
|
||||
typeDef.Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed;
|
||||
mod.Types.Add(typeDef);
|
||||
return typeDef;
|
||||
}
|
||||
}
|
||||
|
||||
private MethodDef CreateDispatchMethodInfo(MethodSig methodSig)
|
||||
private readonly HashSet<string> _uniqueMethodNames = new HashSet<string>();
|
||||
|
||||
|
||||
private string ToUniqueMethodName(string originalName)
|
||||
{
|
||||
if (_uniqueMethodNames.Add(originalName))
|
||||
{
|
||||
return originalName;
|
||||
}
|
||||
for (int index = 1; ; index++)
|
||||
{
|
||||
string uniqueName = $"{originalName}${index}";
|
||||
if (_uniqueMethodNames.Add(uniqueName))
|
||||
{
|
||||
return uniqueName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string CreateDispatchMethodName(MethodSig methodSig, int index)
|
||||
{
|
||||
// use a stable name for the dispatch method, so that we can reuse it across different modules
|
||||
// this is important for cross-module calls
|
||||
return ToUniqueMethodName($"{ConstValues.ObfuzInternalSymbolNamePrefix}Dispatch_{HashUtil.ComputeHash(methodSig.Params) & 0xFFFF}_{HashUtil.ComputeHash(methodSig.RetType) & 0xFFFFFF}");
|
||||
}
|
||||
|
||||
private MethodDef CreateDispatchMethodInfo(MethodSig methodSig, int index)
|
||||
{
|
||||
if (_proxyTypeDef == null)
|
||||
{
|
||||
_proxyTypeDef = CreateProxyTypeDef();
|
||||
}
|
||||
MethodDef methodDef = new MethodDefUser($"{ConstValues.ObfuzInternalSymbolNamePrefix}ProxyCall$Dispatch${_proxyTypeDef.Methods.Count}", methodSig,
|
||||
MethodDef methodDef = new MethodDefUser(CreateDispatchMethodName(methodSig, index), methodSig,
|
||||
MethodImplAttributes.IL | MethodImplAttributes.Managed,
|
||||
MethodAttributes.Static | MethodAttributes.Private);
|
||||
MethodAttributes.Static | MethodAttributes.Public);
|
||||
methodDef.DeclaringType = _proxyTypeDef;
|
||||
return methodDef;
|
||||
}
|
||||
|
||||
private MethodSig CreateDispatchMethodSig(IMethod method)
|
||||
{
|
||||
MethodSig methodSig = MetaUtil.ToSharedMethodSig(_module.CorLibTypes, MetaUtil.GetInflatedMethodSig(method));
|
||||
ModuleDef mod = Module;
|
||||
MethodSig methodSig = MetaUtil.ToSharedMethodSig(mod.CorLibTypes, MetaUtil.GetInflatedMethodSig(method, null));
|
||||
//MethodSig methodSig = MetaUtil.GetInflatedMethodSig(method).Clone();
|
||||
//methodSig.Params
|
||||
switch (MetaUtil.GetThisArgType(method))
|
||||
{
|
||||
case ThisArgType.Class:
|
||||
{
|
||||
methodSig.Params.Insert(0, _module.CorLibTypes.Object);
|
||||
methodSig.Params.Insert(0, mod.CorLibTypes.Object);
|
||||
break;
|
||||
}
|
||||
case ThisArgType.ValueType:
|
||||
{
|
||||
methodSig.Params.Insert(0, _module.CorLibTypes.IntPtr);
|
||||
methodSig.Params.Insert(0, mod.CorLibTypes.IntPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// extra param for index
|
||||
methodSig.Params.Add(_module.CorLibTypes.Int32);
|
||||
methodSig.Params.Add(mod.CorLibTypes.Int32);
|
||||
return MethodSig.CreateStatic(methodSig.RetType, methodSig.Params.ToArray());
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +178,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
|
||||
private int GenerateEncryptOps(IRandom random)
|
||||
{
|
||||
return EncryptionUtil.GenerateEncryptionOpCodes(random, _encryptionScope.encryptor, _encryptionLevel);
|
||||
return EncryptionUtil.GenerateEncryptionOpCodes(random, EncryptionScope.encryptor, _settings.obfuscationLevel);
|
||||
}
|
||||
|
||||
private DispatchMethodInfo GetDispatchMethod(IMethod method)
|
||||
|
|
@ -172,11 +189,11 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
dispatchMethods = new List<DispatchMethodInfo>();
|
||||
_dispatchMethods.Add(methodSig, dispatchMethods);
|
||||
}
|
||||
if (dispatchMethods.Count == 0 || dispatchMethods.Last().methods.Count >= maxProxyMethodPerDispatchMethod)
|
||||
if (dispatchMethods.Count == 0 || dispatchMethods.Last().methods.Count >= _settings.maxProxyMethodCountPerDispatchMethod)
|
||||
{
|
||||
var newDispatchMethodInfo = new DispatchMethodInfo
|
||||
{
|
||||
methodDef = CreateDispatchMethodInfo(methodSig),
|
||||
methodDef = CreateDispatchMethodInfo(methodSig, dispatchMethods.Count),
|
||||
};
|
||||
dispatchMethods.Add(newDispatchMethodInfo);
|
||||
}
|
||||
|
|
@ -186,7 +203,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
private IRandom CreateRandomForMethod(IMethod method, bool callVir)
|
||||
{
|
||||
int seed = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method);
|
||||
return _encryptionScope.localRandomCreator(seed);
|
||||
return EncryptionScope.localRandomCreator(seed);
|
||||
}
|
||||
|
||||
public ProxyCallMethodData Allocate(IMethod method, bool callVir)
|
||||
|
|
@ -204,7 +221,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
IRandom localRandom = CreateRandomForMethod(method, callVir);
|
||||
int encryptOps = GenerateEncryptOps(localRandom);
|
||||
int salt = GenerateSalt(localRandom);
|
||||
int encryptedIndex = _encryptionScope.encryptor.Encrypt(index, encryptOps, salt);
|
||||
int encryptedIndex = EncryptionScope.encryptor.Encrypt(index, encryptOps, salt);
|
||||
proxyInfo = new MethodProxyInfo()
|
||||
{
|
||||
proxyMethod = methodDispatcher.methodDef,
|
||||
|
|
@ -213,19 +230,32 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
salt = salt,
|
||||
encryptedIndex = encryptedIndex,
|
||||
};
|
||||
methodDispatcher.methods.Add(new CallInfo { method = method, callVir = callVir});
|
||||
methodDispatcher.methods.Add(new CallInfo { id = $"{method}{(callVir ? "" : "v")}", method = method, callVir = callVir });
|
||||
_methodProxys.Add(key, proxyInfo);
|
||||
}
|
||||
return new ProxyCallMethodData(proxyInfo.proxyMethod, proxyInfo.encryptedOps, proxyInfo.salt, proxyInfo.encryptedIndex, proxyInfo.index);
|
||||
}
|
||||
|
||||
public void Done()
|
||||
public override void Done()
|
||||
{
|
||||
if (_done)
|
||||
{
|
||||
throw new Exception("Already done");
|
||||
}
|
||||
_done = true;
|
||||
if (_proxyTypeDef == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// for stable order, we sort methods by name
|
||||
var methodWithNamePairList = _proxyTypeDef.Methods.Select(m => (m, m.ToString())).ToList();
|
||||
methodWithNamePairList.Sort((a, b) => a.Item2.CompareTo(b.Item2));
|
||||
_proxyTypeDef.Methods.Clear();
|
||||
foreach (var methodPair in methodWithNamePairList)
|
||||
{
|
||||
methodPair.Item1.DeclaringType = _proxyTypeDef;
|
||||
}
|
||||
|
||||
foreach (DispatchMethodInfo dispatchMethod in _dispatchMethods.Values.SelectMany(ms => ms))
|
||||
{
|
||||
|
|
@ -246,6 +276,9 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
var switchInst = Instruction.Create(OpCodes.Switch, switchCases);
|
||||
ins.Add(switchInst);
|
||||
var ret = Instruction.Create(OpCodes.Ret);
|
||||
|
||||
// sort methods by signature to ensure stable order
|
||||
//dispatchMethod.methods.Sort((a, b) => a.id.CompareTo(b.id));
|
||||
foreach (CallInfo ci in dispatchMethod.methods)
|
||||
{
|
||||
var callTargetMethod = Instruction.Create(ci.callVir ? OpCodes.Callvirt : OpCodes.Call, ci.method);
|
||||
|
|
@ -257,37 +290,4 @@ namespace Obfuz.ObfusPasses.CallObfus
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<ModuleCallProxyAllocator>(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<ModuleCallProxyAllocator>())
|
||||
{
|
||||
allocator.Done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 16b960455f093854d927c2dbd47a4826
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
using Obfuz.Data;
|
||||
using Obfuz.Emit;
|
||||
using Obfuz.Utils;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obfuz.ObfusPasses.CallObfus
|
||||
{
|
||||
|
||||
public class DispatchProxyObfuscator : ObfuscatorBase
|
||||
{
|
||||
private readonly GroupByModuleEntityManager _moduleEntityManager;
|
||||
|
||||
public DispatchProxyObfuscator(GroupByModuleEntityManager moduleEntityManager)
|
||||
{
|
||||
_moduleEntityManager = moduleEntityManager;
|
||||
}
|
||||
|
||||
public override void Done()
|
||||
{
|
||||
_moduleEntityManager.Done<ModuleDispatchProxyAllocator>();
|
||||
}
|
||||
|
||||
public override bool Obfuscate(MethodDef callerMethod, IMethod calledMethod, bool callVir, List<Instruction> obfuscatedInstructions)
|
||||
{
|
||||
ModuleDispatchProxyAllocator proxyCallAllocator = _moduleEntityManager.GetEntity<ModuleDispatchProxyAllocator>(callerMethod.Module);
|
||||
MethodSig sharedMethodSig = MetaUtil.ToSharedMethodSig(calledMethod.Module.CorLibTypes, MetaUtil.GetInflatedMethodSig(calledMethod, null));
|
||||
ProxyCallMethodData proxyCallMethodData = proxyCallAllocator.Allocate(calledMethod, callVir);
|
||||
DefaultMetadataImporter importer = proxyCallAllocator.GetDefaultModuleMetadataImporter();
|
||||
|
||||
//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));
|
||||
//}
|
||||
|
||||
ConstFieldAllocator constFieldAllocator = proxyCallAllocator.GetEntity<ConstFieldAllocator>();
|
||||
FieldDef cacheField = constFieldAllocator.Allocate(proxyCallMethodData.index);
|
||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
|
||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, proxyCallMethodData.proxyMethod));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e13ba01b03439e049af0e09367825cde
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,34 +1,39 @@
|
|||
// Copyright 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.
|
||||
|
||||
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);
|
||||
bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir);
|
||||
}
|
||||
|
||||
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);
|
||||
public abstract bool NeedObfuscateCalledMethod(MethodDef callerMethod, IMethod calledMethod, bool callVir);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6af3cd881fdefd14d9a55b77088dd5a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -1,23 +1,40 @@
|
|||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet;
|
||||
using System;
|
||||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using dnlib.DotNet.Emit;
|
||||
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<Instruction> obfuscatedInstructions);
|
||||
bool Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, List<Instruction> obfuscatedInstructions);
|
||||
|
||||
void Done();
|
||||
}
|
||||
|
||||
public abstract class ObfuscatorBase : IObfuscator
|
||||
{
|
||||
public abstract void Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, bool needCacheCall, List<Instruction> obfuscatedInstructions);
|
||||
public abstract bool Obfuscate(MethodDef callingMethod, IMethod calledMethod, bool callVir, List<Instruction> obfuscatedInstructions);
|
||||
|
||||
public abstract void Done();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 4156317478f8b1d438ef6d5a280d409f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 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.
|
||||
|
||||
using dnlib.DotNet;
|
||||
using Obfuz.Utils;
|
||||
using System;
|
||||
|
||||
namespace Obfuz.ObfusPasses.CallObfus
|
||||
{
|
||||
class MethodKey : IEquatable<MethodKey>
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue