重构 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
{
public class EncryptOpCode
public class EncryptionInstructionWithOpCode
{
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.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
{
private readonly EncryptOpCode[] _opCodes;
private readonly EncryptionInstructionWithOpCode[] _opCodes;
private readonly int[] _secretKey;
public EncryptionVirtualMachineSimulator(EncryptOpCode[] opCodes, int[] secretKey)
public EncryptionVirtualMachineSimulator(EncryptionVirtualMachine vm)
{
_opCodes = opCodes;
// should be power of 2
Assert.AreEqual(0, opCodes.Length ^ (opCodes.Length - 1));
_secretKey = secretKey;
_opCodes = vm.opCodes;
_secretKey = vm.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)

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 _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 _opKeyIndex;

View File

@ -3,14 +3,14 @@ using System.Linq;
using System.Text;
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;
}

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 _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 byte[] _secretKey;
private readonly int _globalRandomSeed;
private readonly string _encryptionVmSecretKey;
private ObfuscationPassContext _ctx;
@ -38,10 +39,11 @@ namespace Obfuz
List<string> notObfuscatedAssemblyNamesReferencingObfuscated,
List<string> assemblySearchDirs,
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;
_encryptionVmSecretKey = encryptionVmSecretKey;
_toObfuscatedAssemblyNames = toObfuscatedAssemblyNames;
_notObfuscatedAssemblyNamesReferencingObfuscated = notObfuscatedAssemblyNamesReferencingObfuscated;
@ -63,13 +65,20 @@ namespace Obfuz
OnPostObfuscation();
}
private IEncryptor CreateEncryptionVirtualMachine()
{
var vmCreator = new EncryptionVirtualMachineCreator(_encryptionVmSecretKey, _secretKey);
var vm = vmCreator.CreateVirtualMachine(1);
return new EncryptionVirtualMachineSimulator(vm);
}
private void OnPreObfuscation()
{
LoadAssemblies();
var random = new RandomWithKey(_secretKey, _globalRandomSeed);
var encryptor = new NullEncryptor(_secretKey);
var encryptor = CreateEncryptionVirtualMachine();
var rvaDataAllocator = new RvaDataAllocator(random, encryptor);
var constFieldAllocator = new ConstFieldAllocator(encryptor, random, rvaDataAllocator);
_ctx = new ObfuscationPassContext

View File

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