少年修仙传客户端基础资源
client_Hale
2018-09-13 9802ac83bb39af9221793dd9bfe0da0bc39b0ba6
3042 【开发】代码混淆
20个文件已添加
1093 ■■■■■ 已修改文件
Assets/Editor/Confusion.meta 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionDirectoryInfo.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionDirectoryInfo.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionFile.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionFile.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionRelation.cs 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionRelation.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionSetting.cs 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/ConfusionSetting.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor.meta 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionConfig.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionConfig.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionContorller.cs 533 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionContorller.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionEditorWindow.cs 279 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionEditorWindow.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionModel.cs 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/ConfusionModel.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/config.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion/Editor/config.json.meta 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Assets/Editor/Confusion.meta
New file
@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 70e2d34303c93fe40a5b82718604e51c
folderAsset: yes
timeCreated: 1535620874
licenseType: Free
DefaultImporter:
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/ConfusionDirectoryInfo.cs
New file
@@ -0,0 +1,6 @@
[System.Serializable]
public class ConfusionDirectoryInfo
{
    public string path;
    public bool includeChild;
}
Assets/Editor/Confusion/ConfusionDirectoryInfo.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ffd621f5229090c41afeea6296d6b474
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/ConfusionFile.cs
New file
@@ -0,0 +1,5 @@
[System.Serializable]
public class ConfusionFile
{
    public ConfusionRelation[] items;
}
Assets/Editor/Confusion/ConfusionFile.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e739d5ecd1a9d7438a050010140c02d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/ConfusionRelation.cs
New file
@@ -0,0 +1,8 @@
[System.Serializable]
public class ConfusionRelation
{
    public string typeName;
    public string path;
    public string[] keys;
    public string[] values;
}
Assets/Editor/Confusion/ConfusionRelation.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 03b97e134be0ee042868c4477f81f18b
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/ConfusionSetting.cs
New file
@@ -0,0 +1,71 @@
[System.Serializable]
public class ConfusionSetting
{
    public ConfusionDirectoryInfo[] confusionDirectorys;
    private int BitPrivate = 1;
    private int BitProtected = 2;
    private int BitPublic = 4;
    public int confuseField = 1;
    public int confuseMethod = 1;
    public ConfusionSetting()
    {
    }
    public bool IsConfusePrivateField
    {
        get { return (confuseField & BitPrivate) == 1; }
        set
        {
            confuseField = value ? confuseField | BitPrivate : confuseField & ~BitPrivate;
        }
    }
    public bool IsConfuseProtectedField
    {
        get { return ((confuseField & BitProtected) >> 1) == 1; }
        set
        {
            confuseField = value ? confuseField | BitProtected : confuseField & ~BitProtected;
        }
    }
    public bool IsConfusePublicField
    {
        get { return ((confuseField & BitPublic) >> 2) == 1; }
        set
        {
            confuseField = value ? confuseField | BitPublic : confuseField & ~BitPublic;
        }
    }
    public bool IsConfusePrivateMethod
    {
        get { return (confuseMethod & BitPrivate) == 1; }
        set
        {
            confuseMethod = value ? confuseMethod | BitPrivate : confuseMethod & ~BitPrivate;
        }
    }
    public bool IsConfuseProtectedMethod
    {
        get { return ((confuseMethod & BitProtected) >> 1) == 1; }
        set
        {
            confuseMethod = value ? confuseMethod | BitProtected : confuseMethod & ~BitProtected;
        }
    }
    public bool IsConfusePublicMethod
    {
        get { return ((confuseMethod & BitPublic) >> 2) == 1; }
        set
        {
            confuseMethod = value ? confuseMethod | BitPublic : confuseMethod & ~BitPublic;
        }
    }
}
Assets/Editor/Confusion/ConfusionSetting.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a855a92bec1c0434f92ff3ec3c48c5d5
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/Editor.meta
New file
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 923f2e4e4875f754883e46f0ce553808
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/Editor/ConfusionConfig.cs
New file
@@ -0,0 +1,14 @@
[System.Serializable]
public class ConfusionConfig
{
    // 存储变量默认的混淆方式
    public int confusionField;
    // 存储方法默认的混淆方式
    public int confusionMethod;
    // 需要被混淆的路径列表
    public string[] confusionDirectorys;
}
Assets/Editor/Confusion/Editor/ConfusionConfig.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7e0a5afe7434f784cac664fbefed4fc1
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/Editor/ConfusionContorller.cs
New file
@@ -0,0 +1,533 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System;
using System.IO;
using System.Text.RegularExpressions;
public static class ConfusionController
{
    private static List<Type> m_AssemblyTypes;
    public static List<Type> AssemblyTypes
    {
        get
        {
            if (m_AssemblyTypes == null)
            {
                m_AssemblyTypes = new List<Type>();
            }
            if (m_AssemblyTypes.Count == 0)
            {
                var _assembly = Assembly.Load("Assembly-CSharp");
                m_AssemblyTypes.AddRange(_assembly.GetTypes());
            }
            return m_AssemblyTypes;
        }
    }
    private static ConfusionModel m_Model;
    public static ConfusionModel DataModel
    {
        get
        {
            if (m_Model == null)
            {
                m_Model = new ConfusionModel();
            }
            return m_Model;
        }
    }
    public static int SelectDirectoryCount()
    {
        return DataModel.confuseFileSourcePathDict.Count;
    }
    public static void SelectDirectory(string path, bool includeChild = false)
    {
        path = path.Replace("\\", "/");
        path = path.Substring(path.IndexOf("Assets"));
        if (!DataModel.confuseFileSourcePathDict.ContainsKey(path))
        {
            var _directoryInfo = new ConfusionDirectoryInfo();
            _directoryInfo.path = path;
            _directoryInfo.includeChild = includeChild;
            DataModel.confuseFileSourcePathDict[path] = _directoryInfo;
        }
    }
    public static void ForeachSelectDirectory(Action<string, ConfusionDirectoryInfo> callback)
    {
        foreach (var _key in DataModel.confuseFileSourcePathDict.Keys)
        {
            callback(_key, DataModel.confuseFileSourcePathDict[_key]);
        }
    }
    public static void RemoveSelectDirectory(string path)
    {
        if (DataModel.confuseFileSourcePathDict.ContainsKey(path))
        {
            DataModel.confuseFileSourcePathDict.Remove(path);
        }
    }
    public static void BuildAssembleRelation()
    {
        DataModel.confusionTypeDict.Clear();
        int _count = AssemblyTypes.Count;
        int _index = 0;
        foreach (var _type in AssemblyTypes)
        {
            EditorUtility.DisplayProgressBar("开始生成类型内的变量和方法替换逻辑",
                                             "当前处理类型: " + _type.ToString(),
                                             _index * 1f / _count);
            if (IsIgnore(_type))
            {
                continue;
            }
            HandleClassType(_type);
            _index++;
        }
    }
    private static void HandleClassType(Type type)
    {
        if (DataModel.confusionTypeDict.ContainsKey(type))
        {
            return;
        }
        Debug.LogFormat("开始处理类: {0}", type);
        List<string> _typeMemberList = new List<string>();
        DataModel.confusionTypeDict.Add(type, _typeMemberList);
        var _memberInfos = type.GetMembers(BindingFlags.NonPublic
                                         | BindingFlags.Instance
                                         | BindingFlags.Static
                                         | BindingFlags.Public);
        foreach (var _memberinfo in _memberInfos)
        {
            if (!AssemblyTypes.Contains(_memberinfo.DeclaringType))
            {
                continue;
            }
            if (_memberinfo.MemberType == MemberTypes.Field)
            {
                // HandleField((FieldInfo)_memberinfo);
            }
            else if (_memberinfo.MemberType == MemberTypes.Method)
            {
                HandleMethod((MethodInfo)_memberinfo);
            }
        }
    }
    private static void HandleMethod(MethodInfo mi)
    {
        if (mi.IsPrivate && !ConfusionEditorWindow.Setting.IsConfusePrivateMethod)
        {
            return;
        }
        if (mi.IsFamily && !ConfusionEditorWindow.Setting.IsConfuseProtectedMethod)
        {
            return;
        }
        // && !ConfusionEditorWindow.Setting.IsConfusePublicMethod
        if (mi.IsPublic)
        {
            return;
        }
        if(mi.Name.Contains("UpdateOffLinePlayer") && mi.ReflectedType == typeof(GAMgr))
        {
            Debug.Log("aaaa");
        }
        if(!AssemblyTypes.Contains(mi.ReflectedType))
        {
            Debug.LogFormat("<color=red>程序集中不包含方法所归属的类型: {0}</color>", mi.ReflectedType);
            return;
        }
        if(mi.IsSpecialName)
        {
            Debug.LogFormat("不处理set和get方法: {0}", mi.Name);
            return;
        }
        Debug.LogFormat("  |- 开始处理: {0} 的方法: {1} .", mi.ReflectedType, mi.Name);
        Dictionary<string, string> _replacePair = null;
        if (!DataModel.confusionDict.TryGetValue(mi.ReflectedType, out _replacePair))
        {
            _replacePair = new Dictionary<string, string>();
            DataModel.confusionDict.Add(mi.ReflectedType, _replacePair);
        }
        // 检测这个方法是否是父类定义的, 是的话直接使用父类已经更改好的混淆逻辑
        // 1. 非私有
        // 2. 可能是虚方法
        // 3. 可由派生类使用
        if (!mi.IsPrivate
         && (mi.IsVirtual || mi.IsFamily)
         && AssemblyTypes.Contains(mi.ReflectedType.BaseType)
         && !mi.IsHideBySig)
        {
            Debug.LogFormat("这是一个父类定义的方法: {0} != {1} .", mi.DeclaringType, mi.ReflectedType.BaseType);
            // 所以要先处理父类
            if (!DataModel.confusionTypeDict.ContainsKey(mi.ReflectedType.BaseType))
            {
                Debug.LogFormat("未处理类型: {0} 的父类: {1}, 现在进行处理.",
                                mi.ReflectedType,
                                mi.ReflectedType.BaseType);
                HandleClassType(mi.ReflectedType.BaseType);
            }
            // 父类检测和处理完毕后, 这里获取父类的处理结果
            Dictionary<string, string> _parentReplacePair = null;
            if (DataModel.confusionDict.TryGetValue(mi.ReflectedType.BaseType, out _parentReplacePair))
            {
                if(_parentReplacePair.ContainsKey(mi.Name))
                {
                    // 赋值为父类替换名
                    _replacePair[mi.Name] = _parentReplacePair[mi.Name];
                    Debug.LogFormat("遵循: {0} 类的内容: {1} => {2}", mi.ReflectedType.BaseType, mi.Name, _parentReplacePair[mi.Name]);
                }
                else
                {
                    Debug.LogFormat("<color=red>父类: {0} 没有为这个方法进行混淆逻辑处理: {1}</color>", mi.ReflectedType.BaseType,mi.Name);
                }
            }
        }
        else
        {
            // 就是本类定义的则直接赋值替换内容
            if (!_replacePair.ContainsKey(mi.Name))
            {
                _replacePair[mi.Name] = DataModel.NewContent;
                Debug.LogFormat("    |- 处理Method的替换: {1} => {2}", mi.DeclaringType, mi.Name, _replacePair[mi.Name]);
            }
        }
    }
    private static void HandleField(FieldInfo fi)
    {
        if (fi.IsPrivate && !ConfusionEditorWindow.Setting.IsConfusePrivateField)
        {
            return;
        }
        if (fi.IsFamily && !ConfusionEditorWindow.Setting.IsConfuseProtectedField)
        {
            return;
        }
        // && !ConfusionEditorWindow.Setting.IsConfusePublicField
        if (fi.IsPublic)
        {
            return;
        }
        Dictionary<string, string> _replacePair = null;
        if (!DataModel.confusionDict.TryGetValue(fi.ReflectedType, out _replacePair))
        {
            _replacePair = new Dictionary<string, string>();
            DataModel.confusionDict.Add(fi.ReflectedType, _replacePair);
        }
        // 是否反射的类型与定义此变量的类型不相同, 代表这个类型是父类定义的
        if (fi.DeclaringType != fi.ReflectedType)
        {
            // 所以要先处理父类
            if (!DataModel.confusionTypeDict.ContainsKey(fi.DeclaringType))
            {
                HandleClassType(fi.DeclaringType);
            }
            // 父类检测和处理完毕后, 这里获取父类的处理结果
            Dictionary<string, string> _parentReplacePair = null;
            if (DataModel.confusionDict.TryGetValue(fi.DeclaringType, out _parentReplacePair))
            {
                // 赋值为父类替换名
                _replacePair[fi.Name] = _parentReplacePair[fi.Name];
            }
        }
        else
        {
            // 就是本类定义的则直接赋值替换内容
            if (!_replacePair.ContainsKey(fi.Name))
            {
                _replacePair[fi.Name] = DataModel.NewContent;
            }
        }
    }
    public static void DecideClassType()
    {
        var _index = 0;
        var _count = DataModel.confusionScriptFilePath.Count;
        foreach (var _path in DataModel.confusionScriptFilePath)
        {
            var _p = _path.Substring(_path.IndexOf("Assets"));
            var _script = AssetDatabase.LoadAssetAtPath<MonoScript>(_p);
            var _type = _script.GetClass();
            EditorUtility.DisplayProgressBar("开始处理选择文件夹的文件信息",
                                 "当前处理类型: " + _type.ToString(),
                                 _index * 1f / _count);
            DataModel.typeToPathDict[_type] = Path.GetFullPath(_path).Replace("\\", "/");
        }
    }
    public static void ReplaceFieldAndMethod()
    {
        var _index = 0;
        var _count = DataModel.confusionScriptFilePath.Count;
        string _scriptContent = null;
        foreach (var _type in DataModel.typeToPathDict.Keys)
        {
            EditorUtility.DisplayProgressBar("开始执行替换逻辑",
                                             "当前处理类型: " + _type.ToString(),
                                             _index * 1f / _count);
            if (!DataModel.confusionTypeDict.ContainsKey(_type))
            {
                Debug.LogWarningFormat("不存在将要混淆的类型: {0} 的混淆逻辑");
                continue;
            }
            using (var _streamReader = new StreamReader(DataModel.typeToPathDict[_type]))
            {
                _scriptContent = _streamReader.ReadToEnd();
            }
            // 文件存在且有内容
            if (!string.IsNullOrEmpty(_scriptContent))
            {
                // 读取替换内容
                foreach (var _replaceContent in DataModel.confusionDict[_type].Keys)
                {
                    var _newContent = DataModel.confusionDict[_type][_replaceContent];
                    // 进行替换
                    _scriptContent = ReplaceWholeWord(_scriptContent, _replaceContent, _newContent);
                    // 存储替换逻辑
                    if (!DataModel.reConfusionDict.ContainsKey(_type))
                    {
                        DataModel.reConfusionDict.Add(_type, new Dictionary<string, string>());
                    }
                    DataModel.reConfusionDict[_type][_newContent] = _replaceContent;
                }
            }
            using (var _streamWritter = new StreamWriter(DataModel.typeToPathDict[_type]))
            {
                _streamWritter.Write(_scriptContent);
            }
            _index++;
        }
        AssetDatabase.Refresh();
    }
    public static void CollectConfusionDirectory()
    {
        DataModel.confusionScriptFilePath.Clear();
        foreach (var _path in DataModel.confuseFileSourcePathDict.Keys)
        {
            DoCollectChildDirectory(_path, DataModel.confuseFileSourcePathDict[_path].includeChild);
        }
    }
    private static void DoCollectChildDirectory(string parent, bool includeChild = false)
    {
        EditorUtility.DisplayProgressBar("搜集所有脚本文件",
                                         "当前处理文件: " + parent,
                                         1f);
        var _files = Directory.GetFiles(parent, "*.cs");
        foreach (var _file in _files)
        {
            var _path = Path.GetFullPath(_file).Replace("\\", "/");
            if (!DataModel.confusionScriptFilePath.Contains(_path))
            {
                DataModel.confusionScriptFilePath.Add(_path);
            }
        }
        if (includeChild)
        {
            var _directoryInfo = new DirectoryInfo(parent);
            var _directories = _directoryInfo.GetDirectories();
            foreach (var _directory in _directories)
            {
                DoCollectChildDirectory(_directory.FullName, includeChild);
            }
        }
    }
    public static void ReConfusion(string path)
    {
        if (string.IsNullOrEmpty(path))
        {
            EditorUtility.DisplayDialog("警告", "请指定反混淆文件", "返回");
            return;
        }
        string _confusionRelationFile = null;
        using (var _streamReader = new StreamReader(path))
        {
            _confusionRelationFile = _streamReader.ReadToEnd();
        }
        if (string.IsNullOrEmpty(_confusionRelationFile))
        {
            return;
        }
        ConfusionFile _file = JsonUtility.FromJson<ConfusionFile>(_confusionRelationFile);
        if (_file == null)
        {
            return;
        }
        if (_file.items == null || _file.items.Length == 0)
        {
            return;
        }
        foreach (var _item in _file.items)
        {
            if (string.IsNullOrEmpty(_item.path))
            {
                UnityEngine.Debug.LogFormat("未定义脚本文件地址");
                continue;
            }
            if (string.IsNullOrEmpty(_item.typeName))
            {
                UnityEngine.Debug.LogFormat("未定义类型名称");
                continue;
            }
            string _scriptContent = null;
            using (var _streamReader = new StreamReader(_item.path))
            {
                _scriptContent = _streamReader.ReadToEnd();
            }
            if (string.IsNullOrEmpty(_scriptContent))
            {
                continue;
            }
            for (int i = 0; i < _item.keys.Length; ++i)
            {
                _scriptContent = ReplaceWholeWord(_scriptContent, _item.keys[i], _item.values[i]);
            }
            using (var _streamReader = new StreamWriter(_item.path))
            {
                _streamReader.Write(_scriptContent);
            }
        }
        AssetDatabase.Refresh();
    }
    public static void BuildConfusionRelation()
    {
        var _file = new ConfusionFile();
        _file.items = new ConfusionRelation[DataModel.reConfusionDict.Count];
        int _index = 0;
        int _jndex = 0;
        foreach (var _type in DataModel.reConfusionDict.Keys)
        {
            _file.items[_index] = new ConfusionRelation();
            _file.items[_index].typeName = _type.ToString();
            _file.items[_index].path = DataModel.typeToPathDict[_type];
            _file.items[_index].keys = new string[DataModel.reConfusionDict[_type].Count];
            _file.items[_index].values = new string[DataModel.reConfusionDict[_type].Count];
            _jndex = 0;
            foreach (var _key in DataModel.reConfusionDict[_type].Keys)
            {
                _file.items[_index].keys[_jndex] = _key;
                _file.items[_index].values[_jndex] = DataModel.reConfusionDict[_type][_key];
                _jndex++;
            }
            _index++;
        }
        string _json = JsonUtility.ToJson(_file);
        if (!Directory.Exists(DataModel.ReConfuseMapFileDir))
        {
            Directory.CreateDirectory(DataModel.ReConfuseMapFileDir);
        }
        using (var _streamWriter = new StreamWriter(DataModel.ReConfuseMapFileDir +
                                                    "/Map_" +
                                                    DateTime.Now.ToString("yyyy_MM_dd_HH_MM_ss") +
                                                    ".json"))
        {
            _streamWriter.Write(_json);
        }
    }
    public static void Reset()
    {
        if (m_AssemblyTypes != null)
        {
            m_AssemblyTypes.Clear();
        }
        DataModel.Reset();
    }
    private static bool IsIgnore(Type type)
    {
        if (!DataModel.typeToPathDict.ContainsKey(type))
        {
            return true;
        }
        if (type.BaseType == typeof(Editor)
         || type.BaseType == typeof(EditorWindow)
         || type.BaseType == typeof(ScriptableObject)
         || type.BaseType == typeof(MonoBehaviour)
         || type.IsSerializable)
        {
            return true;
        }
        return false;
    }
    private static string ReplaceWholeWord(string original, string wordToFind, string replacement, RegexOptions regexOptions = RegexOptions.None)
    {
        string pattern = String.Format(@"[^\.]\b{0}\b", wordToFind);
        string ret = Regex.Replace(original, pattern, " " + replacement, regexOptions);
        return ret;
    }
}
Assets/Editor/Confusion/Editor/ConfusionContorller.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a942b945029314443b5fad3fc765c6c6
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/Editor/ConfusionEditorWindow.cs
New file
@@ -0,0 +1,279 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Reflection;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Linq;
public class ConfusionEditorWindow : EditorWindow
{
    [MenuItem("Tools/Confusion")]
    static void Init()
    {
        var _win = CreateInstance<ConfusionEditorWindow>();
        _win.minSize = new Vector2(420, 400);
        _win.maxSize = _win.minSize;
        _win.Show();
    }
    private string LS_KEY_CONFIG_PATH;
    private string m_MapFilePath = "";
    private List<string> removePathList = new List<string>();
    private Vector2 m_ScrollVec2;
    private Color m_LabelColor = new Color(.9f, .9f, .8f, 1);
    public static ConfusionSetting Setting { get; private set; }
    void OnEnable()
    {
        ConfusionController.Reset();
        LS_KEY_CONFIG_PATH = Application.dataPath + "LS_KEY_CONFIG_PATH";
        BuildConfig();
    }
    private void BuildConfig()
    {
        // 确认配置位置
        string _configPath = EditorPrefs.GetString(LS_KEY_CONFIG_PATH, "");
        // 有配置地址,读取配置地址
        if (string.IsNullOrEmpty(_configPath))
        {
            var _files = Directory.GetFiles(Application.dataPath, "*.cs", SearchOption.AllDirectories);
            foreach (var _file in _files)
            {
                if (_file.Contains("ConfusionEditorWindow"))
                {
                    _configPath = Path.GetDirectoryName(_file).Replace("\\", "/");
                    break;
                }
            }
            _configPath += "/config.json";
        }
        // 判断配置地址下是否有配置文件
        if (File.Exists(_configPath))
        {
            string _json = null;
            using (StreamReader _sr = new StreamReader(_configPath))
            {
                _json = _sr.ReadToEnd();
            }
            if (!string.IsNullOrEmpty(_json))
            {
                Setting = JsonUtility.FromJson<ConfusionSetting>(_json);
            }
        }
        if (Setting == null)
        {
            Setting = new ConfusionSetting();
            EditorPrefs.SetString(LS_KEY_CONFIG_PATH, _configPath);
            File.Create(_configPath);
        }
        if (Setting.confusionDirectorys != null)
        {
            foreach (var _info in Setting.confusionDirectorys)
            {
                ConfusionController.SelectDirectory(_info.path, _info.includeChild);
            }
        }
    }
    private void SaveConfig()
    {
        ConfusionSetting _setting = new ConfusionSetting();
        _setting.confuseField = Setting.confuseField;
        _setting.confuseMethod = Setting.confuseMethod;
        int _count = ConfusionController.SelectDirectoryCount();
        _setting.confusionDirectorys = new ConfusionDirectoryInfo[_count];
        int _index = 0;
        ConfusionController.ForeachSelectDirectory((_path, _info) =>
        {
            _setting.confusionDirectorys[_index] = new ConfusionDirectoryInfo();
            _setting.confusionDirectorys[_index].path = _path;
            _setting.confusionDirectorys[_index].includeChild = _info.includeChild;
            _index++;
        });
        string _json = JsonUtility.ToJson(_setting);
        Debug.Log(_json);
        string _configPath = EditorPrefs.GetString(LS_KEY_CONFIG_PATH, "");
        if (string.IsNullOrEmpty(_configPath))
        {
            Debug.LogErrorFormat("找不到配置地址!");
            return;
        }
        using (StreamWriter _sw = new StreamWriter(_configPath))
        {
            _sw.Write(_json);
        }
    }
    void OnGUI()
    {
        Color _defaultColor = GUI.color;
        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
        GUI.color = m_LabelColor;
        GUILayout.Label("ConfusionDiretory", EditorStyles.toolbarButton, GUILayout.Width(110));
        GUI.color = _defaultColor;
        if (GUILayout.Button("ADD +", EditorStyles.toolbarButton, GUILayout.ExpandWidth(true)))
        {
            var _path = EditorUtility.OpenFolderPanel("选择要被混淆的脚本文件夹",
                                                      Application.dataPath, "");
            if (!string.IsNullOrEmpty(_path))
            {
                ConfusionController.SelectDirectory(_path);
            }
        }
        EditorGUILayout.EndHorizontal();
        if (ConfusionController.SelectDirectoryCount() == 0)
        {
            EditorGUILayout.HelpBox("点击[ADD+]按钮添加一个想要被混淆的脚本文件夹,可以多次添加\r\n"
                                  + "添加完毕以后点击Confusion按钮进行混淆\r\n"
                                  + "混淆后会生成一个混淆列表文件,可以将混淆的文件恢复回来.", MessageType.Info);
        }
        removePathList.Clear();
        m_ScrollVec2 = EditorGUILayout.BeginScrollView(m_ScrollVec2);
        int _i = 1;
        ConfusionController.ForeachSelectDirectory((key, info) =>
        {
            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
            GUILayout.Label("└", GUILayout.Width(18));
            GUILayout.Label(_i.ToString(), EditorStyles.toolbarButton, GUILayout.Width(20));
            GUILayout.Label(key, EditorStyles.textField, GUILayout.ExpandWidth(true));
            info.includeChild = GUILayout.Toggle(info.includeChild,
                                                "IncludeChild",
                                                 EditorStyles.toolbarButton,
                                                 GUILayout.Width(80));
            if (GUILayout.Button("DEL -", EditorStyles.toolbarButton, GUILayout.Width(70)))
            {
                removePathList.Add(key);
            }
            EditorGUILayout.EndHorizontal();
            _i++;
        });
        EditorGUILayout.EndScrollView();
        for (int i = 0; i < removePathList.Count; ++i)
        {
            ConfusionController.RemoveSelectDirectory(removePathList[i]);
        }
        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
        GUI.color = m_LabelColor;
        GUILayout.Label("Confuse Field", EditorStyles.toolbarButton);
        GUI.color = _defaultColor;
        bool _toggle = Setting.IsConfusePrivateField;
        var _newToggle = GUILayout.Toggle(_toggle, "Private", EditorStyles.toolbarButton, GUILayout.Width(100));
        if (_toggle != _newToggle)
        {
            Setting.IsConfusePrivateField = _newToggle;
        }
        _toggle = Setting.IsConfuseProtectedField;
        _newToggle = GUILayout.Toggle(_toggle, "Protected", EditorStyles.toolbarButton, GUILayout.Width(100));
        if (_toggle != _newToggle)
        {
            Setting.IsConfuseProtectedField = _newToggle;
        }
        _toggle = Setting.IsConfusePublicField;
        _toggle = GUILayout.Toggle(_toggle, "Public", EditorStyles.toolbarButton, GUILayout.Width(100));
        Setting.IsConfusePublicField = _toggle;
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
        GUI.color = m_LabelColor;
        GUILayout.Label("Confuse Method", EditorStyles.toolbarButton);
        GUI.color = _defaultColor;
        _toggle = Setting.IsConfusePrivateMethod;
        _toggle = GUILayout.Toggle(_toggle, "Private", EditorStyles.toolbarButton, GUILayout.Width(100));
        Setting.IsConfusePrivateMethod = _toggle;
        _toggle = Setting.IsConfuseProtectedMethod;
        _toggle = GUILayout.Toggle(_toggle, "Protected", EditorStyles.toolbarButton, GUILayout.Width(100));
        Setting.IsConfuseProtectedMethod = _toggle;
        _toggle = Setting.IsConfusePublicMethod;
        _toggle = GUILayout.Toggle(_toggle, "Public", EditorStyles.toolbarButton, GUILayout.Width(100));
        Setting.IsConfusePublicMethod = _toggle;
        EditorGUILayout.EndHorizontal();
        if (GUILayout.Button("Confusion", GUILayout.Height(100)))
        {
            SaveConfig();
            Confusion();
        }
        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
        GUI.color = m_LabelColor;
        GUILayout.Label("MapFileSavePath", EditorStyles.toolbarButton, GUILayout.Width(110));
        GUI.color = _defaultColor;
        GUILayout.TextField(ConfusionController.DataModel.ReConfuseMapFileDir, EditorStyles.toolbarTextField, GUILayout.Width(222));
        if (GUILayout.Button("SELECT", EditorStyles.toolbarButton, GUILayout.Width(70)))
        {
            var _path = EditorUtility.OpenFolderPanel("选择混淆替换对应文件存放路径",
                                                      Application.dataPath, "");
            if (!string.IsNullOrEmpty(_path))
            {
                ConfusionController.DataModel.ReConfuseMapFileDir = _path.Replace("\\", "/");
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
        GUI.color = m_LabelColor;
        GUILayout.Label("ReConfusionMapFile", EditorStyles.toolbarButton, GUILayout.Width(110));
        GUI.color = _defaultColor;
        GUILayout.TextField(m_MapFilePath, EditorStyles.toolbarTextField, GUILayout.Width(222));
        if (GUILayout.Button("SELECT", EditorStyles.toolbarButton, GUILayout.Width(70)))
        {
            m_MapFilePath = EditorUtility.OpenFilePanel("选择要反混淆的文件",
                                                        ConfusionController.DataModel.ReConfuseMapFileDir, "json");
        }
        GUILayout.FlexibleSpace();
        EditorGUILayout.EndHorizontal();
        if (GUILayout.Button("ReConfusion", GUILayout.Height(100)))
        {
            ConfusionController.ReConfusion(m_MapFilePath);
        }
    }
    private void Confusion()
    {
        if (ConfusionController.SelectDirectoryCount() == 0)
        {
            EditorUtility.DisplayDialog("警告", "未指定要混淆的文件夹\r\n请点击 [ADD +] 按钮进行添加", "返回");
            return;
        }
        ConfusionController.CollectConfusionDirectory();
        ConfusionController.DecideClassType();
        ConfusionController.BuildAssembleRelation();
        //ConfusionController.ReplaceFieldAndMethod();
        //ConfusionController.BuildConfusionRelation();
        EditorUtility.ClearProgressBar();
    }
}
Assets/Editor/Confusion/Editor/ConfusionEditorWindow.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a4c42e02d3fcf7943b06a77a1a059ab9
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/Editor/ConfusionModel.cs
New file
@@ -0,0 +1,64 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
public class ConfusionModel
{
    private string LS_KEY_RECONFUSION_MAP_FILE = Application.dataPath + "ReConfuseMapFile";
    // 通过Assembly找到需要被混淆的ClassType
    // 对这些ClassType的Field和Method根据配置建立索引
    private const string PREV_FIX = "_";
    private static int m_Seed = 0;
    public string NewContent
    {
        get
        {
            return string.Format("{0}{1}", PREV_FIX, m_Seed++);
        }
    }
    // 想要被混淆的文件夹路径
    public Dictionary<string, ConfusionDirectoryInfo> confuseFileSourcePathDict = new Dictionary<string, ConfusionDirectoryInfo>();
    // 类型对应的文件路径
    public Dictionary<Type, string> typeToPathDict = new Dictionary<Type, string>();
    // 类型里需要被混淆的变量或者方法名称对应列表
    public Dictionary<Type, List<string>> confusionTypeDict = new Dictionary<Type, List<string>>();
    // 记录类型里最终被混淆成了什么内容, 用于反混淆的时候替换
    public Dictionary<Type, Dictionary<string, string>> confusionDict = new Dictionary<Type, Dictionary<string, string>>();
    // 记录类型里最终被混淆成了什么内容, 用于反混淆的时候替换
    public Dictionary<Type, Dictionary<string, string>> reConfusionDict = new Dictionary<Type, Dictionary<string, string>>();
    // 通过反射搜集到的文件路径
    public List<string> confusionScriptFilePath = new List<string>();
    // 替换表生成路径
    public string ReConfuseMapFileDir
    {
        get
        {
            return EditorPrefs.GetString(LS_KEY_RECONFUSION_MAP_FILE, Application.dataPath + "/ReConfusionMapFiles");
        }
        set
        {
            EditorPrefs.SetString(LS_KEY_RECONFUSION_MAP_FILE, value);
        }
    }
    public ConfusionModel()
    {
        Reset();
    }
    public void Reset()
    {
        m_Seed = 0;
        typeToPathDict.Clear();
        confuseFileSourcePathDict.Clear();
        confusionTypeDict.Clear();
        confusionDict.Clear();
    }
}
Assets/Editor/Confusion/Editor/ConfusionModel.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 70a2051eca557674b84aa32f391390c8
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Assets/Editor/Confusion/Editor/config.json
New file
@@ -0,0 +1 @@
{"confusionDirectorys":[{"path":"Assets/Scripts/Fight/GameActor","includeChild":false}],"confuseField":3,"confuseMethod":3}
Assets/Editor/Confusion/Editor/config.json.meta
New file
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6a436ca306c67d94b9aa5a9a1af2ddd3
TextScriptImporter:
  externalObjects: {}
  userData:
  assetBundleName:
  assetBundleVariant: