接入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,8 @@
fileFormatVersion: 2
guid: 067341936b8cb2242be3bdc83f3ca3cd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

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:

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Code Philosophy(代码哲学)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3036602f815e31341b4445f0e331b58e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,2 @@
# obfuz4hybridclr
obfuz4hybridclr is a obfuz extension for HybridCLR.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3ab25e7bb5a8e7d4fb3ba4614f2e3822
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
#pragma once
#include "MetadataUtil.h"
namespace hybridclr
{
namespace metadata
{
struct ByteSpan
{
const byte* data;
uint32_t length;
ByteSpan() : data(nullptr), length(0) {}
ByteSpan(const byte* data, uint32_t length) : data(data), length(length) {}
};
class MetadataReader
{
private:
const byte* _data;
public:
MetadataReader(const byte* data) : _data(data) {}
int16_t ReadInt16()
{
int16_t value = GetI2LittleEndian(_data);
_data += 2;
return value;
}
bool ReadBool()
{
return *(_data++) != 0;
}
uint8_t ReadUInt8()
{
return *(_data++);
}
uint16_t ReadUInt16()
{
uint16_t value = GetU2LittleEndian(_data);
_data += 2;
return value;
}
int32_t ReadInt32()
{
int32_t value = GetI4LittleEndian(_data);
_data += 4;
return value;
}
uint32_t ReadUInt32()
{
uint32_t value = GetU4LittleEndian(_data);
_data += 4;
return value;
}
int64_t ReadInt64()
{
int64_t value = GetI8LittleEndian(_data);
_data += 8;
return value;
}
uint64_t ReadUInt64()
{
uint64_t value = GetU8LittleEndian(_data);
_data += 8;
return value;
}
const byte* ReadFixedBytes(int32_t byteCount)
{
const byte* value = _data;
_data += byteCount;
return value;
}
ByteSpan ReadBytes()
{
uint32_t byteCount = ReadUInt32();
const byte* buffer = _data;
_data += byteCount;
return ByteSpan(buffer, byteCount);
}
const byte* CurrentDataPtr() const
{
return _data;
}
};
}
}

View File

@@ -0,0 +1,88 @@
#pragma once
#include "MetadataReader.h"
namespace hybridclr
{
namespace metadata
{
//!!!{{POLYMORPHIC_DATA
struct HeaderBaseData
{
uint32_t metadataSize;
uint32_t sectionCount;
const byte* dummyData;
uint32_t metadataRva;
uint32_t entryPointToken;
void Read(MetadataReader& reader)
{
metadataSize = reader.ReadUInt32();
sectionCount = reader.ReadUInt32();
dummyData = reader.ReadFixedBytes(8);
metadataRva = reader.ReadUInt32();
entryPointToken = reader.ReadUInt32();
}
};
struct SectionData
{
uint32_t rva;
uint32_t fileOffset;
uint32_t virtualSize;
uint32_t fileLength;
void Read(MetadataReader& reader)
{
rva = reader.ReadUInt32();
fileOffset = reader.ReadUInt32();
virtualSize = reader.ReadUInt32();
fileLength = reader.ReadUInt32();
}
};
struct MetadataHeaderBaseData
{
uint32_t signature;
uint8_t reserved2;
ByteSpan versionString;
uint16_t majorVersion;
uint16_t heapsCount;
uint32_t reserved1;
uint8_t storageFlags;
uint16_t minorVersion;
void Read(MetadataReader& reader)
{
signature = reader.ReadUInt32();
reserved2 = reader.ReadUInt8();
versionString = reader.ReadBytes();
majorVersion = reader.ReadUInt16();
heapsCount = reader.ReadUInt16();
reserved1 = reader.ReadUInt32();
storageFlags = reader.ReadUInt8();
minorVersion = reader.ReadUInt16();
}
};
struct TablesHeapHeaderBaseData
{
uint64_t validMask;
uint32_t reserved1;
uint8_t streamFlags;
uint8_t majorVersion;
uint64_t sortedMask;
uint8_t minorVersion;
uint8_t log2Rid;
void Read(MetadataReader& reader)
{
validMask = reader.ReadUInt64();
reserved1 = reader.ReadUInt32();
streamFlags = reader.ReadUInt8();
majorVersion = reader.ReadUInt8();
sortedMask = reader.ReadUInt64();
minorVersion = reader.ReadUInt8();
log2Rid = reader.ReadUInt8();
}
};
//!!!}}POLYMORPHIC_DATA
}
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include "MetadataReader.h"
namespace hybridclr
{
namespace metadata
{
//!!!{{POLYMORPHIC_DEFINES
#define POLYMORPHIC_IMAGE_SIGNATURE "CODEPHPY"
constexpr uint32_t kPolymorphicImageVersion = 1;
constexpr uint32_t kFormatVariantVersion = 0;
//!!!}}POLYMORPHIC_DEFINES
struct PolymorphicImageHeaderData
{
const byte* signature;
uint32_t formatVersion;
uint32_t formatVariant;
void Read(MetadataReader& reader)
{
signature = reader.ReadFixedBytes(8);
formatVersion = reader.ReadUInt32();
formatVariant = reader.ReadUInt32();
}
};
}
}

View File

@@ -0,0 +1,897 @@
#include "PolymorphicRawImage.h"
#include <memory>
#include "PolymorphicDefs.h"
#include "PolymorphicDatas.h"
namespace hybridclr
{
namespace metadata
{
struct RawSectionHeader
{
uint32_t fileOffset;
uint32_t fileLength;
uint32_t rva;
uint32_t virtualSize;
};
LoadImageErrorCode PolymorphicRawImage::LoadCLIHeader(uint32_t& entryPointToken, uint32_t& metadataRva, uint32_t& metadataSize)
{
if (_imageLength < 0x100)
{
return LoadImageErrorCode::BAD_IMAGE;
}
MetadataReader reader(_imageData);
PolymorphicImageHeaderData imageHeaderData = {};
imageHeaderData.Read(reader);
const char* sig = (const char*)_imageData;
if (std::strncmp((const char*)imageHeaderData.signature, POLYMORPHIC_IMAGE_SIGNATURE, sizeof(POLYMORPHIC_IMAGE_SIGNATURE) - 1))
{
return LoadImageErrorCode::BAD_IMAGE;
}
if (imageHeaderData.formatVersion != kPolymorphicImageVersion)
{
return LoadImageErrorCode::UNSUPPORT_FORMAT_VERSION;
}
if (imageHeaderData.formatVariant != kFormatVariantVersion)
{
return LoadImageErrorCode::UNMATCH_FORMAT_VARIANT;
}
//reader.ReadFixedBytes(polymorphic::kImageHeaderDummyDataSize); // Skip dummy data
PolymorphicHeaderBaseData headerBaseData = {};
headerBaseData.Read(reader);
const size_t kEntryPointTokenOffset = 16;
entryPointToken = headerBaseData.entryPointToken;
metadataRva = headerBaseData.metadataRva;
metadataSize = headerBaseData.metadataSize;
uint32_t sectionCount = headerBaseData.sectionCount;
for (uint32_t i = 0; i < sectionCount; i++)
{
PolymorphicSectionData sectionData = {};
sectionData.Read(reader);
_sections.push_back({ sectionData.rva, sectionData.rva + sectionData.virtualSize, sectionData.fileOffset - sectionData.rva });
}
return LoadImageErrorCode::OK;
}
LoadImageErrorCode PolymorphicRawImage::LoadStreamHeaders(uint32_t metadataRva, uint32_t metadataSize)
{
uint32_t metaOffset;
if (!TranslateRVAToImageOffset(metadataRva, metaOffset))
{
return LoadImageErrorCode::BAD_IMAGE;
}
if (metaOffset >= _imageLength)
{
return LoadImageErrorCode::BAD_IMAGE;
}
const byte* ptrMetaData = _imageData + metaOffset;
MetadataReader reader(ptrMetaData);
PolymorphicMetadataHeaderBaseData metadataHeader = {};
metadataHeader.Read(reader);
if (metadataHeader.signature != 0x424A5342)
{
return LoadImageErrorCode::BAD_IMAGE;
}
uint16_t numStreamHeader = metadataHeader.heapsCount;
const StreamHeader* ptrStreamHeaders = (const StreamHeader*)(reader.CurrentDataPtr());
const StreamHeader* curSH = ptrStreamHeaders;
const size_t maxStreamNameSize = 16;
for (int i = 0; i < numStreamHeader; i++)
{
//std::cout << "name:" << (char*)curSH->name << ", offset:" << curSH->offset << ", size:" << curSH->size << std::endl;
if (curSH->offset >= metadataSize)
{
return LoadImageErrorCode::BAD_IMAGE;
}
CliStream* rs = nullptr;
CliStream nonStandardStream;
CliStream pdbStream;
if (!std::strncmp(curSH->name, "#~", maxStreamNameSize))
{
rs = &_streamTables;
}
else if (!std::strncmp(curSH->name, "#Strings", maxStreamNameSize))
{
rs = &_streamStringHeap;
}
else if (!std::strncmp(curSH->name, "#US", maxStreamNameSize))
{
rs = &_streamUS;
}
else if (!std::strncmp(curSH->name, "#GUID", maxStreamNameSize))
{
rs = &_streamGuidHeap;
if (curSH->size % 16 != 0)
{
return LoadImageErrorCode::BAD_IMAGE;
}
}
else if (!std::strncmp(curSH->name, "#Blob", maxStreamNameSize))
{
rs = &_streamBlobHeap;
}
else if (!std::strncmp(curSH->name, "#-", maxStreamNameSize))
{
rs = &nonStandardStream;
}
else if (!std::strncmp(curSH->name, "#Pdb", maxStreamNameSize))
{
rs = &pdbStream;
}
else
{
//std::cerr << "unknown stream name:" << curSH->name << std::endl;
return LoadImageErrorCode::BAD_IMAGE;
}
rs->data = ptrMetaData + curSH->offset;
rs->size = curSH->size;
rs->name = curSH->name;
size_t sizeOfStream = 8 + (std::strlen(curSH->name) / 4 + 1) * 4;
curSH = (const StreamHeader*)((byte*)curSH + sizeOfStream);
}
return LoadImageErrorCode::OK;
}
LoadImageErrorCode PolymorphicRawImage::LoadTables()
{
MetadataReader reader(_streamTables.data);
PolymorphicTablesHeapHeaderBaseData heapHeader = {};
heapHeader.Read(reader);
if (heapHeader.reserved1 != 0 || heapHeader.majorVersion != 2 || heapHeader.minorVersion != 0)
{
return LoadImageErrorCode::BAD_IMAGE;
}
if ((heapHeader.streamFlags & ~0x7))
{
return LoadImageErrorCode::BAD_IMAGE;
}
_4byteStringIndex = heapHeader.streamFlags & 0x1;
_4byteGUIDIndex = heapHeader.streamFlags & 0x2;
_4byteBlobIndex = heapHeader.streamFlags & 0x4;
uint64_t validMask = ((uint64_t)1 << TABLE_NUM) - 1;
if (heapHeader.validMask & ~validMask)
{
return LoadImageErrorCode::BAD_IMAGE;
}
// sorted include not exist table, so check is not need.
//if (heapHeader.sorted & ~validMask)
//{
// return LoadImageErrorCode::BAD_IMAGE;
//}
uint32_t validTableNum = GetNotZeroBitCount(heapHeader.validMask);
//std::cout << "valid table num:" << validTableNum << std::endl;
//printf("#~ size:%0x\n", _streamTables.size);
const uint32_t* tableRowNums = (uint32_t*)(reader.CurrentDataPtr());
const byte* tableDataBegin = (const byte*)(tableRowNums + validTableNum);
{
int curValidTableIndex = 0;
for (int i = 0; i <= MAX_TABLE_INDEX; i++)
{
uint64_t mask = (uint64_t)1 << i;
_tables[i] = {};
if (heapHeader.validMask & mask)
{
uint32_t rowNum = tableRowNums[curValidTableIndex];
_tables[i].rowNum = rowNum;
++curValidTableIndex;
}
}
}
BuildTableRowMetas();
int curValidTableIndex = 0;
const byte* curTableData = tableDataBegin;
for (int i = 0; i <= MAX_TABLE_INDEX; i++)
{
uint64_t mask = (uint64_t)1 << i;
bool sorted = heapHeader.sortedMask & mask;
if (heapHeader.validMask & mask)
{
uint32_t rowNum = tableRowNums[curValidTableIndex];
uint32_t totalSize = 0;
auto& table = _tableRowMetas[i];
for (auto& col : table)
{
col.offset = totalSize;
totalSize += col.size;
}
uint32_t metaDataRowSize = totalSize;
//uint64_t offset = curTableData - _imageData;
_tables[i] = { curTableData, metaDataRowSize, rowNum, true, sorted };
curTableData += metaDataRowSize * rowNum;
//std::cout << "table:" << i << " ," << curValidTableIndex << ", row_size:" << metaDataRowSize << ", row_num:" << rowNum << std::endl;
//printf("table:[%d][%d] offset:%0llx row_size:%d row_count:%d\n", i, curValidTableIndex, offset, metaDataRowSize, rowNum);
++curValidTableIndex;
}
else
{
_tables[i] = { nullptr, 0, 0, false, sorted };
}
}
return LoadImageErrorCode::OK;
}
void PolymorphicRawImage::BuildTableRowMetas()
{
//!!!{{TABLE_ROW_METADS
{
auto& table = _tableRowMetas[(int)TableType::MODULE];
table.push_back({2});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputGUIDIndexByte()});
table.push_back({ComputGUIDIndexByte()});
table.push_back({ComputGUIDIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::TYPEREF];
table.push_back({ComputStringIndexByte()});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputTableIndexByte(TableType::MODULE, TableType::MODULEREF, TableType::ASSEMBLYREF, TableType::TYPEREF, TagBits::ResoulutionScope)});
}
{
auto& table = _tableRowMetas[(int)TableType::TYPEDEF];
table.push_back({ComputStringIndexByte()});
table.push_back({ComputTableIndexByte(TableType::FIELD)});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)});
table.push_back({4});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputTableIndexByte(TableType::METHOD)});
}
{
auto& table = _tableRowMetas[(int)TableType::FIELDPTR];
table.push_back({ComputTableIndexByte(TableType::FIELD)});
}
{
auto& table = _tableRowMetas[(int)TableType::FIELD];
table.push_back({ComputBlobIndexByte()});
table.push_back({2});
table.push_back({ComputStringIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::METHODPTR];
table.push_back({ComputTableIndexByte(TableType::METHOD)});
}
{
auto& table = _tableRowMetas[(int)TableType::METHOD];
table.push_back({ComputBlobIndexByte()});
table.push_back({2});
table.push_back({2});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputTableIndexByte(TableType::PARAM)});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::PARAMPTR];
table.push_back({ComputTableIndexByte(TableType::PARAM)});
}
{
auto& table = _tableRowMetas[(int)TableType::PARAM];
table.push_back({2});
table.push_back({ComputStringIndexByte()});
table.push_back({2});
}
{
auto& table = _tableRowMetas[(int)TableType::INTERFACEIMPL];
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)});
}
{
auto& table = _tableRowMetas[(int)TableType::MEMBERREF];
table.push_back({ComputStringIndexByte()});
table.push_back({ComputBlobIndexByte()});
table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MODULEREF, TableType::TYPEDEF, TableType::TYPEREF, TagBits::MemberRefParent)});
}
{
auto& table = _tableRowMetas[(int)TableType::CONSTANT];
table.push_back({1});
table.push_back({1});
table.push_back({ComputTableIndexByte(TableType::PARAM, TableType::FIELD, TableType::PROPERTY, TagBits::HasConstant)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::CUSTOMATTRIBUTE];
table.push_back({ComputTableIndexByte(HasCustomAttributeAssociateTables, sizeof(HasCustomAttributeAssociateTables) / sizeof(TableType), TagBits::HasCustomAttribute)});
table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::CustomAttributeType)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::FIELDMARSHAL];
table.push_back({ComputTableIndexByte(TableType::FIELD, TableType::PARAM, TagBits::HasFieldMarshal)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::DECLSECURITY];
table.push_back({2});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TableType::ASSEMBLY, TagBits::HasDeclSecurity)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::CLASSLAYOUT];
table.push_back({4});
table.push_back({2});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
}
{
auto& table = _tableRowMetas[(int)TableType::FIELDLAYOUT];
table.push_back({ComputTableIndexByte(TableType::FIELD)});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::STANDALONESIG];
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::EVENTMAP];
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
table.push_back({ComputTableIndexByte(TableType::EVENT)});
}
{
auto& table = _tableRowMetas[(int)TableType::EVENTPTR];
table.push_back({ComputTableIndexByte(TableType::EVENT)});
}
{
auto& table = _tableRowMetas[(int)TableType::EVENT];
table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)});
table.push_back({ComputStringIndexByte()});
table.push_back({2});
}
{
auto& table = _tableRowMetas[(int)TableType::PROPERTYMAP];
table.push_back({ComputTableIndexByte(TableType::PROPERTY)});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
}
{
auto& table = _tableRowMetas[(int)TableType::PROPERTYPTR];
table.push_back({ComputTableIndexByte(TableType::PROPERTY)});
}
{
auto& table = _tableRowMetas[(int)TableType::PROPERTY];
table.push_back({2});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::METHODSEMANTICS];
table.push_back({ComputTableIndexByte(TableType::EVENT, TableType::PROPERTY, TagBits::HasSemantics)});
table.push_back({ComputTableIndexByte(TableType::METHOD)});
table.push_back({2});
}
{
auto& table = _tableRowMetas[(int)TableType::METHODIMPL];
table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)});
table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
}
{
auto& table = _tableRowMetas[(int)TableType::MODULEREF];
table.push_back({ComputStringIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::TYPESPEC];
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::IMPLMAP];
table.push_back({2});
table.push_back({ComputTableIndexByte(TableType::MODULEREF)});
table.push_back({ComputTableIndexByte(TableType::FIELD, TableType::METHOD, TagBits::MemberForwarded)});
table.push_back({ComputStringIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::FIELDRVA];
table.push_back({ComputTableIndexByte(TableType::FIELD)});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ENCLOG];
table.push_back({4});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ENCMAP];
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ASSEMBLY];
table.push_back({2});
table.push_back({4});
table.push_back({2});
table.push_back({2});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputBlobIndexByte()});
table.push_back({2});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ASSEMBLYPROCESSOR];
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ASSEMBLYOS];
table.push_back({4});
table.push_back({4});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ASSEMBLYREF];
table.push_back({4});
table.push_back({2});
table.push_back({2});
table.push_back({ComputBlobIndexByte()});
table.push_back({ComputBlobIndexByte()});
table.push_back({2});
table.push_back({2});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputStringIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::ASSEMBLYREFPROCESSOR];
table.push_back({ComputTableIndexByte(TableType::ASSEMBLYREF)});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::ASSEMBLYREFOS];
table.push_back({4});
table.push_back({4});
table.push_back({4});
table.push_back({ComputTableIndexByte(TableType::ASSEMBLYREF)});
}
{
auto& table = _tableRowMetas[(int)TableType::FILE];
table.push_back({4});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::EXPORTEDTYPE];
table.push_back({4});
table.push_back({4});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputTableIndexByte(TableType::FILE, TableType::EXPORTEDTYPE, TableType::ASSEMBLY, TagBits::Implementation)});
}
{
auto& table = _tableRowMetas[(int)TableType::MANIFESTRESOURCE];
table.push_back({4});
table.push_back({4});
table.push_back({ComputStringIndexByte()});
table.push_back({ComputTableIndexByte(TableType::FILE, TableType::ASSEMBLYREF, TagBits::Implementation)});
}
{
auto& table = _tableRowMetas[(int)TableType::NESTEDCLASS];
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF)});
}
{
auto& table = _tableRowMetas[(int)TableType::GENERICPARAM];
table.push_back({2});
table.push_back({2});
table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::METHOD, TagBits::TypeOrMethodDef)});
table.push_back({ComputStringIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::METHODSPEC];
table.push_back({ComputTableIndexByte(TableType::METHOD, TableType::MEMBERREF, TagBits::MethodDefOrRef)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::GENERICPARAMCONSTRAINT];
table.push_back({ComputTableIndexByte(TableType::TYPEDEF, TableType::TYPEREF, TableType::TYPESPEC, TagBits::TypeDefOrRef)});
table.push_back({ComputTableIndexByte(TableType::GENERICPARAM)});
}
{
auto& table = _tableRowMetas[(int)TableType::DOCUMENT];
table.push_back({ComputBlobIndexByte()});
table.push_back({ComputGUIDIndexByte()});
table.push_back({ComputBlobIndexByte()});
table.push_back({ComputGUIDIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::METHODDEBUGINFORMATION];
table.push_back({ComputTableIndexByte(TableType::DOCUMENT)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::LOCALSCOPE];
table.push_back({ComputTableIndexByte(TableType::METHOD)});
table.push_back({ComputTableIndexByte(TableType::IMPORTSCOPE)});
table.push_back({ComputTableIndexByte(TableType::LOCALVARIABLE)});
table.push_back({ComputTableIndexByte(TableType::LOCALCONSTANT)});
table.push_back({4});
table.push_back({4});
}
{
auto& table = _tableRowMetas[(int)TableType::LOCALVARIABLE];
table.push_back({2});
table.push_back({2});
table.push_back({ComputStringIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::LOCALCONSTANT];
table.push_back({ComputStringIndexByte()});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::IMPORTSCOPE];
table.push_back({ComputTableIndexByte(TableType::IMPORTSCOPE)});
table.push_back({ComputBlobIndexByte()});
}
{
auto& table = _tableRowMetas[(int)TableType::STATEMACHINEMETHOD];
table.push_back({ComputTableIndexByte(TableType::METHOD)});
table.push_back({ComputTableIndexByte(TableType::METHOD)});
}
{
auto& table = _tableRowMetas[(int)TableType::CUSTOMDEBUGINFORMATION];
table.push_back({ComputTableIndexByte(HasCustomDebugInformation, sizeof(HasCustomDebugInformation) / sizeof(TableType), TagBits::HasCustomDebugInformation)});
table.push_back({ComputGUIDIndexByte()});
table.push_back({ComputBlobIndexByte()});
}
//!!!}}TABLE_ROW_METADS
for (int i = 0; i < TABLE_NUM; i++)
{
auto& table = _tableRowMetas[i];
if (table.empty())
{
IL2CPP_ASSERT(_tables[i].rowNum == 0 && _tables[i].rowMetaDataSize == 0);
}
else
{
uint32_t totalSize = 0;
for (auto& col : table)
{
col.offset = totalSize;
totalSize += col.size;
}
uint32_t computSize = ComputTableRowMetaDataSize((TableType)i);
IL2CPP_ASSERT(totalSize == computSize);
}
}
}
//!!!{{READ_TABLES_IMPLEMENTATIONS
TbTypeRef PolymorphicRawImage::ReadTypeRef(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::TYPEREF).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::TYPEREF, rawIndex);
auto& rowSchema = GetRowSchema(TableType::TYPEREF);
TbTypeRef data;
data.typeNamespace = ReadColumn(rowPtr, rowSchema[0]);
data.typeName = ReadColumn(rowPtr, rowSchema[1]);
data.resolutionScope = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbTypeDef PolymorphicRawImage::ReadTypeDef(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::TYPEDEF).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::TYPEDEF, rawIndex);
auto& rowSchema = GetRowSchema(TableType::TYPEDEF);
TbTypeDef data;
data.typeName = ReadColumn(rowPtr, rowSchema[0]);
data.fieldList = ReadColumn(rowPtr, rowSchema[1]);
data.extends = ReadColumn(rowPtr, rowSchema[2]);
data.flags = ReadColumn(rowPtr, rowSchema[3]);
data.typeNamespace = ReadColumn(rowPtr, rowSchema[4]);
data.methodList = ReadColumn(rowPtr, rowSchema[5]);
return data;
}
TbField PolymorphicRawImage::ReadField(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::FIELD).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::FIELD, rawIndex);
auto& rowSchema = GetRowSchema(TableType::FIELD);
TbField data;
data.signature = ReadColumn(rowPtr, rowSchema[0]);
data.flags = ReadColumn(rowPtr, rowSchema[1]);
data.name = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbMethod PolymorphicRawImage::ReadMethod(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHOD).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::METHOD, rawIndex);
auto& rowSchema = GetRowSchema(TableType::METHOD);
TbMethod data;
data.signature = ReadColumn(rowPtr, rowSchema[0]);
data.flags = ReadColumn(rowPtr, rowSchema[1]);
data.implFlags = ReadColumn(rowPtr, rowSchema[2]);
data.name = ReadColumn(rowPtr, rowSchema[3]);
data.paramList = ReadColumn(rowPtr, rowSchema[4]);
data.rva = ReadColumn(rowPtr, rowSchema[5]);
return data;
}
TbParam PolymorphicRawImage::ReadParam(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::PARAM).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::PARAM, rawIndex);
auto& rowSchema = GetRowSchema(TableType::PARAM);
TbParam data;
data.flags = ReadColumn(rowPtr, rowSchema[0]);
data.name = ReadColumn(rowPtr, rowSchema[1]);
data.sequence = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbInterfaceImpl PolymorphicRawImage::ReadInterfaceImpl(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::INTERFACEIMPL).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::INTERFACEIMPL, rawIndex);
auto& rowSchema = GetRowSchema(TableType::INTERFACEIMPL);
TbInterfaceImpl data;
data.classIdx = ReadColumn(rowPtr, rowSchema[0]);
data.interfaceIdx = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbMemberRef PolymorphicRawImage::ReadMemberRef(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::MEMBERREF).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::MEMBERREF, rawIndex);
auto& rowSchema = GetRowSchema(TableType::MEMBERREF);
TbMemberRef data;
data.name = ReadColumn(rowPtr, rowSchema[0]);
data.signature = ReadColumn(rowPtr, rowSchema[1]);
data.classIdx = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbConstant PolymorphicRawImage::ReadConstant(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::CONSTANT).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::CONSTANT, rawIndex);
auto& rowSchema = GetRowSchema(TableType::CONSTANT);
TbConstant data;
data.padding = ReadColumn(rowPtr, rowSchema[0]);
data.type = ReadColumn(rowPtr, rowSchema[1]);
data.parent = ReadColumn(rowPtr, rowSchema[2]);
data.value = ReadColumn(rowPtr, rowSchema[3]);
return data;
}
TbCustomAttribute PolymorphicRawImage::ReadCustomAttribute(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::CUSTOMATTRIBUTE).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::CUSTOMATTRIBUTE, rawIndex);
auto& rowSchema = GetRowSchema(TableType::CUSTOMATTRIBUTE);
TbCustomAttribute data;
data.parent = ReadColumn(rowPtr, rowSchema[0]);
data.type = ReadColumn(rowPtr, rowSchema[1]);
data.value = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbClassLayout PolymorphicRawImage::ReadClassLayout(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::CLASSLAYOUT).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::CLASSLAYOUT, rawIndex);
auto& rowSchema = GetRowSchema(TableType::CLASSLAYOUT);
TbClassLayout data;
data.classSize = ReadColumn(rowPtr, rowSchema[0]);
data.packingSize = ReadColumn(rowPtr, rowSchema[1]);
data.parent = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbFieldLayout PolymorphicRawImage::ReadFieldLayout(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::FIELDLAYOUT).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::FIELDLAYOUT, rawIndex);
auto& rowSchema = GetRowSchema(TableType::FIELDLAYOUT);
TbFieldLayout data;
data.field = ReadColumn(rowPtr, rowSchema[0]);
data.offset = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbStandAloneSig PolymorphicRawImage::ReadStandAloneSig(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::STANDALONESIG).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::STANDALONESIG, rawIndex);
auto& rowSchema = GetRowSchema(TableType::STANDALONESIG);
TbStandAloneSig data;
data.signature = ReadColumn(rowPtr, rowSchema[0]);
return data;
}
TbEventMap PolymorphicRawImage::ReadEventMap(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::EVENTMAP).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::EVENTMAP, rawIndex);
auto& rowSchema = GetRowSchema(TableType::EVENTMAP);
TbEventMap data;
data.parent = ReadColumn(rowPtr, rowSchema[0]);
data.eventList = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbEvent PolymorphicRawImage::ReadEvent(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::EVENT).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::EVENT, rawIndex);
auto& rowSchema = GetRowSchema(TableType::EVENT);
TbEvent data;
data.eventType = ReadColumn(rowPtr, rowSchema[0]);
data.name = ReadColumn(rowPtr, rowSchema[1]);
data.eventFlags = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbPropertyMap PolymorphicRawImage::ReadPropertyMap(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::PROPERTYMAP).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::PROPERTYMAP, rawIndex);
auto& rowSchema = GetRowSchema(TableType::PROPERTYMAP);
TbPropertyMap data;
data.propertyList = ReadColumn(rowPtr, rowSchema[0]);
data.parent = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbProperty PolymorphicRawImage::ReadProperty(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::PROPERTY).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::PROPERTY, rawIndex);
auto& rowSchema = GetRowSchema(TableType::PROPERTY);
TbProperty data;
data.flags = ReadColumn(rowPtr, rowSchema[0]);
data.name = ReadColumn(rowPtr, rowSchema[1]);
data.type = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbMethodSemantics PolymorphicRawImage::ReadMethodSemantics(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHODSEMANTICS).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::METHODSEMANTICS, rawIndex);
auto& rowSchema = GetRowSchema(TableType::METHODSEMANTICS);
TbMethodSemantics data;
data.association = ReadColumn(rowPtr, rowSchema[0]);
data.method = ReadColumn(rowPtr, rowSchema[1]);
data.semantics = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbMethodImpl PolymorphicRawImage::ReadMethodImpl(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHODIMPL).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::METHODIMPL, rawIndex);
auto& rowSchema = GetRowSchema(TableType::METHODIMPL);
TbMethodImpl data;
data.methodDeclaration = ReadColumn(rowPtr, rowSchema[0]);
data.methodBody = ReadColumn(rowPtr, rowSchema[1]);
data.classIdx = ReadColumn(rowPtr, rowSchema[2]);
return data;
}
TbModuleRef PolymorphicRawImage::ReadModuleRef(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::MODULEREF).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::MODULEREF, rawIndex);
auto& rowSchema = GetRowSchema(TableType::MODULEREF);
TbModuleRef data;
data.name = ReadColumn(rowPtr, rowSchema[0]);
return data;
}
TbTypeSpec PolymorphicRawImage::ReadTypeSpec(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::TYPESPEC).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::TYPESPEC, rawIndex);
auto& rowSchema = GetRowSchema(TableType::TYPESPEC);
TbTypeSpec data;
data.signature = ReadColumn(rowPtr, rowSchema[0]);
return data;
}
TbImplMap PolymorphicRawImage::ReadImplMap(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::IMPLMAP).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::IMPLMAP, rawIndex);
auto& rowSchema = GetRowSchema(TableType::IMPLMAP);
TbImplMap data;
data.mappingFlags = ReadColumn(rowPtr, rowSchema[0]);
data.importScope = ReadColumn(rowPtr, rowSchema[1]);
data.memberForwarded = ReadColumn(rowPtr, rowSchema[2]);
data.importName = ReadColumn(rowPtr, rowSchema[3]);
return data;
}
TbFieldRVA PolymorphicRawImage::ReadFieldRVA(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::FIELDRVA).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::FIELDRVA, rawIndex);
auto& rowSchema = GetRowSchema(TableType::FIELDRVA);
TbFieldRVA data;
data.field = ReadColumn(rowPtr, rowSchema[0]);
data.rva = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbAssembly PolymorphicRawImage::ReadAssembly(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::ASSEMBLY).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::ASSEMBLY, rawIndex);
auto& rowSchema = GetRowSchema(TableType::ASSEMBLY);
TbAssembly data;
data.minorVersion = ReadColumn(rowPtr, rowSchema[0]);
data.hashAlgId = ReadColumn(rowPtr, rowSchema[1]);
data.buildNumber = ReadColumn(rowPtr, rowSchema[2]);
data.revisionNumber = ReadColumn(rowPtr, rowSchema[3]);
data.locale = ReadColumn(rowPtr, rowSchema[4]);
data.name = ReadColumn(rowPtr, rowSchema[5]);
data.publicKey = ReadColumn(rowPtr, rowSchema[6]);
data.majorVersion = ReadColumn(rowPtr, rowSchema[7]);
data.flags = ReadColumn(rowPtr, rowSchema[8]);
return data;
}
TbAssemblyRef PolymorphicRawImage::ReadAssemblyRef(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::ASSEMBLYREF).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::ASSEMBLYREF, rawIndex);
auto& rowSchema = GetRowSchema(TableType::ASSEMBLYREF);
TbAssemblyRef data;
data.flags = ReadColumn(rowPtr, rowSchema[0]);
data.majorVersion = ReadColumn(rowPtr, rowSchema[1]);
data.buildNumber = ReadColumn(rowPtr, rowSchema[2]);
data.publicKeyOrToken = ReadColumn(rowPtr, rowSchema[3]);
data.hashValue = ReadColumn(rowPtr, rowSchema[4]);
data.revisionNumber = ReadColumn(rowPtr, rowSchema[5]);
data.minorVersion = ReadColumn(rowPtr, rowSchema[6]);
data.locale = ReadColumn(rowPtr, rowSchema[7]);
data.name = ReadColumn(rowPtr, rowSchema[8]);
return data;
}
TbNestedClass PolymorphicRawImage::ReadNestedClass(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::NESTEDCLASS).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::NESTEDCLASS, rawIndex);
auto& rowSchema = GetRowSchema(TableType::NESTEDCLASS);
TbNestedClass data;
data.enclosingClass = ReadColumn(rowPtr, rowSchema[0]);
data.nestedClass = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbGenericParam PolymorphicRawImage::ReadGenericParam(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::GENERICPARAM).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::GENERICPARAM, rawIndex);
auto& rowSchema = GetRowSchema(TableType::GENERICPARAM);
TbGenericParam data;
data.flags = ReadColumn(rowPtr, rowSchema[0]);
data.number = ReadColumn(rowPtr, rowSchema[1]);
data.owner = ReadColumn(rowPtr, rowSchema[2]);
data.name = ReadColumn(rowPtr, rowSchema[3]);
return data;
}
TbMethodSpec PolymorphicRawImage::ReadMethodSpec(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::METHODSPEC).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::METHODSPEC, rawIndex);
auto& rowSchema = GetRowSchema(TableType::METHODSPEC);
TbMethodSpec data;
data.method = ReadColumn(rowPtr, rowSchema[0]);
data.instantiation = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
TbGenericParamConstraint PolymorphicRawImage::ReadGenericParamConstraint(uint32_t rawIndex)
{
IL2CPP_ASSERT(rawIndex > 0 && rawIndex <= GetTable(TableType::GENERICPARAMCONSTRAINT).rowNum);
const byte* rowPtr = GetTableRowPtr(TableType::GENERICPARAMCONSTRAINT, rawIndex);
auto& rowSchema = GetRowSchema(TableType::GENERICPARAMCONSTRAINT);
TbGenericParamConstraint data;
data.constraint = ReadColumn(rowPtr, rowSchema[0]);
data.owner = ReadColumn(rowPtr, rowSchema[1]);
return data;
}
//!!!}}READ_TABLES_IMPLEMENTATIONS
}
}

View File

@@ -0,0 +1,58 @@
#pragma once
#include "DotNetRawImageBase.h"
namespace hybridclr
{
namespace metadata
{
class PolymorphicRawImage : public DotNetRawImageBase
{
public:
PolymorphicRawImage() : DotNetRawImageBase()
{
}
LoadImageErrorCode LoadCLIHeader(uint32_t& entryPointToken, uint32_t& metadataRva, uint32_t& metadataSize) override;
virtual LoadImageErrorCode LoadStreamHeaders(uint32_t metadataRva, uint32_t metadataSize) override;
virtual LoadImageErrorCode LoadTables() override;
virtual void BuildTableRowMetas() override;
//!!!{{READ_TABLES_OVERRIDES
virtual TbTypeRef ReadTypeRef(uint32_t rawIndex) override;
virtual TbTypeDef ReadTypeDef(uint32_t rawIndex) override;
virtual TbField ReadField(uint32_t rawIndex) override;
virtual TbMethod ReadMethod(uint32_t rawIndex) override;
virtual TbParam ReadParam(uint32_t rawIndex) override;
virtual TbInterfaceImpl ReadInterfaceImpl(uint32_t rawIndex) override;
virtual TbMemberRef ReadMemberRef(uint32_t rawIndex) override;
virtual TbConstant ReadConstant(uint32_t rawIndex) override;
virtual TbCustomAttribute ReadCustomAttribute(uint32_t rawIndex) override;
virtual TbClassLayout ReadClassLayout(uint32_t rawIndex) override;
virtual TbFieldLayout ReadFieldLayout(uint32_t rawIndex) override;
virtual TbStandAloneSig ReadStandAloneSig(uint32_t rawIndex) override;
virtual TbEventMap ReadEventMap(uint32_t rawIndex) override;
virtual TbEvent ReadEvent(uint32_t rawIndex) override;
virtual TbPropertyMap ReadPropertyMap(uint32_t rawIndex) override;
virtual TbProperty ReadProperty(uint32_t rawIndex) override;
virtual TbMethodSemantics ReadMethodSemantics(uint32_t rawIndex) override;
virtual TbMethodImpl ReadMethodImpl(uint32_t rawIndex) override;
virtual TbModuleRef ReadModuleRef(uint32_t rawIndex) override;
virtual TbTypeSpec ReadTypeSpec(uint32_t rawIndex) override;
virtual TbImplMap ReadImplMap(uint32_t rawIndex) override;
virtual TbFieldRVA ReadFieldRVA(uint32_t rawIndex) override;
virtual TbAssembly ReadAssembly(uint32_t rawIndex) override;
virtual TbAssemblyRef ReadAssemblyRef(uint32_t rawIndex) override;
virtual TbNestedClass ReadNestedClass(uint32_t rawIndex) override;
virtual TbGenericParam ReadGenericParam(uint32_t rawIndex) override;
virtual TbMethodSpec ReadMethodSpec(uint32_t rawIndex) override;
virtual TbGenericParamConstraint ReadGenericParamConstraint(uint32_t rawIndex) override;
//!!!}}READ_TABLES_OVERRIDES
private:
};
}
}

View File

@@ -0,0 +1,22 @@
{
"name": "com.code-philosophy.obfuz4hybridclr",
"version": "1.0.0-beta.1",
"displayName": "Obfuz4HybridCLR",
"description": "Obfuz4HybridCLR is a obfuz extension for HybridCLR",
"category": "Scripting",
"documentationUrl": "https://www.obfuz.com",
"changelogUrl": "https://github.com/focus-creative-games/obfuz/commits/main/",
"licensesUrl": "https://github.com/focus-creative-games/obfuz/blob/main/com.code-philosophy.obfuz4hybridclr/LICENSE",
"keywords": [
"obfuz",
"obfuscation",
"obfuscator",
"confuser",
"code-philosophy"
],
"author": {
"name": "Code Philosophy",
"email": "obfuz@code-philosophy.com",
"url": "https://code-philosophy.com"
}
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9ac66e213a764b840b2533ee30123717
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: