修复 GeneratedEncryptionVirtualMachine Decrypt时没有逆序ops的bug

backup
walon 2025-05-14 10:46:42 +08:00
parent cabc6c2980
commit 542585b1f7
11 changed files with 84 additions and 26 deletions

View File

@ -5,6 +5,7 @@ using Obfuz.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
@ -31,6 +32,7 @@ namespace Obfuz.Data
private readonly Dictionary<FieldDef, ConstFieldInfo> _field2Fields = new Dictionary<FieldDef, ConstFieldInfo>();
private readonly List<TypeDef> _holderTypeDefs = new List<TypeDef>();
private bool _done;
public ModuleConstFieldAllocator(IEncryptor encryptor, IRandom random, RvaDataAllocator rvaDataAllocator, GroupByModuleEntityManager moduleEntityManager)
@ -89,6 +91,10 @@ namespace Obfuz.Data
private FieldDef AllocateAny(object value)
{
if (_done)
{
throw new Exception("can't Allocate after done");
}
if (!_allocatedFields.TryGetValue(value, out var field))
{
field = CreateConstFieldInfo(value);
@ -248,6 +254,11 @@ namespace Obfuz.Data
public void Done()
{
if (_done)
{
throw new Exception("Already done");
}
_done = true;
foreach (var typeDef in _holderTypeDefs)
{
CreateCCtorOfRvaTypeDef(typeDef);

View File

@ -69,6 +69,7 @@ namespace Obfuz.Data
private TypeDef _rvaTypeDef;
private readonly Dictionary<int, TypeDef> _dataHolderTypeBySizes = new Dictionary<int, TypeDef>();
private bool _done;
public ModuleRvaDataAllocator(IRandom random, IEncryptor encryptor, GroupByModuleEntityManager moduleEntityManager)
{
@ -99,10 +100,10 @@ namespace Obfuz.Data
}
var holderField = new FieldDefUser($"$RVA_Data{_rvaTypeDef.Fields.Count}", new FieldSig(dataHolderType.ToTypeSig()), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
var holderField = new FieldDefUser($"$RVA_Data{_rvaFields.Count}", new FieldSig(dataHolderType.ToTypeSig()), FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
holderField.DeclaringType = _rvaTypeDef;
var runtimeValueField = new FieldDefUser($"$RVA_Value{_rvaTypeDef.Fields.Count}", new FieldSig(new SZArraySig(_module.CorLibTypes.Byte)), FieldAttributes.Static);
var runtimeValueField = new FieldDefUser($"$RVA_Value{_rvaFields.Count}", new FieldSig(new SZArraySig(_module.CorLibTypes.Byte)), FieldAttributes.Static);
runtimeValueField.DeclaringType = _rvaTypeDef;
return (holderField, runtimeValueField);
}
@ -145,6 +146,10 @@ namespace Obfuz.Data
private RvaField GetRvaField(int preservedSize, int alignment)
{
if (_done)
{
throw new Exception("can't GetRvaField after done");
}
Assert.IsTrue(preservedSize % alignment == 0);
// for big size, create a new field
if (preservedSize >= maxRvaDataSize)
@ -279,6 +284,11 @@ namespace Obfuz.Data
public void Done()
{
if (_done)
{
throw new Exception("can't call Done twice");
}
_done = true;
SetFieldsRVA();
CreateCCtorOfRvaTypeDef();
}

View File

@ -152,12 +152,21 @@ namespace Obfuz.EncryptionVM
public override int Encrypt(int value, int opts, int salt)
{
int revertOps = 0;
while (opts > 0)
{
int opCode = opts & kOpCodeMask;
value = ExecuteEncrypt(value, opCode, salt);
revertOps <<= kOpCodeBits;
revertOps |= opCode;
opts >>= kOpCodeBits;
}
while (revertOps > 0)
{
int opCode = revertOps & kOpCodeMask;
value = ExecuteEncrypt(value, opCode, salt);
revertOps >>= kOpCodeBits;
}
return value;
}

View File

@ -57,24 +57,24 @@ namespace Obfuz.EncryptionVM
}
}
private List<ushort> DecodeOps(int ops)
private List<uint> DecodeOps(uint ops)
{
var codes = new List<ushort>();
var codes = new List<uint>();
while (ops > 0)
{
var code = (ushort)(ops % _opCodes.Length);
uint code = ops % (uint)_opCodes.Length;
codes.Add(code);
ops >>= 16;
ops /= (uint)_opCodes.Length;
}
return codes;
}
public override int Encrypt(int value, int ops, int salt)
{
var codes = DecodeOps(ops);
foreach (var code in codes)
var codes = DecodeOps((uint)ops);
for (int i = codes.Count - 1; i >= 0; i--)
{
var opCode = _opCodes[code];
var opCode = _opCodes[codes[i]];
value = opCode.Encrypt(value, _secretKey, salt);
}
return value;
@ -82,10 +82,10 @@ namespace Obfuz.EncryptionVM
public override int Decrypt(int value, int ops, int salt)
{
var codes = DecodeOps(ops);
for (int i = codes.Count - 1; i >= 0; i--)
var codes = DecodeOps((uint)ops);
foreach (var code in codes)
{
var opCode = _opCodes[codes[i]];
var opCode = _opCodes[code];
value = opCode.Decrypt(value, _secretKey, salt);
}
return value;

View File

@ -36,6 +36,7 @@ namespace Obfuz.ObfusPasses.CallObfus
private readonly RandomCreator _randomCreator;
private readonly IEncryptor _encryptor;
private readonly int _encryptionLevel;
private bool _done;
class MethodKey : IEquatable<MethodKey>
{
@ -188,6 +189,10 @@ namespace Obfuz.ObfusPasses.CallObfus
public ProxyCallMethodData Allocate(IMethod method, bool callVir)
{
if (_done)
{
throw new Exception("can't Allocate after done");
}
var key = new MethodKey(method, callVir);
if (!_methodProxys.TryGetValue(key, out var proxyInfo))
{
@ -214,6 +219,12 @@ namespace Obfuz.ObfusPasses.CallObfus
public void Done()
{
if (_done)
{
throw new Exception("Already done");
}
_done = true;
foreach (DispatchMethodInfo dispatchMethod in _dispatchMethods.Values.SelectMany(ms => ms))
{
var methodDef = dispatchMethod.methodDef;

View File

@ -36,7 +36,7 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public override void Stop()
{
_dataObfuscator.Done();
}
protected override bool NeedObfuscateMethod(MethodDef method)

View File

@ -196,8 +196,6 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public void Done()
{
_rvaDataAllocator.Done();
_constFieldAllocator.Done();
}
}
}

View File

@ -18,8 +18,6 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
void ObfuscateString(MethodDef method, bool needCacheValue, string value, List<Instruction> obfuscatedInstructions);
void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List<Instruction> obfuscatedInstructions);
void Done();
}
public abstract class ConstEncryptorBase : IConstEncryptor
@ -30,6 +28,5 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public abstract void ObfuscateInt(MethodDef method, bool needCacheValue, int value, List<Instruction> obfuscatedInstructions);
public abstract void ObfuscateLong(MethodDef method, bool needCacheValue, long value, List<Instruction> obfuscatedInstructions);
public abstract void ObfuscateString(MethodDef method, bool needCacheValue, string value, List<Instruction> obfuscatedInstructions);
public abstract void Done();
}
}

View File

@ -8,7 +8,7 @@ namespace Obfuz.ObfusPasses.SymbolObfus.Policies
public override bool NeedRename(TypeDef typeDef)
{
string name = typeDef.Name;
if (name == "<Module>")
if (name == "<Module>" || name == "ObfuzIgnoreAttribute")
{
return false;
}

View File

@ -129,16 +129,18 @@ namespace Obfuz
var gvmInstance = (IEncryptor)Activator.CreateInstance(generatedVmTypes[0], new object[] { _byteSecret } );
int testValue = 11223344;
string testString = "hello,world";
for (int i = 0; i < vm.opCodes.Length; i++)
{
int encryptedValueOfVms = vms.Encrypt(testValue, i, i);
int decryptedValueOfVms = vms.Decrypt(encryptedValueOfVms, i, i);
int ops = i * vm.opCodes.Length + i;
int encryptedValueOfVms = vms.Encrypt(testValue, ops, i);
int decryptedValueOfVms = vms.Decrypt(encryptedValueOfVms, ops, i);
if (decryptedValueOfVms != testValue)
{
throw new Exception($"VirtualMachineSimulator decrypt failed! opCode:{i}, originalValue:{testValue} decryptedValue:{decryptedValueOfVms}");
}
int encryptedValueOfGvm = gvmInstance.Encrypt(testValue, i, i);
int decryptedValueOfGvm = gvmInstance.Decrypt(encryptedValueOfGvm, i, i);
int encryptedValueOfGvm = gvmInstance.Encrypt(testValue, ops, i);
int decryptedValueOfGvm = gvmInstance.Decrypt(encryptedValueOfGvm, ops, i);
if (encryptedValueOfGvm != encryptedValueOfVms)
{
throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testValue} encryptedValue VirtualMachineSimulator:{encryptedValueOfVms} GeneratedEncryptionVirtualMachine:{encryptedValueOfGvm}");
@ -147,6 +149,23 @@ namespace Obfuz
{
throw new Exception($"GeneratedEncryptionVirtualMachine decrypt failed! opCode:{i}, originalValue:{testValue} decryptedValue:{decryptedValueOfGvm}");
}
byte[] encryptedStrOfVms = vms.Encrypt(testString, ops, i);
string descryptedStrOfVms = vms.DecryptString(encryptedStrOfVms, 0, encryptedStrOfVms.Length, ops, i);
if (descryptedStrOfVms != testString)
{
throw new Exception($"VirtualMachineSimulator decrypt string failed! opCode:{i}, originalValue:{testString} decryptedValue:{descryptedStrOfVms}");
}
byte[] encryptedStrOfGvm = gvmInstance.Encrypt(testString, ops, i);
string descryptedStrOfGvm = gvmInstance.DecryptString(encryptedStrOfGvm, 0, encryptedStrOfGvm.Length, ops, i);
if (!encryptedStrOfGvm.SequenceEqual(encryptedStrOfVms))
{
throw new Exception($"encryptedValue not match! opCode:{i}, originalValue:{testString} encryptedValue VirtualMachineSimulator:{encryptedStrOfVms} GeneratedEncryptionVirtualMachine:{encryptedStrOfGvm}");
}
if (descryptedStrOfGvm != testString)
{
throw new Exception($"GeneratedEncryptionVirtualMachine decrypt string failed! opCode:{i}, originalValue:{testString} decryptedValue:{descryptedStrOfGvm}");
}
}
return vms;
@ -223,6 +242,9 @@ namespace Obfuz
private void OnPostObfuscation(Pipeline pipeline)
{
pipeline.Stop();
_ctx.constFieldAllocator.Done();
_ctx.rvaDataAllocator.Done();
WriteAssemblies();
}
}

View File

@ -30,8 +30,8 @@ namespace Obfuz.Utils
for (int i = 0; i < encryptionLevel; i++)
{
ops *= vmOpCodeCount;
// first op code can't be 0
int op = random.NextInt(i == 0 ? 1 : 0, vmOpCodeCount);
// don't use 0
int op = random.NextInt(1, vmOpCodeCount);
ops |= (uint)op;
if (ops > uint.MaxValue)
{