支持变量加密

backup
walon 2025-05-01 12:23:22 +08:00
parent 6b476c7091
commit b75b87191d
4 changed files with 601 additions and 72 deletions

View File

@ -0,0 +1,87 @@
using dnlib.DotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine.Assertions;
namespace Obfuz.Emit
{
public class ModuleMetadataImporter
{
private readonly ModuleDef _module;
public ModuleMetadataImporter(ModuleDef module)
{
_module = module;
_module = module;
InitMetadatas(module);
}
private static IMethod s_castIntAsFloat;
private static IMethod s_castLongAsDouble;
private static IMethod s_castFloatAsInt;
private static IMethod s_castDoubleAsLong;
private void InitMetadatas(ModuleDef mod)
{
if (s_castFloatAsInt != null)
{
return;
}
var constUtilityType = typeof(ConstUtility);
s_castIntAsFloat = mod.Import(constUtilityType.GetMethod("CastIntAsFloat"));
Assert.IsNotNull(s_castIntAsFloat, "CastIntAsFloat not found");
s_castLongAsDouble = mod.Import(constUtilityType.GetMethod("CastLongAsDouble"));
Assert.IsNotNull(s_castLongAsDouble, "CastLongAsDouble not found");
s_castFloatAsInt = mod.Import(constUtilityType.GetMethod("CastFloatAsInt"));
Assert.IsNotNull(s_castFloatAsInt, "CastFloatAsInt not found");
s_castDoubleAsLong = mod.Import(constUtilityType.GetMethod("CastDoubleAsLong"));
Assert.IsNotNull(s_castDoubleAsLong, "CastDoubleAsLong not found");
}
public IMethod GetCastIntAsFloat()
{
return s_castIntAsFloat;
}
public IMethod GetCastLongAsDouble()
{
return s_castLongAsDouble;
}
public IMethod GetCastFloatAsInt()
{
return s_castFloatAsInt;
}
public IMethod GetCastDoubleAsLong()
{
return s_castDoubleAsLong;
}
}
public class MetadataImporter
{
private readonly Dictionary<ModuleDef, ModuleMetadataImporter> _moduleMetadataImporters = new Dictionary<ModuleDef, ModuleMetadataImporter>();
public static MetadataImporter Instance { get; private set; }
public static void Reset()
{
Instance = new MetadataImporter();
}
public ModuleMetadataImporter GetModuleMetadataImporter(ModuleDef module)
{
if (!_moduleMetadataImporters.TryGetValue(module, out var importer))
{
importer = new ModuleMetadataImporter(module);
_moduleMetadataImporters[module] = importer;
}
return importer;
}
}
}

View File

