构建过程中自动转换link.xml中原始的类型名为混淆后的名称,确保混淆后能正确保留类型
parent
b85f3f54a0
commit
28ac98352d
|
@ -54,6 +54,11 @@ namespace Obfuz.Settings
|
|||
return $"{ObfuzRootDir}/{target}/TempObfuscatedAssemblies";
|
||||
}
|
||||
|
||||
public string GetObfuscatedLinkXmlPath(BuildTarget target)
|
||||
{
|
||||
return $"{ObfuzRootDir}/{target}/link.xml";
|
||||
}
|
||||
|
||||
private static ObfuzSettings s_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