obfuz/Editor/ObfusPasses/ConstEncrypt/DefaultConstEncryptor.cs

194 lines
9.3 KiB
C#
Raw Normal View History

2025-05-07 22:55:07 +08:00
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using Obfuz.Emit;
using Obfuz.Data;
using Obfuz.Utils;
using System;
using System.Collections.Generic;
using NUnit.Framework;
2025-05-08 08:54:18 +08:00
using System.Text;
2025-05-07 22:55:07 +08:00
2025-05-09 19:26:59 +08:00
namespace Obfuz.ObfusPasses.ConstEncrypt
2025-05-07 22:55:07 +08:00
{
2025-05-09 19:26:59 +08:00
public class DefaultConstEncryptor : IConstEncryptor
2025-05-07 22:55:07 +08:00
{
private readonly IRandom _random;
private readonly RvaDataAllocator _rvaDataAllocator;
private readonly ConstFieldAllocator _constFieldAllocator;
private readonly IEncryptor _encryptor;
private readonly GroupByModuleEntityManager _moduleEntityManager;
private readonly int _encryptionLevel;
2025-05-07 22:55:07 +08:00
public DefaultConstEncryptor(IRandom random, IEncryptor encryptor, RvaDataAllocator rvaDataAllocator, ConstFieldAllocator constFieldAllocator, GroupByModuleEntityManager moduleEntityManager, int encryptionLevel)
2025-05-07 22:55:07 +08:00
{
2025-05-10 11:25:07 +08:00
_random = random;
_encryptor = encryptor;
_rvaDataAllocator = rvaDataAllocator;
_constFieldAllocator = constFieldAllocator;
_moduleEntityManager = moduleEntityManager;
_encryptionLevel = encryptionLevel;
2025-05-07 22:55:07 +08:00
}
private int GenerateEncryptionOperations()
{
return EncryptionUtil.GenerateEncryptionOpCodes(_random, _encryptor, _encryptionLevel);
2025-05-07 22:55:07 +08:00
}
public int GenerateSalt()
{
return _random.NextInt();
}
2025-05-11 08:53:48 +08:00
private DefaultMetadataImporter GetModuleMetadataImporter(MethodDef method)
2025-05-07 22:55:07 +08:00
{
return _moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module);
2025-05-07 22:55:07 +08:00
}
public void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List<Instruction> obfuscatedInstructions)
2025-05-07 22:55:07 +08:00
{
2025-05-09 11:28:17 +08:00
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
2025-05-07 22:55:07 +08:00
int ops = GenerateEncryptionOperations();
int salt = GenerateSalt();
int encryptedValue = _encryptor.Encrypt(value, ops, salt);
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
2025-05-11 08:53:48 +08:00
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
2025-05-07 22:55:07 +08:00
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaInt));
2025-05-07 22:55:07 +08:00
}
public void ObfuscateLong(MethodDef method, bool needCacheValue, long value, List<Instruction> obfuscatedInstructions)
2025-05-07 22:55:07 +08:00
{
2025-05-09 11:28:17 +08:00
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
2025-05-07 22:55:07 +08:00
int ops = GenerateEncryptionOperations();
int salt = GenerateSalt();
long encryptedValue = _encryptor.Encrypt(value, ops, salt);
2025-05-08 08:54:18 +08:00
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
2025-05-07 22:55:07 +08:00
2025-05-11 08:53:48 +08:00
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
2025-05-07 22:55:07 +08:00
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaLong));
2025-05-07 22:55:07 +08:00
}
public void ObfuscateFloat(MethodDef method, bool needCacheValue, float value, List<Instruction> obfuscatedInstructions)
2025-05-07 22:55:07 +08:00
{
2025-05-09 11:28:17 +08:00
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
2025-05-07 22:55:07 +08:00
int ops = GenerateEncryptionOperations();
int salt = GenerateSalt();
float encryptedValue = _encryptor.Encrypt(value, ops, salt);
2025-05-08 08:54:18 +08:00
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
2025-05-07 22:55:07 +08:00
2025-05-11 08:53:48 +08:00
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
2025-05-07 22:55:07 +08:00
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaFloat));
2025-05-07 22:55:07 +08:00
}
public void ObfuscateDouble(MethodDef method, bool needCacheValue, double value, List<Instruction> obfuscatedInstructions)
2025-05-07 22:55:07 +08:00
{
2025-05-09 11:28:17 +08:00
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
2025-05-07 22:55:07 +08:00
int ops = GenerateEncryptionOperations();
int salt = GenerateSalt();
double encryptedValue = _encryptor.Encrypt(value, ops, salt);
2025-05-08 08:54:18 +08:00
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
2025-05-11 08:53:48 +08:00
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
2025-05-07 22:55:07 +08:00
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
2025-05-08 08:54:18 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaDouble));
2025-05-07 22:55:07 +08:00
}
public void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List<Instruction> obfuscatedInstructions)
2025-05-07 22:55:07 +08:00
{
throw new NotSupportedException("ObfuscateBytes is not supported yet.");
//if (needCacheValue)
//{
// FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
// obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
// return;
//}
//int ops = GenerateEncryptionOperations();
//int salt = GenerateSalt();
//byte[] encryptedValue = _encryptor.Encrypt(value, 0, value.Length, ops, salt);
//Assert.IsTrue(encryptedValue.Length % 4 == 0);
//RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
//DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
//obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
//// should use value.Length, can't use rvaData.size, because rvaData.size is align to 4, it's not the actual length.
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(value.Length));
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
//obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaBytes));
2025-05-07 22:55:07 +08:00
}
public void ObfuscateString(MethodDef method, bool needCacheValue, string value, List<Instruction> obfuscatedInstructions)
2025-05-07 22:55:07 +08:00
{
2025-05-09 11:28:17 +08:00
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
int ops = GenerateEncryptionOperations();
int salt = GenerateSalt();
int stringByteLength = Encoding.UTF8.GetByteCount(value);
byte[] encryptedValue = _encryptor.Encrypt(value, ops, salt);
Assert.IsTrue(encryptedValue.Length % 4 == 0);
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
2025-05-11 08:53:48 +08:00
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
2025-05-09 11:28:17 +08:00
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
// should use stringByteLength, can't use rvaData.size, because rvaData.size is align to 4, it's not the actual length.
obfuscatedInstructions.Add(Instruction.CreateLdcI4(stringByteLength));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaString));
2025-05-07 22:55:07 +08:00
}
public void Done()
{
_rvaDataAllocator.Done();
_constFieldAllocator.Done();
}
}
}