const加密支持多种混淆方式

dev
walon 2025-06-21 09:20:36 +08:00
parent b1731a8c38
commit f8571ada9e
4 changed files with 334 additions and 188 deletions

View File

@ -49,50 +49,146 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List<Instruction> obfuscatedInstructions)
{
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module);
IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode());
int ops = GenerateEncryptionOperations(encryptionScope, random);
int salt = GenerateSalt(random);
int encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt);
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
ModuleConstFieldAllocator moduleConstFieldAllocator = _constFieldAllocator.GetModuleAllocator(method.Module);
switch (random.NextInt(5))
{
case 0:
{
// = c = encrypted static field
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
break;
}
case 1:
{
// c = a + b
int a = random.NextInt();
int b = value - a;
float constProbability = 0.5f;
ConstObfusUtil.LoadConstTwoInt(a, b, random, constProbability, moduleConstFieldAllocator, obfuscatedInstructions);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Add));
break;
}
case 2:
{
// c = a * b
int a = random.NextInt() | 0x1;
int ra = MathUtil.ModInverse32(a);
int b = ra * value;
float constProbability = 0.5f;
ConstObfusUtil.LoadConstTwoInt(a, b, random, constProbability, moduleConstFieldAllocator, obfuscatedInstructions);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Mul));
break;
}
case 3:
{
// c = a ^ b
int a = random.NextInt();
int b = a ^ value;
float constProbability = 0.5f;
ConstObfusUtil.LoadConstTwoInt(a, b, random, constProbability, moduleConstFieldAllocator, obfuscatedInstructions);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Xor));
break;
}
default:
{
if (needCacheValue)
{
FieldDef cacheField = moduleConstFieldAllocator.Allocate(value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
int ops = GenerateEncryptionOperations(encryptionScope, random);
int salt = GenerateSalt(random);
int encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt);
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));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaInt));
break;
}
}
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaInt));
}
public void ObfuscateLong(MethodDef method, bool needCacheValue, long value, List<Instruction> obfuscatedInstructions)
{
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(method.Module);
IRandom random = CreateRandomForValue(encryptionScope, value.GetHashCode());
int ops = GenerateEncryptionOperations(encryptionScope, random);
int salt = GenerateSalt(random);
long encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt);
RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
ModuleConstFieldAllocator moduleConstFieldAllocator = _constFieldAllocator.GetModuleAllocator(method.Module);
switch (random.NextInt(5))
{
case 0:
{
// c = encrypted static field
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
break;
}
case 1:
{
// c = a + b
long a = random.NextLong();
long b = value - a;
float constProbability = 0.5f;
ConstObfusUtil.LoadConstTwoLong(a, b, random, constProbability, moduleConstFieldAllocator, obfuscatedInstructions);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Add));
break;
}
case 2:
{
// c = a * b
long a = random.NextLong() | 0x1;
long ra = MathUtil.ModInverse64(a);
long b = ra * value;
float constProbability = 0.5f;
ConstObfusUtil.LoadConstTwoLong(a, b, random, constProbability, moduleConstFieldAllocator, obfuscatedInstructions);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Mul));
break;
}
case 3:
{
// c = a ^ b
long a = random.NextLong();
long b = a ^ value;
float constProbability = 0.5f;
ConstObfusUtil.LoadConstTwoLong(a, b, random, constProbability, moduleConstFieldAllocator, obfuscatedInstructions);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Xor));
break;
}
default:
{
if (needCacheValue)
{
FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
return;
}
int ops = GenerateEncryptionOperations(encryptionScope, random);
int salt = GenerateSalt(random);
long encryptedValue = encryptionScope.encryptor.Encrypt(value, ops, salt);
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));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaLong));
break;
}
}
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaLong));
}
public void ObfuscateFloat(MethodDef method, bool needCacheValue, float value, List<Instruction> obfuscatedInstructions)

View File

