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

View File

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

View File

@ -1,4 +1,5 @@
using System; using NUnit.Framework;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
@ -9,14 +10,12 @@ namespace Obfuz.Utils
{ {
public static class KeyGenerator public static class KeyGenerator
{ {
public const int KeyLength = 1024; public static byte[] GenerateKey(string initialString, int keyLength)
public static byte[] GenerateKey(string initialString)
{ {
byte[] initialBytes = Encoding.UTF8.GetBytes(initialString); byte[] initialBytes = Encoding.UTF8.GetBytes(initialString);
using var sha512 = SHA512.Create(); using var sha512 = SHA512.Create();
byte[] hash = sha512.ComputeHash(initialBytes); byte[] hash = sha512.ComputeHash(initialBytes);
byte[] key = new byte[KeyLength]; byte[] key = new byte[keyLength];
int bytesCopied = 0; int bytesCopied = 0;
while (bytesCopied < key.Length) while (bytesCopied < key.Length)
{ {
@ -31,5 +30,14 @@ namespace Obfuz.Utils
} }
return key; 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) public RandomWithKey(byte[] key, int seed)
{ {
_key = ConvertToIntKey(key); _key = KeyGenerator.ConvertToIntKey(key);
_seed = seed; _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) public int NextInt(int min, int max)
{ {
return min + NextInt(max - min); return min + NextInt(max - min);