重构 EncryptionVirtualMachine

backup
walon 2025-05-11 12:48:53 +08:00
parent af60d0703d
commit f0818e3df1
17 changed files with 142 additions and 138 deletions

View File

@ -1,8 +0,0 @@
namespace Obfuz.Encryption
{
public abstract class EncryptInstructionBase : IEncryptInstruction
{
public abstract int Encrypt(int value, int[] secretKey, int salt);
public abstract int Decrypt(int value, int[] secretKey, int salt);
}
}

View File

@ -1,12 +1,12 @@
namespace Obfuz.Encryption namespace Obfuz.Encryption
{ {
public class EncryptOpCode public class EncryptionInstructionWithOpCode
{ {
public readonly ushort code; public readonly ushort code;
public readonly EncryptFunction function; public readonly IEncryptionInstruction function;
public EncryptOpCode(ushort code, EncryptFunction function) public EncryptionInstructionWithOpCode(ushort code, IEncryptionInstruction function)
{ {
this.code = code; this.code = code;
this.function = function; this.function = function;

View File

@ -0,0 +1,16 @@
namespace Obfuz.Encryption
{
public class EncryptionVirtualMachine
{
public const int SecretKeyLength = 1024;
public readonly int[] secretKey;
public readonly EncryptionInstructionWithOpCode[] opCodes;
public EncryptionVirtualMachine(int[] secretKey, EncryptionInstructionWithOpCode[] opCodes)
{
this.secretKey = secretKey;
this.opCodes = opCodes;
}
}
}

View File

@ -0,0 +1,56 @@
using Obfuz.Encryption.Instructions;
using Obfuz.Utils;
using UnityEngine.Assertions;
namespace Obfuz.Encryption
{
public class EncryptionVirtualMachineCreator
{
private readonly int[] _vmGenerationSecretKey;
private readonly byte[] _encryptionSecretKey;
private readonly IRandom _random;
public const int CodeGenerationSecretKeyLength = 1024;
public EncryptionVirtualMachineCreator(string vmGenerationSecretKey, byte[] encryptionSecretKey)
{
_vmGenerationSecretKey = KeyGenerator.ConvertToIntKey(KeyGenerator.GenerateKey(vmGenerationSecretKey, CodeGenerationSecretKeyLength));
_encryptionSecretKey = encryptionSecretKey;
_random = new RandomWithKey(encryptionSecretKey, 0);
}
private IEncryptionInstruction CreateRandomInstruction(int intSecretKeyLength)
{
switch (_random.NextInt(3))
{
case 0:
return new AddInstruction(_random.NextInt(), _random.NextInt(intSecretKeyLength));
case 1:
return new XorInstruction(_random.NextInt(), _random.NextInt(intSecretKeyLength));
case 2:
return new BitRotateInstruction(_random.NextInt(32), _random.NextInt(intSecretKeyLength));
default:
throw new System.Exception("Invalid instruction type");
}
}
private EncryptionInstructionWithOpCode CreateEncryptOpCode(ushort code)
{
IEncryptionInstruction inst = CreateRandomInstruction(EncryptionVirtualMachine.SecretKeyLength / sizeof(int));
Assert.AreEqual(1234, inst.Decrypt(inst.Encrypt(1234, _vmGenerationSecretKey, 0x12345678), _vmGenerationSecretKey, 0x12345678));
return new EncryptionInstructionWithOpCode(code, inst);
}
public EncryptionVirtualMachine CreateVirtualMachine(int opCodeCount)
{
Assert.IsTrue(opCodeCount > 0);
Assert.AreEqual(0, opCodeCount & (opCodeCount - 1));
var opCodes = new EncryptionInstructionWithOpCode[opCodeCount];
for (int i = 0; i < opCodes.Length; i++)
{
opCodes[i] = CreateEncryptOpCode((ushort)i);
}
return new EncryptionVirtualMachine(_vmGenerationSecretKey, opCodes);
}
}
}

View File

@ -12,15 +12,26 @@ namespace Obfuz.Encryption
public class EncryptionVirtualMachineSimulator : EncryptorBase public class EncryptionVirtualMachineSimulator : EncryptorBase
{ {
private readonly EncryptOpCode[] _opCodes; private readonly EncryptionInstructionWithOpCode[] _opCodes;
private readonly int[] _secretKey; private readonly int[] _secretKey;
public EncryptionVirtualMachineSimulator(EncryptOpCode[] opCodes, int[] secretKey) public EncryptionVirtualMachineSimulator(EncryptionVirtualMachine vm)
{ {
_opCodes = opCodes; _opCodes = vm.opCodes;
// should be power of 2 _secretKey = vm.secretKey;
Assert.AreEqual(0, opCodes.Length ^ (opCodes.Length - 1));
_secretKey = secretKey; VerifyInstructions();
}
private void VerifyInstructions()
{
int value = 0x11223344;
for (int i = 0; i < _opCodes.Length; i++)
{
int encryptedValue = _opCodes[i].Encrypt(value, _secretKey, i);
int decryptedValue = _opCodes[i].Decrypt(encryptedValue, _secretKey, i);
Assert.AreEqual(value, decryptedValue);
}
} }
private List<ushort> DecodeOps(int ops) private List<ushort> DecodeOps(int ops)

View File

@ -1,9 +0,0 @@
namespace Obfuz.Encryption
{
public interface IEncryptInstruction
{
int Encrypt(int value, int[] secretKey, int salt);
int Decrypt(int value, int[] secretKey, int salt);
}
}

View File

@ -0,0 +1,15 @@
namespace Obfuz.Encryption
{
public interface IEncryptionInstruction
{
int Encrypt(int value, int[] secretKey, int salt);
int Decrypt(int value, int[] secretKey, int salt);
}
public abstract class EncryptionInstructionBase : IEncryptionInstruction
{
public abstract int Encrypt(int value, int[] secretKey, int salt);
public abstract int Decrypt(int value, int[] secretKey, int salt);
}
}

View File

@ -1,7 +0,0 @@
namespace Obfuz.Encryption
{
public interface IVirtualMachineCreator
{
VirtualMachine CreateVirtualMachine(int opCodeCount);
}
}

View File

@ -1,6 +1,6 @@
namespace Obfuz.Encryption namespace Obfuz.Encryption.Instructions
{ {
public class AddInstruction : EncryptInstructionBase public class AddInstruction : EncryptionInstructionBase
{ {
private readonly int _addValue; private readonly int _addValue;
private readonly int _opKeyIndex; private readonly int _opKeyIndex;

View File

@ -1,6 +1,6 @@
namespace Obfuz.Encryption namespace Obfuz.Encryption.Instructions
{ {
public class BitRotateInstruction : EncryptInstructionBase public class BitRotateInstruction : EncryptionInstructionBase
{ {
private readonly int _rotateBitNum; private readonly int _rotateBitNum;
private readonly int _opKeyIndex; private readonly int _opKeyIndex;

View File

@ -3,14 +3,14 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Obfuz.Encryption namespace Obfuz.Encryption.Instructions
{ {
public class EncryptFunction : EncryptInstructionBase public class EncryptFunction : EncryptionInstructionBase
{ {
private readonly IEncryptInstruction[] _instructions; private readonly IEncryptionInstruction[] _instructions;
public EncryptFunction(IEncryptInstruction[] instructions) public EncryptFunction(IEncryptionInstruction[] instructions)
{ {
_instructions = instructions; _instructions = instructions;
} }

View File

@ -1,6 +1,6 @@
namespace Obfuz.Encryption namespace Obfuz.Encryption.Instructions
{ {
public class XorInstruction : EncryptInstructionBase public class XorInstruction : EncryptionInstructionBase
{ {
private readonly int _xorValue; private readonly int _xorValue;
private readonly int _opKeyIndex; private readonly int _opKeyIndex;

View File

@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Encryption
{
}

View File

@ -1,61 +0,0 @@
using Obfuz.Utils;
using UnityEngine.Assertions;
namespace Obfuz.Encryption
{
public class RandomVirtualMachineCreator : IVirtualMachineCreator
{
private readonly byte[] _byteSecretKey;
private readonly int[] _secretKey;
private readonly IRandom _random;
public RandomVirtualMachineCreator(byte[] secretKey)
{
_byteSecretKey = secretKey;
_secretKey = KeyGenerator.ConvertToIntKey(secretKey);
_random = new RandomWithKey(secretKey, 0);
}
private IEncryptInstruction CreateRandomInstruction(int secretKeyLength)
{
switch (_random.NextInt(3))
{
case 0:
return new AddInstruction(_random.NextInt(), _random.NextInt(secretKeyLength));
case 1:
return new XorInstruction(_random.NextInt(), _random.NextInt(secretKeyLength));
case 2:
return new BitRotateInstruction(_random.NextInt(32), _random.NextInt(secretKeyLength));
default:
throw new System.Exception("Invalid instruction type");
}
}
private EncryptOpCode CreateEncryptOpCode(ushort code, int opCodeCount)
{
Assert.IsTrue(code < opCodeCount);
var insts = new IEncryptInstruction[opCodeCount];
for (int i = 0; i < insts.Length; i++)
{
IEncryptInstruction inst = CreateRandomInstruction(VirtualMachine.SecretKeyLength);
Assert.AreEqual(1234, inst.Decrypt(inst.Encrypt(1234, _secretKey, i), _secretKey, i));
insts[i] = CreateRandomInstruction(opCodeCount);
}
var function = new EncryptFunction(insts);
Assert.AreEqual(1234, function.Decrypt(function.Encrypt(1234, _secretKey, code), _secretKey, code));
return new EncryptOpCode(code, function);
}
public VirtualMachine CreateVirtualMachine(int opCodeCount)
{
Assert.IsTrue(opCodeCount > 0);
Assert.AreEqual(0, opCodeCount ^ (opCodeCount - 1));
var opCodes = new EncryptOpCode[opCodeCount];
for (int i = 0; i < opCodes.Length; i++)
{
opCodes[i] = CreateEncryptOpCode((ushort)i, opCodeCount);
}
return new VirtualMachine(_byteSecretKey, opCodes);
}
}
}

View File

@ -1,16 +0,0 @@
namespace Obfuz.Encryption
{
public class VirtualMachine
{
public const int SecretKeyLength = 1024;
public readonly byte[] secretKey;
public readonly EncryptOpCode[] opCodes;
public VirtualMachine(byte[] secretKey, EncryptOpCode[] opCodes)
{
this.secretKey = secretKey;
this.opCodes = opCodes;
}
}
}

View File

@ -31,6 +31,7 @@ namespace Obfuz
private readonly Pipeline _pipeline = new Pipeline(); private readonly Pipeline _pipeline = new Pipeline();
private readonly byte[] _secretKey; private readonly byte[] _secretKey;
private readonly int _globalRandomSeed; private readonly int _globalRandomSeed;
private readonly string _encryptionVmSecretKey;
private ObfuscationPassContext _ctx; private ObfuscationPassContext _ctx;
@ -38,10 +39,11 @@ namespace Obfuz
List<string> notObfuscatedAssemblyNamesReferencingObfuscated, List<string> notObfuscatedAssemblyNamesReferencingObfuscated,
List<string> assemblySearchDirs, List<string> assemblySearchDirs,
string obfuscatedAssemblyOutputDir, string obfuscatedAssemblyOutputDir,
List<IObfuscationPass> obfuscationPasses, string rawSecretKey, int globalRandomSeed) List<IObfuscationPass> obfuscationPasses, string rawSecretKey, int globalRandomSeed, string encryptionVmSecretKey)
{ {
_secretKey = KeyGenerator.GenerateKey(rawSecretKey, VirtualMachine.SecretKeyLength); _secretKey = KeyGenerator.GenerateKey(rawSecretKey, EncryptionVirtualMachine.SecretKeyLength);
_globalRandomSeed = globalRandomSeed; _globalRandomSeed = globalRandomSeed;
_encryptionVmSecretKey = encryptionVmSecretKey;
_toObfuscatedAssemblyNames = toObfuscatedAssemblyNames; _toObfuscatedAssemblyNames = toObfuscatedAssemblyNames;
_notObfuscatedAssemblyNamesReferencingObfuscated = notObfuscatedAssemblyNamesReferencingObfuscated; _notObfuscatedAssemblyNamesReferencingObfuscated = notObfuscatedAssemblyNamesReferencingObfuscated;
@ -63,13 +65,20 @@ namespace Obfuz
OnPostObfuscation(); OnPostObfuscation();
} }
private IEncryptor CreateEncryptionVirtualMachine()
{
var vmCreator = new EncryptionVirtualMachineCreator(_encryptionVmSecretKey, _secretKey);
var vm = vmCreator.CreateVirtualMachine(1);
return new EncryptionVirtualMachineSimulator(vm);
}
private void OnPreObfuscation() private void OnPreObfuscation()
{ {
LoadAssemblies(); LoadAssemblies();
var random = new RandomWithKey(_secretKey, _globalRandomSeed); var random = new RandomWithKey(_secretKey, _globalRandomSeed);
var encryptor = new NullEncryptor(_secretKey); var encryptor = CreateEncryptionVirtualMachine();
var rvaDataAllocator = new RvaDataAllocator(random, encryptor); var rvaDataAllocator = new RvaDataAllocator(random, encryptor);
var constFieldAllocator = new ConstFieldAllocator(encryptor, random, rvaDataAllocator); var constFieldAllocator = new ConstFieldAllocator(encryptor, random, rvaDataAllocator);
_ctx = new ObfuscationPassContext _ctx = new ObfuscationPassContext

View File

@ -15,6 +15,7 @@ namespace Obfuz
{ {
private string _secretKey; private string _secretKey;
private int _globalRandomSeed; private int _globalRandomSeed;
private string _encryptionVmGenerationSecretKey;
private List<string> _toObfuscatedAssemblyNames = new List<string>(); private List<string> _toObfuscatedAssemblyNames = new List<string>();
private List<string> _notObfuscatedAssemblyNamesReferencingObfuscated = new List<string>(); private List<string> _notObfuscatedAssemblyNamesReferencingObfuscated = new List<string>();
private List<string> _assemblySearchDirs = new List<string>(); private List<string> _assemblySearchDirs = new List<string>();
@ -34,6 +35,12 @@ namespace Obfuz
set => _globalRandomSeed = value; set => _globalRandomSeed = value;
} }
public string EncryptionVmGenerationSecretKey
{
get => _encryptionVmGenerationSecretKey;
set => _encryptionVmGenerationSecretKey = value;
}
public List<string> ToObfuscatedAssemblyNames public List<string> ToObfuscatedAssemblyNames
{ {
get => _toObfuscatedAssemblyNames; get => _toObfuscatedAssemblyNames;
@ -75,7 +82,7 @@ namespace Obfuz
_notObfuscatedAssemblyNamesReferencingObfuscated, _notObfuscatedAssemblyNamesReferencingObfuscated,
_assemblySearchDirs, _assemblySearchDirs,
_obfuscatedAssemblyOutputDir, _obfuscatedAssemblyOutputDir,
_obfuscationPasses, _secretKey, _globalRandomSeed); _obfuscationPasses, _secretKey, _globalRandomSeed, _encryptionVmGenerationSecretKey);
} }
public static ObfuscatorBuilder FromObfuzSettings(ObfuzSettings settings, BuildTarget target) public static ObfuscatorBuilder FromObfuzSettings(ObfuzSettings settings, BuildTarget target)
@ -84,12 +91,17 @@ namespace Obfuz
{ {
_secretKey = settings.secretKey, _secretKey = settings.secretKey,
_globalRandomSeed = settings.globalRandomSeed, _globalRandomSeed = settings.globalRandomSeed,
_encryptionVmGenerationSecretKey = settings.encryptionVMSettings.codeGenerationSecretKey,
_toObfuscatedAssemblyNames = settings.toObfuscatedAssemblyNames.ToList(), _toObfuscatedAssemblyNames = settings.toObfuscatedAssemblyNames.ToList(),
_notObfuscatedAssemblyNamesReferencingObfuscated = settings.notObfuscatedAssemblyNamesReferencingObfuscated.ToList(), _notObfuscatedAssemblyNamesReferencingObfuscated = settings.notObfuscatedAssemblyNamesReferencingObfuscated.ToList(),
_assemblySearchDirs = settings.extraAssemblySearchDirs.ToList(), _assemblySearchDirs = settings.extraAssemblySearchDirs.ToList(),
_obfuscatedAssemblyOutputDir = settings.GetObfuscatedAssemblyOutputDir(target), _obfuscatedAssemblyOutputDir = settings.GetObfuscatedAssemblyOutputDir(target),
}; };
ObfuscationPassType obfuscationPasses = settings.enabledObfuscationPasses; ObfuscationPassType obfuscationPasses = settings.enabledObfuscationPasses;
if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncrypt))
{
builder.AddPass(new ConstEncryptPass(settings.constEncryptSettings));
}
if (obfuscationPasses.HasFlag(ObfuscationPassType.FieldEncrypt)) if (obfuscationPasses.HasFlag(ObfuscationPassType.FieldEncrypt))
{ {
builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings)); builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings));
@ -98,10 +110,6 @@ namespace Obfuz
{ {
builder.AddPass(new CallObfusPass(settings.callObfusSettings)); builder.AddPass(new CallObfusPass(settings.callObfusSettings));
} }
if (obfuscationPasses.HasFlag(ObfuscationPassType.ConstEncrypt))
{
builder.AddPass(new ConstEncryptPass(settings.constEncryptSettings));
}
if (obfuscationPasses.HasFlag(ObfuscationPassType.ExprObfus)) if (obfuscationPasses.HasFlag(ObfuscationPassType.ExprObfus))
{ {
builder.AddPass(new ExprObfusPass()); builder.AddPass(new ExprObfusPass());