支持 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)
{
_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;
}

View File

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

View File

@ -16,6 +16,7 @@ namespace Obfuz.ObfusPasses.CallObfus
public class CallObfusPass : BasicBlockObfuscationPassBase
{
private readonly List<string> _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);
}

View File

@ -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<MethodKey>
{
@ -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<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)

View File

@ -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()

View File

@ -16,18 +16,20 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public class ConstEncryptPass : BasicBlockObfuscationPassBase
{
private readonly List<string> _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)

View File

@ -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()

View File

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

View File

@ -13,19 +13,21 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
public class FieldEncryptPass : InstructionObfuscationPassBase
{
private readonly List<string> _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);
}

View File

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

View File

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

View File

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

View File

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

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)
{
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);
}
}
}

View File

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

View File

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

View File

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