From f3762f05cee8df7c9b073c67f8e05dcac121cb74 Mon Sep 17 00:00:00 2001 From: walon Date: Wed, 23 Apr 2025 11:55:42 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E6=B7=BB=E5=8A=A0=20Obfuz.Runtime=20-=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0float=E5=92=8Cdouble=E6=B7=B7=E6=B7=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/Obfuz.Editor.asmdef | 3 +- Editor/Virtualization/ConstValue.cs | 15 +++- .../Virtualization/DefaultDataObfuscator.cs | 12 +-- .../Virtualization/Functions/FunctionBase.cs | 4 +- Editor/Virtualization/Functions/IntAdd.cs | 2 +- .../Functions/IntRotateShift.cs | 2 +- Editor/Virtualization/Functions/IntXor.cs | 2 +- .../Functions/MemoryCastIntAsFloat.cs | 76 +++++++++++++++++++ .../Virtualization/RandomDataNodeCreator.cs | 15 +++- Runtime/ConstUtility.cs | 64 ++++++++++++++++ Runtime/Obfuz.Runtime.asmdef | 14 ++++ 11 files changed, 192 insertions(+), 17 deletions(-) create mode 100644 Editor/Virtualization/Functions/MemoryCastIntAsFloat.cs create mode 100644 Runtime/ConstUtility.cs create mode 100644 Runtime/Obfuz.Runtime.asmdef diff --git a/Editor/Obfuz.Editor.asmdef b/Editor/Obfuz.Editor.asmdef index 8c0e02a..485efac 100644 --- a/Editor/Obfuz.Editor.asmdef +++ b/Editor/Obfuz.Editor.asmdef @@ -2,7 +2,8 @@ "name": "Obfuz", "rootNamespace": "", "references": [ - "GUID:7e4de3067c2ab5c43a03ac49273dfb68" + "GUID:7e4de3067c2ab5c43a03ac49273dfb68", + "GUID:370c0d0004ef2414cb803d3ffd331dce" ], "includePlatforms": [ "Editor" diff --git a/Editor/Virtualization/ConstValue.cs b/Editor/Virtualization/ConstValue.cs index c3bc001..8c90bed 100644 --- a/Editor/Virtualization/ConstValue.cs +++ b/Editor/Virtualization/ConstValue.cs @@ -1,4 +1,7 @@ -namespace Obfuz.Virtualization +using System; +using UnityEngine.Assertions; + +namespace Obfuz.Virtualization { public struct ConstValue { @@ -7,6 +10,16 @@ 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; } diff --git a/Editor/Virtualization/DefaultDataObfuscator.cs b/Editor/Virtualization/DefaultDataObfuscator.cs index 63ef5ee..9ad00f7 100644 --- a/Editor/Virtualization/DefaultDataObfuscator.cs +++ b/Editor/Virtualization/DefaultDataObfuscator.cs @@ -47,16 +47,16 @@ namespace Obfuz.Virtualization public void ObfuscateFloat(MethodDef method, float value, List obfuscatedInstructions) { - //IDataNode node = _nodeCreator.CreateRandom(DataNodeType.Float32, value); - //CompileNode(node, method, obfuscatedInstructions); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_R4, value)); + IDataNode node = _nodeCreator.CreateRandom(DataNodeType.Float32, value); + CompileNode(node, method, obfuscatedInstructions); + //obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_R4, value)); } public void ObfuscateDouble(MethodDef method, double value, List obfuscatedInstructions) { - //IDataNode node = _nodeCreator.CreateRandom(DataNodeType.Float64, value); - //CompileNode(node, method, obfuscatedInstructions); - obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_R8, value)); + IDataNode node = _nodeCreator.CreateRandom(DataNodeType.Float64, value); + CompileNode(node, method, obfuscatedInstructions); + //obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_R8, value)); } public void ObfuscateBytes(MethodDef method, Array value, List obfuscatedInstructions) diff --git a/Editor/Virtualization/Functions/FunctionBase.cs b/Editor/Virtualization/Functions/FunctionBase.cs index f62ba30..edf4b2e 100644 --- a/Editor/Virtualization/Functions/FunctionBase.cs +++ b/Editor/Virtualization/Functions/FunctionBase.cs @@ -11,7 +11,7 @@ namespace Obfuz.Virtualization public abstract void CreateArguments(DataNodeType type, object value, CreateExpressionOptions options, List args); - public abstract void CompileSelf(CompileContext ctx, List output); + public abstract void CompileSelf(CompileContext ctx, List inputs, List output); public virtual void Compile(CompileContext ctx, List inputs, ConstValue result) { @@ -19,7 +19,7 @@ namespace Obfuz.Virtualization { input.Compile(ctx); } - CompileSelf(ctx, ctx.output); + CompileSelf(ctx, inputs, ctx.output); } public virtual IDataNode CreateExpr(DataNodeType type, object value, CreateExpressionOptions options) diff --git a/Editor/Virtualization/Functions/IntAdd.cs b/Editor/Virtualization/Functions/IntAdd.cs index ea542ba..d9296db 100644 --- a/Editor/Virtualization/Functions/IntAdd.cs +++ b/Editor/Virtualization/Functions/IntAdd.cs @@ -42,7 +42,7 @@ namespace Obfuz.Virtualization.Functions } } - public override void CompileSelf(CompileContext ctx, List output) + public override void CompileSelf(CompileContext ctx, List inputs, List output) { output.Add(Instruction.Create(OpCodes.Add)); } diff --git a/Editor/Virtualization/Functions/IntRotateShift.cs b/Editor/Virtualization/Functions/IntRotateShift.cs index dd95bdb..c9d5ca3 100644 --- a/Editor/Virtualization/Functions/IntRotateShift.cs +++ b/Editor/Virtualization/Functions/IntRotateShift.cs @@ -53,7 +53,7 @@ namespace Obfuz.Virtualization.Functions } } - public override void CompileSelf(CompileContext ctx, List output) + public override void CompileSelf(CompileContext ctx, List inputs, List output) { output.Add(Instruction.Create(OpCodes.Xor)); } diff --git a/Editor/Virtualization/Functions/IntXor.cs b/Editor/Virtualization/Functions/IntXor.cs index 93c7a13..d4080da 100644 --- a/Editor/Virtualization/Functions/IntXor.cs +++ b/Editor/Virtualization/Functions/IntXor.cs @@ -38,7 +38,7 @@ namespace Obfuz.Virtualization.Functions } } - public override void CompileSelf(CompileContext ctx, List output) + public override void CompileSelf(CompileContext ctx, List inputs, List output) { output.Add(Instruction.Create(OpCodes.Xor)); } diff --git a/Editor/Virtualization/Functions/MemoryCastIntAsFloat.cs b/Editor/Virtualization/Functions/MemoryCastIntAsFloat.cs new file mode 100644 index 0000000..3e2f13e --- /dev/null +++ b/Editor/Virtualization/Functions/MemoryCastIntAsFloat.cs @@ -0,0 +1,76 @@ +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.Virtualization.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 inputs, List 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 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"); + } + } + } + } +} diff --git a/Editor/Virtualization/RandomDataNodeCreator.cs b/Editor/Virtualization/RandomDataNodeCreator.cs index c356fa3..ccac00f 100644 --- a/Editor/Virtualization/RandomDataNodeCreator.cs +++ b/Editor/Virtualization/RandomDataNodeCreator.cs @@ -1,5 +1,6 @@  using Obfuz.Utils; +using Obfuz.Virtualization.DataNodes; using Obfuz.Virtualization.Functions; using System.Collections.Generic; @@ -14,7 +15,7 @@ namespace Obfuz.Virtualization public RandomDataNodeCreator(IRandom random) { _random = random; - var int32Funcs = new List() + var intFuncs = new List() { new IntAdd(), new IntXor(), @@ -22,8 +23,15 @@ namespace Obfuz.Virtualization //new ConstFromFieldRvaDataCreator(), //new ConstDataCreator(), }; - _functions.Add(DataNodeType.Int32, int32Funcs); - _functions.Add(DataNodeType.Int64, int32Funcs); + _functions.Add(DataNodeType.Int32, intFuncs); + _functions.Add(DataNodeType.Int64, intFuncs); + + var floatFuncs = new List() + { + new MemoryCastIntAsFloat(), + }; + _functions.Add(DataNodeType.Float32, floatFuncs); + _functions.Add(DataNodeType.Float64, floatFuncs); } public override IDataNode CreateRandom(DataNodeType type, object value, CreateExpressionOptions options) @@ -41,7 +49,6 @@ namespace Obfuz.Virtualization new ConstDataNode() { Type = type, Value = value }; } var func = funcs[options.random.NextInt(funcs.Count)]; - ++options.depth; return func.CreateExpr(type, value, options); } diff --git a/Runtime/ConstUtility.cs b/Runtime/ConstUtility.cs new file mode 100644 index 0000000..cfcfb4f --- /dev/null +++ b/Runtime/ConstUtility.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Unity.Collections.LowLevel.Unsafe; +using UnityEngine; + +namespace Obfuz +{ + public static class ConstUtility + { + public static int GetInt(byte[] data, int offset) + { + return BitConverter.ToInt32(data, offset); + } + + public static long GetLong(byte[] data, int offset) + { + return BitConverter.ToInt64(data, offset); + } + + public static float GetFloat(byte[] data, int offset) + { + return BitConverter.ToSingle(data, offset); + } + + public static double GetDouble(byte[] data, int offset) + { + return BitConverter.ToDouble(data, offset); + } + + public static string GetString(byte[] data, int offset, int length) + { + return Encoding.UTF8.GetString(data, offset, length); + } + + public static byte[] GetBytes(byte[] data, int offset, int length) + { + byte[] result = new byte[length]; + Array.Copy(data, offset, result, 0, length); + return result; + } + + public static int CastFloatAsInt(float value) + { + return UnsafeUtility.As(ref value); + } + + public static float CastIntAsFloat(int value) + { + return UnsafeUtility.As(ref value); + } + + public static long CastDoubleAsLong(double value) + { + return UnsafeUtility.As(ref value); + } + + public static double CastLongAsDouble(long value) + { + return UnsafeUtility.As(ref value); + } + } +} diff --git a/Runtime/Obfuz.Runtime.asmdef b/Runtime/Obfuz.Runtime.asmdef new file mode 100644 index 0000000..4ee1d16 --- /dev/null +++ b/Runtime/Obfuz.Runtime.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Obfuz.Runtime", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file