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

View File

@ -69,6 +69,7 @@ namespace Obfuz.Data
private TypeDef _rvaTypeDef; private TypeDef _rvaTypeDef;
private readonly Dictionary<int, TypeDef> _dataHolderTypeBySizes = new Dictionary<int, TypeDef>(); private readonly Dictionary<int, TypeDef> _dataHolderTypeBySizes = new Dictionary<int, TypeDef>();
private bool _done;
public ModuleRvaDataAllocator(IRandom random, IEncryptor encryptor, GroupByModuleEntityManager moduleEntityManager) 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; 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; runtimeValueField.DeclaringType = _rvaTypeDef;
return (holderField, runtimeValueField); return (holderField, runtimeValueField);
} }
@ -145,6 +146,10 @@ namespace Obfuz.Data
private RvaField GetRvaField(int preservedSize, int alignment) private RvaField GetRvaField(int preservedSize, int alignment)
{ {
if (_done)
{
throw new Exception("can't GetRvaField after done");
}
Assert.IsTrue(preservedSize % alignment == 0); Assert.IsTrue(preservedSize % alignment == 0);
// for big size, create a new field // for big size, create a new field
if (preservedSize >= maxRvaDataSize) if (preservedSize >= maxRvaDataSize)
@ -279,6 +284,11 @@ namespace Obfuz.Data
public void Done() public void Done()
{ {
if (_done)
{
throw new Exception("can't call Done twice");
}
_done = true;
SetFieldsRVA(); SetFieldsRVA();
CreateCCtorOfRvaTypeDef(); CreateCCtorOfRvaTypeDef();
} }

View File

@ -152,12 +152,21 @@ namespace Obfuz.EncryptionVM
public override int Encrypt(int value, int opts, int salt) public override int Encrypt(int value, int opts, int salt)
{ {
int revertOps = 0;
while (opts > 0) while (opts > 0)
{ {
int opCode = opts & kOpCodeMask; int opCode = opts & kOpCodeMask;
value = ExecuteEncrypt(value, opCode, salt); revertOps <<= kOpCodeBits;
revertOps |= opCode;
opts >>= kOpCodeBits; opts >>= kOpCodeBits;
} }
while (revertOps > 0)
{
int opCode = revertOps & kOpCodeMask;
value = ExecuteEncrypt(value, opCode, salt);
revertOps >>= kOpCodeBits;
}
return value; 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) while (ops > 0)
{ {
var code = (ushort)(ops % _opCodes.Length); uint code = ops % (uint)_opCodes.Length;
codes.Add(code); codes.Add(code);
ops >>= 16; ops /= (uint)_opCodes.Length;
} }
return codes; return codes;
} }
public override int Encrypt(int value, int ops, int salt) public override int Encrypt(int value, int ops, int salt)
{ {
var codes = DecodeOps(ops); var codes = DecodeOps((uint)ops);
foreach (var code in codes) for (int i = codes.Count - 1; i >= 0; i--)
{ {
var opCode = _opCodes[code]; var opCode = _opCodes[codes[i]];
value = opCode.Encrypt(value, _secretKey, salt); value = opCode.Encrypt(value, _secretKey, salt);
} }
return value; return value;
@ -82,10 +82,10 @@ namespace Obfuz.EncryptionVM
public override int Decrypt(int value, int ops, int salt) public override int Decrypt(int value, int ops, int salt)
{ {
var codes = DecodeOps(ops); var codes = DecodeOps((uint)ops);
for (int i = codes.Count - 1; i >= 0; i--) foreach (var code in codes)
{ {
var opCode = _opCodes[codes[i]]; var opCode = _opCodes[code];
value = opCode.Decrypt(value, _secretKey, salt); value = opCode.Decrypt(value, _secretKey, salt);
} }
return value; return value;

View File

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

View File

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

View File

@ -196,8 +196,6 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
public void Done() 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 ObfuscateString(MethodDef method, bool needCacheValue, string value, List<Instruction> obfuscatedInstructions);
void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List<Instruction> obfuscatedInstructions); void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List<Instruction> obfuscatedInstructions);
void Done();
} }
public abstract class ConstEncryptorBase : IConstEncryptor 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 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 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 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) public override bool NeedRename(TypeDef typeDef)
{ {
string name = typeDef.Name; string name = typeDef.Name;
if (name == "<Module>") if (name == "<Module>" || name == "ObfuzIgnoreAttribute")
{ {
return false; return false;
} }

View File

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

View File

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