feature: 支持代码水印
parent
4db68f707b
commit
1e027e6299
|
@ -17,6 +17,7 @@ namespace Obfuz.ObfusPasses
|
||||||
EvalStackObfus = 0x1000,
|
EvalStackObfus = 0x1000,
|
||||||
|
|
||||||
RemoveConstField = 0x100000,
|
RemoveConstField = 0x100000,
|
||||||
|
WaterMark = 0x200000,
|
||||||
|
|
||||||
AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus | EvalStackObfus,
|
AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus | EvalStackObfus,
|
||||||
AllEncrypt = ConstEncrypt | FieldEncrypt,
|
AllEncrypt = ConstEncrypt | FieldEncrypt,
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8b381c6b90aae174a994bd6f2ae6464f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,112 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using dnlib.DotNet.PolymorphicWriter.Utilities;
|
||||||
|
using Obfuz.Settings;
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEngine;
|
||||||
|
using FieldAttributes = dnlib.DotNet.FieldAttributes;
|
||||||
|
using KeyGenerator = Obfuz.Utils.KeyGenerator;
|
||||||
|
using TypeAttributes = dnlib.DotNet.TypeAttributes;
|
||||||
|
|
||||||
|
namespace Obfuz.ObfusPasses.Watermark
|
||||||
|
{
|
||||||
|
public class WatermarkPass : ObfuscationPassBase
|
||||||
|
{
|
||||||
|
private readonly WatermarkSettingsFacade _watermarkSettings;
|
||||||
|
|
||||||
|
public WatermarkPass(WatermarkSettingsFacade watermarkSettingsFacade)
|
||||||
|
{
|
||||||
|
this._watermarkSettings = watermarkSettingsFacade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.WaterMark;
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Process()
|
||||||
|
{
|
||||||
|
var ctx = ObfuscationPassContext.Current;
|
||||||
|
foreach (ModuleDef mod in ctx.modulesToObfuscate)
|
||||||
|
{
|
||||||
|
AddWaterMarkToAssembly(mod, _watermarkSettings.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeDef GetDataHolderType(ModuleDef module, TypeDef declaringType, int size)
|
||||||
|
{
|
||||||
|
|
||||||
|
using (var scope = new DisableTypeDefFindCacheScope(module))
|
||||||
|
{
|
||||||
|
var dataHolderType = new TypeDefUser($"$Obfuz$WatermarkDataHolderSize{size}_{declaringType.NestedTypes.Count}", module.Import(typeof(System.ValueType)));
|
||||||
|
dataHolderType.Attributes = TypeAttributes.NestedPrivate | TypeAttributes.Sealed;
|
||||||
|
dataHolderType.Layout = TypeAttributes.ExplicitLayout;
|
||||||
|
dataHolderType.PackingSize = 1;
|
||||||
|
dataHolderType.ClassSize = (uint)size;
|
||||||
|
dataHolderType.DeclaringType = declaringType;
|
||||||
|
return dataHolderType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddWaterMarkToAssembly(ModuleDef module, string waterMarkText)
|
||||||
|
{
|
||||||
|
string finalWatermarkText = $"{waterMarkText} [{module.Name}]";
|
||||||
|
TypeDef moduleType = module.FindNormal("<PrivateImplementationDetails>");
|
||||||
|
if (moduleType == null)
|
||||||
|
{
|
||||||
|
//throw new Exception($"Module '{module.Name}' does not contain a '<PrivateImplementationDetails>' type.");
|
||||||
|
moduleType = new TypeDefUser("<PrivateImplementationDetails>", module.Import(typeof(object)));
|
||||||
|
moduleType.Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed;
|
||||||
|
moduleType.CustomAttributes.Add(new CustomAttribute(module.Import(module.Import(typeof(CompilerGeneratedAttribute)).ResolveTypeDefThrow().FindDefaultConstructor())));
|
||||||
|
module.Types.Add(moduleType);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ctx = ObfuscationPassContext.Current;
|
||||||
|
EncryptionScopeInfo encryptionScope = ctx.moduleEntityManager.EncryptionScopeProvider.GetScope(module);
|
||||||
|
var random = encryptionScope.localRandomCreator(0);
|
||||||
|
byte[] watermarkBytes = KeyGenerator.GenerateKey(finalWatermarkText, _watermarkSettings.signatureLength);
|
||||||
|
for (int subIndex = 0; subIndex < watermarkBytes.Length;)
|
||||||
|
{
|
||||||
|
int subSegmentLength = Math.Min(random.NextInt(16, 32) & ~3, watermarkBytes.Length - subIndex);
|
||||||
|
int paddingLength = random.NextInt(8, 32) & ~3;
|
||||||
|
int totalLength = subSegmentLength + paddingLength;
|
||||||
|
TypeDef dataHolderType = GetDataHolderType(module, moduleType, totalLength);
|
||||||
|
|
||||||
|
byte[] subSegment = new byte[totalLength];
|
||||||
|
Buffer.BlockCopy(watermarkBytes, subIndex, subSegment, 0, subSegmentLength);
|
||||||
|
|
||||||
|
for (int i = subSegmentLength; i < totalLength; i++)
|
||||||
|
{
|
||||||
|
subSegment[i] = (byte)random.NextInt(0, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
subIndex += subSegmentLength;
|
||||||
|
var field = new FieldDefUser($"$Obfuz$WatermarkDataHolderField{moduleType.Fields.Count}",
|
||||||
|
new FieldSig(dataHolderType.ToTypeSig()),
|
||||||
|
FieldAttributes.Assembly | FieldAttributes.InitOnly | FieldAttributes.Static | FieldAttributes.HasFieldRVA);
|
||||||
|
field.DeclaringType = moduleType;
|
||||||
|
field.InitialValue = subSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
var moduleTypeFields = moduleType.Fields.ToList();
|
||||||
|
RandomUtil.ShuffleList(moduleTypeFields, random);
|
||||||
|
moduleType.Fields.Clear();
|
||||||
|
foreach (var field in moduleTypeFields)
|
||||||
|
{
|
||||||
|
moduleType.Fields.Add(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 20c95bc217949f344909cc7049d6046e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -8,6 +8,7 @@ using Obfuz.ObfusPasses.ExprObfus;
|
||||||
using Obfuz.ObfusPasses.FieldEncrypt;
|
using Obfuz.ObfusPasses.FieldEncrypt;
|
||||||
using Obfuz.ObfusPasses.RemoveConstField;
|
using Obfuz.ObfusPasses.RemoveConstField;
|
||||||
using Obfuz.ObfusPasses.SymbolObfus;
|
using Obfuz.ObfusPasses.SymbolObfus;
|
||||||
|
using Obfuz.ObfusPasses.Watermark;
|
||||||
using Obfuz.Settings;
|
using Obfuz.Settings;
|
||||||
using Obfuz.Utils;
|
using Obfuz.Utils;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -202,6 +203,10 @@ namespace Obfuz
|
||||||
{
|
{
|
||||||
builder.AddPass(new ControlFlowObfusPass(settings.controlFlowObfusSettings.ToFacade()));
|
builder.AddPass(new ControlFlowObfusPass(settings.controlFlowObfusSettings.ToFacade()));
|
||||||
}
|
}
|
||||||
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.WaterMark))
|
||||||
|
{
|
||||||
|
builder.AddPass(new WatermarkPass(settings.watermarkSettings.ToFacade()));
|
||||||
|
}
|
||||||
if (obfuscationPasses.HasFlag(ObfuscationPassType.SymbolObfus))
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.SymbolObfus))
|
||||||
{
|
{
|
||||||
builder.AddPass(new SymbolObfusPass(settings.symbolObfusSettings.ToFacade()));
|
builder.AddPass(new SymbolObfusPass(settings.symbolObfusSettings.ToFacade()));
|
||||||
|
|
|
@ -50,6 +50,9 @@ namespace Obfuz.Settings
|
||||||
[Tooltip("garbage code generator settings")]
|
[Tooltip("garbage code generator settings")]
|
||||||
public GarbageCodeGenerationSettings garbageCodeGenerationSettings;
|
public GarbageCodeGenerationSettings garbageCodeGenerationSettings;
|
||||||
|
|
||||||
|
[Tooltip("watermark settings")]
|
||||||
|
public WatermarkSettings watermarkSettings;
|
||||||
|
|
||||||
[Tooltip("polymorphic dll settings")]
|
[Tooltip("polymorphic dll settings")]
|
||||||
public PolymorphicDllSettings polymorphicDllSettings;
|
public PolymorphicDllSettings polymorphicDllSettings;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace Obfuz.Settings
|
||||||
private SerializedProperty _controlFlowObfusSettings;
|
private SerializedProperty _controlFlowObfusSettings;
|
||||||
|
|
||||||
private SerializedProperty _garbageCodeGenerationSettings;
|
private SerializedProperty _garbageCodeGenerationSettings;
|
||||||
|
private SerializedProperty _watermarkSettings;
|
||||||
|
|
||||||
private SerializedProperty _polymorphicDllSettings;
|
private SerializedProperty _polymorphicDllSettings;
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ namespace Obfuz.Settings
|
||||||
_controlFlowObfusSettings = _serializedObject.FindProperty("controlFlowObfusSettings");
|
_controlFlowObfusSettings = _serializedObject.FindProperty("controlFlowObfusSettings");
|
||||||
|
|
||||||
_garbageCodeGenerationSettings = _serializedObject.FindProperty("garbageCodeGenerationSettings");
|
_garbageCodeGenerationSettings = _serializedObject.FindProperty("garbageCodeGenerationSettings");
|
||||||
|
_watermarkSettings = _serializedObject.FindProperty("watermarkSettings");
|
||||||
|
|
||||||
_polymorphicDllSettings = _serializedObject.FindProperty("polymorphicDllSettings");
|
_polymorphicDllSettings = _serializedObject.FindProperty("polymorphicDllSettings");
|
||||||
}
|
}
|
||||||
|
@ -113,6 +115,7 @@ namespace Obfuz.Settings
|
||||||
EditorGUILayout.PropertyField(_controlFlowObfusSettings);
|
EditorGUILayout.PropertyField(_controlFlowObfusSettings);
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_garbageCodeGenerationSettings);
|
EditorGUILayout.PropertyField(_garbageCodeGenerationSettings);
|
||||||
|
EditorGUILayout.PropertyField(_watermarkSettings);
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_polymorphicDllSettings);
|
EditorGUILayout.PropertyField(_polymorphicDllSettings);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Obfuz.Settings
|
||||||
|
{
|
||||||
|
public class WatermarkSettingsFacade
|
||||||
|
{
|
||||||
|
public string text;
|
||||||
|
|
||||||
|
public int signatureLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class WatermarkSettings
|
||||||
|
{
|
||||||
|
[Tooltip("Watermark text")]
|
||||||
|
public string text = "Obfuscated by Obfuz";
|
||||||
|
|
||||||
|
[Tooltip("Length of the signature in bytes")]
|
||||||
|
public int signatureLength = 256;
|
||||||
|
|
||||||
|
public WatermarkSettingsFacade ToFacade()
|
||||||
|
{
|
||||||
|
return new WatermarkSettingsFacade
|
||||||
|
{
|
||||||
|
text = text,
|
||||||
|
signatureLength = signatureLength
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 52885711cad0a9541ab5987b98cdcce5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue