重构 EncryptionVM

backup
walon 2025-05-11 10:49:04 +08:00
parent a7db16475a
commit af60d0703d
6 changed files with 40 additions and 41 deletions

View File

@ -2,6 +2,6 @@
{
public interface IVirtualMachineCreator
{
VirtualMachine CreateVirtualMachine(int opCodeCount, int vmSeed);
VirtualMachine CreateVirtualMachine(int opCodeCount);
}
}

View File

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

View File

@ -4,12 +4,12 @@
{
public const int SecretKeyLength = 1024;
public readonly int vmSeed;
public readonly byte[] secretKey;
public readonly EncryptOpCode[] opCodes;
public VirtualMachine(int vmSeed, EncryptOpCode[] opCodes)
public VirtualMachine(byte[] secretKey, EncryptOpCode[] opCodes)
{
this.vmSeed = vmSeed;
this.secretKey = secretKey;
this.opCodes = opCodes;
}
}

View File

@ -2,6 +2,7 @@
using dnlib.Protection;
using Obfuz.Data;
using Obfuz.Emit;
using Obfuz.Encryption;
using Obfuz.ObfusPasses;
using Obfuz.ObfusPasses.CleanUp;
using Obfuz.Utils;
@ -39,7 +40,7 @@ namespace Obfuz
string obfuscatedAssemblyOutputDir,
List<IObfuscationPass> obfuscationPasses, string rawSecretKey, int globalRandomSeed)
{
_secretKey = KeyGenerator.GenerateKey(rawSecretKey);
_secretKey = KeyGenerator.GenerateKey(rawSecretKey, VirtualMachine.SecretKeyLength);
_globalRandomSeed = globalRandomSeed;
_toObfuscatedAssemblyNames = toObfuscatedAssemblyNames;

View File

@ -1,4 +1,5 @@
using System;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
@ -9,14 +10,12 @@ namespace Obfuz.Utils
{
public static class KeyGenerator
{
public const int KeyLength = 1024;
public static byte[] GenerateKey(string initialString)
public static byte[] GenerateKey(string initialString, int keyLength)
{
byte[] initialBytes = Encoding.UTF8.GetBytes(initialString);
using var sha512 = SHA512.Create();
byte[] hash = sha512.ComputeHash(initialBytes);
byte[] key = new byte[KeyLength];
byte[] key = new byte[keyLength];
int bytesCopied = 0;
while (bytesCopied < key.Length)
{
@ -31,5 +30,14 @@ namespace Obfuz.Utils
}
return key;
}
public static int[] ConvertToIntKey(byte[] key)
{
Assert.AreEqual(0, key.Length % 4);
int align4Length = key.Length / 4;
int[] intKey = new int[align4Length];
Buffer.BlockCopy(key, 0, intKey, 0, key.Length);
return intKey;
}
}
}

View File

@ -21,19 +21,10 @@ namespace Obfuz.Utils
public RandomWithKey(byte[] key, int seed)
{
_key = ConvertToIntKey(key);
_key = KeyGenerator.ConvertToIntKey(key);
_seed = seed;
}
private static int[] ConvertToIntKey(byte[] key)
{
// ignore last bytes if not aligned to 4
int align4Length = key.Length / 4;
int[] intKey = new int[align4Length];
Buffer.BlockCopy(key, 0, intKey, 0, align4Length * 4);
return intKey;
}
public int NextInt(int min, int max)
{
return min + NextInt(max - min);