- 移除Emit模块下无用的Random Node Creator

- 修复RandomWithKey的byte[]为key的问题
- 重构MetadataModuleImpoter
backup
walon 2025-05-11 08:46:01 +08:00
parent 856e924ed8
commit d14d0f913c
42 changed files with 104 additions and 1605 deletions

View File

@ -12,7 +12,7 @@ using UnityEngine.Assertions;
namespace Obfuz.Data
{
public class ModuleConstFieldAllocator : IModuleEmitManager
public class ModuleConstFieldAllocator : IGroupByModuleEntity
{
private ModuleDef _module;
private readonly IRandom _random;
@ -138,7 +138,7 @@ namespace Obfuz.Data
private DefaultModuleMetadataImporter GetModuleMetadataImporter()
{
return MetadataImporter.Instance.GetDefaultModuleMetadataImporter(_module);
return GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(_module);
}
private void CreateCCtorOfRvaTypeDef(TypeDef type)
@ -268,7 +268,7 @@ namespace Obfuz.Data
private ModuleConstFieldAllocator GetModuleAllocator(ModuleDef mod)
{
return EmitManager.Ins.GetEmitManager<ModuleConstFieldAllocator>(mod, () => new ModuleConstFieldAllocator(_encryptor, _random, _rvaDataAllocator));
return GroupByModuleManager.Ins.GetEntity<ModuleConstFieldAllocator>(mod, () => new ModuleConstFieldAllocator(_encryptor, _random, _rvaDataAllocator));
}
public FieldDef Allocate(ModuleDef mod, int value)
@ -303,7 +303,7 @@ namespace Obfuz.Data
public void Done()
{
foreach (var moduleAllocator in EmitManager.Ins.GetEmitManagers<ModuleConstFieldAllocator>())
foreach (var moduleAllocator in GroupByModuleManager.Ins.GetEntities<ModuleConstFieldAllocator>())
{
moduleAllocator.Done();
}

View File

@ -25,7 +25,7 @@ namespace Obfuz.Data
}
}
public class ModuleRvaDataAllocator : ModuleEmitManagerBase
public class ModuleRvaDataAllocator : GroupByModuleEntityBase
{
// randomized
const int maxRvaDataSize = 0x1000;
@ -234,7 +234,7 @@ namespace Obfuz.Data
cctorMethod.Body = body;
var ins = body.Instructions;
DefaultModuleMetadataImporter importer = MetadataImporter.Instance.GetDefaultModuleMetadataImporter(mod);
DefaultModuleMetadataImporter importer = GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(mod);
foreach (var field in _rvaFields)
{
// ldc
@ -296,7 +296,7 @@ namespace Obfuz.Data
private ModuleRvaDataAllocator GetModuleRvaDataAllocator(ModuleDef mod)
{
return EmitManager.Ins.GetEmitManager<ModuleRvaDataAllocator>(mod, () => new ModuleRvaDataAllocator(_random, _encryptor));
return GroupByModuleManager.Ins.GetEntity<ModuleRvaDataAllocator>(mod, () => new ModuleRvaDataAllocator(_random, _encryptor));
}
public RvaData Allocate(ModuleDef mod, int value)
@ -331,7 +331,7 @@ namespace Obfuz.Data
public void Done()
{
foreach (var allocator in EmitManager.Ins.GetEmitManagers<ModuleRvaDataAllocator>())
foreach (var allocator in GroupByModuleManager.Ins.GetEntities<ModuleRvaDataAllocator>())
{
allocator.Done();
}

View File

@ -1,17 +0,0 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using NUnit.Framework;
using Obfuz.Emit;
using Obfuz.Data;
using System.Collections.Generic;
namespace Obfuz.Emit
{
public class CompileContext
{
public MethodDef method;
public List<Instruction> output;
public RvaDataAllocator rvaDataAllocator;
public ConstFieldAllocator constFieldAllocator;
}
}

View File

@ -1,27 +0,0 @@
using System;
using UnityEngine.Assertions;
namespace Obfuz.Emit
{
public struct ConstValue
{
public readonly DataNodeType type;
public readonly object value;
public ConstValue(DataNodeType type, object value)
{
switch (type)
{
case DataNodeType.Int32: Assert.IsTrue(value is int); break;
case DataNodeType.Int64: Assert.IsTrue(value is long); break;
case DataNodeType.Float32: Assert.IsTrue(value is float); break;
case DataNodeType.Float64: Assert.IsTrue(value is double); break;
case DataNodeType.String: Assert.IsTrue(value is string); break;
case DataNodeType.Bytes: Assert.IsTrue(value is byte[]); break;
default: throw new NotSupportedException($"Unsupported type {type} for ConstValue");
}
this.type = type;
this.value = value;
}
}
}

View File

@ -1,12 +0,0 @@
using Obfuz.Emit;
using Obfuz.Utils;
namespace Obfuz.Emit
{
public struct CreateExpressionOptions
{
public IRandom random;
public IDataNodeCreator expressionCreator;
public int depth;
}
}

View File

@ -1,7 +0,0 @@
namespace Obfuz.Emit
{
public abstract class DataNodeCreatorBase : IDataNodeCreator
{
public abstract IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options);
}
}

View File

@ -1,14 +0,0 @@
namespace Obfuz.Emit
{
public enum DataNodeType
{
//Byte,
Int32,
Int64,
Float32,
Float64,
String,
Bytes,
//Null,
}
}

View File

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit
{
[NodeOutput(DataNodeType.Bytes)]
public class BytesFromEncryptedBytesNode : DataNodeAny
{
public override void Compile(CompileContext ctx)
{
// only support Int32, int64, bytes.
// string can only create from StringFromBytesNode
// x = memcpy array.GetRange(index, length);
}
}
}

View File

@ -1,78 +0,0 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Emit;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static UnityEngine.Networking.UnityWebRequest;
using UnityEngine.UIElements;
using Obfuz.Data;
namespace Obfuz.Emit
{
[NodeOutput(DataNodeType.Int32)]
[NodeOutput(DataNodeType.Int64)]
[NodeOutput(DataNodeType.Float32)]
[NodeOutput(DataNodeType.Float64)]
[NodeOutput(DataNodeType.Bytes)]
[NodeOutput(DataNodeType.String)]
public class BytesInitializeFromFieldRvaDataNode : DataNodeAny
{
private RvaData AllocateRvaData(CompileContext ctx)
{
ModuleDef mod = ctx.method.Module;
RvaDataAllocator allocator = ctx.rvaDataAllocator;
switch (Type)
{
//case DataNodeType.Int32: return allocator.Allocate(mod, IntValue);
//case DataNodeType.Int64: return allocator.Allocate(mod, LongValue);
//case DataNodeType.Float32: return allocator.Allocate(mod, FloatValue);
//case DataNodeType.Float64: return allocator.Allocate(mod, DoubleValue);
case DataNodeType.Bytes: return allocator.Allocate(mod, BytesValue);
//case DataNodeType.String: return allocator.Allocate(mod, StringValue);
default:
throw new NotSupportedException($"Unsupported type: {Type}.");
}
}
private static IMethod s_convertBytes;
private void InitImportMetadatas(ModuleDef mod)
{
if (s_convertBytes != null)
{
return;
}
s_convertBytes = mod.Import(typeof(ConstUtility).GetMethod("InitializeArray", new[] { typeof(Array), typeof(byte[]), typeof(int), typeof(int) }));
}
IMethod GetConvertMethod(ModuleDef mod)
{
InitImportMetadatas(mod);
return s_convertBytes;
}
public override void Compile(CompileContext ctx)
{
// only support Int32, int64, bytes.
// string can only create from StringFromBytesNode
// x = memcpy array.GetRange(index, length);
var output = ctx.output;
RvaData rvaData = AllocateRvaData(ctx);
ModuleDef mod = ctx.method.Module;
IMethod convertMethod = GetConvertMethod(mod);
ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.offset));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size));
//output.Add(Instruction.Create(OpCodes.Newarr, mod.CorLibTypes.Byte.ToTypeDefOrRef()));
//output.Add(Instruction.Create(OpCodes.Ldc_I4, 0));
//output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size));
output.Add(Instruction.Create(OpCodes.Call, convertMethod));
}
}
}

View File

@ -1,40 +0,0 @@
using dnlib.DotNet.Emit;
using System;
namespace Obfuz.Emit
{
[NodeOutput(DataNodeType.Int32)]
[NodeOutput(DataNodeType.Int64)]
public class ConstDataNode : DataNodeAny
{
public override void Compile(CompileContext ctx)
{
// only Int32 - Null,
// to avoid GC,
// the leaf node that can create string or bytes is ConstFieldDataNode.
// float and double can only come from RawCastAs int32 and int64.
// so we only need to deal int32 and int64
switch (Type)
{
case DataNodeType.Int32:
{
// create ldloc.i4
ctx.output.Add(Instruction.CreateLdcI4(IntValue));
break;
}
case DataNodeType.Int64:
{
// create ldloc.i8
ctx.output.Add(Instruction.Create(OpCodes.Ldc_I8, LongValue));
break;
}
default:
{
throw new NotImplementedException($"Type:{Type} not implemented");
}
}
}
}
}

View File

@ -1,27 +0,0 @@
using System.Collections.Generic;
namespace Obfuz.Emit
{
[NodeOutput(DataNodeType.Int32)]
[NodeOutput(DataNodeType.Int64)]
[NodeOutput(DataNodeType.Bytes)]
public class ConstExpression : DataNodeAny
{
public IFunction function;
public readonly List<IDataNode> inputs;
public readonly ConstValue result;
public ConstExpression(IFunction function, List<IDataNode> inputs, ConstValue result)
{
this.function = function;
this.inputs = inputs;
Type = result.type;
this.result = result;
}
public override void Compile(CompileContext ctx)
{
function.Compile(ctx, inputs, result);
}
}
}

View File

@ -1,60 +0,0 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Obfuz.Emit
{
public class ConstFieldDataNode : DataNodeAny
{
public override void Compile(CompileContext ctx)
{
ModuleDef mod = ctx.method.Module;
var output = ctx.output;
FieldDef field;
switch (Type)
{
case DataNodeType.Int32:
{
field = ctx.constFieldAllocator.Allocate(mod, IntValue);
break;
}
case DataNodeType.Int64:
{
field = ctx.constFieldAllocator.Allocate(mod, LongValue);
break;
}
case DataNodeType.Float32:
{
field = ctx.constFieldAllocator.Allocate(mod, FloatValue);
break;
}
case DataNodeType.Float64:
{
field = ctx.constFieldAllocator.Allocate(mod, DoubleValue);
break;
}
case DataNodeType.String:
{
field = ctx.constFieldAllocator.Allocate(mod, StringValue);
break;
}
case DataNodeType.Bytes:
{
// ldsfld
// ldtoken
// RuntimeHelpers.InitializeArray(array, fieldHandle);
//break;
throw new NotSupportedException("Bytes not supported");
}
default:
{
throw new NotImplementedException($"Type:{Type} not implemented");
}
}
output.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
}
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit
{
public class ConstFromBytesNode : DataNodeAny
{
public override void Compile(CompileContext ctx)
{
// only support Int32, int64, bytes.
// string can only create from StringFromBytesNode
// x = memcpy array.GetRange(index, length);
}
}
}

View File

@ -1,117 +0,0 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Emit;
using System;
using Obfuz.Data;
namespace Obfuz.Emit
{
[NodeOutput(DataNodeType.Int32)]
[NodeOutput(DataNodeType.Int64)]
[NodeOutput(DataNodeType.Float32)]
[NodeOutput(DataNodeType.Float64)]
[NodeOutput(DataNodeType.Bytes)]
[NodeOutput(DataNodeType.String)]
public class ConstFromFieldRvaDataNode : DataNodeAny
{
private RvaData AllocateRvaData(CompileContext ctx)
{
ModuleDef mod = ctx.method.Module;
RvaDataAllocator allocator = ctx.rvaDataAllocator;
switch (Type)
{
case DataNodeType.Int32: return allocator.Allocate(mod, IntValue);
case DataNodeType.Int64: return allocator.Allocate(mod, LongValue);
case DataNodeType.Float32: return allocator.Allocate(mod, FloatValue);
case DataNodeType.Float64: return allocator.Allocate(mod, DoubleValue);
case DataNodeType.Bytes: return allocator.Allocate(mod, BytesValue);
case DataNodeType.String: return allocator.Allocate(mod, StringValue);
default:
throw new NotSupportedException($"Unsupported type: {Type}.");
}
}
private static IMethod s_convertInt;
private static IMethod s_convertLong;
private static IMethod s_convertFloat;
private static IMethod s_convertDouble;
private static IMethod s_convertString;
//private static IField s_Encoding_Utf8;
private static IMethod s_convertBytes;
private void InitImportMetadatas(ModuleDef mod)
{
if (s_convertInt != null)
{
return;
}
s_convertInt = mod.Import(typeof(ConstUtility).GetMethod("GetInt", new[] { typeof(byte[]), typeof(int) }));
s_convertLong = mod.Import(typeof(ConstUtility).GetMethod("GetLong", new[] { typeof(byte[]), typeof(int) }));
s_convertFloat = mod.Import(typeof(ConstUtility).GetMethod("GetFloat", new[] { typeof(byte[]), typeof(int) }));
s_convertDouble = mod.Import(typeof(ConstUtility).GetMethod("GetDouble", new[] { typeof(byte[]), typeof(int) }));
s_convertString = mod.Import(typeof(ConstUtility).GetMethod("GetString", new[] { typeof(byte[]), typeof(int), typeof(int) }));
//s_Encoding_Utf8 = mod.Import(typeof(Encoding).GetField("UTF8"));
s_convertBytes = mod.Import(typeof(ConstUtility).GetMethod("GetBytes", new[] { typeof(byte[]), typeof(int), typeof(int) }));
}
IMethod GetConvertMethod(ModuleDef mod)
{
InitImportMetadatas(mod);
switch (Type)
{
case DataNodeType.Int32: return s_convertInt;
case DataNodeType.Int64: return s_convertLong;
case DataNodeType.Float32: return s_convertFloat;
case DataNodeType.Float64: return s_convertDouble;
case DataNodeType.String: return s_convertString;
case DataNodeType.Bytes: return s_convertBytes;
default: throw new NotSupportedException($"Unsupported type: {Type}.");
}
}
public override void Compile(CompileContext ctx)
{
// only support Int32, int64, bytes.
// string can only create from StringFromBytesNode
// x = memcpy array.GetRange(index, length);
var output = ctx.output;
RvaData rvaData = AllocateRvaData(ctx);
ModuleDef mod = ctx.method.Module;
IMethod convertMethod = GetConvertMethod(mod);
switch (Type)
{
case DataNodeType.Int32:
case DataNodeType.Int64:
case DataNodeType.Float32:
case DataNodeType.Float64:
{
ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.offset));
output.Add(Instruction.Create(OpCodes.Call, convertMethod));
break;
}
case DataNodeType.String:
case DataNodeType.Bytes:
{
// Encoding.UTF8.GetString(data, offset, length);
//ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, s_Encoding_Utf8));
//ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
//output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.offset));
//output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size));
//output.Add(Instruction.Create(OpCodes.Call, convertMethod));
ctx.output.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.offset));
output.Add(Instruction.Create(OpCodes.Ldc_I4, rvaData.size));
output.Add(Instruction.Create(OpCodes.Call, convertMethod));
break;
}
default:
throw new NotSupportedException($"Unsupported type: {Type}.");
}
}
}
}

View File

@ -1,54 +0,0 @@
using dnlib.DotNet;
namespace Obfuz.Emit
{
public abstract class DataNodeBase : IDataNode
{
public DataNodeType Type { get; set; }
public abstract object Value { get; set; }
public int IntValue => (int)Value;
public long LongValue => (long) Value;
public float FloatValue => (float)Value;
public double DoubleValue => (double)Value;
public string StringValue => (string)Value;
public byte[] BytesValue => (byte[])Value;
public virtual void Init(CreateExpressionOptions options)
{
}
public abstract void Compile(CompileContext ctx);
}
public abstract class DataNodeBase<T> : DataNodeBase
{
public T Value2 { get; set; }
public override object Value
{
get => Value2;
set => Value2 = (T)value;
}
}
public abstract class DataNodeAny : DataNodeBase
{
private object _value;
public override object Value
{
get => _value;
set => _value = value;
}
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit
{
public class RvaBytesNode : DataNodeBase<byte[]>
{
public override void Compile(CompileContext ctx)
{
}
}
}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit
{
public class StringFromEncryptedBytesNode : DataNodeAny
{
public override void Compile(CompileContext ctx)
{
// only support Int32, int64, bytes.
// string can only create from StringFromBytesNode
// x = memcpy array.GetRange(index, length);
}
}
}

View File

@ -4,7 +4,7 @@ using UnityEngine.Assertions;
namespace Obfuz.Emit
{
public class DefaultModuleMetadataImporter : ModuleMetadataImporterBase
public class DefaultModuleMetadataImporter : GroupByModuleEntityBase
{
public DefaultModuleMetadataImporter() { }

View File

@ -1,17 +0,0 @@
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit.Functions
{
public class BytesInitializeFromFieldRvaDataCreator : NodeCreatorBase
{
public override IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options)
{
return new BytesInitializeFromFieldRvaDataNode { Type = type, Value = value };
}
}
}

View File

@ -1,17 +0,0 @@
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit.Functions
{
public class ConstDataCreator : NodeCreatorBase
{
public override IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options)
{
return new ConstDataNode { Type = type, Value = value };
}
}
}

View File

@ -1,16 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit.Functions
{
public class ConstFieldDataCreator : NodeCreatorBase
{
public override IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options)
{
return new ConstFieldDataNode { Type = type, Value = value };
}
}
}

View File

@ -1,17 +0,0 @@
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit.Functions
{
public class ConstFromFieldRvaDataCreator : NodeCreatorBase
{
public override IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options)
{
return new ConstFromFieldRvaDataNode { Type = type, Value = value };
}
}
}

View File

@ -1,41 +0,0 @@
using dnlib.DotNet.Emit;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;
namespace Obfuz.Emit
{
public abstract class FunctionBase : IFunction
{
public abstract void CreateArguments(DataNodeType type, object value, CreateExpressionOptions options, List<ConstValue> args);
public abstract void CompileSelf(CompileContext ctx, List<IDataNode> inputs, List<Instruction> output);
public virtual void Compile(CompileContext ctx, List<IDataNode> inputs, ConstValue result)
{
foreach (var input in inputs)
{
input.Compile(ctx);
}
CompileSelf(ctx, inputs, ctx.output);
}
public virtual IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options)
{
var args = new List<ConstValue>();
CreateArguments(type, value, options, args);
options.depth += 1;
var argNodes = new List<IDataNode>();
foreach (ConstValue cv in args)
{
var argNode = options.expressionCreator.CreateRandom(cv.type, cv.value, options);
argNodes.Add(argNode);
}
return new ConstExpression(this, args.Select(a => options.expressionCreator.CreateRandom(a.type, a.value, options)).ToList(), new ConstValue(type, value));
}
}
}

View File

