简单内存加密

backup
walon 2025-04-30 22:40:16 +08:00
parent bf9dbefda9
commit 27d952aa4d
5 changed files with 196 additions and 1 deletions

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -12,6 +12,7 @@ namespace Obfuz.MemEncrypt
public class MemoryEncryptionPass : MethodBodyObfuscationPassBase
{
private readonly IEncryptionPolicy _encryptionPolicy = new ConfigEncryptionPolicy();
private readonly IMemoryEncryptor _memoryEncryptor = new DefaultMemoryEncryptor();
public override void Start(ObfuscatorContext ctx)
{
@ -57,22 +58,31 @@ namespace Obfuz.MemEncrypt
{
return false;
}
var ctx = new MemoryEncryptionContext
{
module = callingMethod.Module,
currentInstruction = inst,
};
switch (code)
{
case Code.Ldfld:
{
_memoryEncryptor.Decrypt(fieldDef, outputInstructions, ctx);
break;
}
case Code.Stfld:
{
_memoryEncryptor.Encrypt(fieldDef, outputInstructions, ctx);
break;
}
case Code.Ldsfld:
{
_memoryEncryptor.Decrypt(fieldDef, outputInstructions, ctx);
break;
}
case Code.Stsfld:
{
_memoryEncryptor.Encrypt(fieldDef, outputInstructions, ctx);
break;
}
case Code.Ldflda:
@ -83,7 +93,6 @@ namespace Obfuz.MemEncrypt
default: return false;
}
Debug.Log($"memory encrypt field: {field}");
outputInstructions.Add(inst);
return true;
}
}

View File

@ -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);
}
}

View File

@ -1,6 +1,7 @@
using dnlib.DotNet;
using Obfuz.DynamicProxy;
using Obfuz.ExprObfuscation;
using Obfuz.MemEncrypt;
using Obfuz.Rename;
using Obfuz.Virtualization;
using System;