@ -0,0 +1,483 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine.Assertions;
namespace Obfuz.Emit
{
public class EncryptionCompileContext
{
public ModuleDef module;
}
public interface IVariableTransformer
{
object Compute(object value);
object ReverseCompute(object value);
void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx);
void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx);
}
public abstract class VariableTransformerBase : IVariableTransformer
{
public abstract object Compute(object value);
public abstract object ReverseCompute(object value);
public abstract void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx);
public abstract void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx);
}
public class AddVariableTransformer : VariableTransformerBase
{
private readonly DataNodeType _type;
private readonly object _addValue;
public AddVariableTransformer(DataNodeType type, object addValue)
{
_type = type;
_addValue = addValue;
}
public override object Compute(object value)
{
switch (_type)
{
case DataNodeType.Int32:
return (int)value + (int)_addValue;
case DataNodeType.Int64:
return (long)value + (long)_addValue;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public override object ReverseCompute(object value)
{
switch (_type)
{
case DataNodeType.Int32:
return (int)value - (int)_addValue;
case DataNodeType.Int64:
return (long)value - (long)_addValue;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public override void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_type)
{
case DataNodeType.Int32:
output.Add(Instruction.Create(OpCodes.Ldc_I4, (int)_addValue));
output.Add(Instruction.Create(OpCodes.Add));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Ldc_I8, (long)_addValue));
output.Add(Instruction.Create(OpCodes.Add));
break;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public override void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_type)
{
case DataNodeType.Int32:
output.Add(Instruction.Create(OpCodes.Ldc_I4, -(int)_addValue));
output.Add(Instruction.Create(OpCodes.Add));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Ldc_I8, -(long)_addValue));
output.Add(Instruction.Create(OpCodes.Add));
break;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public static AddVariableTransformer Create(DataNodeType type, IRandom random)
{
switch (type)
{
case DataNodeType.Int32: return new AddVariableTransformer(type, random.NextInt());
case DataNodeType.Int64: return new AddVariableTransformer(type, random.NextLong());
default:
throw new NotSupportedException($"Unsupported type: {type}");
}
}
}
public class XorVariableTransformer : VariableTransformerBase
{
private readonly DataNodeType _type;
private readonly object _xorValue;
public XorVariableTransformer(DataNodeType type, object xorValue)
{
_type = type;
_xorValue = xorValue;
}
public override object Compute(object value)
{
switch (_type)
{
case DataNodeType.Int32:
return (int)value ^ (int)_xorValue;
case DataNodeType.Int64:
return (long)value ^ (long)_xorValue;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public override object ReverseCompute(object value)
{
switch (_type)
{
case DataNodeType.Int32:
return (int)value ^ (int)_xorValue;
case DataNodeType.Int64:
return (long)value ^ (long)_xorValue;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public override void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_type)
{
case DataNodeType.Int32:
output.Add(Instruction.Create(OpCodes.Ldc_I4, (int)_xorValue));
output.Add(Instruction.Create(OpCodes.Xor));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Ldc_I8, (long)_xorValue));
output.Add(Instruction.Create(OpCodes.Xor));
break;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public override void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_type)
{
case DataNodeType.Int32:
output.Add(Instruction.Create(OpCodes.Ldc_I4, (int)_xorValue));
output.Add(Instruction.Create(OpCodes.Xor));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Ldc_I8, (long)_xorValue));
output.Add(Instruction.Create(OpCodes.Xor));
break;
default: throw new NotSupportedException($"Unsupported type: {_type}");
}
}
public static XorVariableTransformer Create(DataNodeType type, IRandom random)
{
switch (type)
{
case DataNodeType.Int32: return new XorVariableTransformer(type, random.NextInt());
case DataNodeType.Int64: return new XorVariableTransformer(type, random.NextLong());
default:
throw new NotSupportedException($"Unsupported type: {type}");
}
}
}
public class CastFloatAsIntTransformer : VariableTransformerBase
{
private readonly DataNodeType _outputType;
public CastFloatAsIntTransformer(DataNodeType srcType)
{
switch (srcType)
{
case DataNodeType.Float32: _outputType = DataNodeType.Int32; break;
case DataNodeType.Float64: _outputType = DataNodeType.Int64; break;
default: throw new NotSupportedException($"Unsupported type: {srcType}");
}
}
public override object Compute(object value)
{
switch (_outputType)
{
case DataNodeType.Int32:
return ConstUtility.CastFloatAsInt((float)value);
case DataNodeType.Int64:
return ConstUtility.CastDoubleAsLong((double)value);
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public override object ReverseCompute(object value)
{
switch (_outputType)
{
case DataNodeType.Int32:
return ConstUtility.CastIntAsFloat((int)value);
case DataNodeType.Int64:
return ConstUtility.CastLongAsDouble((long)value);
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public override void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_outputType)
{
case DataNodeType.Int32:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastFloatAsInt()));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastDoubleAsLong()));
break;
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public override void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_outputType)
{
case DataNodeType.Int32:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastIntAsFloat()));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastLongAsDouble()));
break;
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public static CastFloatAsIntTransformer Create(DataNodeType type)
{
switch (type)
{
case DataNodeType.Float32:
case DataNodeType.Float64: return new CastFloatAsIntTransformer(type);
default:
throw new NotSupportedException($"Unsupported type: {type}");
}
}
}
public class CastIntAsFloatTransformer : VariableTransformerBase
{
private readonly DataNodeType _outputType;
public CastIntAsFloatTransformer(DataNodeType srcType)
{
switch (srcType)
{
case DataNodeType.Int32: _outputType = DataNodeType.Float32; break;
case DataNodeType.Int64: _outputType = DataNodeType.Float64; break;
default: throw new NotSupportedException($"Unsupported type: {srcType}");
}
}
public override object Compute(object value)
{
switch (_outputType)
{
case DataNodeType.Float32:
return ConstUtility.CastIntAsFloat((int)value);
case DataNodeType.Float64:
return ConstUtility.CastLongAsDouble((long)value);
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public override object ReverseCompute(object value)
{
switch (_outputType)
{
case DataNodeType.Float32:
return ConstUtility.CastFloatAsInt((float)value);
case DataNodeType.Float64:
return ConstUtility.CastDoubleAsLong((double)value);
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public override void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_outputType)
{
case DataNodeType.Float32:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastIntAsFloat()));
break;
case DataNodeType.Float64:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastLongAsDouble()));
break;
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public override void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
switch (_outputType)
{
case DataNodeType.Float32:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastFloatAsInt()));
break;
case DataNodeType.Float64:
output.Add(Instruction.Create(OpCodes.Call, MetadataImporter.Instance.GetModuleMetadataImporter(ctx.module).GetCastDoubleAsLong()));
break;
default: throw new NotSupportedException($"Unsupported type: {_outputType}");
}
}
public static CastIntAsFloatTransformer Create(DataNodeType type)
{
switch (type)
{
case DataNodeType.Int32:
case DataNodeType.Int64: return new CastIntAsFloatTransformer(type);
default:
throw new NotSupportedException($"Unsupported type: {type}");
}
}
}
public class VariableEncryption
{
private readonly List<IVariableTransformer> _transformers = new List<IVariableTransformer>();
private readonly DataNodeType _type;
public VariableEncryption(DataNodeType type, IRandom random)
{
_type = type;
if (type == DataNodeType.Float32)
{
_transformers.Add(CastFloatAsIntTransformer.Create(type));
_transformers.AddRange(CreateTransformers(DataNodeType.Int32, random));
_transformers.Add(CastIntAsFloatTransformer.Create(DataNodeType.Int32));
Assert.AreEqual(1.0f, (float)ComputeValueAfterRevertTransform(ComputeValueAfterTransform(1.0f, _transformers), _transformers));
}
else if (type == DataNodeType.Float64)
{
_transformers.Add(CastFloatAsIntTransformer.Create(type));
_transformers.AddRange(CreateTransformers(DataNodeType.Int64, random));
_transformers.Add(CastIntAsFloatTransformer.Create(DataNodeType.Int64));
Assert.AreEqual(1.0, (double)ComputeValueAfterRevertTransform(ComputeValueAfterTransform(1.0, _transformers), _transformers));
}
else if (type == DataNodeType.Int32)
{
_transformers.AddRange(CreateTransformers(type, random));
Assert.AreEqual(1, (int)ComputeValueAfterRevertTransform(ComputeValueAfterTransform(1, _transformers), _transformers));
}
else if (type == DataNodeType.Int64)
{
_transformers.AddRange(CreateTransformers(type, random));
Assert.AreEqual(1L, (long)ComputeValueAfterRevertTransform(ComputeValueAfterTransform(1L, _transformers), _transformers));
}
else
{
throw new NotSupportedException($"Unsupported type: {type} for VariableEncryption");
}
}
private List<IVariableTransformer> CreateTransformers(DataNodeType type, IRandom random)
{
var output = new List<IVariableTransformer>();
output.Add(XorVariableTransformer.Create(type, random));
output.Add(AddVariableTransformer.Create(type, random));
output.Add(XorVariableTransformer.Create(type, random));
//int count = 3;
//for (int i = 0; i < count; i++)
//{
// switch(random.NextInt(2))
// {
// case 0:
// {
// var transformer = AddVariableTransformer.Create(type, random);
// output.Add(transformer);
// break;
// }
// case 1:
// {
// var transformer = XorVariableTransformer.Create(type, random);
// output.Add(transformer);
// break;
// }
// }
//}
AddMapZeroToZeroTransform(type, random, output);
return output;
}
public static object ComputeValueAfterTransform(object value, List<IVariableTransformer> transformers)
{
foreach (var transformer in transformers)
{
value = transformer.Compute(value);
}
return value;
}
public static object ComputeValueAfterRevertTransform(object value, List<IVariableTransformer> transformers)
{
for (int i = transformers.Count - 1; i >= 0; i--)
{
var transformer = transformers[i];
value = transformer.ReverseCompute(value);
}
return value;
}
private void AddMapZeroToZeroTransform(DataNodeType type, IRandom random, List<IVariableTransformer> output)
{
switch (type)
{
case DataNodeType.Int32:
{
int value = (int)ComputeValueAfterTransform(0, output);
if (value != 0)
{
output.Add(new AddVariableTransformer(type, -value));
}
break;
}
case DataNodeType.Int64:
{
long value = (long)ComputeValueAfterTransform(0L, output);
if (value != 0)
{
output.Add(new AddVariableTransformer(type, -value));
}
break;
}
default:
throw new NotSupportedException($"Unsupported type: {type}");
}
}
public void EmitTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
foreach (var transformer in _transformers)
{
transformer.EmitTransform(output, ctx);
}
}
public void EmitRevertTransform(List<Instruction> output, EncryptionCompileContext ctx)
{
for (int i = _transformers.Count - 1; i >= 0; i--)
{
var transformer = _transformers[i];
transformer.EmitRevertTransform(output, ctx);
}
}
}
}

View File

@ -1,5 +1,7 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Emit;
using Obfuz.Utils;
using System;
using System.Collections.Generic;
using UnityEngine.Assertions;
@ -42,44 +44,32 @@ namespace Obfuz.MemEncrypt
Assert.IsNotNull(s_castDoubleAsLong, "CastDoubleAsLong not found");
}
private VariableEncryption CreateEncryption(ElementType type)
{
IRandom random = new RandomWithKey(new byte[16], 1234);
switch (type)
{
case ElementType.I4:
return new VariableEncryption(DataNodeType.Int32, random);
case ElementType.I8:
return new VariableEncryption(DataNodeType.Int64, random);
case ElementType.R4:
return new VariableEncryption(DataNodeType.Float32, random);
case ElementType.R8:
return new VariableEncryption(DataNodeType.Float64, random);
default: throw new Exception($"Unsupported type {type} for MemoryEncryptor");
}
}
public void Encrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx)
{
ElementType type = field.FieldType.RemovePinnedAndModifiers().ElementType;
if (type == ElementType.R4)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castFloatAsInt));
type = ElementType.I4;
}
else if (type == ElementType.R8)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castDoubleAsLong));
type = ElementType.I8;
}
if (type == ElementType.I4)
{
outputInstructions.Add(Instruction.CreateLdcI4(100));
outputInstructions.Add(Instruction.Create(OpCodes.Add));
}
else if (type == ElementType.I8)
{
outputInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, 100L));
outputInstructions.Add(Instruction.Create(OpCodes.Add));
}
else
{
throw new NotSupportedException($"Unsupported type {type} for MemoryEncryptor");
}
if (type == ElementType.R4)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castIntAsFloat));
type = ElementType.I4;
}
else if (type == ElementType.R8)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castLongAsDouble));
type = ElementType.I8;
}
ElementType type = field.FieldType.RemovePinnedAndModifiers().ElementType;
var encryption = CreateEncryption(type);
encryption.EmitTransform(outputInstructions, new EncryptionCompileContext { module = _module });
outputInstructions.Add(ctx.currentInstruction.Clone());
}
@ -87,41 +77,9 @@ namespace Obfuz.MemEncrypt
{
outputInstructions.Add(ctx.currentInstruction.Clone());
ElementType type = field.FieldType.RemovePinnedAndModifiers().ElementType;
if (type == ElementType.R4)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castFloatAsInt));
type = ElementType.I4;
}
else if (type == ElementType.R8)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castDoubleAsLong));
type = ElementType.I8;
}
var encryption = CreateEncryption(type);
if (type == ElementType.I4)
{
outputInstructions.Add(Instruction.CreateLdcI4(100));
outputInstructions.Add(Instruction.Create(OpCodes.Sub));
}
else if (type == ElementType.I8)
{
outputInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, 100L));
outputInstructions.Add(Instruction.Create(OpCodes.Sub));
}
else
{
throw new NotSupportedException($"Unsupported type {type} for MemoryEncryptor");
}
if (type == ElementType.R4)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castIntAsFloat));
type = ElementType.I4;
}
else if (type == ElementType.R8)
{
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castLongAsDouble));
type = ElementType.I8;
}
encryption.EmitRevertTransform(outputInstructions, new EncryptionCompileContext { module = _module });
}
}

View File

@ -46,12 +46,13 @@ namespace Obfuz
{
_options = options;
_obfuscationAssemblyNames = options.obfuscationAssemblyNames;
MetadataImporter.Reset();
_assemblyCache = new AssemblyCache(new PathAssemblyResolver(options.assemblySearchDirs.ToArray()));
_pipeline.AddPass(new MemoryEncryptionPass());
_pipeline.AddPass(new ProxyCallPass());
_pipeline.AddPass(new ExprObfuscationPass());
_pipeline.AddPass(new DataVirtualizationPass());
//_pipeline.AddPass(new ProxyCallPass());
//_pipeline.AddPass(new ExprObfuscationPass());
//_pipeline.AddPass(new DataVirtualizationPass());
_pipeline.AddPass(new RenameSymbolPass());
_pipeline.AddPass(new CleanUpInstructionPass());