构建过程中自动转换link.xml中原始的类型名为混淆后的名称,确保混淆后能正确保留类型
parent
b85f3f54a0
commit
28ac98352d
|
@ -54,6 +54,11 @@ namespace Obfuz.Settings
|
||||||
return $"{ObfuzRootDir}/{target}/TempObfuscatedAssemblies";
|
return $"{ObfuzRootDir}/{target}/TempObfuscatedAssemblies";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetObfuscatedLinkXmlPath(BuildTarget target)
|
||||||
|
{
|
||||||
|
return $"{ObfuzRootDir}/{target}/link.xml";
|
||||||
|
}
|
||||||
|
|
||||||
private static ObfuzSettings s_Instance;
|
private static ObfuzSettings s_Instance;
|
||||||
|
|
||||||
public static ObfuzSettings Instance
|
public static ObfuzSettings Instance
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
using Obfuz.Settings;
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEditor.Build;
|
||||||
|
using UnityEditor.Build.Reporting;
|
||||||
|
using UnityEditor.UnityLinker;
|
||||||
|
using UnityEngine;
|
||||||
|
using static UnityEngine.GraphicsBuffer;
|
||||||
|
using FileUtil = Obfuz.Utils.FileUtil;
|
||||||
|
|
||||||
|
namespace Obfuz.Unity
|
||||||
|
{
|
||||||
|
public class LinkXmlProcess : IUnityLinkerProcessor
|
||||||
|
{
|
||||||
|
public int callbackOrder => 10000;
|
||||||
|
|
||||||
|
public string GenerateAdditionalLinkXmlFile(BuildReport report, UnityLinkerBuildPipelineData data)
|
||||||
|
{
|
||||||
|
return GenerateAdditionalLinkXmlFile(data.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateAdditionalLinkXmlFile(BuildTarget target)
|
||||||
|
{
|
||||||
|
ObfuzSettings settings = ObfuzSettings.Instance;
|
||||||
|
string linkXmlPath = settings.GetObfuscatedLinkXmlPath(target);
|
||||||
|
FileUtil.CreateParentDir(linkXmlPath);
|
||||||
|
|
||||||
|
var writer = System.Xml.XmlWriter.Create(linkXmlPath,
|
||||||
|
new System.Xml.XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true });
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string[] linkGuids = AssetDatabase.FindAssets("t:TextAsset");
|
||||||
|
var linkXmlPaths = linkGuids.Select(guid => AssetDatabase.GUIDToAssetPath(guid))
|
||||||
|
.Where(f => Path.GetFileName(f) == "link.xml")
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var symbolMapping = new LiteSymbolMappingReader(settings.symbolObfusSettings.symbolMappingFile);
|
||||||
|
var assembliesToObfuscated = new HashSet<string>(settings.assemblySettings.GetAssembliesToObfuscate());
|
||||||
|
|
||||||
|
writer.WriteStartDocument();
|
||||||
|
writer.WriteStartElement("linker");
|
||||||
|
foreach (string linkPath in linkXmlPaths)
|
||||||
|
{
|
||||||
|
TransformLinkXml(linkPath, symbolMapping, assembliesToObfuscated, writer);
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
writer.WriteEndDocument();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
writer.Close();
|
||||||
|
}
|
||||||
|
Debug.Log($"LinkXmlProcess write {linkXmlPath}");
|
||||||
|
return linkXmlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TransformLinkXml(string xmlFile, LiteSymbolMappingReader symbolMapping, HashSet<string> assembliesToObfuscated, XmlWriter writer)
|
||||||
|
{
|
||||||
|
Debug.Log($"LinkXmlProcess transform link.xml:{xmlFile}");
|
||||||
|
var doc = new XmlDocument();
|
||||||
|
doc.Load(xmlFile);
|
||||||
|
var root = doc.DocumentElement;
|
||||||
|
foreach (XmlNode assNode in root.ChildNodes)
|
||||||
|
{
|
||||||
|
if (!(assNode is XmlElement assElement))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (assElement.Name == "assembly")
|
||||||
|
{
|
||||||
|
string assemblyName = assElement.GetAttribute("fullname");
|
||||||
|
if (string.IsNullOrEmpty(assemblyName))
|
||||||
|
{
|
||||||
|
throw new Exception($"Invalid node name: {assElement.Name}. attribute 'fullname' missing.");
|
||||||
|
}
|
||||||
|
if (!assembliesToObfuscated.Contains(assemblyName))
|
||||||
|
{
|
||||||
|
continue; // Skip assemblies that are not to be obfuscated
|
||||||
|
}
|
||||||
|
writer.WriteStartElement("assembly");
|
||||||
|
writer.WriteAttributeString("fullname", assemblyName);
|
||||||
|
if (assElement.HasAttribute("preserve"))
|
||||||
|
{
|
||||||
|
writer.WriteAttributeString("preserve", assElement.GetAttribute("preserve"));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (XmlNode typeNode in assElement.ChildNodes)
|
||||||
|
{
|
||||||
|
if (typeNode is XmlElement typeElement)
|
||||||
|
{
|
||||||
|
if (typeElement.Name == "type")
|
||||||
|
{
|
||||||
|
string typeName = typeElement.GetAttribute("fullname");
|
||||||
|
if (string.IsNullOrEmpty(typeName))
|
||||||
|
{
|
||||||
|
throw new Exception($"Invalid node name: {typeElement.Name}. attribute 'fullname' missing.");
|
||||||
|
}
|
||||||
|
if (!symbolMapping.TryGetNewTypeName(assemblyName, typeName, out string newTypeName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteStartElement("type");
|
||||||
|
writer.WriteAttributeString("fullname", newTypeName);
|
||||||
|
if (typeElement.HasAttribute("preserve"))
|
||||||
|
{
|
||||||
|
writer.WriteAttributeString("preserve", typeElement.GetAttribute("preserve"));
|
||||||
|
}
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 66881cca1e4a78c44b4c9fcd7f8b4fb9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,116 @@
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Obfuz.Unity
|
||||||
|
{
|
||||||
|
|
||||||
|
public class LiteSymbolMappingReader
|
||||||
|
{
|
||||||
|
class TypeMappingInfo
|
||||||
|
{
|
||||||
|
public string oldFullName;
|
||||||
|
public string newFullName;
|
||||||
|
|
||||||
|
//public Dictionary<string, string> MethodMappings = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AssemblyMappingInfo
|
||||||
|
{
|
||||||
|
public Dictionary<string, string> TypeMappings = new Dictionary<string, string>();
|
||||||
|
public Dictionary<string, string> MethodMappings = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<string, AssemblyMappingInfo> _assemblies = new Dictionary<string, AssemblyMappingInfo>();
|
||||||
|
|
||||||
|
public LiteSymbolMappingReader(string mappingFile)
|
||||||
|
{
|
||||||
|
LoadXmlMappingFile(mappingFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadXmlMappingFile(string mappingFile)
|
||||||
|
{
|
||||||
|
var doc = new XmlDocument();
|
||||||
|
doc.Load(mappingFile);
|
||||||
|
var root = doc.DocumentElement;
|
||||||
|
foreach (XmlNode node in root.ChildNodes)
|
||||||
|
{
|
||||||
|
if (!(node is XmlElement element))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LoadAssemblyMapping(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadAssemblyMapping(XmlElement ele)
|
||||||
|
{
|
||||||
|
if (ele.Name != "assembly")
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Invalid node name: {ele.Name}. Expected 'assembly'.");
|
||||||
|
}
|
||||||
|
string assName = ele.GetAttribute("name");
|
||||||
|
if (string.IsNullOrEmpty(assName))
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Invalid node name: {ele.Name}. attribute 'name' missing.");
|
||||||
|
}
|
||||||
|
if (!_assemblies.TryGetValue(assName, out var assemblyMappingInfo))
|
||||||
|
{
|
||||||
|
assemblyMappingInfo = new AssemblyMappingInfo();
|
||||||
|
_assemblies[assName] = assemblyMappingInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (XmlNode node in ele.ChildNodes)
|
||||||
|
{
|
||||||
|
if (!(node is XmlElement element))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (element.Name == "type")
|
||||||
|
{
|
||||||
|
LoadTypeMapping(element, assemblyMappingInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadTypeMapping(XmlElement ele, AssemblyMappingInfo assemblyMappingInfo)
|
||||||
|
{
|
||||||
|
string oldFullName = ele.GetAttribute("fullName");
|
||||||
|
string newFullName = ele.GetAttribute("newFullName");
|
||||||
|
string status = ele.GetAttribute("status");
|
||||||
|
if (status == "Renamed")
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(oldFullName) || string.IsNullOrEmpty(newFullName))
|
||||||
|
{
|
||||||
|
throw new System.Exception($"Invalid node name: {ele.Name}. attributes 'fullName' or 'newFullName' missing.");
|
||||||
|
}
|
||||||
|
assemblyMappingInfo.TypeMappings[oldFullName] = newFullName;
|
||||||
|
}
|
||||||
|
//foreach (XmlNode node in ele.ChildNodes)
|
||||||
|
//{
|
||||||
|
// if (!(node is XmlElement c))
|
||||||
|
// {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if (node.Name == "method")
|
||||||
|
// {
|
||||||
|
// LoadMethodMapping(c);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetNewTypeName(string assemblyName, string oldFullName, out string newFullName)
|
||||||
|
{
|
||||||
|
newFullName = null;
|
||||||
|
if (_assemblies.TryGetValue(assemblyName, out var assemblyMappingInfo))
|
||||||
|
{
|
||||||
|
if (assemblyMappingInfo.TypeMappings.TryGetValue(oldFullName, out newFullName))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8429e75dcc6a7e742a3cabaa3e8491c5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue