支持 obfuscationLevel和encryptionLevel

backup
walon 2025-05-11 20:12:33 +08:00
parent b1a19e9ef7
commit db86070fdb
18 changed files with 116 additions and 41 deletions

View File

@ -19,27 +19,17 @@ namespace Obfuz.EncryptionVM
public VirtualMachineCodeGenerator(string vmCodeGenerateSecretKey, int opCodeCount) public VirtualMachineCodeGenerator(string vmCodeGenerateSecretKey, int opCodeCount)
{ {
_opCodeCount = opCodeCount; _opCodeCount = opCodeCount;
_opCodeBits = GetBitCount(opCodeCount - 1); _opCodeBits = EncryptionUtil.GetBitCount(opCodeCount - 1);
_vm = new VirtualMachineCreator(vmCodeGenerateSecretKey).CreateVirtualMachine(opCodeCount); _vm = new VirtualMachineCreator(vmCodeGenerateSecretKey).CreateVirtualMachine(opCodeCount);
} }
public VirtualMachineCodeGenerator(VirtualMachine vm) public VirtualMachineCodeGenerator(VirtualMachine vm)
{ {
_opCodeCount = vm.opCodes.Length; _opCodeCount = vm.opCodes.Length;
_opCodeBits = GetBitCount(_opCodeCount - 1); _opCodeBits = EncryptionUtil.GetBitCount(_opCodeCount - 1);
_vm = vm; _vm = vm;
} }
private static int GetBitCount(int value)
{
int count = 0;
while (value > 0)
{
count++;
value >>= 1;
}
return count;
}
public bool ValidateMatch(string outputFile) public bool ValidateMatch(string outputFile)
{ {
@ -143,11 +133,11 @@ namespace Obfuz.EncryptionVM
public class GeneratedEncryptionVirtualMachine : Obfuz.EncryptorBase public class GeneratedEncryptionVirtualMachine : Obfuz.EncryptorBase
{"); {");
lines.Add(@$" 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(@" lines.Add(@"
@ -158,13 +148,15 @@ namespace Obfuz.EncryptionVM
this._secretKey = ConvertToIntKey(secretKey); this._secretKey = ConvertToIntKey(secretKey);
} }
public override int OpCodeCount => kOpCodeCount;
public override int Encrypt(int value, int opts, int salt) public override int Encrypt(int value, int opts, int salt)
{ {
while (opts > 0) while (opts > 0)
{ {
int opCode = opts & OpCodeMask; int opCode = opts & kOpCodeMask;
value = ExecuteEncrypt(value, opCode, salt); value = ExecuteEncrypt(value, opCode, salt);
opts >>= OpCodeBits; opts >>= kOpCodeBits;
} }
return value; return value;
} }
@ -173,9 +165,9 @@ namespace Obfuz.EncryptionVM
{ {
while (opts > 0) while (opts > 0)
{ {
int opCode = opts & OpCodeMask; int opCode = opts & kOpCodeMask;
value = ExecuteDecrypt(value, opCode, salt); value = ExecuteDecrypt(value, opCode, salt);
opts >>= OpCodeBits; opts >>= kOpCodeBits;
} }
return value; return value;
} }

View File

@ -15,6 +15,8 @@ namespace Obfuz.EncryptionVM
private readonly EncryptionInstructionWithOpCode[] _opCodes; private readonly EncryptionInstructionWithOpCode[] _opCodes;
private readonly int[] _secretKey; private readonly int[] _secretKey;
public override int OpCodeCount => _opCodes.Length;
public VirtualMachineSimulator(VirtualMachine vm, byte[] byteSecretKey) public VirtualMachineSimulator(VirtualMachine vm, byte[] byteSecretKey)
{ {
_opCodes = vm.opCodes; _opCodes = vm.opCodes;

View File

@ -16,6 +16,7 @@ namespace Obfuz.ObfusPasses.CallObfus
public class CallObfusPass : BasicBlockObfuscationPassBase public class CallObfusPass : BasicBlockObfuscationPassBase
{ {
private readonly List<string> _configFiles; private readonly List<string> _configFiles;
private readonly int _obfuscationLevel;
private IRandom _random; private IRandom _random;
private IEncryptor _encryptor; private IEncryptor _encryptor;
private IObfuscator _dynamicProxyObfuscator; private IObfuscator _dynamicProxyObfuscator;
@ -24,6 +25,7 @@ namespace Obfuz.ObfusPasses.CallObfus
public CallObfusPass(CallObfusSettings settings) public CallObfusPass(CallObfusSettings settings)
{ {
_configFiles = settings.configFiles.ToList(); _configFiles = settings.configFiles.ToList();
_obfuscationLevel = settings.callObfuscationLevel;
} }
public override void Stop(ObfuscationPassContext ctx) public override void Stop(ObfuscationPassContext ctx)
@ -35,7 +37,7 @@ namespace Obfuz.ObfusPasses.CallObfus
{ {
_random = ctx.random; _random = ctx.random;
_encryptor = ctx.encryptor; _encryptor = ctx.encryptor;
_dynamicProxyObfuscator = new DefaultCallProxyObfuscator(_random, _encryptor, ctx.constFieldAllocator); _dynamicProxyObfuscator = new DefaultCallProxyObfuscator(_random, _encryptor, ctx.constFieldAllocator, _obfuscationLevel);
_dynamicProxyPolicy = new ConfigurableObfuscationPolicy(ctx.toObfuscatedAssemblyNames, _configFiles); _dynamicProxyPolicy = new ConfigurableObfuscationPolicy(ctx.toObfuscatedAssemblyNames, _configFiles);
} }

View File

@ -35,6 +35,7 @@ namespace Obfuz.ObfusPasses.CallObfus
private ModuleDef _module; private ModuleDef _module;
private readonly IRandom _random; private readonly IRandom _random;
private readonly IEncryptor _encryptor; private readonly IEncryptor _encryptor;
private readonly int _encryptionLevel;
class MethodKey : IEquatable<MethodKey> class MethodKey : IEquatable<MethodKey>
{ {
@ -92,10 +93,11 @@ namespace Obfuz.ObfusPasses.CallObfus
private TypeDef _proxyTypeDef; private TypeDef _proxyTypeDef;
public ModuleCallProxyAllocator(IRandom random, IEncryptor encryptor) public ModuleCallProxyAllocator(IRandom random, IEncryptor encryptor, int encryptionLevel)
{ {
_random = random; _random = random;
_encryptor = encryptor; _encryptor = encryptor;
_encryptionLevel = encryptionLevel;
} }
public void Init(ModuleDef mod) public void Init(ModuleDef mod)
@ -156,7 +158,7 @@ namespace Obfuz.ObfusPasses.CallObfus
private int GenerateEncryptOps() private int GenerateEncryptOps()
{ {
return _random.NextInt(); return EncryptionUtil.GenerateEncryptionOpCodes(_random, _encryptor, _encryptionLevel);
} }
private DispatchMethodInfo GetDispatchMethod(IMethod method) private DispatchMethodInfo GetDispatchMethod(IMethod method)
@ -240,16 +242,18 @@ namespace Obfuz.ObfusPasses.CallObfus
{ {
private readonly IRandom _random; private readonly IRandom _random;
private readonly IEncryptor _encryptor; private readonly IEncryptor _encryptor;
private readonly int _encryptionLevel;
public CallProxyAllocator(IRandom random, IEncryptor encryptor) public CallProxyAllocator(IRandom random, IEncryptor encryptor, int encryptionLevel)
{ {
_random = random; _random = random;
_encryptor = encryptor; _encryptor = encryptor;
_encryptionLevel = encryptionLevel;
} }
private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod) private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod)
{ {
return GroupByModuleEntityManager.Ins.GetEntity<ModuleCallProxyAllocator>(mod, () => new ModuleCallProxyAllocator(_random, _encryptor)); return GroupByModuleEntityManager.Ins.GetEntity<ModuleCallProxyAllocator>(mod, () => new ModuleCallProxyAllocator(_random, _encryptor, _encryptionLevel));
} }
public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir) public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir)

View File

@ -10,17 +10,15 @@ namespace Obfuz.ObfusPasses.CallObfus
{ {
public class DefaultCallProxyObfuscator : ObfuscatorBase public class DefaultCallProxyObfuscator : ObfuscatorBase
{ {
private readonly IRandom _random;
private readonly IEncryptor _encryptor; private readonly IEncryptor _encryptor;
private readonly ConstFieldAllocator _constFieldAllocator; private readonly ConstFieldAllocator _constFieldAllocator;
private readonly CallProxyAllocator _proxyCallAllocator; 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; _encryptor = encryptor;
_constFieldAllocator = constFieldAllocator; _constFieldAllocator = constFieldAllocator;
_proxyCallAllocator = new CallProxyAllocator(random, _encryptor); _proxyCallAllocator = new CallProxyAllocator(random, _encryptor, encryptionLevel);
} }
public override void Done() public override void Done()

View File

@ -16,18 +16,20 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public class ConstEncryptPass : BasicBlockObfuscationPassBase public class ConstEncryptPass : BasicBlockObfuscationPassBase
{ {
private readonly List<string> _configFiles; private readonly List<string> _configFiles;
private readonly int _encryptionLevel;
private IEncryptPolicy _dataObfuscatorPolicy; private IEncryptPolicy _dataObfuscatorPolicy;
private IConstEncryptor _dataObfuscator; private IConstEncryptor _dataObfuscator;
public ConstEncryptPass(ConstEncryptSettings settings) public ConstEncryptPass(ConstEncryptSettings settings)
{ {
_configFiles = settings.configFiles.ToList(); _configFiles = settings.configFiles.ToList();
_encryptionLevel = settings.encryptionLevel;
} }
public override void Start(ObfuscationPassContext ctx) public override void Start(ObfuscationPassContext ctx)
{ {
_dataObfuscatorPolicy = new ConfigurableEncryptPolicy(ctx.toObfuscatedAssemblyNames, _configFiles); _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) public override void Stop(ObfuscationPassContext ctx)

View File

@ -16,18 +16,20 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
private readonly RvaDataAllocator _rvaDataAllocator; private readonly RvaDataAllocator _rvaDataAllocator;
private readonly ConstFieldAllocator _constFieldAllocator; private readonly ConstFieldAllocator _constFieldAllocator;
private readonly IEncryptor _encryptor; 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; _random = random;
_encryptor = encryptor; _encryptor = encryptor;
_rvaDataAllocator = rvaDataAllocator; _rvaDataAllocator = rvaDataAllocator;
_constFieldAllocator = constFieldAllocator; _constFieldAllocator = constFieldAllocator;
_encryptionLevel = encryptionLevel;
} }
private int GenerateEncryptionOperations() private int GenerateEncryptionOperations()
{ {
return _random.NextInt(); return EncryptionUtil.GenerateEncryptionOpCodes(_random, _encryptor, _encryptionLevel);
} }
public int GenerateSalt() public int GenerateSalt()

View File

@ -14,11 +14,13 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
{ {
private readonly IRandom _random; private readonly IRandom _random;
private readonly IEncryptor _encryptor; private readonly IEncryptor _encryptor;
private readonly int _encryptionLevel;
public DefaultFieldEncryptor(IRandom random, IEncryptor encryptor) public DefaultFieldEncryptor(IRandom random, IEncryptor encryptor, int encryptionLevel)
{ {
_random = random; _random = random;
_encryptor = encryptor; _encryptor = encryptor;
_encryptionLevel = encryptionLevel;
} }
private DefaultMetadataImporter GetMetadataImporter(MethodDef method) 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) private FieldEncryptInfo GetFieldEncryptInfo(FieldDef field)
{ {
if (_fieldEncryptInfoCache.TryGetValue(field, out var info)) if (_fieldEncryptInfoCache.TryGetValue(field, out var info))
@ -61,8 +74,8 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
return info; return info;
} }
int encryptOps = _random.NextInt(); int encryptOps = GenerateEncryptionOperations();
int salt = _random.NextInt(); int salt = GenerateSalt();
ElementType fieldType = field.FieldSig.Type.RemovePinnedAndModifiers().ElementType; ElementType fieldType = field.FieldSig.Type.RemovePinnedAndModifiers().ElementType;
long xorValueForZero = CalcXorValueForZero(fieldType, encryptOps, salt); long xorValueForZero = CalcXorValueForZero(fieldType, encryptOps, salt);

View File

@ -13,19 +13,21 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
public class FieldEncryptPass : InstructionObfuscationPassBase public class FieldEncryptPass : InstructionObfuscationPassBase
{ {
private readonly List<string> _configFiles; private readonly List<string> _configFiles;
private readonly int _encryptionLevel;
private IEncryptPolicy _encryptionPolicy; private IEncryptPolicy _encryptionPolicy;
private IFieldEncryptor _memoryEncryptor; private IFieldEncryptor _memoryEncryptor;
public FieldEncryptPass(FieldEncryptSettings settings) public FieldEncryptPass(FieldEncryptSettings settings)
{ {
_configFiles = settings.configFiles.ToList(); _configFiles = settings.configFiles.ToList();
_encryptionLevel = settings.encryptionLevel;
} }
protected override bool NeedProcessNotObfuscatedAssembly => true; protected override bool NeedProcessNotObfuscatedAssembly => true;
public override void Start(ObfuscationPassContext ctx) 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); _encryptionPolicy = new ConfigurableEncryptPolicy(ctx.toObfuscatedAssemblyNames, _configFiles);
} }

View File

@ -19,7 +19,7 @@ namespace Obfuz
private int _globalRandomSeed; private int _globalRandomSeed;
private string _encryptionVmGenerationSecretKey; private string _encryptionVmGenerationSecretKey;
private int _encryptionVmOpCodeCount; private int _encryptionVmOpCodeCount;
public string _encryptionVmCodeFile; private string _encryptionVmCodeFile;
private List<string> _toObfuscatedAssemblyNames = new List<string>(); private List<string> _toObfuscatedAssemblyNames = new List<string>();
private List<string> _notObfuscatedAssemblyNamesReferencingObfuscated = new List<string>(); private List<string> _notObfuscatedAssemblyNamesReferencingObfuscated = new List<string>();

View File

@ -10,6 +10,10 @@ namespace Obfuz.Settings
[Serializable] [Serializable]
public class CallObfusSettings 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")] [Tooltip("config xml files")]
public string[] configFiles; public string[] configFiles;
} }

View File

@ -10,6 +10,10 @@ namespace Obfuz.Settings
[Serializable] [Serializable]
public class ConstEncryptSettings 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")] [Tooltip("config xml files")]
public string[] configFiles; public string[] configFiles;
} }

View File

@ -10,6 +10,10 @@ namespace Obfuz.Settings
[Serializable] [Serializable]
public class FieldEncryptSettings 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")] [Tooltip("config xml files")]
public string[] configFiles; public string[] configFiles;
} }

View File

@ -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;
}
}
}

View File

@ -33,11 +33,7 @@ namespace Obfuz.Utils
public static int[] ConvertToIntKey(byte[] key) public static int[] ConvertToIntKey(byte[] key)
{ {
Assert.AreEqual(0, key.Length % 4); return EncryptorBase.ConvertToIntKey(key);
int align4Length = key.Length / 4;
int[] intKey = new int[align4Length];
Buffer.BlockCopy(key, 0, intKey, 0, key.Length);
return intKey;
} }
} }
} }

View File

@ -7,6 +7,8 @@ namespace Obfuz
{ {
public abstract class EncryptorBase : IEncryptor public abstract class EncryptorBase : IEncryptor
{ {
public abstract int OpCodeCount { get; }
public static int[] ConvertToIntKey(byte[] key) public static int[] ConvertToIntKey(byte[] key)
{ {
Assert.AreEqual(0, key.Length % 4); Assert.AreEqual(0, key.Length % 4);

View File

@ -6,6 +6,8 @@ namespace Obfuz
{ {
public interface IEncryptor public interface IEncryptor
{ {
int OpCodeCount { get; }
void EncryptBlock(byte[] data, int ops, int salt); void EncryptBlock(byte[] data, int ops, int salt);
void DecryptBlock(byte[] data, int ops, int salt); void DecryptBlock(byte[] data, int ops, int salt);

View File

@ -10,6 +10,8 @@ namespace Obfuz
{ {
private readonly byte[] _key; private readonly byte[] _key;
public override int OpCodeCount => 256;
public NullEncryptor(byte[] key) public NullEncryptor(byte[] key)
{ {
_key = key; _key = key;