接入obfuz->2.0

This commit is contained in:
Alex-Rachel
2025-07-26 08:10:41 +08:00
parent f2c7ff4336
commit cb86d8868e
713 changed files with 57092 additions and 10 deletions

View File

@@ -0,0 +1,118 @@
using dnlib.DotNet;
using dnlib.DotNet.PolymorphicWriter;
using HybridCLR.Editor;
using Obfuz;
using Obfuz.Settings;
using Obfuz.Unity;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Obfuz4HybridCLR
{
public static class ObfuscateUtil
{
public static string PackageName { get; } = "com.code-philosophy.obfuz4hybridclr";
public static string TemplatePathInPackage => $"Packages/{PackageName}/Templates~";
public static bool AreSameDirectory(string path1, string path2)
{
try
{
var dir1 = new DirectoryInfo(path1);
var dir2 = new DirectoryInfo(path2);
return dir1.FullName.TrimEnd('\\') == dir2.FullName.TrimEnd('\\');
}
catch
{
return false;
}
}
public static void ObfuscateHotUpdateAssemblies(BuildTarget target, string outputDir)
{
string hotUpdateDllPath = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
AssemblySettings assemblySettings = ObfuzSettings.Instance.assemblySettings;
ObfuscationProcess.ValidateReferences(hotUpdateDllPath, new HashSet<string>(assemblySettings.GetAssembliesToObfuscate()), new HashSet<string>(assemblySettings.GetObfuscationRelativeAssemblyNames()));
var assemblySearchPaths = new List<string>
{
hotUpdateDllPath,
};
if (AreSameDirectory(hotUpdateDllPath, outputDir))
{
throw new Exception($"hotUpdateDllPath:{hotUpdateDllPath} can't be same to outputDir:{outputDir}");
}
Obfuscate(target, assemblySearchPaths, outputDir);
foreach (string hotUpdateAssemblyName in SettingsUtil.HotUpdateAssemblyNamesExcludePreserved)
{
string srcFile = $"{hotUpdateDllPath}/{hotUpdateAssemblyName}.dll";
string dstFile = $"{outputDir}/{hotUpdateAssemblyName}.dll";
// only copy non obfuscated assemblies
if (File.Exists(srcFile) && !File.Exists(dstFile))
{
File.Copy(srcFile, dstFile, true);
Debug.Log($"[CompileAndObfuscateDll] Copy nonObfuscated assembly {srcFile} to {dstFile}");
}
}
}
public static void Obfuscate(BuildTarget target, List<string> assemblySearchPaths, string obfuscatedAssemblyOutputPath)
{
var obfuzSettings = ObfuzSettings.Instance;
var assemblySearchDirs = assemblySearchPaths;
ObfuscatorBuilder builder = ObfuscatorBuilder.FromObfuzSettings(obfuzSettings, target, true);
builder.InsertTopPriorityAssemblySearchPaths(assemblySearchDirs);
builder.CoreSettingsFacade.obfuscatedAssemblyOutputPath = obfuscatedAssemblyOutputPath;
foreach (var assemblySearchDir in builder.CoreSettingsFacade.assemblySearchPaths)
{
if (AreSameDirectory(assemblySearchDir, obfuscatedAssemblyOutputPath))
{
throw new Exception($"assemblySearchDir:{assemblySearchDir} can't be same to ObfuscatedAssemblyOutputPath:{obfuscatedAssemblyOutputPath}");
}
}
Obfuscator obfuz = builder.Build();
obfuz.Run();
}
public static void GeneratePolymorphicDll(string originalDllPath, string outputDllPath)
{
ModuleDef oldMod = ModuleDefMD.Load(originalDllPath);
var obfuzSettings = ObfuzSettings.Instance;
var opt = new NewDllModuleWriterOptions(oldMod)
{
MetadataWriter = new PolymorphicMetadataWriter(obfuzSettings.polymorphicDllSettings.codeGenerationSecretKey),
};
PolymorphicModuleWriter writer = new PolymorphicModuleWriter(oldMod, opt);
writer.Write(outputDllPath);
Debug.Log($"GeneratePolymorphicDll {originalDllPath} => {outputDllPath}");
}
public static void GeneratePolymorphicCodes(string libil2cppDir)
{
PolymorphicDllSettings settings = ObfuzSettings.Instance.polymorphicDllSettings;
if (!settings.enable)
{
UnityEngine.Debug.LogWarning("Polymorphic code generation is disabled in Obfuz settings.");
return;
}
var options = new PolymorphicCodeGenerator.Options
{
GenerationSecretKey = settings.codeGenerationSecretKey,
Libil2cppDir = libil2cppDir,
TemplateDir = ObfuscateUtil.TemplatePathInPackage,
DisableLoadStandardDll = settings.disableLoadStandardDll,
};
var generator = new PolymorphicCodeGenerator(options);
generator.Generate();
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
{
"name": "Obfuz4HybridCLR.Editor",
"rootNamespace": "",
"references": [
"GUID:2373f786d14518f44b0f475db77ba4de",
"GUID:66e09fc524ec6594b8d6ca1d91aa1a41"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3743e71edcd5bd8499007797ef02cbfb
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 52d353fb8d6d94c4aa03452a2cd9773f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using dnlib.DotNet.PolymorphicWriter;
using HybridCLR.Editor.Template;
public class PolymorphicCodeGenerator
{
public class Options
{
public string GenerationSecretKey { get; set; }
public string Libil2cppDir { get; set; }
public string TemplateDir { get; set; }
public bool DisableLoadStandardDll { get; set; } = true;
}
private readonly string _libil2cppDir;
private readonly string _metadataDir;
private readonly string _templateDir;
private readonly string _generationSecretKey;
private readonly bool _disableLoadStandardImage;
private readonly PolymorphicMetadataWriter writer;
public PolymorphicCodeGenerator(Options options)
{
_libil2cppDir = options.Libil2cppDir;
_metadataDir = Path.Combine(_libil2cppDir, "hybridclr", "metadata");
_templateDir = options.TemplateDir;
_generationSecretKey = options.GenerationSecretKey;
_disableLoadStandardImage = options.DisableLoadStandardDll;
writer = new PolymorphicMetadataWriter(_generationSecretKey);
}
private void CopyMetadataReaderHeader()
{
string srcFile = $"{_templateDir}/MetadataReader.h.tpl";
string dstFile = $"{_metadataDir}/MetadataReader.h";
File.Copy(srcFile, dstFile, true);
UnityEngine.Debug.Log($"Copy MetadataReader header from {srcFile} to {dstFile}");
}
private void GeneratePolymorphicDefs()
{
string tplFile = $"{_templateDir}/PolymorphicDefs.h.tpl";
var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8));
var lines = new List<string>();
lines.Add($"#define POLYMORPHIC_IMAGE_SIGNATURE \"{writer.ImageSignature}\"");
lines.Add($"\tconstexpr uint32_t kPolymorphicImageVersion = {writer.FormatVersion};");
lines.Add($"\tconstexpr uint32_t kFormatVariantVersion = {writer.FormatVariant};");
string codes = string.Join("\n", lines);
frr.Replace("POLYMORPHIC_DEFINES", codes);
string outputFile = $"{_metadataDir}/PolymorphicDefs.h";
frr.Commit(outputFile);
}
private void GeneratePolymorphicDatas()
{
string tplFile = $"{_templateDir}/PolymorphicDatas.h.tpl";
var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8));
List<string> lines = new List<string>();
var sb = new StringBuilder();
foreach (var type in writer.GetPolymorphicTypes())
{
var polymorphicType = writer.GetPolymorphicClassDef(type);
lines.Add($"\tstruct {type.Name}");
lines.Add("\t{");
foreach (var field in polymorphicType.Fields)
{
lines.Add($"\t\t{field.fieldWriter.CppTypeName} {field.name};");
}
lines.Add("\t\tvoid Read(MetadataReader& reader)");
lines.Add("\t\t{");
foreach (var field in polymorphicType.Fields)
{
lines.Add($"\t\t\t{field.fieldWriter.GetMarshalCode(field.name, "reader")};");
}
lines.Add("\t\t}");
lines.Add("\t};");
lines.Add("");
}
string codes = string.Join("\n", lines);
frr.Replace("POLYMORPHIC_DATA", codes);
string outputFile = $"{_metadataDir}/PolymorphicDatas.h";
frr.Commit(outputFile);
}
private void GeneratePolymorphicRawImageHeader()
{
string tplFile = $"{_templateDir}/PolymorphicRawImage.h.tpl";
var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8));
var tableMetaInfoMap = TableMetaInfos.tableMetaInfos.ToDictionary(t => "Raw" + t.csharpTypeName + "Row");
List<string> lines = new List<string>();
foreach (Type rowType in writer.GetPolymorphicTableRowTypes())
{
TableMetaInfo table = tableMetaInfoMap[rowType.Name];
lines.Add($"\t\tvirtual Tb{table.cppTypeName} Read{table.cppTypeName}(uint32_t rawIndex) override;");
}
frr.Replace("READ_TABLES_OVERRIDES", string.Join("\n", lines));
string outputFile = $"{_metadataDir}/PolymorphicRawImage.h";
frr.Commit(outputFile);
}
private void GeneratePolymorphicRawImageSource()
{
string tplFile = $"{_templateDir}/PolymorphicRawImage.cpp.tpl";
var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8));
var tableMetaInfoMap = TableMetaInfos.tableMetaInfos.ToDictionary(t => "Raw" + t.csharpTypeName + "Row");
{
List<string> lines = new List<string>();
foreach (Type rowType in writer.GetAllTableRowTypes())
{
TableMetaInfo table = tableMetaInfoMap[rowType.Name];
PolymorphicClassDef polymorphicClassDef = writer.CreateTableRowClassDefForCodeGeneration(rowType);
lines.Add("\t\t{");
lines.Add($"\t\t\tauto& table = _tableRowMetas[(int)TableType::{table.cppEnumName}];");
foreach (var fieldDef in polymorphicClassDef.Fields)
{
FieldMetaInfo field = table.fields.First(f => f.csharpName == fieldDef.name);
lines.Add($"\t\t\ttable.push_back({{{field.cppRowSize}}});");
}
lines.Add("\t\t}");
}
string codes = string.Join("\n", lines);
frr.Replace("TABLE_ROW_METADS", codes);
}
{
List<string> lines = new List<string>();
foreach (Type rowType in writer.GetPolymorphicTableRowTypes())
{
TableMetaInfo table = tableMetaInfoMap[rowType.Name];
PolymorphicClassDef polymorphicClassDef = writer.CreateTableRowClassDefForCodeGeneration(rowType);
lines.Add($"\tTb{table.cppTypeName} PolymorphicRawImage::Read{table.cppTypeName}(uint32_t rawIndex)");
lines.Add("\t{");
lines.Add($"\t\tIL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::{table.cppEnumName}).rowNum);");
lines.Add($"\t\tconst byte* rowPtr = GetTableRowPtr(TableType::{table.cppEnumName}, rawIndex);");
lines.Add($"\t\tauto& rowSchema = GetRowSchema(TableType::{table.cppEnumName});");
lines.Add($"\t\tTb{table.cppTypeName} data;");
for (int i = 0; i < polymorphicClassDef.Fields.Count; i++)
{
var fieldDef = polymorphicClassDef.Fields[i];
FieldMetaInfo field = table.fields.First(f => f.csharpName == fieldDef.name);
lines.Add($"\t\tdata.{field.cppName} = ReadColumn(rowPtr, rowSchema[{i}]);");
}
lines.Add("\t\treturn data;");
lines.Add("\t}");
}
frr.Replace("READ_TABLES_IMPLEMENTATIONS", string.Join("\n", lines));
}
string outputFile = $"{_metadataDir}/PolymorphicRawImage.cpp";
frr.Commit(outputFile);
}
private void GenerateRawImageInit()
{
string tplFile = $"{_metadataDir}/Image.cpp";
var frr = new FileRegionReplace(File.ReadAllText(tplFile, Encoding.UTF8));
{
List<string> lines = new List<string>();
lines.Add(@"#include ""PolymorphicRawImage.h""");
frr.Replace("INCLUDE_RAW_IMAGE_HEADERS", string.Join("\n", lines));
}
{
List<string> lines = new List<string>();
lines.Add("\t\tif (std::strncmp((const char*)imageData, \"CODEPHPY\", 8) == 0)");
lines.Add("\t\t{");
lines.Add("\t\t\t_rawImage = new PolymorphicRawImage();");
lines.Add("\t\t}");
lines.Add("\t\telse");
lines.Add("\t\t{");
if (_disableLoadStandardImage)
{
lines.Add("\t\t\treturn LoadImageErrorCode::UNKNOWN_IMAGE_FORMAT;");
}
else
{
lines.Add("\t\t\t_rawImage = new RawImage();");
}
lines.Add("\t\t}");
lines.Add("\t\treturn LoadImageErrorCode::OK;");
frr.Replace("INIT_RAW_IMAGE", string.Join("\n", lines));
}
frr.Commit(tplFile);
}
public void Generate()
{
CopyMetadataReaderHeader();
GeneratePolymorphicDefs();
GeneratePolymorphicDatas();
GeneratePolymorphicRawImageHeader();
GeneratePolymorphicRawImageSource();
GenerateRawImageInit();
}
}

View File

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

View File

@@ -0,0 +1,300 @@
using System.Collections.Generic;
class FieldMetaInfo {
public readonly string csharpName;
public readonly string cppName;
public readonly string cppRowSize;
public FieldMetaInfo(string csharpName, string cppName, string cppRowSize) {
this.csharpName = csharpName;
this.cppName = cppName;
this.cppRowSize = cppRowSize;
}
public FieldMetaInfo(string csharpName, string cppRowSize) : this(csharpName, csharpName.Substring(0, 1).ToLower() + csharpName.Substring(1), cppRowSize) {
}
}
class TableMetaInfo {
public readonly string csharpTypeName;
public readonly string cppTypeName;
public readonly string cppEnumName;
public readonly List<FieldMetaInfo> fields;
public TableMetaInfo(string csharpTypeName, string cppTypeName, string cppEnumName, List<FieldMetaInfo> fields) {
this.csharpTypeName = csharpTypeName;
this.cppTypeName = cppTypeName;
this.cppEnumName = cppEnumName;
this.fields = fields;
}
public TableMetaInfo(string csharpTypeName, List<FieldMetaInfo> fields) : this(csharpTypeName, csharpTypeName, csharpTypeName.ToUpper(), fields) {
}
}
class TableMetaInfos {
public static readonly List<TableMetaInfo> tableMetaInfos = new List<TableMetaInfo> {
new TableMetaInfo("Module", new List<FieldMetaInfo> {
new FieldMetaInfo("Generation", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Mvid", "ComputGUIDIndexByte()"),
new FieldMetaInfo("EncId", "ComputGUIDIndexByte()"),
new FieldMetaInfo("EncBaseId", "ComputGUIDIndexByte()"),
}),
new TableMetaInfo("TypeRef", new List<FieldMetaInfo> {
new FieldMetaInfo("ResolutionScope", "ComputTableIndexByte(TableType::MODULE, TableType::MODULEREF, TableType::ASSEMBLYREF, TableType::TYPEREF, TagBits::ResoulutionScope)"),
new FieldMetaInfo("Name", "typeName", "ComputStringIndexByte()"),
new FieldMetaInfo("Namespace", "typeNamespace", "ComputStringIndexByte()"),
}),
new TableMetaInfo("TypeDef", new List<FieldMetaInfo> {
new FieldMetaInfo("Flags", "4"),
new FieldMetaInfo("Name", "typeName", "ComputStringIndexByte()"),
new FieldMetaInfo("Namespace", "typeNamespace", "ComputStringIndexByte()"),
new FieldMetaInfo("Extends", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"),
new FieldMetaInfo("FieldList", "ComputTableIndexByte(TableType::FIELD)"),
new FieldMetaInfo("MethodList", "ComputTableIndexByte(TableType::METHOD)"),
}),
new TableMetaInfo("FieldPtr", new List<FieldMetaInfo> {
new FieldMetaInfo("Field", "ComputTableIndexByte(TableType::FIELD)"),
}),
new TableMetaInfo("Field", new List<FieldMetaInfo> {
new FieldMetaInfo("Flags", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Signature", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("MethodPtr", new List<FieldMetaInfo> {
new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD)"),
}),
new TableMetaInfo("Method", new List<FieldMetaInfo> {
new FieldMetaInfo("RVA", "rva", "4"),
new FieldMetaInfo("ImplFlags", "2"),
new FieldMetaInfo("Flags", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Signature", "ComputBlobIndexByte()"),
new FieldMetaInfo("ParamList", "ComputTableIndexByte(TableType::PARAM)"),
}),
new TableMetaInfo("ParamPtr", new List<FieldMetaInfo> {
new FieldMetaInfo("Param", "ComputTableIndexByte(TableType::PARAM)"),
}),
new TableMetaInfo("Param", new List<FieldMetaInfo> {
new FieldMetaInfo("Flags", "2"),
new FieldMetaInfo("Sequence", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
}),
new TableMetaInfo("InterfaceImpl", new List<FieldMetaInfo> {
new FieldMetaInfo("Class", "classIdx", "ComputTableIndexByte(TableType::TYPEDEF)"),
new FieldMetaInfo("Interface", "interfaceIdx", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"),
}),
new TableMetaInfo("MemberRef", new List<FieldMetaInfo> {
new FieldMetaInfo("Class", "classIdx", "ComputTableIndexByte(TableType::METHOD, TableType::MODULEREF, TableType::TYPEDEF, TableType::TYPEREF, TagBits::MemberRefParent)"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Signature", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("Constant", new List<FieldMetaInfo> {
new FieldMetaInfo("Type", "1"),
new FieldMetaInfo("Padding", "1"),
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::PARAM, TableType::FIELD, TableType::PROPERTY, TagBits::HasConstant)"),
new FieldMetaInfo("Value", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("CustomAttribute", new List<FieldMetaInfo> {
new FieldMetaInfo("Parent", "ComputTableIndexByte(HasCustomAttributeAssociateTables, sizeof(HasCustomAttributeAssociateTables) / sizeof(TableType), TagBits::HasCustomAttribute)"),
new FieldMetaInfo("Type", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::CustomAttributeType)"),
new FieldMetaInfo("Value", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("FieldMarshal", new List<FieldMetaInfo> {
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::FIELD, TableType::PARAM, TagBits::HasFieldMarshal)"),
new FieldMetaInfo("NativeType", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("DeclSecurity", new List<FieldMetaInfo> {
new FieldMetaInfo("Action", "2"),
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TableType::ASSEMBLY, TagBits::HasDeclSecurity)"),
new FieldMetaInfo("PermissionSet", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("ClassLayout", new List<FieldMetaInfo> {
new FieldMetaInfo("PackingSize", "2"),
new FieldMetaInfo("ClassSize", "4"),
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF)"),
}),
new TableMetaInfo("FieldLayout", new List<FieldMetaInfo> {
new FieldMetaInfo("OffSet", "offset", "4"),
new FieldMetaInfo("Field", "ComputTableIndexByte(TableType::FIELD)"),
}),
new TableMetaInfo("StandAloneSig", new List<FieldMetaInfo> {
new FieldMetaInfo("Signature", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("EventMap", new List<FieldMetaInfo> {
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF)"),
new FieldMetaInfo("EventList", "ComputTableIndexByte(TableType::EVENT)"),
}),
new TableMetaInfo("EventPtr", new List<FieldMetaInfo> {
new FieldMetaInfo("Event", "ComputTableIndexByte(TableType::EVENT)"),
}),
new TableMetaInfo("Event", new List<FieldMetaInfo> {
new FieldMetaInfo("EventFlags", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("EventType", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"),
}),
new TableMetaInfo("PropertyMap", new List<FieldMetaInfo> {
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::TYPEDEF)"),
new FieldMetaInfo("PropertyList", "ComputTableIndexByte(TableType::PROPERTY)"),
}),
new TableMetaInfo("PropertyPtr", new List<FieldMetaInfo> {
new FieldMetaInfo("Property", "ComputTableIndexByte(TableType::PROPERTY)"),
}),
new TableMetaInfo("Property", new List<FieldMetaInfo> {
new FieldMetaInfo("PropFlags", "flags", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Type", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("MethodSemantics", new List<FieldMetaInfo> {
new FieldMetaInfo("Semantic", "semantics", "2"),
new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD)"),
new FieldMetaInfo("Association", "ComputTableIndexByte(TableType::EVENT, TableType::PROPERTY, TagBits::HasSemantics)"),
}),
new TableMetaInfo("MethodImpl", new List<FieldMetaInfo> {
new FieldMetaInfo("Class", "classIdx", "ComputTableIndexByte(TableType::TYPEDEF)"),
new FieldMetaInfo("MethodBody", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)"),
new FieldMetaInfo("MethodDeclaration", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)"),
}),
new TableMetaInfo("ModuleRef", new List<FieldMetaInfo> {
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
}),
new TableMetaInfo("TypeSpec", new List<FieldMetaInfo> {
new FieldMetaInfo("Signature", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("ImplMap", new List<FieldMetaInfo> {
new FieldMetaInfo("MappingFlags", "2"),
new FieldMetaInfo("MemberForwarded", "ComputTableIndexByte(TableType::FIELD, TableType::METHOD, TagBits::MemberForwarded)"),
new FieldMetaInfo("ImportName", "ComputStringIndexByte()"),
new FieldMetaInfo("ImportScope", "ComputTableIndexByte(TableType::MODULEREF)"),
}),
new TableMetaInfo("FieldRVA", new List<FieldMetaInfo> {
new FieldMetaInfo("RVA", "rva", "4"),
new FieldMetaInfo("Field", "ComputTableIndexByte(TableType::FIELD)"),
}),
new TableMetaInfo("ENCLog","EncLog", "ENCLOG", new List<FieldMetaInfo> {
new FieldMetaInfo("Token", "4"),
new FieldMetaInfo("FuncCode", "4"),
}),
new TableMetaInfo("ENCMap", "EncMap", "ENCMAP", new List<FieldMetaInfo> {
new FieldMetaInfo("Token", "4"),
}),
new TableMetaInfo("Assembly", new List<FieldMetaInfo> {
new FieldMetaInfo("HashAlgId", "4"),
new FieldMetaInfo("MajorVersion", "2"),
new FieldMetaInfo("MinorVersion", "2"),
new FieldMetaInfo("BuildNumber", "2"),
new FieldMetaInfo("RevisionNumber", "2"),
new FieldMetaInfo("Flags", "4"),
new FieldMetaInfo("PublicKey", "ComputBlobIndexByte()"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Locale", "ComputStringIndexByte()"),
}),
new TableMetaInfo("AssemblyProcessor", new List<FieldMetaInfo> {
new FieldMetaInfo("Processor", "4"),
}),
new TableMetaInfo("AssemblyOS", new List<FieldMetaInfo> {
new FieldMetaInfo("OSPlatformId", "osPlatformId", "4"),
new FieldMetaInfo("OSMajorVersion", "osMajorVersion", "4"),
new FieldMetaInfo("OSMinorVersion", "osMinorVersion", "4"),
}),
new TableMetaInfo("AssemblyRef", new List<FieldMetaInfo> {
new FieldMetaInfo("MajorVersion", "2"),
new FieldMetaInfo("MinorVersion", "2"),
new FieldMetaInfo("BuildNumber", "2"),
new FieldMetaInfo("RevisionNumber", "2"),
new FieldMetaInfo("Flags", "4"),
new FieldMetaInfo("PublicKeyOrToken", "ComputBlobIndexByte()"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Locale", "ComputStringIndexByte()"),
new FieldMetaInfo("HashValue", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("AssemblyRefProcessor", new List<FieldMetaInfo> {
new FieldMetaInfo("AssemblyRef", "4"),
new FieldMetaInfo("Processor", "ComputTableIndexByte(TableType::ASSEMBLYREF)"),
}),
new TableMetaInfo("AssemblyRefOS", new List<FieldMetaInfo> {
new FieldMetaInfo("OSPlatformId", "osPlatformId", "4"),
new FieldMetaInfo("OSMajorVersion", "osMajorVersion", "4"),
new FieldMetaInfo("OSMinorVersion", "osMinorVersion", "4"),
new FieldMetaInfo("AssemblyRef", "ComputTableIndexByte(TableType::ASSEMBLYREF)"),
}),
new TableMetaInfo("File", new List<FieldMetaInfo> {
new FieldMetaInfo("Flags", "4"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("HashValue", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("ExportedType", new List<FieldMetaInfo> {
new FieldMetaInfo("Flags", "4"),
new FieldMetaInfo("TypeDefId", "4"),
new FieldMetaInfo("TypeName", "ComputStringIndexByte()"),
new FieldMetaInfo("TypeNamespace", "ComputStringIndexByte()"),
new FieldMetaInfo("Implementation", "ComputTableIndexByte(TableType::FILE, TableType::EXPORTEDTYPE, TableType::ASSEMBLY, TagBits::Implementation)"),
}),
new TableMetaInfo("ManifestResource", new List<FieldMetaInfo> {
new FieldMetaInfo("Offset", "4"),
new FieldMetaInfo("Flags", "4"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Implementation", "ComputTableIndexByte(TableType::FILE, TableType::ASSEMBLYREF, TagBits::Implementation)"),
}),
new TableMetaInfo("NestedClass", new List<FieldMetaInfo> {
new FieldMetaInfo("NestedClass", "ComputTableIndexByte(TableType::TYPEDEF)"),
new FieldMetaInfo("EnclosingClass", "ComputTableIndexByte(TableType::TYPEDEF)"),
}),
new TableMetaInfo("GenericParam", new List<FieldMetaInfo> {
new FieldMetaInfo("Number", "2"),
new FieldMetaInfo("Flags", "2"),
new FieldMetaInfo("Owner", "ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TagBits::TypeOrMethodDef)"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
}),
new TableMetaInfo("MethodSpec", new List<FieldMetaInfo> {
new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)"),
new FieldMetaInfo("Instantiation", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("GenericParamConstraint", new List<FieldMetaInfo> {
new FieldMetaInfo("Owner", "ComputTableIndexByte(TableType::GENERICPARAM)"),
new FieldMetaInfo("Constraint", "ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)"),
}),
new TableMetaInfo("Document", new List<FieldMetaInfo> {
new FieldMetaInfo("Name", "ComputBlobIndexByte()"),
new FieldMetaInfo("HashAlgorithm", "ComputGUIDIndexByte()"),
new FieldMetaInfo("Hash", "ComputBlobIndexByte()"),
new FieldMetaInfo("Language", "ComputGUIDIndexByte()"),
}),
new TableMetaInfo("MethodDebugInformation", new List<FieldMetaInfo> {
new FieldMetaInfo("Document", "ComputTableIndexByte(TableType::DOCUMENT)"),
new FieldMetaInfo("SequencePoints", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("LocalScope", new List<FieldMetaInfo> {
new FieldMetaInfo("Method", "ComputTableIndexByte(TableType::METHOD)"),
new FieldMetaInfo("ImportScope", "ComputTableIndexByte(TableType::IMPORTSCOPE)"),
new FieldMetaInfo("VariableList", "variables", "ComputTableIndexByte(TableType::LOCALVARIABLE)"),
new FieldMetaInfo("ConstantList", "constants", "ComputTableIndexByte(TableType::LOCALCONSTANT)"),
new FieldMetaInfo("StartOffset", "4"),
new FieldMetaInfo("Length", "4"),
}),
new TableMetaInfo("LocalVariable", new List<FieldMetaInfo> {
new FieldMetaInfo("Attributes", "2"),
new FieldMetaInfo("Index", "2"),
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
}),
new TableMetaInfo("LocalConstant", new List<FieldMetaInfo> {
new FieldMetaInfo("Name", "ComputStringIndexByte()"),
new FieldMetaInfo("Signature", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("ImportScope", new List<FieldMetaInfo> {
new FieldMetaInfo("Parent", "ComputTableIndexByte(TableType::IMPORTSCOPE)"),
new FieldMetaInfo("Imports", "ComputBlobIndexByte()"),
}),
new TableMetaInfo("StateMachineMethod", new List<FieldMetaInfo> {
new FieldMetaInfo("MoveNextMethod", "ComputTableIndexByte(TableType::METHOD)"),
new FieldMetaInfo("KickoffMethod", "ComputTableIndexByte(TableType::METHOD)"),
}),
new TableMetaInfo("CustomDebugInformation", new List<FieldMetaInfo> {
new FieldMetaInfo("Parent", "ComputTableIndexByte(HasCustomDebugInformation, sizeof(HasCustomDebugInformation) / sizeof(TableType), TagBits::HasCustomDebugInformation)"),
new FieldMetaInfo("Kind", "ComputGUIDIndexByte()"),
new FieldMetaInfo("Value", "ComputBlobIndexByte()"),
}),
};
}

View File

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

View File

@@ -0,0 +1,164 @@
using HybridCLR.Editor.Commands;
using HybridCLR.Editor;
using Obfuz.Settings;
using Obfuz;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.Reflection;
using System;
using System.IO;
using HybridCLR.Editor.Link;
using HybridCLR.Editor.Meta;
using UnityEditor.Build;
using HybridCLR.Editor.Installer;
using HybridCLR.Editor.MethodBridge;
using System.Linq;
using Analyzer = HybridCLR.Editor.MethodBridge.Analyzer;
using HybridCLR.Editor.Settings;
using Obfuz.Utils;
using FileUtil = Obfuz.Utils.FileUtil;
using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver;
using CombinedAssemblyResolver = HybridCLR.Editor.Meta.CombinedAssemblyResolver;
using MetaUtil = HybridCLR.Editor.Meta.MetaUtil;
using AssemblyCache = HybridCLR.Editor.Meta.AssemblyCache;
using HybridCLR.Editor.AOT;
using Analyzer2 = HybridCLR.Editor.AOT.Analyzer;
namespace Obfuz4HybridCLR
{
public static class PrebuildCommandExt
{
public static string GetObfuscatedHotUpdateAssemblyOutputPath(BuildTarget target)
{
return $"{ObfuzSettings.Instance.ObfuzRootDir}/{target}/ObfuscatedHotUpdateAssemblies";
}
[MenuItem("HybridCLR/ObfuzExtension/GenerateAll")]
public static void GenerateAll()
{
var installer = new InstallerController();
if (!installer.HasInstalledHybridCLR())
{
throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'");
}
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
Il2CppDefGeneratorCommand.GenerateIl2CppDef();
GeneratePolymorphicCodesWhenEnable();
LinkGeneratorCommand.GenerateLinkXml(target);
StripAOTDllCommand.GenerateStripedAOTDlls(target);
string obfuscatedHotUpdateDllPath = GetObfuscatedHotUpdateAssemblyOutputPath(target);
ObfuscateUtil.ObfuscateHotUpdateAssemblies(target, obfuscatedHotUpdateDllPath);
GenerateMethodBridgeAndReversePInvokeWrapper(target, obfuscatedHotUpdateDllPath);
GenerateAOTGenericReference(target, obfuscatedHotUpdateDllPath);
}
[MenuItem("HybridCLR/ObfuzExtension/CompileAndObfuscateDll")]
public static void CompileAndObfuscateDll()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
string obfuscatedHotUpdateDllPath = GetObfuscatedHotUpdateAssemblyOutputPath(target);
ObfuscateUtil.ObfuscateHotUpdateAssemblies(target, obfuscatedHotUpdateDllPath);
}
[MenuItem("HybridCLR/ObfuzExtension/GeneratePolymorphicCodes")]
public static void GeneratePolymorphicCodes()
{
ObfuscateUtil.GeneratePolymorphicCodes($"{SettingsUtil.LocalIl2CppDir}/libil2cpp");
}
private static void GeneratePolymorphicCodesWhenEnable()
{
PolymorphicDllSettings settings = ObfuzSettings.Instance.polymorphicDllSettings;
if (!settings.enable)
{
UnityEngine.Debug.LogWarning("Polymorphic code generation is disabled.");
return;
}
GeneratePolymorphicCodes();
}
public static IAssemblyResolver CreateObfuscatedHotUpdateAssemblyResolver(BuildTarget target, List<string> obfuscatedHotUpdateAssemblies, string obfuscatedHotUpdateDllPath)
{
return new FixedSetAssemblyResolver(obfuscatedHotUpdateDllPath, obfuscatedHotUpdateAssemblies);
}
public static IAssemblyResolver CreateObfuscatedHotUpdateAndAOTAssemblyResolver(BuildTarget target, List<string> hotUpdateAssemblies, List<string> assembliesToObfuscate, string obfuscatedHotUpdateDllPath)
{
return new CombinedAssemblyResolver(
CreateObfuscatedHotUpdateAssemblyResolver(target, hotUpdateAssemblies.Intersect(assembliesToObfuscate).ToList(), obfuscatedHotUpdateDllPath),
MetaUtil.CreateHotUpdateAssemblyResolver(target, hotUpdateAssemblies.Except(assembliesToObfuscate).ToList()),
MetaUtil.CreateAOTAssemblyResolver(target)
);
}
public static void GenerateMethodBridgeAndReversePInvokeWrapper(BuildTarget target, string obfuscatedHotUpdateDllPath)
{
string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ?
Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList()
: new List<string>();
if (aotAssemblyNames.Count == 0)
{
throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/MethodBridge`");
}
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames);
var methodBridgeAnalyzer = new Analyzer(new Analyzer.Options
{
MaxIterationCount = Math.Min(20, SettingsUtil.HybridCLRSettings.maxMethodBridgeGenericIteration),
Collector = collector,
});
methodBridgeAnalyzer.Run();
List<string> hotUpdateDlls = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
var cache = new AssemblyCache(CreateObfuscatedHotUpdateAndAOTAssemblyResolver(target, hotUpdateDlls, ObfuzSettings.Instance.assemblySettings.GetAssembliesToObfuscate(), obfuscatedHotUpdateDllPath));
var reversePInvokeAnalyzer = new MonoPInvokeCallbackAnalyzer(cache, hotUpdateDlls);
reversePInvokeAnalyzer.Run();
var calliAnalyzer = new CalliAnalyzer(cache, hotUpdateDlls);
calliAnalyzer.Run();
var pinvokeAnalyzer = new PInvokeAnalyzer(cache, hotUpdateDlls);
pinvokeAnalyzer.Run();
var callPInvokeMethodSignatures = pinvokeAnalyzer.PInvokeMethodSignatures;
string templateFile = $"{SettingsUtil.TemplatePathInPackage}/MethodBridge.cpp.tpl";
string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp";
var callNativeMethodSignatures = calliAnalyzer.CalliMethodSignatures.Concat(pinvokeAnalyzer.PInvokeMethodSignatures).ToList();
var generateMethodBridgeMethod = typeof(MethodBridgeGeneratorCommand).GetMethod("GenerateMethodBridgeCppFile", BindingFlags.NonPublic | BindingFlags.Static);
generateMethodBridgeMethod.Invoke(null, new object[] { methodBridgeAnalyzer.GenericMethods, reversePInvokeAnalyzer.ReversePInvokeMethods, callNativeMethodSignatures, templateFile, outputFile });
MethodBridgeGeneratorCommand.CleanIl2CppBuildCache();
}
public static void GenerateAOTGenericReference(BuildTarget target, string obfuscatedHotUpdateDllPath)
{
var gs = SettingsUtil.HybridCLRSettings;
List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(
CreateObfuscatedHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames, ObfuzSettings.Instance.assemblySettings.GetAssembliesToObfuscate(), obfuscatedHotUpdateDllPath), hotUpdateDllNames);
var analyzer = new Analyzer2(new Analyzer2.Options
{
MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration),
Collector = collector,
});
analyzer.Run();
var writer = new GenericReferenceWriter();
writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}");
AssetDatabase.Refresh();
}
}
}

View File

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