添加ConfigGarbageCodeGenerator

dev
walon 2025-06-28 13:10:37 +08:00
parent 9d46b5438a
commit af8477f4b3
6 changed files with 212 additions and 139 deletions

View File

@ -52,7 +52,6 @@ namespace Obfuz.EncryptionVM
File.WriteAllText(outputFile, code, Encoding.UTF8);
Debug.Log($"Generate EncryptionVM code to {outputFile}");
UnityEditor.AssetDatabase.Refresh();
}
private string GenerateCode()

View File

@ -4,135 +4,14 @@ using Obfuz.Settings;
using Obfuz.Utils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Obfuz.GarbageCodeGeneration
{
public abstract class SpecificGarbageCodeGeneratorBase : ISpecificGarbageCodeGenerator
{
protected interface IClassGenerationInfo
{
string Namespace { get; set; }
string Name { get; set; }
IList<object> Fields { get; set; }
IList<object> Methods { get; set; }
}
protected class ClassGenerationInfo : IClassGenerationInfo
{
public string Namespace { get; set; }
public string Name { get; set; }
public IList<object> Fields { get; set; } = new List<object>();
public IList<object> Methods { get; set; } = new List<object>();
}
public virtual void Generate(GenerationParameters parameters)
{
FileUtil.RecreateDir(parameters.outputPath);
for (int i = 0; i < parameters.classCount; i++)
{
Debug.Log($"[{GetType().Name}] Generating class {i}");
var localRandom = new RandomWithKey(((RandomWithKey)parameters.random).Key, parameters.random.NextInt());
string outputFile = $"{parameters.outputPath}/__GeneratedGarbageClass_{i}.cs";
var result = new StringBuilder(64 * 1024);
GenerateClass(i, localRandom, result, parameters);
File.WriteAllText(outputFile, result.ToString(), Encoding.UTF8);
Debug.Log($"[{GetType().Name}] Generated class {i} to {outputFile}");
}
}
protected virtual void GenerateClass(int classIndex, IRandom random, StringBuilder result, GenerationParameters parameters)
{
IClassGenerationInfo cgi = CreateClassGenerationInfo(parameters.classNamespace, $"{parameters.classNamePrefix}{classIndex}", random, parameters);
result.AppendLine("using System;");
result.AppendLine("using System.Collections.Generic;");
result.AppendLine("using System.Linq;");
result.AppendLine("using System.IO;");
result.AppendLine("using UnityEngine;");
GenerateUsings(result, cgi);
result.AppendLine($"namespace {cgi.Namespace}");
result.AppendLine("{");
result.AppendLine($" public class {cgi.Name}");
result.AppendLine(" {");
string indent = " ";
foreach (object field in cgi.Fields)
{
GenerateField(result, cgi, field, indent);
}
foreach (object method in cgi.Methods)
{
GenerateMethod(result, cgi, method, indent);
}
result.AppendLine(" }");
result.AppendLine("}");
}
protected abstract IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters);
protected abstract void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi);
protected abstract void GenerateField(StringBuilder result, IClassGenerationInfo cgi, object field, string indent);
protected abstract void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, object method, string indent);
}
public class ConfigGarbageCodeGenerator : SpecificGarbageCodeGeneratorBase
{
class FieldGenerationInfo
{
public int index;
public string name;
public string type;
}
class MethodGenerationInfo
{
public int index;
public string name;
}
protected override IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters)
{
var cgi = new ClassGenerationInfo
{
Namespace = classNamespace,
Name = className,
};
for (int i = 0; i < parameters.fieldCountPerClass; i++)
{
var fieldInfo = new FieldGenerationInfo
{
index = i,
name = $"x{i}",
type = CreateRandomType(random),
};
cgi.Fields.Add(fieldInfo);
}
for (int i = 0; i < parameters.methodCountPerClass; i++)
{
var methodInfo = new MethodGenerationInfo
{
index = i,
name = $"Load{i}",
};
cgi.Methods.Add(methodInfo);
}
return cgi;
}
private readonly string[] _types = new string[]
{
@ -150,17 +29,6 @@ namespace Obfuz.GarbageCodeGeneration
return _types[random.NextInt(_types.Length)];
}
protected override void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi)
{
}
protected override void GenerateField(StringBuilder result, IClassGenerationInfo cgi, object field, string indent)
{
var fgi = (FieldGenerationInfo)field;
result.AppendLine($"{indent}public {fgi.type} {fgi.name};");
}
private string GetReadMethodNameOfType(string type)
{
switch (type)
@ -175,16 +43,76 @@ namespace Obfuz.GarbageCodeGeneration
default: throw new ArgumentException($"Unsupported type: {type}");
}
}
protected override void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, object method, string indent)
class FieldGenerationInfo
{
result.AppendLine($"{indent}void Load(BinaryReader reader)");
public int index;
public string name;
public string type;
}
class MethodGenerationInfo
{
public int index;
public string name;
}
protected override object CreateField(int index, IRandom random, GenerationParameters parameters)
{
return new FieldGenerationInfo
{
index = index,
name = $"x{index}",
type = CreateRandomType(random),
};
}
protected override object CreateMethod(int index, IRandom random, GenerationParameters parameters)
{
return new MethodGenerationInfo
{
index = index,
name = $"Load{index}",
};
}
protected override void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi)
{
}
protected override void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent)
{
var fgi = (FieldGenerationInfo)field;
result.AppendLine($"{indent}public {fgi.type} {fgi.name};");
}
protected override void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent)
{
var mgi = (MethodGenerationInfo)method;
result.AppendLine($"{indent}public void {mgi.name}(BinaryReader reader)");
result.AppendLine($"{indent}{{");
string indent2 = indent + " ";
foreach (FieldGenerationInfo fgi in cgi.Fields)
result.AppendLine($"{indent2}int a = 0;");
result.AppendLine($"{indent2}int b = 0;");
int maxN = 100;
var shuffledFields = cgi.Fields.ToList();
RandomUtil.ShuffleList(shuffledFields, random);
foreach (FieldGenerationInfo fgi in shuffledFields)
{
result.AppendLine($"{indent2}this.{fgi.name} = reader.{GetReadMethodNameOfType(fgi.type)}();");
if (random.NextInPercentage(0.5f))
{
result.AppendLine($"{indent2}a = b * {random.NextInt(maxN)} + reader.ReadInt32();");
result.AppendLine($"{indent2}b = a * reader.ReadInt32() + {random.NextInt(maxN)};");
}
if (random.NextInPercentage(0.5f))
{
result.AppendLine($"{indent2}a += {random.NextInt(0, 10000)};");
}
if (random.NextInPercentage(0.5f))
{
result.AppendLine($"{indent2}b += {random.NextInt(0, 10000)};");
}
}
result.AppendLine($"{indent}}}");

View File

@ -37,6 +37,22 @@ namespace Obfuz.GarbageCodeGeneration
}
}
public void CleanCodes()
{
Debug.Log($"Cleaning generated garbage codes begin.");
if (_settings.defaultTask != null)
{
FileUtil.RemoveDir(_settings.defaultTask.outputPath, true);
}
if (_settings.additionalTasks != null && _settings.additionalTasks.Length > 0)
{
foreach (var task in _settings.additionalTasks)
{
FileUtil.RemoveDir(task.outputPath, true);
}
}
}
private void GenerateTask(GarbageCodeGenerationTask task)
{
Debug.Log($"Generating garbage code with seed: {task.codeGenerationRandomSeed}, class count: {task.classCount}, method count per class: {task.methodCountPerClass}, types: {task.garbageCodeTypes}, output path: {task.outputPath}");

View File

@ -0,0 +1,106 @@
using Obfuz.Utils;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
namespace Obfuz.GarbageCodeGeneration
{
public abstract class SpecificGarbageCodeGeneratorBase : ISpecificGarbageCodeGenerator
{
protected interface IClassGenerationInfo
{
string Namespace { get; set; }
string Name { get; set; }
IList<object> Fields { get; set; }
IList<object> Methods { get; set; }
}
protected class ClassGenerationInfo : IClassGenerationInfo
{
public string Namespace { get; set; }
public string Name { get; set; }
public IList<object> Fields { get; set; } = new List<object>();
public IList<object> Methods { get; set; } = new List<object>();
}
public virtual void Generate(GenerationParameters parameters)
{
FileUtil.RecreateDir(parameters.outputPath);
for (int i = 0; i < parameters.classCount; i++)
{
Debug.Log($"[{GetType().Name}] Generating class {i}");
var localRandom = new RandomWithKey(((RandomWithKey)parameters.random).Key, parameters.random.NextInt());
string outputFile = $"{parameters.outputPath}/__GeneratedGarbageClass_{i}.cs";
var result = new StringBuilder(64 * 1024);
GenerateClass(i, localRandom, result, parameters);
File.WriteAllText(outputFile, result.ToString(), Encoding.UTF8);
Debug.Log($"[{GetType().Name}] Generated class {i} to {outputFile}");
}
}
protected abstract object CreateField(int index, IRandom random, GenerationParameters parameters);
protected abstract object CreateMethod(int index, IRandom random, GenerationParameters parameters);
protected virtual IClassGenerationInfo CreateClassGenerationInfo(string classNamespace, string className, IRandom random, GenerationParameters parameters)
{
var cgi = new ClassGenerationInfo
{
Namespace = classNamespace,
Name = className,
};
for (int i = 0; i < parameters.fieldCountPerClass; i++)
{
cgi.Fields.Add(CreateField(i, random, parameters));
}
for (int i = 0; i < parameters.methodCountPerClass; i++)
{
cgi.Methods.Add(CreateMethod(i, random, parameters));
}
return cgi;
}
protected virtual void GenerateClass(int classIndex, IRandom random, StringBuilder result, GenerationParameters parameters)
{
IClassGenerationInfo cgi = CreateClassGenerationInfo(parameters.classNamespace, $"{parameters.classNamePrefix}{classIndex}", random, parameters);
result.AppendLine("using System;");
result.AppendLine("using System.Collections.Generic;");
result.AppendLine("using System.Linq;");
result.AppendLine("using System.IO;");
result.AppendLine("using UnityEngine;");
GenerateUsings(result, cgi);
result.AppendLine($"namespace {cgi.Namespace}");
result.AppendLine("{");
result.AppendLine($" public class {cgi.Name}");
result.AppendLine(" {");
string indent = " ";
foreach (object field in cgi.Fields)
{
GenerateField(result, cgi, random, field, indent);
}
foreach (object method in cgi.Methods)
{
GenerateMethod(result, cgi, random, method, indent);
}
result.AppendLine(" }");
result.AppendLine("}");
}
protected abstract void GenerateUsings(StringBuilder result, IClassGenerationInfo cgi);
protected abstract void GenerateField(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object field, string indent);
protected abstract void GenerateMethod(StringBuilder result, IClassGenerationInfo cgi, IRandom random, object method, string indent);
}
}

View File

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

View File

@ -21,6 +21,7 @@ namespace Obfuz.Unity
EncryptionVMSettings settings = ObfuzSettings.Instance.encryptionVMSettings;
var generator = new VirtualMachineCodeGenerator(settings.codeGenerationSecretKey, settings.encryptionOpCodeCount);
generator.Generate(settings.codeOutputPath);
AssetDatabase.Refresh();
}
[MenuItem("Obfuz/GenerateSecretKeyFile", priority = 63)]
@ -37,16 +38,28 @@ namespace Obfuz.Unity
AssetDatabase.Refresh();
}
[MenuItem("Obfuz/GenerateGarbageCodes", priority = 100)]
[MenuItem("Obfuz/GarbageCode/GenerateCodes", priority = 100)]
public static void GenerateGarbageCodes()
{
Debug.Log($"Generating garbage codes begin.");
GarbageCodeGeneratorSettings settings = ObfuzSettings.Instance.garbageCodeGeneratorSettings;
var generator = new GarbageCodeGenerator(settings);
generator.Generate();
AssetDatabase.Refresh();
Debug.Log($"Generating garbage codes end.");
}
[MenuItem("Obfuz/GarbageCode/CleanGeneratedCodes", priority = 101)]
public static void CleanGeneratedGarbageCodes()
{
Debug.Log($"Clean generated garbage codes begin.");
GarbageCodeGeneratorSettings settings = ObfuzSettings.Instance.garbageCodeGeneratorSettings;
var generator = new GarbageCodeGenerator(settings);
generator.CleanCodes();
AssetDatabase.Refresh();
Debug.Log($"Clean generated garbage codes end.");
}
private static void SaveKey(byte[] secret, string secretOutputPath)
{
FileUtil.CreateParentDir(secretOutputPath);