简单内存加密
parent
bf9dbefda9
commit
27d952aa4d
|
@ -0,0 +1,150 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine.Assertions;
|
||||||
|
|
||||||
|
namespace Obfuz.MemEncrypt
|
||||||
|
{
|
||||||
|
public class DefaultMemoryEncryptor : MemoryEncryptorBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private class ModuleDefaultMemoryEncryptor
|
||||||
|
{
|
||||||
|
private readonly ModuleDef _module;
|
||||||
|
|
||||||
|
public ModuleDefaultMemoryEncryptor(ModuleDef module)
|
||||||
|
{
|
||||||
|
_module = module;
|
||||||
|
InitMetadatas(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IMethod s_castIntAsFloat;
|
||||||
|
private static IMethod s_castLongAsDouble;
|
||||||
|
private static IMethod s_castFloatAsInt;
|
||||||
|
private static IMethod s_castDoubleAsLong;
|
||||||
|
|
||||||
|
private void InitMetadatas(ModuleDef mod)
|
||||||
|
{
|
||||||
|
if (s_castFloatAsInt != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var constUtilityType = typeof(ConstUtility);
|
||||||
|
|
||||||
|
s_castIntAsFloat = mod.Import(constUtilityType.GetMethod("CastIntAsFloat"));
|
||||||
|
Assert.IsNotNull(s_castIntAsFloat, "CastIntAsFloat not found");
|
||||||
|
s_castLongAsDouble = mod.Import(constUtilityType.GetMethod("CastLongAsDouble"));
|
||||||
|
Assert.IsNotNull(s_castLongAsDouble, "CastLongAsDouble not found");
|
||||||
|
s_castFloatAsInt = mod.Import(constUtilityType.GetMethod("CastFloatAsInt"));
|
||||||
|
Assert.IsNotNull(s_castFloatAsInt, "CastFloatAsInt not found");
|
||||||
|
s_castDoubleAsLong = mod.Import(constUtilityType.GetMethod("CastDoubleAsLong"));
|
||||||
|
Assert.IsNotNull(s_castDoubleAsLong, "CastDoubleAsLong not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Encrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx)
|
||||||
|
{
|
||||||
|
ElementType type = field.FieldType.RemovePinnedAndModifiers().ElementType;
|
||||||
|
if (type == ElementType.R4)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castFloatAsInt));
|
||||||
|
type = ElementType.I4;
|
||||||
|
}
|
||||||
|
else if (type == ElementType.R8)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castDoubleAsLong));
|
||||||
|
type = ElementType.I8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ElementType.I4)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.CreateLdcI4(100));
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
}
|
||||||
|
else if (type == ElementType.I8)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, 100L));
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException($"Unsupported type {type} for MemoryEncryptor");
|
||||||
|
}
|
||||||
|
if (type == ElementType.R4)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castIntAsFloat));
|
||||||
|
type = ElementType.I4;
|
||||||
|
}
|
||||||
|
else if (type == ElementType.R8)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castLongAsDouble));
|
||||||
|
type = ElementType.I8;
|
||||||
|
}
|
||||||
|
outputInstructions.Add(ctx.currentInstruction.Clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Decrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(ctx.currentInstruction.Clone());
|
||||||
|
ElementType type = field.FieldType.RemovePinnedAndModifiers().ElementType;
|
||||||
|
if (type == ElementType.R4)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castFloatAsInt));
|
||||||
|
type = ElementType.I4;
|
||||||
|
}
|
||||||
|
else if (type == ElementType.R8)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castDoubleAsLong));
|
||||||
|
type = ElementType.I8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ElementType.I4)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.CreateLdcI4(100));
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Sub));
|
||||||
|
}
|
||||||
|
else if (type == ElementType.I8)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Ldc_I8, 100L));
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Sub));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException($"Unsupported type {type} for MemoryEncryptor");
|
||||||
|
}
|
||||||
|
if (type == ElementType.R4)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castIntAsFloat));
|
||||||
|
type = ElementType.I4;
|
||||||
|
}
|
||||||
|
else if (type == ElementType.R8)
|
||||||
|
{
|
||||||
|
outputInstructions.Add(Instruction.Create(OpCodes.Call, s_castLongAsDouble));
|
||||||
|
type = ElementType.I8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<ModuleDef, ModuleDefaultMemoryEncryptor> _moduleEncryptors = new Dictionary<ModuleDef, ModuleDefaultMemoryEncryptor>();
|
||||||
|
|
||||||
|
private ModuleDefaultMemoryEncryptor GetModuleEncryptor(ModuleDef module)
|
||||||
|
{
|
||||||
|
if (!_moduleEncryptors.TryGetValue(module, out var encryptor))
|
||||||
|
{
|
||||||
|
encryptor = new ModuleDefaultMemoryEncryptor(module);
|
||||||
|
_moduleEncryptors.Add(module, encryptor);
|
||||||
|
}
|
||||||
|
return encryptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Encrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx)
|
||||||
|
{
|
||||||
|
GetModuleEncryptor(ctx.module).Encrypt(field, outputInstructions, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Decrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx)
|
||||||
|
{
|
||||||
|
GetModuleEncryptor(ctx.module).Decrypt(field, outputInstructions, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Obfuz.MemEncrypt
|
||||||
|
{
|
||||||
|
public class MemoryEncryptionContext
|
||||||
|
{
|
||||||
|
public ModuleDef module;
|
||||||
|
|
||||||
|
public Instruction currentInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IMemoryEncryptor
|
||||||
|
{
|
||||||
|
void Encrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx);
|
||||||
|
|
||||||
|
void Decrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ namespace Obfuz.MemEncrypt
|
||||||
public class MemoryEncryptionPass : MethodBodyObfuscationPassBase
|
public class MemoryEncryptionPass : MethodBodyObfuscationPassBase
|
||||||
{
|
{
|
||||||
private readonly IEncryptionPolicy _encryptionPolicy = new ConfigEncryptionPolicy();
|
private readonly IEncryptionPolicy _encryptionPolicy = new ConfigEncryptionPolicy();
|
||||||
|
private readonly IMemoryEncryptor _memoryEncryptor = new DefaultMemoryEncryptor();
|
||||||
|
|
||||||
public override void Start(ObfuscatorContext ctx)
|
public override void Start(ObfuscatorContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -57,22 +58,31 @@ namespace Obfuz.MemEncrypt
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
var ctx = new MemoryEncryptionContext
|
||||||
|
{
|
||||||
|
module = callingMethod.Module,
|
||||||
|
currentInstruction = inst,
|
||||||
|
};
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case Code.Ldfld:
|
case Code.Ldfld:
|
||||||
{
|
{
|
||||||
|
_memoryEncryptor.Decrypt(fieldDef, outputInstructions, ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Code.Stfld:
|
case Code.Stfld:
|
||||||
{
|
{
|
||||||
|
_memoryEncryptor.Encrypt(fieldDef, outputInstructions, ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Code.Ldsfld:
|
case Code.Ldsfld:
|
||||||
{
|
{
|
||||||
|
_memoryEncryptor.Decrypt(fieldDef, outputInstructions, ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Code.Stsfld:
|
case Code.Stsfld:
|
||||||
{
|
{
|
||||||
|
_memoryEncryptor.Encrypt(fieldDef, outputInstructions, ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Code.Ldflda:
|
case Code.Ldflda:
|
||||||
|
@ -83,7 +93,6 @@ namespace Obfuz.MemEncrypt
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
Debug.Log($"memory encrypt field: {field}");
|
Debug.Log($"memory encrypt field: {field}");
|
||||||
outputInstructions.Add(inst);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Obfuz.MemEncrypt
|
||||||
|
{
|
||||||
|
public abstract class MemoryEncryptorBase : IMemoryEncryptor
|
||||||
|
{
|
||||||
|
public abstract void Encrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx);
|
||||||
|
public abstract void Decrypt(FieldDef field, List<Instruction> outputInstructions, MemoryEncryptionContext ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using Obfuz.DynamicProxy;
|
using Obfuz.DynamicProxy;
|
||||||
using Obfuz.ExprObfuscation;
|
using Obfuz.ExprObfuscation;
|
||||||
|
using Obfuz.MemEncrypt;
|
||||||
using Obfuz.Rename;
|
using Obfuz.Rename;
|
||||||
using Obfuz.Virtualization;
|
using Obfuz.Virtualization;
|
||||||
using System;
|
using System;
|
||||||
|
|
Loading…
Reference in New Issue