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;
|
|
|
|
|
|
2025-05-10 11:25:07 +08:00
|
|
|
|
public DefaultConstEncryptor(IRandom random, IEncryptor encryptor, RvaDataAllocator rvaDataAllocator, ConstFieldAllocator constFieldAllocator)
|
2025-05-07 22:55:07 +08:00
|
|
|
|
{
|
2025-05-10 11:25:07 +08:00
|
|
|
|
_random = random;
|
|
|
|
|
_encryptor = encryptor;
|
|
|
|
|
_rvaDataAllocator = rvaDataAllocator;
|
|
|
|
|
_constFieldAllocator = constFieldAllocator;
|
2025-05-07 22:55:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int GenerateEncryptionOperations()
|
|
|
|
|
{
|
|
|
|
|
return _random.NextInt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GenerateSalt()
|
|
|
|
|
{
|
|
|
|
|
return _random.NextInt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private DefaultModuleMetadataImporter GetModuleMetadataImporter(MethodDef method)
|
|
|
|
|
{
|
|
|
|
|
return MetadataImporter.Instance.GetDefaultModuleMetadataImporter(method.Module);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-09 11:03:05 +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-09 11:03:05 +08:00
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
DefaultModuleMetadataImporter 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
|
|
|
|
}
|
|
|
|
|
|
2025-05-09 11:03:05 +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
|
|
|
|
|
|
|
|
|
DefaultModuleMetadataImporter 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
|
|
|
|
}
|
|
|
|
|
|
2025-05-09 11:03:05 +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
|
|
|
|
|
|
|
|
|
DefaultModuleMetadataImporter 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
|
|
|
|
}
|
|
|
|
|
|
2025-05-09 11:03:05 +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-07 22:55:07 +08:00
|
|
|
|
DefaultModuleMetadataImporter 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
|
|
|
|
}
|
|
|
|
|
|
2025-05-09 11:03:05 +08:00
|
|
|
|
public void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] 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();
|
2025-05-08 08:54:18 +08:00
|
|
|
|
byte[] encryptedValue = _encryptor.Encrypt(value, 0, value.Length, ops, salt);
|
|
|
|
|
Assert.IsTrue(encryptedValue.Length % 4 == 0);
|
|
|
|
|
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
|
2025-05-07 22:55:07 +08:00
|
|
|
|
|
2025-05-08 08:54:18 +08:00
|
|
|
|
DefaultModuleMetadataImporter 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
|
|
|
|
}
|
|
|
|
|
|
2025-05-09 11:03:05 +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);
|
|
|
|
|
|
|
|
|
|
DefaultModuleMetadataImporter importer = GetModuleMetadataImporter(method);
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|