From db86070fdba23ec9ef5f095a16be9a83bae64d27 Mon Sep 17 00:00:00 2001 From: walon Date: Sun, 11 May 2025 20:12:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=20obfuscationLevel=E5=92=8Ce?= =?UTF-8?q?ncryptionLevel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VirtualMachineCodeGenerator.cs | 30 +++++-------- .../EncryptionVM/VirtualMachineSimulator.cs | 2 + Editor/ObfusPasses/CallObfus/CallObfusPass.cs | 4 +- .../CallObfus/CallProxyAllocator.cs | 12 +++-- .../CallObfus/DefaultCallProxyObfuscator.cs | 6 +-- .../ConstEncrypt/ConstEncryptPass.cs | 4 +- .../ConstEncrypt/DefaultConstEncryptor.cs | 6 ++- .../FieldEncrypt/DefaultFieldEncryptor.cs | 19 ++++++-- .../FieldEncrypt/FieldEncryptPass.cs | 4 +- Editor/ObfuscatorBuilder.cs | 2 +- Editor/Settings/CallObfusSettings.cs | 4 ++ Editor/Settings/ConstEncryptSettings.cs | 4 ++ Editor/Settings/FieldEncryptSettings.cs | 4 ++ Editor/Utils/EncryptionUtil.cs | 44 +++++++++++++++++++ Editor/Utils/KeyGenerator.cs | 6 +-- Runtime/EncryptorBase.cs | 2 + Runtime/IEncryptor.cs | 2 + Runtime/NullEncryptor.cs | 2 + 18 files changed, 116 insertions(+), 41 deletions(-) create mode 100644 Editor/Utils/EncryptionUtil.cs diff --git a/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs b/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs index da08a3d..ef27f3d 100644 --- a/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs +++ b/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs @@ -19,27 +19,17 @@ namespace Obfuz.EncryptionVM public VirtualMachineCodeGenerator(string vmCodeGenerateSecretKey, int opCodeCount) { _opCodeCount = opCodeCount; - _opCodeBits = GetBitCount(opCodeCount - 1); + _opCodeBits = EncryptionUtil.GetBitCount(opCodeCount - 1); _vm = new VirtualMachineCreator(vmCodeGenerateSecretKey).CreateVirtualMachine(opCodeCount); } public VirtualMachineCodeGenerator(VirtualMachine vm) { _opCodeCount = vm.opCodes.Length; - _opCodeBits = GetBitCount(_opCodeCount - 1); + _opCodeBits = EncryptionUtil.GetBitCount(_opCodeCount - 1); _vm = vm; } - private static int GetBitCount(int value) - { - int count = 0; - while (value > 0) - { - count++; - value >>= 1; - } - return count; - } public bool ValidateMatch(string outputFile) { @@ -143,11 +133,11 @@ namespace Obfuz.EncryptionVM public class GeneratedEncryptionVirtualMachine : Obfuz.EncryptorBase {"); lines.Add(@$" - private const int OpCodeBits = {_opCodeBits}; + private const int kOpCodeBits = {_opCodeBits}; - private const int OpCodeCount = {_opCodeCount}; + private const int kOpCodeCount = {_opCodeCount}; - private const int OpCodeMask = {_opCodeCount - 1}; + private const int kOpCodeMask = {_opCodeCount - 1}; "); lines.Add(@" @@ -158,13 +148,15 @@ namespace Obfuz.EncryptionVM this._secretKey = ConvertToIntKey(secretKey); } + public override int OpCodeCount => kOpCodeCount; + public override int Encrypt(int value, int opts, int salt) { while (opts > 0) { - int opCode = opts & OpCodeMask; + int opCode = opts & kOpCodeMask; value = ExecuteEncrypt(value, opCode, salt); - opts >>= OpCodeBits; + opts >>= kOpCodeBits; } return value; } @@ -173,9 +165,9 @@ namespace Obfuz.EncryptionVM { while (opts > 0) { - int opCode = opts & OpCodeMask; + int opCode = opts & kOpCodeMask; value = ExecuteDecrypt(value, opCode, salt); - opts >>= OpCodeBits; + opts >>= kOpCodeBits; } return value; } diff --git a/Editor/EncryptionVM/VirtualMachineSimulator.cs b/Editor/EncryptionVM/VirtualMachineSimulator.cs index 0c67adb..9bfd308 100644 --- a/Editor/EncryptionVM/VirtualMachineSimulator.cs +++ b/Editor/EncryptionVM/VirtualMachineSimulator.cs @@ -15,6 +15,8 @@ namespace Obfuz.EncryptionVM private readonly EncryptionInstructionWithOpCode[] _opCodes; private readonly int[] _secretKey; + public override int OpCodeCount => _opCodes.Length; + public VirtualMachineSimulator(VirtualMachine vm, byte[] byteSecretKey) { _opCodes = vm.opCodes; diff --git a/Editor/ObfusPasses/CallObfus/CallObfusPass.cs b/Editor/ObfusPasses/CallObfus/CallObfusPass.cs index 6248bf5..48f30e7 100644 --- a/Editor/ObfusPasses/CallObfus/CallObfusPass.cs +++ b/Editor/ObfusPasses/CallObfus/CallObfusPass.cs @@ -16,6 +16,7 @@ namespace Obfuz.ObfusPasses.CallObfus public class CallObfusPass : BasicBlockObfuscationPassBase { private readonly List _configFiles; + private readonly int _obfuscationLevel; private IRandom _random; private IEncryptor _encryptor; private IObfuscator _dynamicProxyObfuscator; @@ -24,6 +25,7 @@ namespace Obfuz.ObfusPasses.CallObfus public CallObfusPass(CallObfusSettings settings) { _configFiles = settings.configFiles.ToList(); + _obfuscationLevel = settings.callObfuscationLevel; } public override void Stop(ObfuscationPassContext ctx) @@ -35,7 +37,7 @@ namespace Obfuz.ObfusPasses.CallObfus { _random = ctx.random; _encryptor = ctx.encryptor; - _dynamicProxyObfuscator = new DefaultCallProxyObfuscator(_random, _encryptor, ctx.constFieldAllocator); + _dynamicProxyObfuscator = new DefaultCallProxyObfuscator(_random, _encryptor, ctx.constFieldAllocator, _obfuscationLevel); _dynamicProxyPolicy = new ConfigurableObfuscationPolicy(ctx.toObfuscatedAssemblyNames, _configFiles); } diff --git a/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs b/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs index 70160c8..0d5a413 100644 --- a/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs +++ b/Editor/ObfusPasses/CallObfus/CallProxyAllocator.cs @@ -35,6 +35,7 @@ namespace Obfuz.ObfusPasses.CallObfus private ModuleDef _module; private readonly IRandom _random; private readonly IEncryptor _encryptor; + private readonly int _encryptionLevel; class MethodKey : IEquatable { @@ -92,10 +93,11 @@ namespace Obfuz.ObfusPasses.CallObfus private TypeDef _proxyTypeDef; - public ModuleCallProxyAllocator(IRandom random, IEncryptor encryptor) + public ModuleCallProxyAllocator(IRandom random, IEncryptor encryptor, int encryptionLevel) { _random = random; _encryptor = encryptor; + _encryptionLevel = encryptionLevel; } public void Init(ModuleDef mod) @@ -156,7 +158,7 @@ namespace Obfuz.ObfusPasses.CallObfus private int GenerateEncryptOps() { - return _random.NextInt(); + return EncryptionUtil.GenerateEncryptionOpCodes(_random, _encryptor, _encryptionLevel); } private DispatchMethodInfo GetDispatchMethod(IMethod method) @@ -240,16 +242,18 @@ namespace Obfuz.ObfusPasses.CallObfus { private readonly IRandom _random; private readonly IEncryptor _encryptor; + private readonly int _encryptionLevel; - public CallProxyAllocator(IRandom random, IEncryptor encryptor) + public CallProxyAllocator(IRandom random, IEncryptor encryptor, int encryptionLevel) { _random = random; _encryptor = encryptor; + _encryptionLevel = encryptionLevel; } private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod) { - return GroupByModuleEntityManager.Ins.GetEntity(mod, () => new ModuleCallProxyAllocator(_random, _encryptor)); + return GroupByModuleEntityManager.Ins.GetEntity(mod, () => new ModuleCallProxyAllocator(_random, _encryptor, _encryptionLevel)); } public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir) diff --git a/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs b/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs index af27b15..6265556 100644 --- a/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs +++ b/Editor/ObfusPasses/CallObfus/DefaultCallProxyObfuscator.cs @@ -10,17 +10,15 @@ namespace Obfuz.ObfusPasses.CallObfus { public class DefaultCallProxyObfuscator : ObfuscatorBase { - private readonly IRandom _random; private readonly IEncryptor _encryptor; private readonly ConstFieldAllocator _constFieldAllocator; private readonly CallProxyAllocator _proxyCallAllocator; - public DefaultCallProxyObfuscator(IRandom random, IEncryptor encryptor, ConstFieldAllocator constFieldAllocator) + public DefaultCallProxyObfuscator(IRandom random, IEncryptor encryptor, ConstFieldAllocator constFieldAllocator, int encryptionLevel) { - _random = random; _encryptor = encryptor; _constFieldAllocator = constFieldAllocator; - _proxyCallAllocator = new CallProxyAllocator(random, _encryptor); + _proxyCallAllocator = new CallProxyAllocator(random, _encryptor, encryptionLevel); } public override void Done() diff --git a/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs b/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs index 36f5238..b115eb7 100644 --- a/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs +++ b/Editor/ObfusPasses/ConstEncrypt/ConstEncryptPass.cs @@ -16,18 +16,20 @@ namespace Obfuz.ObfusPasses.ConstEncrypt public class ConstEncryptPass : BasicBlockObfuscationPassBase { private readonly List _configFiles; + private readonly int _encryptionLevel; private IEncryptPolicy _dataObfuscatorPolicy; private IConstEncryptor _dataObfuscator; public ConstEncryptPass(ConstEncryptSettings settings) { _configFiles = settings.configFiles.ToList(); + _encryptionLevel = settings.encryptionLevel; } public override void Start(ObfuscationPassContext ctx) { _dataObfuscatorPolicy = new ConfigurableEncryptPolicy(ctx.toObfuscatedAssemblyNames, _configFiles); - _dataObfuscator = new DefaultConstEncryptor(ctx.random, ctx.encryptor, ctx.rvaDataAllocator, ctx.constFieldAllocator); + _dataObfuscator = new DefaultConstEncryptor(ctx.random, ctx.encryptor, ctx.rvaDataAllocator, ctx.constFieldAllocator, _encryptionLevel); } public override void Stop(ObfuscationPassContext ctx) diff --git a/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs b/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs index ecd569b..5e63c81 100644 --- a/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs +++ b/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs @@ -16,18 +16,20 @@ namespace Obfuz.ObfusPasses.ConstEncrypt private readonly RvaDataAllocator _rvaDataAllocator; private readonly ConstFieldAllocator _constFieldAllocator; private readonly IEncryptor _encryptor; + private readonly int _encryptionLevel; - public DefaultConstEncryptor(IRandom random, IEncryptor encryptor, RvaDataAllocator rvaDataAllocator, ConstFieldAllocator constFieldAllocator) + public DefaultConstEncryptor(IRandom random, IEncryptor encryptor, RvaDataAllocator rvaDataAllocator, ConstFieldAllocator constFieldAllocator, int encryptionLevel) { _random = random; _encryptor = encryptor; _rvaDataAllocator = rvaDataAllocator; _constFieldAllocator = constFieldAllocator; + _encryptionLevel = encryptionLevel; } private int GenerateEncryptionOperations() { - return _random.NextInt(); + return EncryptionUtil.GenerateEncryptionOpCodes(_random, _encryptor, _encryptionLevel); } public int GenerateSalt() diff --git a/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs b/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs index ce21789..03c5f08 100644 --- a/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs +++ b/Editor/ObfusPasses/FieldEncrypt/DefaultFieldEncryptor.cs @@ -14,11 +14,13 @@ namespace Obfuz.ObfusPasses.FieldEncrypt { private readonly IRandom _random; private readonly IEncryptor _encryptor; + private readonly int _encryptionLevel; - public DefaultFieldEncryptor(IRandom random, IEncryptor encryptor) + public DefaultFieldEncryptor(IRandom random, IEncryptor encryptor, int encryptionLevel) { _random = random; _encryptor = encryptor; + _encryptionLevel = encryptionLevel; } private DefaultMetadataImporter GetMetadataImporter(MethodDef method) @@ -54,6 +56,17 @@ namespace Obfuz.ObfusPasses.FieldEncrypt } } + + private int GenerateEncryptionOperations() + { + return EncryptionUtil.GenerateEncryptionOpCodes(_random, _encryptor, _encryptionLevel); + } + + public int GenerateSalt() + { + return _random.NextInt(); + } + private FieldEncryptInfo GetFieldEncryptInfo(FieldDef field) { if (_fieldEncryptInfoCache.TryGetValue(field, out var info)) @@ -61,8 +74,8 @@ namespace Obfuz.ObfusPasses.FieldEncrypt return info; } - int encryptOps = _random.NextInt(); - int salt = _random.NextInt(); + int encryptOps = GenerateEncryptionOperations(); + int salt = GenerateSalt(); ElementType fieldType = field.FieldSig.Type.RemovePinnedAndModifiers().ElementType; long xorValueForZero = CalcXorValueForZero(fieldType, encryptOps, salt); diff --git a/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs b/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs index 713e6f8..af8f77b 100644 --- a/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs +++ b/Editor/ObfusPasses/FieldEncrypt/FieldEncryptPass.cs @@ -13,19 +13,21 @@ namespace Obfuz.ObfusPasses.FieldEncrypt public class FieldEncryptPass : InstructionObfuscationPassBase { private readonly List _configFiles; + private readonly int _encryptionLevel; private IEncryptPolicy _encryptionPolicy; private IFieldEncryptor _memoryEncryptor; public FieldEncryptPass(FieldEncryptSettings settings) { _configFiles = settings.configFiles.ToList(); + _encryptionLevel = settings.encryptionLevel; } protected override bool NeedProcessNotObfuscatedAssembly => true; public override void Start(ObfuscationPassContext ctx) { - _memoryEncryptor = new DefaultFieldEncryptor(ctx.random, ctx.encryptor); + _memoryEncryptor = new DefaultFieldEncryptor(ctx.random, ctx.encryptor, _encryptionLevel); _encryptionPolicy = new ConfigurableEncryptPolicy(ctx.toObfuscatedAssemblyNames, _configFiles); } diff --git a/Editor/ObfuscatorBuilder.cs b/Editor/ObfuscatorBuilder.cs index dcdfb1f..dc147c2 100644 --- a/Editor/ObfuscatorBuilder.cs +++ b/Editor/ObfuscatorBuilder.cs @@ -19,7 +19,7 @@ namespace Obfuz private int _globalRandomSeed; private string _encryptionVmGenerationSecretKey; private int _encryptionVmOpCodeCount; - public string _encryptionVmCodeFile; + private string _encryptionVmCodeFile; private List _toObfuscatedAssemblyNames = new List(); private List _notObfuscatedAssemblyNamesReferencingObfuscated = new List(); diff --git a/Editor/Settings/CallObfusSettings.cs b/Editor/Settings/CallObfusSettings.cs index 280e287..f7d8d18 100644 --- a/Editor/Settings/CallObfusSettings.cs +++ b/Editor/Settings/CallObfusSettings.cs @@ -10,6 +10,10 @@ namespace Obfuz.Settings [Serializable] public class CallObfusSettings { + [Tooltip("The obfuscation level for the obfuscation. Higher levels provide more security but may impact performance.")] + [Range(1, 4)] + public int callObfuscationLevel = 1; + [Tooltip("config xml files")] public string[] configFiles; } diff --git a/Editor/Settings/ConstEncryptSettings.cs b/Editor/Settings/ConstEncryptSettings.cs index 867f255..2909614 100644 --- a/Editor/Settings/ConstEncryptSettings.cs +++ b/Editor/Settings/ConstEncryptSettings.cs @@ -10,6 +10,10 @@ namespace Obfuz.Settings [Serializable] public class ConstEncryptSettings { + [Tooltip("The encryption level for the obfuscation. Higher levels provide more security but may impact performance.")] + [Range(1, 4)] + public int encryptionLevel = 1; + [Tooltip("config xml files")] public string[] configFiles; } diff --git a/Editor/Settings/FieldEncryptSettings.cs b/Editor/Settings/FieldEncryptSettings.cs index 93b4532..5df9d24 100644 --- a/Editor/Settings/FieldEncryptSettings.cs +++ b/Editor/Settings/FieldEncryptSettings.cs @@ -10,6 +10,10 @@ namespace Obfuz.Settings [Serializable] public class FieldEncryptSettings { + [Tooltip("The encryption level for the obfuscation. Higher levels provide more security but may impact performance.")] + [Range(1, 4)] + public int encryptionLevel = 1; + [Tooltip("config xml files")] public string[] configFiles; } diff --git a/Editor/Utils/EncryptionUtil.cs b/Editor/Utils/EncryptionUtil.cs new file mode 100644 index 0000000..edab9f0 --- /dev/null +++ b/Editor/Utils/EncryptionUtil.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz.Utils +{ + public static class EncryptionUtil + { + public static int GetBitCount(int value) + { + int count = 0; + while (value > 0) + { + count++; + value >>= 1; + } + return count; + } + + public static int GenerateEncryptionOpCodes(IRandom random, IEncryptor encryptor, int encryptionLevel) + { + if (encryptionLevel <= 0 || encryptionLevel > 4) + { + throw new ArgumentException($"Invalid encryption level: {encryptionLevel}, should be in range [1,4]"); + } + int vmOpCodeCount = encryptor.OpCodeCount; + long ops = 0; + for (int i = 0; i < encryptionLevel; i++) + { + ops *= vmOpCodeCount; + // first op code can't be 0 + int op = random.NextInt(i == 0 ? 1 : 0, vmOpCodeCount); + ops |= (uint)op; + if (ops > uint.MaxValue) + { + throw new Exception($"OpCode overflow. encryptionLevel:{encryptionLevel}, vmOpCodeCount:{vmOpCodeCount}"); + } + } + return (int)ops; + } + } +} diff --git a/Editor/Utils/KeyGenerator.cs b/Editor/Utils/KeyGenerator.cs index ee6f1f4..f6bfccc 100644 --- a/Editor/Utils/KeyGenerator.cs +++ b/Editor/Utils/KeyGenerator.cs @@ -33,11 +33,7 @@ namespace Obfuz.Utils public static int[] ConvertToIntKey(byte[] key) { - Assert.AreEqual(0, key.Length % 4); - int align4Length = key.Length / 4; - int[] intKey = new int[align4Length]; - Buffer.BlockCopy(key, 0, intKey, 0, key.Length); - return intKey; + return EncryptorBase.ConvertToIntKey(key); } } } diff --git a/Runtime/EncryptorBase.cs b/Runtime/EncryptorBase.cs index efa93d9..f897a25 100644 --- a/Runtime/EncryptorBase.cs +++ b/Runtime/EncryptorBase.cs @@ -7,6 +7,8 @@ namespace Obfuz { public abstract class EncryptorBase : IEncryptor { + public abstract int OpCodeCount { get; } + public static int[] ConvertToIntKey(byte[] key) { Assert.AreEqual(0, key.Length % 4); diff --git a/Runtime/IEncryptor.cs b/Runtime/IEncryptor.cs index 6c6d9ca..8190230 100644 --- a/Runtime/IEncryptor.cs +++ b/Runtime/IEncryptor.cs @@ -6,6 +6,8 @@ namespace Obfuz { public interface IEncryptor { + int OpCodeCount { get; } + void EncryptBlock(byte[] data, int ops, int salt); void DecryptBlock(byte[] data, int ops, int salt); diff --git a/Runtime/NullEncryptor.cs b/Runtime/NullEncryptor.cs index 7643dcf..ec28f36 100644 --- a/Runtime/NullEncryptor.cs +++ b/Runtime/NullEncryptor.cs @@ -10,6 +10,8 @@ namespace Obfuz { private readonly byte[] _key; + public override int OpCodeCount => 256; + public NullEncryptor(byte[] key) { _key = key;