@ -13,148 +13,6 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
{
class AdvancedObfuscator : BasicObfuscator
{
private void LoadConstInt(int a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_I4, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
private void LoadConstLong(long a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_I8, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
private void LoadConstFloat(float a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_R4, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
private void LoadConstDouble(double a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_R8, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
//public override bool ObfuscateBasicUnaryOp(Instruction inst, EvalDataType op, EvalDataType ret, List<Instruction> outputInsts, ObfusMethodContext ctx)
//{
// IRandom random = ctx.localRandom;
// ModuleConstFieldAllocator constFieldAllocator = ctx.constFieldAllocator;
// switch (inst.OpCode.Code)
// {
// case Code.Neg:
// {
// switch (op)
// {
// case EvalDataType.Int32:
// {
// // y = -x = (x * a + b) * (-ra) + b * ra;
// int a = random.NextInt() | 0x1;
// int ra = MathUtil.ModInverse32(a);
// Assert.AreEqual(1, a * ra);
// int b = random.NextInt();
// int b_ra = b * ra;
// float constProbability = 0.5f;
// LoadConstInt(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstInt(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstInt(-ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstInt(b_ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// return true;
// }
// case EvalDataType.Int64:
// {
// // y = -x = (x * a + b) * (-ra) + b * ra;
// long a = random.NextLong() | 0x1L;
// long ra = MathUtil.ModInverse64(a);
// Assert.AreEqual(1L, a * ra);
// long b = random.NextLong();
// long b_ra = b * ra;
// float constProbability = 0.5f;
// LoadConstLong(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstLong(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstLong(-ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// LoadConstLong(b_ra, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// return true;
// }
// case EvalDataType.Float:
// {
// // y = -x = (x + a) * b; a = 0.0f, b = 1.0f,
// float a = 0.0f;
// float b = -1.0f;
// float constProbability = 0f;
// LoadConstFloat(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstFloat(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// return true;
// }
// case EvalDataType.Double:
// {
// // y = -x = (x + a) * b; a = 0.0, b = -1.0,
// double a = 0.0;
// double b = -1.0;
// float constProbability = 0f;
// LoadConstDouble(a, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Add));
// LoadConstDouble(b, random, constProbability, constFieldAllocator, outputInsts);
// outputInsts.Add(Instruction.Create(OpCodes.Mul));
// return true;
// }
// }
// break;
// }
// }
// return base.ObfuscateBasicUnaryOp(inst, op, ret, outputInsts, ctx);
//}
protected bool GenerateIdentityTransformForArgument(Instruction inst, EvalDataType op, List<Instruction> outputInsts, ObfusMethodContext ctx)
{
IRandom random = ctx.localRandom;
@ -169,13 +27,13 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
int b = random.NextInt();
int b_ra = -b * ra;
float constProbability = 0.5f;
LoadConstInt(a, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstInt(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstInt(b, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstInt(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstInt(ra, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstInt(ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstInt(b_ra, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstInt(b_ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add));
outputInsts.Add(inst.Clone());
return true;
@ -188,13 +46,13 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
long b = random.NextLong();
long b_ra = -b * ra;
float constProbability = 0.5f;
LoadConstLong(a, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstLong(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstLong(b, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstLong(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstLong(ra, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstLong(ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul));
LoadConstLong(b_ra, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstLong(b_ra, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add));
outputInsts.Add(inst.Clone());
return true;
@ -205,9 +63,9 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
float a = 0.0f;
float b = 1.0f;
float constProbability = 0f;
LoadConstFloat(a, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstFloat(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstFloat(b, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstFloat(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul));
outputInsts.Add(inst.Clone());
return true;
@ -218,9 +76,9 @@ namespace Obfuz.ObfusPasses.ExprObfus.Obfuscators
double a = 0.0;
double b = 1.0;
float constProbability = 0f;
LoadConstDouble(a, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstDouble(a, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Add));
LoadConstDouble(b, random, constProbability, constFieldAllocator, outputInsts);
ConstObfusUtil.LoadConstDouble(b, random, constProbability, constFieldAllocator, outputInsts);
outputInsts.Add(Instruction.Create(OpCodes.Mul));
outputInsts.Add(inst.Clone());
return true;

View File

@ -0,0 +1,181 @@
using dnlib.DotNet.Emit;
using dnlib.DotNet;
using Obfuz.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Utils
{
internal static class ConstObfusUtil
{
public static void LoadConstInt(int a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_I4, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
public static void LoadConstLong(long a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_I8, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
public static void LoadConstFloat(float a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_R4, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
public static void LoadConstDouble(double a, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
Instruction inst;
if (random.NextInPercentage(constProbability))
{
inst = Instruction.Create(OpCodes.Ldc_R8, a);
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
inst = Instruction.Create(OpCodes.Ldsfld, field);
}
outputInsts.Add(inst);
}
public static void LoadConstTwoInt(int a, int b, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
if (random.NextInPercentage(constProbability))
{
outputInsts.Add(Instruction.Create(OpCodes.Ldc_I4, a));
// at most one ldc instruction
FieldDef field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
if (random.NextInPercentage(constProbability))
{
// at most one ldc instruction
outputInsts.Add(Instruction.Create(OpCodes.Ldc_I4, b));
}
else
{
field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
}
}
public static void LoadConstTwoLong(long a, long b, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
if (random.NextInPercentage(constProbability))
{
outputInsts.Add(Instruction.Create(OpCodes.Ldc_I8, a));
// at most one ldc instruction
FieldDef field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
if (random.NextInPercentage(constProbability))
{
// at most one ldc instruction
outputInsts.Add(Instruction.Create(OpCodes.Ldc_I8, b));
}
else
{
field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
}
}
public static void LoadConstTwoFloat(float a, float b, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
if (random.NextInPercentage(constProbability))
{
outputInsts.Add(Instruction.Create(OpCodes.Ldc_R4, a));
// at most one ldc instruction
FieldDef field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
if (random.NextInPercentage(constProbability))
{
// at most one ldc instruction
outputInsts.Add(Instruction.Create(OpCodes.Ldc_R4, b));
}
else
{
field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
}
}
public static void LoadConstTwoDouble(double a, double b, IRandom random, float constProbability, ModuleConstFieldAllocator constFieldAllocator, List<Instruction> outputInsts)
{
if (random.NextInPercentage(constProbability))
{
outputInsts.Add(Instruction.Create(OpCodes.Ldc_R8, a));
// at most one ldc instruction
FieldDef field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
else
{
FieldDef field = constFieldAllocator.Allocate(a);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
if (random.NextInPercentage(constProbability))
{
// at most one ldc instruction
outputInsts.Add(Instruction.Create(OpCodes.Ldc_R8, b));
}
else
{
field = constFieldAllocator.Allocate(b);
outputInsts.Add(Instruction.Create(OpCodes.Ldsfld, field));
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4330e358b953be54c9f1ada2ff34156d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: