支持 obfuscationLevel和encryptionLevel
parent
b1a19e9ef7
commit
db86070fdb
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace Obfuz
|
|||
{
|
||||
private readonly byte[] _key;
|
||||
|
||||
public override int OpCodeCount => 256;
|
||||
|
||||
public NullEncryptor(byte[] key)
|
||||
{
|
||||
_key = key;
|
||||
|
|
Loading…
Reference in New Issue