@ -1,49 +0,0 @@
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit.Functions
{
public class IntAdd : FunctionBase
{
public override void CreateArguments(DataNodeType type, object v, CreateExpressionOptions options, List<ConstValue> args)
{
switch (type)
{
case DataNodeType.Int32:
{
int value = (int)v;
int op1 = options.random.NextInt();
int op2 = value - op1;
args.Add(new ConstValue(DataNodeType.Int32, op1));
args.Add(new ConstValue(DataNodeType.Int32, op2));
break;
}
case DataNodeType.Int64:
{
long value = (long)v;
long op1 = options.random.NextLong();
long op2 = value - op1;
args.Add(new ConstValue(DataNodeType.Int64, op1));
args.Add(new ConstValue(DataNodeType.Int64, op2));
break;
}
default:
{
throw new NotSupportedException($"Unsupported type: {type}");
}
}
}
public override void CompileSelf(CompileContext ctx, List<IDataNode> inputs, List<Instruction> output)
{
output.Add(Instruction.Create(OpCodes.Add));
}
}
}

View File

@ -1,73 +0,0 @@
using dnlib.DotNet.Emit;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static UnityEngine.Networking.UnityWebRequest;
namespace Obfuz.Emit.Functions
{
public class IntRotateShift : FunctionBase
{
public override void CreateArguments(DataNodeType type, object v, CreateExpressionOptions options, List<ConstValue> args)
{
switch (type)
{
case DataNodeType.Int32:
{
int value = (int)v;
// (value >> amount) | (value << (32 - amount))
// << amount
// value = b31 b30 .. b0;
int leftShiftAmount = options.random.NextInt(8, 16);
uint op1 = (uint)value >> leftShiftAmount;
int rightShiftAmount = 32 - leftShiftAmount;
uint op2 = (uint)value << rightShiftAmount;
Assert.AreEqual((uint)value, (op1 << leftShiftAmount) | (op2 >> rightShiftAmount));
args.Add(new ConstValue(DataNodeType.Int32, (int)op1));
args.Add(new ConstValue(DataNodeType.Int32, leftShiftAmount));
args.Add(new ConstValue(DataNodeType.Int32, (int)op2));
args.Add(new ConstValue(DataNodeType.Int32, rightShiftAmount));
break;
}
case DataNodeType.Int64:
{
long value = (long)v;
int leftShiftAmount = options.random.NextInt(16, 32);
ulong op1 = (ulong)value >> leftShiftAmount;
int rightShiftAmount = 64 - leftShiftAmount;
ulong op2 = (ulong)value << rightShiftAmount;
Assert.AreEqual((ulong)value, (op1 << leftShiftAmount) | (op2 >> rightShiftAmount));
args.Add(new ConstValue(DataNodeType.Int64, (long)op1));
args.Add(new ConstValue(DataNodeType.Int32, leftShiftAmount));
args.Add(new ConstValue(DataNodeType.Int64, (long)op2));
args.Add(new ConstValue(DataNodeType.Int32, rightShiftAmount));
break;
}
default: throw new NotSupportedException($"Unsupported type {type} for IntRotateShift");
}
}
public override void CompileSelf(CompileContext ctx, List<IDataNode> inputs, List<Instruction> output)
{
output.Add(Instruction.Create(OpCodes.Xor));
}
public override void Compile(CompileContext ctx, List<IDataNode> inputs, ConstValue result)
{
Assert.AreEqual(inputs.Count, 4);
inputs[0].Compile(ctx);
inputs[1].Compile(ctx);
ctx.output.Add(Instruction.Create(OpCodes.Shl));
inputs[2].Compile(ctx);
inputs[3].Compile(ctx);
ctx.output.Add(Instruction.Create(OpCodes.Shr_Un));
ctx.output.Add(Instruction.Create(OpCodes.Or));
}
}
}

View File

@ -1,46 +0,0 @@
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static UnityEngine.Networking.UnityWebRequest;
namespace Obfuz.Emit.Functions
{
public class IntXor : FunctionBase
{
public override void CreateArguments(DataNodeType type, object v, CreateExpressionOptions options, List<ConstValue> args)
{
switch (type)
{
case DataNodeType.Int32:
{
int value = (int)v;
int op1 = options.random.NextInt();
int op2 = value ^ op1;
args.Add(new ConstValue(DataNodeType.Int32, op1));
args.Add(new ConstValue(DataNodeType.Int32, op2));
break;
}
case DataNodeType.Int64:
{
long value = (long)v;
long op1 = options.random.NextLong();
long op2 = value ^ op1;
args.Add(new ConstValue(DataNodeType.Int64, op1));
args.Add(new ConstValue(DataNodeType.Int64, op2));
break;
}
default: throw new NotSupportedException($"Unsupported type {type} for Int32FunctionXor");
}
}
public override void CompileSelf(CompileContext ctx, List<IDataNode> inputs, List<Instruction> output)
{
output.Add(Instruction.Create(OpCodes.Xor));
}
}
}

View File

