- 移除Emit模块下无用的Random Node Creator
- 修复RandomWithKey的byte[]为key的问题 - 重构MetadataModuleImpoterbackup
parent
856e924ed8
commit
d14d0f913c
|
@ -12,7 +12,7 @@ using UnityEngine.Assertions;
|
||||||
|
|
||||||
namespace Obfuz.Data
|
namespace Obfuz.Data
|
||||||
{
|
{
|
||||||
public class ModuleConstFieldAllocator : IModuleEmitManager
|
public class ModuleConstFieldAllocator : IGroupByModuleEntity
|
||||||
{
|
{
|
||||||
private ModuleDef _module;
|
private ModuleDef _module;
|
||||||
private readonly IRandom _random;
|
private readonly IRandom _random;
|
||||||
|
@ -138,7 +138,7 @@ namespace Obfuz.Data
|
||||||
|
|
||||||
private DefaultModuleMetadataImporter GetModuleMetadataImporter()
|
private DefaultModuleMetadataImporter GetModuleMetadataImporter()
|
||||||
{
|
{
|
||||||
return MetadataImporter.Instance.GetDefaultModuleMetadataImporter(_module);
|
return GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateCCtorOfRvaTypeDef(TypeDef type)
|
private void CreateCCtorOfRvaTypeDef(TypeDef type)
|
||||||
|
@ -268,7 +268,7 @@ namespace Obfuz.Data
|
||||||
|
|
||||||
private ModuleConstFieldAllocator GetModuleAllocator(ModuleDef mod)
|
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)
|
public FieldDef Allocate(ModuleDef mod, int value)
|
||||||
|
@ -303,7 +303,7 @@ namespace Obfuz.Data
|
||||||
|
|
||||||
public void Done()
|
public void Done()
|
||||||
{
|
{
|
||||||
foreach (var moduleAllocator in EmitManager.Ins.GetEmitManagers<ModuleConstFieldAllocator>())
|
foreach (var moduleAllocator in GroupByModuleManager.Ins.GetEntities<ModuleConstFieldAllocator>())
|
||||||
{
|
{
|
||||||
moduleAllocator.Done();
|
moduleAllocator.Done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Obfuz.Data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ModuleRvaDataAllocator : ModuleEmitManagerBase
|
public class ModuleRvaDataAllocator : GroupByModuleEntityBase
|
||||||
{
|
{
|
||||||
// randomized
|
// randomized
|
||||||
const int maxRvaDataSize = 0x1000;
|
const int maxRvaDataSize = 0x1000;
|
||||||
|
@ -234,7 +234,7 @@ namespace Obfuz.Data
|
||||||
cctorMethod.Body = body;
|
cctorMethod.Body = body;
|
||||||
var ins = body.Instructions;
|
var ins = body.Instructions;
|
||||||
|
|
||||||
DefaultModuleMetadataImporter importer = MetadataImporter.Instance.GetDefaultModuleMetadataImporter(mod);
|
DefaultModuleMetadataImporter importer = GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(mod);
|
||||||
foreach (var field in _rvaFields)
|
foreach (var field in _rvaFields)
|
||||||
{
|
{
|
||||||
// ldc
|
// ldc
|
||||||
|
@ -296,7 +296,7 @@ namespace Obfuz.Data
|
||||||
|
|
||||||
private ModuleRvaDataAllocator GetModuleRvaDataAllocator(ModuleDef mod)
|
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)
|
public RvaData Allocate(ModuleDef mod, int value)
|
||||||
|
@ -331,7 +331,7 @@ namespace Obfuz.Data
|
||||||
|
|
||||||
public void Done()
|
public void Done()
|
||||||
{
|
{
|
||||||
foreach (var allocator in EmitManager.Ins.GetEmitManagers<ModuleRvaDataAllocator>())
|
foreach (var allocator in GroupByModuleManager.Ins.GetEntities<ModuleRvaDataAllocator>())
|
||||||
{
|
{
|
||||||
allocator.Done();
|
allocator.Done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Obfuz.Emit
|
|
||||||
{
|
|
||||||
public abstract class DataNodeCreatorBase : IDataNodeCreator
|
|
||||||
{
|
|
||||||
public abstract IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
namespace Obfuz.Emit
|
|
||||||
{
|
|
||||||
public enum DataNodeType
|
|
||||||
{
|
|
||||||
//Byte,
|
|
||||||
Int32,
|
|
||||||
Int64,
|
|
||||||
Float32,
|
|
||||||
Float64,
|
|
||||||
String,
|
|
||||||
Bytes,
|
|
||||||
//Null,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,7 @@ using UnityEngine.Assertions;
|
||||||
|
|
||||||
namespace Obfuz.Emit
|
namespace Obfuz.Emit
|
||||||
{
|
{
|
||||||
public class DefaultModuleMetadataImporter : ModuleMetadataImporterBase
|
public class DefaultModuleMetadataImporter : GroupByModuleEntityBase
|
||||||
{
|
{
|
||||||
public DefaultModuleMetadataImporter() { }
|
public DefaultModuleMetadataImporter() { }
|
||||||
|
|
||||||
|
|
|
@ -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 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,29 +7,29 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Obfuz.Emit
|
namespace Obfuz.Emit
|
||||||
{
|
{
|
||||||
public interface IModuleEmitManager
|
public interface IGroupByModuleEntity
|
||||||
{
|
{
|
||||||
void Init(ModuleDef mod);
|
void Init(ModuleDef mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ModuleEmitManagerBase : IModuleEmitManager
|
public abstract class GroupByModuleEntityBase : IGroupByModuleEntity
|
||||||
{
|
{
|
||||||
public abstract void Init(ModuleDef mod);
|
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()
|
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));
|
var key = (mod, typeof(T));
|
||||||
if (_moduleEmitManagers.TryGetValue(key, out var emitManager))
|
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>();
|
var managers = new List<T>();
|
||||||
foreach (var kv in _moduleEmitManagers)
|
foreach (var kv in _moduleEmitManagers)
|
||||||
|
@ -65,5 +65,10 @@ namespace Obfuz.Emit
|
||||||
}
|
}
|
||||||
return managers;
|
return managers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DefaultModuleMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module)
|
||||||
|
{
|
||||||
|
return GetEntity<DefaultModuleMetadataImporter>(module);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Obfuz.Emit
|
|
||||||
{
|
|
||||||
public interface IDataNodeCreator
|
|
||||||
{
|
|
||||||
IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +1,73 @@
|
||||||
using dnlib.DotNet;
|
//using dnlib.DotNet;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Obfuz.Emit
|
//namespace Obfuz.Emit
|
||||||
{
|
//{
|
||||||
public interface IModuleMetadataImporter
|
// public interface IModuleMetadataImporter
|
||||||
{
|
// {
|
||||||
void Init(ModuleDef mod);
|
// void Init(ModuleDef mod);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public abstract class ModuleMetadataImporterBase : IModuleMetadataImporter
|
// public abstract class ModuleMetadataImporterBase : IModuleMetadataImporter
|
||||||
{
|
// {
|
||||||
public abstract void Init(ModuleDef mod);
|
// public abstract void Init(ModuleDef mod);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public class MetadataImporter
|
// public class MetadataImporter
|
||||||
{
|
// {
|
||||||
private readonly Dictionary<(ModuleDef, Type), IModuleMetadataImporter> _customModuleMetadataImporters = new Dictionary<(ModuleDef, Type), IModuleMetadataImporter>();
|
// 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()
|
// public static void Reset()
|
||||||
{
|
// {
|
||||||
Instance = new MetadataImporter();
|
// Instance = new MetadataImporter();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public DefaultModuleMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module)
|
// public DefaultModuleMetadataImporter GetDefaultModuleMetadataImporter(ModuleDef module)
|
||||||
{
|
// {
|
||||||
return GetCustomModuleMetadataImporter<DefaultModuleMetadataImporter>(module);
|
// return GetCustomModuleMetadataImporter<DefaultModuleMetadataImporter>(module);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public List<DefaultModuleMetadataImporter> GetDefaultModuleMetadataImporters()
|
// public List<DefaultModuleMetadataImporter> GetDefaultModuleMetadataImporters()
|
||||||
{
|
// {
|
||||||
return GetCustomModuleMetadataImporters<DefaultModuleMetadataImporter>();
|
// return GetCustomModuleMetadataImporters<DefaultModuleMetadataImporter>();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public T GetCustomModuleMetadataImporter<T>(ModuleDef module, Func<ModuleDef, T> creator = null) where T : IModuleMetadataImporter
|
// public T GetCustomModuleMetadataImporter<T>(ModuleDef module, Func<ModuleDef, T> creator = null) where T : IModuleMetadataImporter
|
||||||
{
|
// {
|
||||||
var key = (module, typeof(T));
|
// var key = (module, typeof(T));
|
||||||
if (!_customModuleMetadataImporters.TryGetValue(key, out var importer))
|
// if (!_customModuleMetadataImporters.TryGetValue(key, out var importer))
|
||||||
{
|
// {
|
||||||
if (creator != null)
|
// if (creator != null)
|
||||||
{
|
// {
|
||||||
importer = creator(module);
|
// importer = creator(module);
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
importer = (IModuleMetadataImporter)Activator.CreateInstance(typeof(T));
|
// importer = (IModuleMetadataImporter)Activator.CreateInstance(typeof(T));
|
||||||
}
|
// }
|
||||||
importer.Init(module);
|
// importer.Init(module);
|
||||||
_customModuleMetadataImporters[key] = importer;
|
// _customModuleMetadataImporters[key] = importer;
|
||||||
}
|
// }
|
||||||
return (T)importer;
|
// return (T)importer;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public List<T> GetCustomModuleMetadataImporters<T>()
|
// public List<T> GetCustomModuleMetadataImporters<T>()
|
||||||
{
|
// {
|
||||||
var result = new List<T>();
|
// var result = new List<T>();
|
||||||
foreach (var kvp in _customModuleMetadataImporters)
|
// foreach (var kvp in _customModuleMetadataImporters)
|
||||||
{
|
// {
|
||||||
if (kvp.Key.Item2 == typeof(T))
|
// if (kvp.Key.Item2 == typeof(T))
|
||||||
{
|
// {
|
||||||
result.Add((T)kvp.Value);
|
// result.Add((T)kvp.Value);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,7 +30,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModuleCallProxyAllocator : IModuleEmitManager
|
class ModuleCallProxyAllocator : IGroupByModuleEntity
|
||||||
{
|
{
|
||||||
private ModuleDef _module;
|
private ModuleDef _module;
|
||||||
private readonly IRandom _random;
|
private readonly IRandom _random;
|
||||||
|
@ -249,7 +249,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
||||||
|
|
||||||
private ModuleCallProxyAllocator GetModuleAllocator(ModuleDef mod)
|
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)
|
public ProxyCallMethodData Allocate(ModuleDef mod, IMethod method, bool callVir)
|
||||||
|
@ -260,7 +260,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
||||||
|
|
||||||
public void Done()
|
public void Done()
|
||||||
{
|
{
|
||||||
foreach (var allocator in EmitManager.Ins.GetEmitManagers<ModuleCallProxyAllocator>())
|
foreach (var allocator in GroupByModuleManager.Ins.GetEntities<ModuleCallProxyAllocator>())
|
||||||
{
|
{
|
||||||
allocator.Done();
|
allocator.Done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace Obfuz.ObfusPasses.CallObfus
|
||||||
|
|
||||||
MethodSig sharedMethodSig = MetaUtil.ToSharedMethodSig(calledMethod.Module.CorLibTypes, MetaUtil.GetInflatedMethodSig(calledMethod));
|
MethodSig sharedMethodSig = MetaUtil.ToSharedMethodSig(calledMethod.Module.CorLibTypes, MetaUtil.GetInflatedMethodSig(calledMethod));
|
||||||
ProxyCallMethodData proxyCallMethodData = _proxyCallAllocator.Allocate(callerMethod.Module, calledMethod, callVir);
|
ProxyCallMethodData proxyCallMethodData = _proxyCallAllocator.Allocate(callerMethod.Module, calledMethod, callVir);
|
||||||
DefaultModuleMetadataImporter importer = MetadataImporter.Instance.GetDefaultModuleMetadataImporter(callerMethod.Module);
|
DefaultModuleMetadataImporter importer = GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(callerMethod.Module);
|
||||||
|
|
||||||
if (needCacheCall)
|
if (needCacheCall)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
|
||||||
|
|
||||||
private DefaultModuleMetadataImporter GetModuleMetadataImporter(MethodDef method)
|
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)
|
public void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List<Instruction> obfuscatedInstructions)
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Obfuz.ObfusPasses.FieldEncrypt
|
||||||
|
|
||||||
private DefaultModuleMetadataImporter GetMetadataImporter(MethodDef method)
|
private DefaultModuleMetadataImporter GetMetadataImporter(MethodDef method)
|
||||||
{
|
{
|
||||||
return MetadataImporter.Instance.GetDefaultModuleMetadataImporter(method.Module);
|
return GroupByModuleManager.Ins.GetDefaultModuleMetadataImporter(method.Module);
|
||||||
}
|
}
|
||||||
|
|
||||||
class FieldEncryptInfo
|
class FieldEncryptInfo
|
||||||
|
|
|
@ -41,8 +41,7 @@ namespace Obfuz
|
||||||
_notObfuscatedAssemblyNamesReferencingObfuscated = notObfuscatedAssemblyNamesReferencingObfuscated;
|
_notObfuscatedAssemblyNamesReferencingObfuscated = notObfuscatedAssemblyNamesReferencingObfuscated;
|
||||||
_obfuscatedAssemblyOutputDir = obfuscatedAssemblyOutputDir;
|
_obfuscatedAssemblyOutputDir = obfuscatedAssemblyOutputDir;
|
||||||
|
|
||||||
MetadataImporter.Reset();
|
GroupByModuleManager.Reset();
|
||||||
EmitManager.Reset();
|
|
||||||
_assemblyCache = new AssemblyCache(new PathAssemblyResolver(assemblySearchDirs.ToArray()));
|
_assemblyCache = new AssemblyCache(new PathAssemblyResolver(assemblySearchDirs.ToArray()));
|
||||||
foreach (var pass in obfuscationPasses)
|
foreach (var pass in obfuscationPasses)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Obfuz.Utils
|
||||||
private const long c = 1013904223;
|
private const long c = 1013904223;
|
||||||
private const long m = 4294967296; // 2^32
|
private const long m = 4294967296; // 2^32
|
||||||
|
|
||||||
private readonly byte[] _key;
|
private readonly int[] _key;
|
||||||
|
|
||||||
private int _nextIndex;
|
private int _nextIndex;
|
||||||
|
|
||||||
|
@ -22,10 +22,19 @@ namespace Obfuz.Utils
|
||||||
|
|
||||||
public RandomWithKey(byte[] key, int seed)
|
public RandomWithKey(byte[] key, int seed)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = ConvertToIntKey(key);
|
||||||
_seed = seed;
|
_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)
|
public int NextInt(int min, int max)
|
||||||
{
|
{
|
||||||
return min + NextInt(max - min);
|
return min + NextInt(max - min);
|
||||||
|
|
Loading…
Reference in New Issue