支持 Bytes混淆

backup
walon 2025-04-23 13:46:50 +08:00
parent db26f5d3ce
commit 09a6b6f6af
10 changed files with 146 additions and 5 deletions

View File

@ -38,5 +38,10 @@ namespace Obfuz.Virtualization
{
return true;
}
public override bool NeedObfuscateArray(MethodDef method, byte[] array)
{
return true;
}
}
}

View File

@ -0,0 +1,77 @@
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;
namespace Obfuz.Virtualization
{
[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

@ -59,7 +59,7 @@ namespace Obfuz.Virtualization
s_convertDouble = mod.Import(typeof(BitConverter).GetMethod("ToDouble", new[] { typeof(byte[]), typeof(int) }));
s_convertString = mod.Import(typeof(Encoding).GetMethod("GetString", new[] { typeof(byte[]), typeof(int), typeof(int) }));
s_Encoding_Utf8 = mod.Import(typeof(Encoding).GetField("UTF8"));
s_convertBytes = mod.Import(typeof(Array).GetMethod("Copy", new[] { typeof(Array), typeof(int), typeof(Array), typeof(int), typeof(int) }));
s_convertBytes = mod.Import(typeof(ConstUtility).GetMethod("GetBytes", new[] { typeof(byte[]), typeof(int), typeof(int) }));
}
IMethod GetConvertMethod(ModuleDef mod)
@ -116,9 +116,9 @@ namespace Obfuz.Virtualization
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.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));
break;
}

View File

@ -33,5 +33,10 @@ namespace Obfuz.Virtualization
{
return true;
}
public virtual bool NeedObfuscateArray(MethodDef method, byte[] array)
{
return true;
}
}
}

View File

@ -6,6 +6,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine.Assertions;
namespace Obfuz.Virtualization
{
@ -138,6 +139,28 @@ namespace Obfuz.Virtualization
}
break;
}
case OperandType.InlineMethod:
{
if (((IMethod)inst.Operand).FullName == "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
{
Instruction prevInst = instructions[i - 1];
if (prevInst.OpCode.Code == Code.Ldtoken)
{
IField rvaField = (IField)prevInst.Operand;
FieldDef ravFieldDef = rvaField.ResolveFieldDefThrow();
byte[] data = ravFieldDef.InitialValue;
if (data != null && _dataObfuscatorPolicy.NeedObfuscateArray(method, data))
{
// remove prev ldtoken instruction
Assert.AreEqual(Code.Ldtoken, resultInstructions[resultInstructions.Count - 1].OpCode.Code);
resultInstructions.RemoveAt(resultInstructions.Count - 1);
_dataObfuscator.ObfuscateBytes(method, data, obfuscatedInstructions);
obfuscated = true;
}
}
}
break;
}
}
resultInstructions.Add(inst);
if (obfuscated)

View File

@ -64,7 +64,9 @@ namespace Obfuz.Virtualization
public void ObfuscateBytes(MethodDef method, Array value, List<Instruction> obfuscatedInstructions)
{
throw new NotSupportedException();
IDataNode node = _nodeCreator.CreateRandom(DataNodeType.Bytes, value);
CompileNode(node, method, obfuscatedInstructions);
//throw new NotSupportedException();
//obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldc_I4, value.Length));
}

View File

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

View File

@ -20,5 +20,7 @@ namespace Obfuz.Virtualization
bool NeedObfuscateDouble(MethodDef method, double value);
bool NeedObfuscateString(MethodDef method, string value);
bool NeedObfuscateArray(MethodDef method, byte[] array);
}
}

View File

@ -38,6 +38,11 @@ namespace Obfuz.Virtualization
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)

View File

@ -41,6 +41,11 @@ namespace Obfuz
return result;
}
public static void InitializeArray(Array array, byte[] data, int offset, int length)
{
Buffer.BlockCopy(data, offset, array, 0, length);
}
public static int CastFloatAsInt(float value)
{
return UnsafeUtility.As<float, int>(ref value);