@ -1,76 +0,0 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Assertions;
namespace Obfuz.Emit.DataNodes
{
public class MemoryCastIntAsFloat : FunctionBase
{
private static IMethod s_castIntAsFloat;
private static IMethod s_castLongAsDouble;
private void InitMetadatas(ModuleDef mod)
{
if (s_castIntAsFloat != 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");
}
public override void CompileSelf(CompileContext ctx, List<IDataNode> inputs, List<Instruction> output)
{
Assert.AreEqual(1, inputs.Count);
InitMetadatas(ctx.method.Module);
switch (inputs[0].Type)
{
case DataNodeType.Int32:
{
output.Add(Instruction.Create(OpCodes.Call, s_castIntAsFloat));
break;
}
case DataNodeType.Int64:
{
output.Add(Instruction.Create(OpCodes.Call, s_castLongAsDouble));
break;
}
default: throw new NotSupportedException($"Unsupported type {inputs[0].Type} for MemoryCastIntAsFloat");
}
}
public override void CreateArguments(DataNodeType type, object v, CreateExpressionOptions options, List<ConstValue> args)
{
switch (type)
{
case DataNodeType.Float32:
{
float value = (float)v;
int intValue = ConstUtility.CastFloatAsInt(value);
args.Add(new ConstValue(DataNodeType.Int32, intValue));
break;
}
case DataNodeType.Float64:
{
double value = (double)v;
long longValue = ConstUtility.CastDoubleAsLong(value);
args.Add(new ConstValue(DataNodeType.Int64, longValue));
break;
}
default:
{
throw new NotImplementedException($"Type:{type} not implemented");
}
}
}
}
}

View File

@ -1,14 +0,0 @@
using System.Collections.Generic;
namespace Obfuz.Emit
{
public abstract class NodeCreatorBase : IFunction
{
void IFunction.Compile(CompileContext ctx, List<IDataNode> inputs, ConstValue result)
{
throw new System.NotSupportedException("This function is not supported in this context.");
}
public abstract IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options);
}
}

View File

@ -7,29 +7,29 @@ using System.Threading.Tasks;
namespace Obfuz.Emit
{
public interface IModuleEmitManager
public interface IGroupByModuleEntity
{
void Init(ModuleDef mod);
}
public abstract class ModuleEmitManagerBase : IModuleEmitManager
public abstract class GroupByModuleEntityBase : IGroupByModuleEntity
{
public abstract void Init(ModuleDef mod);
}
public class EmitManager
public class GroupByModuleManager
{
public static EmitManager Ins { get; private set; }
public static GroupByModuleManager Ins { get; private set; }
private readonly Dictionary<(ModuleDef, Type), IModuleEmitManager> _moduleEmitManagers = new System.Collections.Generic.Dictionary<(ModuleDef, Type), IModuleEmitManager>();
private readonly Dictionary<(ModuleDef, Type), IGroupByModuleEntity> _moduleEmitManagers = new Dictionary<(ModuleDef, Type), IGroupByModuleEntity>();
public static void Reset()
{
Ins = new EmitManager();
Ins = new GroupByModuleManager();
}
public T GetEmitManager<T>(ModuleDef mod, Func<T> creator = null) where T : IModuleEmitManager
public T GetEntity<T>(ModuleDef mod, Func<T> creator = null) where T : IGroupByModuleEntity
{
var key = (mod, typeof(T));
if (_moduleEmitManagers.TryGetValue(key, out var emitManager))
@ -53,7 +53,7 @@ namespace Obfuz.Emit
}
}
public List<T> GetEmitManagers<T>() where T: IModuleEmitManager
public List<T> GetEntities<T>() where T: IGroupByModuleEntity
{
var managers = new List<T>();
foreach (var kv in _moduleEmitManagers)
@ -65,5 +65,10 @@ namespace Obfuz.Emit
}
return managers;
}
public DefaultModuleMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module)
{
return GetEntity<DefaultModuleMetadataImporter>(module);
}
}
}

View File

@ -1,20 +0,0 @@
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
namespace Obfuz.Emit
{
public interface IDataNode
{
DataNodeType Type { get; }
object Value { get; }
void Init(CreateExpressionOptions options);
void Compile(CompileContext ctx);
}
}

View File

@ -1,7 +0,0 @@
namespace Obfuz.Emit
{
public interface IDataNodeCreator
{
IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options);
}
}

View File

@ -1,12 +0,0 @@
using System.Collections.Generic;
namespace Obfuz.Emit
{
public interface IFunction
{
IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options);
void Compile(CompileContext ctx, List<IDataNode> inputs, ConstValue result);
}
}

View File

@ -1,73 +1,73 @@
using dnlib.DotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using dnlib.DotNet;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
namespace Obfuz.Emit
{
public interface IModuleMetadataImporter
{
void Init(ModuleDef mod);
}
//namespace Obfuz.Emit
//{
// public interface IModuleMetadataImporter
// {
// void Init(ModuleDef mod);
// }
public abstract class ModuleMetadataImporterBase : IModuleMetadataImporter
{
public abstract void Init(ModuleDef mod);
}
// public abstract class ModuleMetadataImporterBase : IModuleMetadataImporter
// {
// public abstract void Init(ModuleDef mod);
// }
public class MetadataImporter
{
private readonly Dictionary<(ModuleDef, Type), IModuleMetadataImporter> _customModuleMetadataImporters = new Dictionary<(ModuleDef, Type), IModuleMetadataImporter>();
// public class MetadataImporter
// {
// private readonly Dictionary<(ModuleDef, Type), IModuleMetadataImporter> _customModuleMetadataImporters = new Dictionary<(ModuleDef, Type), IModuleMetadataImporter>();
public static MetadataImporter Instance { get; private set; }
// public static MetadataImporter Instance { get; private set; }
public static void Reset()
{
Instance = new MetadataImporter();
}
// public static void Reset()
// {
// Instance = new MetadataImporter();
// }
public DefaultModuleMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module)
{
return GetCustomModuleMetadataImporter<DefaultModuleMetadataImporter>(module);
}
// public DefaultModuleMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module)
// {
// return GetCustomModuleMetadataImporter<DefaultModuleMetadataImporter>(module);
// }
public List<DefaultModuleMetadataImporter> GetDefaultModuleMetadataImporters()
{
return GetCustomModuleMetadataImporters<DefaultModuleMetadataImporter>();
}
// public List<DefaultModuleMetadataImporter> GetDefaultModuleMetadataImporters()
// {
// return GetCustomModuleMetadataImporters<DefaultModuleMetadataImporter>();
// }
public T GetCustomModuleMetadataImporter<T>(ModuleDef module, Func<ModuleDef, T> creator = null) where T : IModuleMetadataImporter
{
var key = (module, typeof(T));
if (!_customModuleMetadataImporters.TryGetValue(key, out var importer))
{
if (creator != null)
{
importer = creator(module);
}
else
{
importer = (IModuleMetadataImporter)Activator.CreateInstance(typeof(T));
}
importer.Init(module);
_customModuleMetadataImporters[key] = importer;
}
return (T)importer;
}
// public T GetCustomModuleMetadataImporter<T>(ModuleDef module, Func<ModuleDef, T> creator = null) where T : IModuleMetadataImporter
// {
// var key = (module, typeof(T));
// if (!_customModuleMetadataImporters.TryGetValue(key, out var importer))
// {
// if (creator != null)
// {
// importer = creator(module);
// }
// else
// {
// importer = (IModuleMetadataImporter)Activator.CreateInstance(typeof(T));
// }
// importer.Init(module);
// _customModuleMetadataImporters[key] = importer;
// }
// return (T)importer;
// }
public List<T> GetCustomModuleMetadataImporters<T>()
{
var result = new List<T>();
foreach (var kvp in _customModuleMetadataImporters)
{
if (kvp.Key.Item2 == typeof(T))
{
result.Add((T)kvp.Value);
}
}
return result;
}
}
}
// public List<T> GetCustomModuleMetadataImporters<T>()
// {
// var result = new List<T>();
// foreach (var kvp in _customModuleMetadataImporters)
// {
// if (kvp.Key.Item2 == typeof(T))
// {
// result.Add((T)kvp.Value);
// }
// }
// return result;
// }
// }
//}

View File

@ -1,19 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Emit
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
public class NodeOutputAttribute : Attribute
{
public DataNodeType Type { get; }
public NodeOutputAttribute(DataNodeType type)
{
Type = type;
}
}
}

View File

@ -1,77 +0,0 @@

using Obfuz.Utils;
using Obfuz.Emit.DataNodes;
using Obfuz.Emit.Functions;
using System.Collections.Generic;
namespace Obfuz.Emit
{
public class RandomDataNodeCreator : DataNodeCreatorBase
{
private readonly Dictionary<DataNodeType, List<IFunction>> _functions = new Dictionary<DataNodeType, List<IFunction>>();
private readonly IRandom _random;
public RandomDataNodeCreator(IRandom random)
{
_random = random;
var intFuncs = new List<IFunction>()
{
new IntAdd(),
new IntXor(),
new IntRotateShift(),
//new ConstFromFieldRvaDataCreator(),
//new ConstDataCreator(),
};
_functions.Add(DataNodeType.Int32, intFuncs);
_functions.Add(DataNodeType.Int64, intFuncs);
var floatFuncs = new List<IFunction>()
{
new MemoryCastIntAsFloat(),
};
_functions.Add(DataNodeType.Float32, floatFuncs);
_functions.Add(DataNodeType.Float64, floatFuncs);
var stringFuncs = new List<IFunction>()
{
new ConstFieldDataCreator(),
};
_functions.Add(DataNodeType.String, stringFuncs);
var bytesFuncs = new List<IFunction>()
{
new BytesInitializeFromFieldRvaDataCreator(),
};
_functions.Add(DataNodeType.Bytes, bytesFuncs);
}
public override IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options)
{
if (!_functions.TryGetValue(type, out var funcs))
{
throw new System.Exception($"No functions available for type {type}");
}
if (options.depth >= 2)
{
//return new ConstDataNode() { Type = type, Value = value };
return _random.NextInt(100) < 50 ?
//return true ?
new ConstFromFieldRvaDataNode() { Type = type, Value = value } :
new ConstDataNode() { Type = type, Value = value };
}
var func = funcs[options.random.NextInt(funcs.Count)];
return func.CreateExpr(type, value, options);
}
public IDataNode CreateRandom(DataNodeType type, object value)
{
var options = new CreateExpressionOptions
{
depth = 0,
random = _random,
expressionCreator = this,
};
return CreateRandom(type, value, options);
}
}
}

View File

@ -1,485 +0,0 @@
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 DefaultModuleMetadataImporter DefaultModuleMetadataImporter => MetadataImporter.Instance.GetDefaultModuleMetadataImporter(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, ctx.DefaultModuleMetadataImporter.CastFloatAsInt));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Call, ctx.DefaultModuleMetadataImporter.CastDoubleAsLong));
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, ctx.DefaultModuleMetadataImporter.CastIntAsFloat));
break;
case DataNodeType.Int64:
output.Add(Instruction.Create(OpCodes.Call, ctx.DefaultModuleMetadataImporter.CastLongAsDouble));
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, ctx.DefaultModuleMetadataImporter.CastIntAsFloat));
break;
case DataNodeType.Float64:
output.Add(Instruction.Create(OpCodes.Call, ctx.DefaultModuleMetadataImporter.CastLongAsDouble));
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, ctx.DefaultModuleMetadataImporter.CastFloatAsInt));
break;
case DataNodeType.Float64:
output.Add(Instruction.Create(OpCodes.Call, ctx.DefaultModuleMetadataImporter.CastDoubleAsLong));
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

@ -30,7 +30,7 @@ namespace Obfuz.ObfusPasses.CallObfus
}
}
class ModuleCallProxyAllocator : IModuleEmitManager
class ModuleCallProxyAllocator : IGroupByModuleEntity
{
private ModuleDef _module;
private readonly IRandom _random;
@ -249,7 +249,7 @@ namespace Obfuz.ObfusPasses.CallObfus
private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod)
{
return EmitManager.Ins.GetEmitManager<ModuleCallProxyAllocator>(mod, () => new ModuleCallProxyAllocator(_random, _encryptor));
return GroupByModuleManager.Ins.GetEntity<ModuleCallProxyAllocator>(mod, () => new ModuleCallProxyAllocator(_random, _encryptor));
}
public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir)
@ -260,7 +260,7 @@ namespace Obfuz.ObfusPasses.CallObfus
public void Done()
{
foreach (var allocator in EmitManager.Ins.GetEmitManagers<ModuleCallProxyAllocator>())
foreach (var allocator in GroupByModuleManager.Ins.GetEntities<ModuleCallProxyAllocator>())
{
allocator.Done();
}

View File

@ -33,7 +33,7 @@ namespace Obfuz.ObfusPasses.CallObfus
MethodSig sharedMethodSig = MetaUtil.ToSharedMethodSig(calledMethod.Module.CorLibTypes, MetaUtil.GetInflatedMethodSig(calledMethod));
ProxyCallMethodData proxyCallMethodData = _proxyCallAllocator.Allocate(callerMethod.Module, calledMethod, callVir);
DefaultModuleMetadataImporter importer = MetadataImporter.Instance.GetDefaultModuleMetadataImporter(callerMethod.Module);
DefaultModuleMetadataImporter importer = GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(callerMethod.Module);
if (needCacheCall)
{

View File

@ -37,7 +37,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
private DefaultModuleMetadataImporter GetModuleMetadataImporter(MethodDef method)
{
return MetadataImporter.Instance.GetDefaultModuleMetadataImporter(method.Module);
return GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(method.Module);
}
public void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List<Instruction> obfuscatedInstructions)

View File

@ -23,7 +23,7 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
private DefaultModuleMetadataImporter GetMetadataImporter(MethodDef method)
{
return MetadataImporter.Instance.GetDefaultModuleMetadataImporter(method.Module);
return GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(method.Module);
}
class FieldEncryptInfo

View File

@ -41,8 +41,7 @@ namespace Obfuz
_notObfuscatedAssemblyNamesReferencingObfuscated = notObfuscatedAssemblyNamesReferencingObfuscated;
_obfuscatedAssemblyOutputDir = obfuscatedAssemblyOutputDir;
MetadataImporter.Reset();
EmitManager.Reset();
GroupByModuleManager.Reset();
_assemblyCache = new AssemblyCache(new PathAssemblyResolver(assemblySearchDirs.ToArray()));
foreach (var pass in obfuscationPasses)
{

View File

@ -14,7 +14,7 @@ namespace Obfuz.Utils
private const long c = 1013904223;
private const long m = 4294967296; // 2^32
private readonly byte[] _key;
private readonly int[] _key;
private int _nextIndex;
@ -22,10 +22,19 @@ namespace Obfuz.Utils
public RandomWithKey(byte[] key, int seed)
{
_key = key;
_key = ConvertToIntKey(key);
_seed = seed;
}
private static int[] ConvertToIntKey(byte[] key)
{
// ignore last bytes if not aligned to 4
int align4Length = key.Length / 4;
int[] intKey = new int[align4Length];
Buffer.BlockCopy(key, 0, intKey, 0, align4Length * 4);
return intKey;
}
public int NextInt(int min, int max)
{
return min + NextInt(max - min);