常量加密支持array(byte[],int[],float[],int[,]等等)
parent
28ac98352d
commit
a6863b5089
|
@ -31,6 +31,8 @@ namespace Obfuz.Emit
|
||||||
private IMethod _decryptFromRvaString;
|
private IMethod _decryptFromRvaString;
|
||||||
private IMethod _decryptFromRvaBytes;
|
private IMethod _decryptFromRvaBytes;
|
||||||
|
|
||||||
|
private IMethod _decryptInitializeArray;
|
||||||
|
|
||||||
public IMethod EncryptBlock => _encryptBlock;
|
public IMethod EncryptBlock => _encryptBlock;
|
||||||
public IMethod DecryptBlock => _decryptBlock;
|
public IMethod DecryptBlock => _decryptBlock;
|
||||||
|
|
||||||
|
@ -54,6 +56,8 @@ namespace Obfuz.Emit
|
||||||
public IMethod DecryptFromRvaBytes => _decryptFromRvaBytes;
|
public IMethod DecryptFromRvaBytes => _decryptFromRvaBytes;
|
||||||
public IMethod DecryptFromRvaString => _decryptFromRvaString;
|
public IMethod DecryptFromRvaString => _decryptFromRvaString;
|
||||||
|
|
||||||
|
public IMethod DecryptInitializeArray => _decryptInitializeArray;
|
||||||
|
|
||||||
public EncryptionServiceMetadataImporter(ModuleDef mod, Type encryptionServiceType)
|
public EncryptionServiceMetadataImporter(ModuleDef mod, Type encryptionServiceType)
|
||||||
{
|
{
|
||||||
_module = mod;
|
_module = mod;
|
||||||
|
@ -99,6 +103,8 @@ namespace Obfuz.Emit
|
||||||
Assert.IsNotNull(_decryptFromRvaBytes);
|
Assert.IsNotNull(_decryptFromRvaBytes);
|
||||||
_decryptFromRvaString = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaString", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) }));
|
_decryptFromRvaString = mod.Import(encryptionServiceType.GetMethod("DecryptFromRvaString", new[] { typeof(byte[]), typeof(int), typeof(int), typeof(int), typeof(int) }));
|
||||||
Assert.IsNotNull(_decryptFromRvaString);
|
Assert.IsNotNull(_decryptFromRvaString);
|
||||||
|
_decryptInitializeArray = mod.Import(encryptionServiceType.GetMethod("DecryptInitializeArray", new[] { typeof(System.Array), typeof(System.RuntimeFieldHandle), typeof(int), typeof(int), typeof(int) }));
|
||||||
|
Assert.IsNotNull(_decryptInitializeArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,5 +200,6 @@ namespace Obfuz.Emit
|
||||||
public IMethod DecryptFromRvaBytes => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaBytes;
|
public IMethod DecryptFromRvaBytes => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaBytes;
|
||||||
public IMethod DecryptFromRvaString => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaString;
|
public IMethod DecryptFromRvaString => _defaultEncryptionServiceMetadataImporter.DecryptFromRvaString;
|
||||||
|
|
||||||
|
public IMethod DecryptInitializeArray => _defaultEncryptionServiceMetadataImporter.DecryptInitializeArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
using dnlib.DotNet.Emit;
|
using dnlib.DotNet.Emit;
|
||||||
using Obfuz.Emit;
|
using Obfuz.Emit;
|
||||||
using Obfuz.Settings;
|
using Obfuz.Settings;
|
||||||
|
using Obfuz.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
using UnityEngine.Assertions;
|
using UnityEngine.Assertions;
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.ConstEncrypt
|
namespace Obfuz.ObfusPasses.ConstEncrypt
|
||||||
|
@ -113,34 +115,27 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
|
||||||
}
|
}
|
||||||
case Code.Call:
|
case Code.Call:
|
||||||
{
|
{
|
||||||
//if (((IMethod)inst.Operand).FullName == "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
|
if (((IMethod)inst.Operand).FullName == "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
|
||||||
//{
|
{
|
||||||
// Instruction prevInst = globalInstructions[instructionIndex - 1];
|
Instruction prevInst = globalInstructions[instructionIndex - 1];
|
||||||
// if (prevInst.OpCode.Code == Code.Ldtoken)
|
if (prevInst.OpCode.Code == Code.Ldtoken)
|
||||||
// {
|
{
|
||||||
// IField rvaField = (IField)prevInst.Operand;
|
IField rvaField = (IField)prevInst.Operand;
|
||||||
// FieldDef ravFieldDef = rvaField.ResolveFieldDefThrow();
|
FieldDef ravFieldDef = rvaField.ResolveFieldDefThrow();
|
||||||
// byte[] data = ravFieldDef.InitialValue;
|
if (ravFieldDef.Module != method.Module)
|
||||||
// if (data != null && _dataObfuscatorPolicy.NeedObfuscateArray(method, currentInLoop, data))
|
{
|
||||||
// {
|
return false;
|
||||||
// if (_encryptedRvaFields.Add(ravFieldDef))
|
}
|
||||||
// {
|
byte[] data = ravFieldDef.InitialValue;
|
||||||
|
if (data != null && data.Length > 0 && _dataObfuscatorPolicy.NeedObfuscateArray(method, currentInLoop, data))
|
||||||
// }
|
{
|
||||||
|
// don't need cache for byte array obfuscation
|
||||||
// // remove prev ldtoken instruction
|
needCache = false;
|
||||||
// Assert.AreEqual(Code.Ldtoken, totalFinalInstructions.Last().OpCode.Code);
|
_dataObfuscator.ObfuscateBytes(method, needCache, ravFieldDef, data, outputInstructions);
|
||||||
// //totalFinalInstructions.RemoveAt(totalFinalInstructions.Count - 1);
|
return true;
|
||||||
// // dup arr argument for decryption operation
|
}
|
||||||
// totalFinalInstructions.Insert(totalFinalInstructions.Count - 1, Instruction.Create(OpCodes.Dup));
|
}
|
||||||
// totalFinalInstructions.Add(inst.Clone());
|
}
|
||||||
// //bool needCache = currentInLoop ? constCachePolicy.cacheStringInLoop : constCachePolicy.cacheStringNotInLoop;
|
|
||||||
// bool needCache = false;
|
|
||||||
// _dataObfuscator.ObfuscateBytes(method, needCache, data, outputInstructions);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
default: return false;
|
default: return false;
|
||||||
|
|
|
@ -8,6 +8,7 @@ using System.Collections.Generic;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Obfuz.Settings;
|
using Obfuz.Settings;
|
||||||
|
using UnityEngine.Assertions.Must;
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.ConstEncrypt
|
namespace Obfuz.ObfusPasses.ConstEncrypt
|
||||||
{
|
{
|
||||||
|
@ -144,30 +145,60 @@ namespace Obfuz.ObfusPasses.ConstEncrypt
|
||||||
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaDouble));
|
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaDouble));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ObfuscateBytes(MethodDef method, bool needCacheValue, byte[] value, List<Instruction> obfuscatedInstructions)
|
|
||||||
|
class EncryptedRvaDataInfo
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("ObfuscateBytes is not supported yet.");
|
public readonly FieldDef fieldDef;
|
||||||
//if (needCacheValue)
|
public readonly byte[] originalBytes;
|
||||||
//{
|
public readonly byte[] encryptedBytes;
|
||||||
// FieldDef cacheField = _constFieldAllocator.Allocate(method.Module, value);
|
public readonly int opts;
|
||||||
// obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, cacheField));
|
public readonly int salt;
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//int ops = GenerateEncryptionOperations();
|
public EncryptedRvaDataInfo(FieldDef fieldDef, byte[] originalBytes, byte[] encryptedBytes, int opts, int salt)
|
||||||
//int salt = GenerateSalt();
|
{
|
||||||
//byte[] encryptedValue = _encryptor.Encrypt(value, 0, value.Length, ops, salt);
|
this.fieldDef = fieldDef;
|
||||||
//Assert.IsTrue(encryptedValue.Length % 4 == 0);
|
this.originalBytes = originalBytes;
|
||||||
//RvaData rvaData = _rvaDataAllocator.Allocate(method.Module, encryptedValue);
|
this.encryptedBytes = encryptedBytes;
|
||||||
|
this.opts = opts;
|
||||||
|
this.salt = salt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
|
private readonly Dictionary<FieldDef, EncryptedRvaDataInfo> _encryptedRvaFields = new Dictionary<FieldDef, EncryptedRvaDataInfo>();
|
||||||
//obfuscatedInstructions.Add(Instruction.Create(OpCodes.Ldsfld, rvaData.field));
|
|
||||||
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(rvaData.offset));
|
private EncryptedRvaDataInfo GetEncryptedRvaData(FieldDef fieldDef)
|
||||||
//// 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));
|
if (!_encryptedRvaFields.TryGetValue(fieldDef, out var encryptedRvaData))
|
||||||
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(ops));
|
{
|
||||||
//obfuscatedInstructions.Add(Instruction.CreateLdcI4(salt));
|
EncryptionScopeInfo encryptionScope = _encryptionScopeProvider.GetScope(fieldDef.Module);
|
||||||
//obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptFromRvaBytes));
|
IRandom random = CreateRandomForValue(encryptionScope, FieldEqualityComparer.CompareDeclaringTypes.GetHashCode(fieldDef));
|
||||||
|
int ops = GenerateEncryptionOperations(encryptionScope, random);
|
||||||
|
int salt = GenerateSalt(random);
|
||||||
|
byte[] originalBytes = fieldDef.InitialValue;
|
||||||
|
byte[] encryptedBytes = (byte[])originalBytes.Clone();
|
||||||
|
encryptionScope.encryptor.EncryptBlock(encryptedBytes, ops, salt);
|
||||||
|
Assert.AreNotEqual(originalBytes, encryptedBytes, "Original bytes should not be the same as encrypted bytes.");
|
||||||
|
encryptedRvaData = new EncryptedRvaDataInfo(fieldDef, originalBytes, encryptedBytes, ops, salt);
|
||||||
|
_encryptedRvaFields.Add(fieldDef, encryptedRvaData);
|
||||||
|
fieldDef.InitialValue = encryptedBytes;
|
||||||
|
byte[] decryptedBytes = (byte[])encryptedBytes.Clone();
|
||||||
|
encryptionScope.encryptor.DecryptBlock(decryptedBytes, ops, salt);
|
||||||
|
Assert.AreEqual(originalBytes, decryptedBytes, "Decrypted bytes should match the original bytes after encryption and decryption.");
|
||||||
|
}
|
||||||
|
return encryptedRvaData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void ObfuscateBytes(MethodDef method, bool needCacheValue, FieldDef field, byte[] value, List<Instruction> obfuscatedInstructions)
|
||||||
|
{
|
||||||
|
EncryptedRvaDataInfo encryptedData = GetEncryptedRvaData(field);
|
||||||
|
Assert.AreEqual(value.Length, encryptedData.encryptedBytes.Length);
|
||||||
|
|
||||||
|
DefaultMetadataImporter importer = GetModuleMetadataImporter(method);
|
||||||
|
obfuscatedInstructions.Add(Instruction.CreateLdcI4(encryptedData.encryptedBytes.Length));
|
||||||
|
obfuscatedInstructions.Add(Instruction.CreateLdcI4(encryptedData.opts));
|
||||||
|
obfuscatedInstructions.Add(Instruction.CreateLdcI4(encryptedData.salt));
|
||||||
|
obfuscatedInstructions.Add(Instruction.Create(OpCodes.Call, importer.DecryptInitializeArray));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ObfuscateString(MethodDef method, bool needCacheValue, string value, List<Instruction> obfuscatedInstructions)
|
public void ObfuscateString(MethodDef method, bool needCacheValue, string value, List<Instruction> obfuscatedInstructions)
|
||||||
|
|
|
@ -17,7 +17,7 @@ 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, FieldDef field, byte[] value, List<Instruction> obfuscatedInstructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ConstEncryptorBase : IConstEncryptor
|
public abstract class ConstEncryptorBase : IConstEncryptor
|
||||||
|
@ -28,5 +28,6 @@ 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 ObfuscateBytes(MethodDef method, bool needCacheValue, FieldDef field, byte[] value, List<Instruction> obfuscatedInstructions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,8 @@ namespace Obfuz.Settings
|
||||||
obfuscatedNamePrefix = obfuscatedNamePrefix,
|
obfuscatedNamePrefix = obfuscatedNamePrefix,
|
||||||
useConsistentNamespaceObfuscation = useConsistentNamespaceObfuscation,
|
useConsistentNamespaceObfuscation = useConsistentNamespaceObfuscation,
|
||||||
symbolMappingFile = symbolMappingFile,
|
symbolMappingFile = symbolMappingFile,
|
||||||
ruleFiles = ruleFiles.ToList(),
|
ruleFiles = ruleFiles?.ToList() ?? new List<string>(),
|
||||||
customRenamePolicyTypes = customRenamePolicyTypes.Select(typeName => ReflectionUtil.FindUniqueTypeInCurrentAppDomain(typeName)).ToList(),
|
customRenamePolicyTypes = customRenamePolicyTypes?.Select(typeName => ReflectionUtil.FindUniqueTypeInCurrentAppDomain(typeName)).ToList() ?? new List<Type>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,19 @@ namespace Obfuz.Unity
|
||||||
return GenerateAdditionalLinkXmlFile(data.target);
|
return GenerateAdditionalLinkXmlFile(data.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !UNITY_2021_2_OR_NEWER
|
||||||
|
|
||||||
|
public void OnBeforeRun(BuildReport report, UnityLinkerBuildPipelineData data)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnAfterRun(BuildReport report, UnityLinkerBuildPipelineData data)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static string GenerateAdditionalLinkXmlFile(BuildTarget target)
|
public static string GenerateAdditionalLinkXmlFile(BuildTarget target)
|
||||||
{
|
{
|
||||||
ObfuzSettings settings = ObfuzSettings.Instance;
|
ObfuzSettings settings = ObfuzSettings.Instance;
|
||||||
|
|
|
@ -122,5 +122,10 @@ namespace Obfuz
|
||||||
{
|
{
|
||||||
return Decrypt(data, offset, bytesLength, ops, salt);
|
return Decrypt(data, offset, bytesLength, ops, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void DecryptInitializeArray(System.Array arr, System.RuntimeFieldHandle field, int length, int ops, int salt)
|
||||||
|
{
|
||||||
|
_encryptor.DecryptInitializeArray(arr, field, length, ops, salt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Unity.Collections.LowLevel.Unsafe;
|
using Unity.Collections.LowLevel.Unsafe;
|
||||||
using UnityEngine.Assertions;
|
using UnityEngine.Assertions;
|
||||||
|
@ -247,24 +249,116 @@ namespace Obfuz
|
||||||
|
|
||||||
public virtual unsafe void DecryptBlock(byte[] data, int ops, int salt)
|
public virtual unsafe void DecryptBlock(byte[] data, int ops, int salt)
|
||||||
{
|
{
|
||||||
int length = data.Length;
|
fixed(byte* dataPtr = &data[0])
|
||||||
|
{
|
||||||
|
DecryptBlock(dataPtr, data.Length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe void DecryptBlock(byte* data, int length, int ops, int salt)
|
||||||
|
{
|
||||||
int intArrLength = length >> 2;
|
int intArrLength = length >> 2;
|
||||||
|
|
||||||
fixed (byte* dstBytePtr = &data[0])
|
int* dstIntPtr = (int*)data;
|
||||||
|
int last = 0;
|
||||||
|
for (int i = 0; i < intArrLength; i++)
|
||||||
{
|
{
|
||||||
int* dstIntPtr = (int*)dstBytePtr;
|
int oldLast = last;
|
||||||
int last = 0;
|
last = dstIntPtr[i];
|
||||||
for (int i = 0; i < intArrLength; i++)
|
dstIntPtr[i] = Decrypt(oldLast ^ last, ops, salt);
|
||||||
{
|
|
||||||
int oldLast = last;
|
|
||||||
last = dstIntPtr[i];
|
|
||||||
dstIntPtr[i] = Decrypt(oldLast ^ last, ops, salt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int i = intArrLength * 4; i < length; i++)
|
for (int i = intArrLength * 4; i < length; i++)
|
||||||
{
|
{
|
||||||
data[i] = (byte)(data[i] ^ salt);
|
data[i] = (byte)(data[i] ^ salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual unsafe void DecryptInitializeArray(System.Array arr, System.RuntimeFieldHandle field, int length, int ops, int salt)
|
||||||
|
{
|
||||||
|
//Assert.AreEqual(Marshal.SizeOf(arr.GetType().GetElementType()), arr.Length);
|
||||||
|
RuntimeHelpers.InitializeArray(arr, field);
|
||||||
|
if (arr is byte[] byteArr)
|
||||||
|
{
|
||||||
|
fixed (byte* dataPtr = &byteArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock(dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is int[] intArr)
|
||||||
|
{
|
||||||
|
fixed (int* dataPtr = &intArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is long[] longArr)
|
||||||
|
{
|
||||||
|
fixed (long* dataPtr = &longArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is sbyte[] sbyteArr)
|
||||||
|
{
|
||||||
|
fixed (sbyte* dataPtr = &sbyteArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is short[] shortArr)
|
||||||
|
{
|
||||||
|
fixed (short* dataPtr = &shortArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is ushort[] ushortArr)
|
||||||
|
{
|
||||||
|
fixed (ushort* dataPtr = &ushortArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is uint[] uintArr)
|
||||||
|
{
|
||||||
|
fixed (uint* dataPtr = &uintArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is ulong[] ulongArr)
|
||||||
|
{
|
||||||
|
fixed (ulong* dataPtr = &ulongArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is float[] floatArr)
|
||||||
|
{
|
||||||
|
fixed (float* dataPtr = &floatArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arr is double[] doubleArr)
|
||||||
|
{
|
||||||
|
fixed (double* dataPtr = &doubleArr[0])
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
void* dataPtr = UnsafeUtility.PinGCArrayAndGetDataAddress(arr, out ulong handle);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DecryptBlock((byte*)dataPtr, length, ops, salt);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
UnsafeUtility.ReleaseGCObject(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,5 +28,7 @@ namespace Obfuz
|
||||||
|
|
||||||
byte[] Encrypt(string value, int ops, int salt);
|
byte[] Encrypt(string value, int ops, int salt);
|
||||||
string DecryptString(byte[] value, int offset, int stringBytesLength, int ops, int salt);
|
string DecryptString(byte[] value, int offset, int stringBytesLength, int ops, int salt);
|
||||||
|
|
||||||
|
void DecryptInitializeArray(System.Array arr, System.RuntimeFieldHandle field, int length, int ops, int salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue