前言
unity的c#层,编译处理的程序集Assembly_CSharp.dll,通过dnspy反编译出来,可以看到自己写的代码,代码也是公司的财产(大雾),但是开发项目过程中,有什么方法加密程序集呢?指令表(Instruction List,简称IL)是为可编程逻辑控制器(PLC)设计的编程语言,是相关的IEC 61131-3标准中支援几种语言之一,是类似组合语言的低阶语言。
Mono.Ceil 地址Mono.Cecil | Mono
官方wiki:https://github.com/jbevain/cecil/wiki/HOWTO
通过AssemblyDefinition下的ReadAssembly 读取程序集,AssemblyDefinition存储着改程序集的参数
ReadAssembly(assemblyPath, readParams); 其中参数readParams是对该程序集交互的方法,最简单的将’True’初始化给ReaderParameters.ReadSymbols对象 或 WriterParameters.WriteSymbols对象
var readParams = new ReaderParameters();
CustomResolver customResolver = new CustomResolver();
customResolver.SetPath(projectDir, configPath);
readParams.AssemblyResolver = customResolver;
readParams.ReadWrite = true;
readParams.ReadSymbols = true;
这里的CustomResolver是我的自定义类,指定你的自己的AssemblyResolver。通过这种方式你可以控制你加载模块和你解析的一些和他的相关的引用的生命周期。
继承自BaseAssemblyResolver,
添加一该程序集需要的外部引用,我这里是拿依赖unity dll。
dll.Write(baseDllDir, new WriterParameters { WriteSymbols = true });
dll保存
assembly.MainModule获取程序集模块,
var typeArr = assembly.MainModule.Types;获取该程序集所有的类模块
一个TypeDefinition列表, foreach (var t in typeArr)遍历
TypeDefinition.name 就是类名,可以混淆,
TypeDefinition.Methods该类所有方法,可以插入垃圾方法或者垃圾代码type.Methods.Insert(index, mymethod);
代码你可以通过IL指令自己写,也可以写一个垃圾方法类,遍历类的时候,把垃圾方法类提取出来成IL指令,再插入方法。
var mymethod = new MethodDefinition();
Random random = new Random();
for (int it = 0; it < 3; it++)
{
int JunlMethodIndex = random.Next(variableMap.Count);
string methodNameSeed = "";
for (int i = 0; i < 17; i++)
{
methodNameSeed += _zimu[random.Next(52)]; //通过索引下标随机
}
var typeRef = mythodBodyList[JunlMethodIndex].ReturnType;
mymethod = new MethodDefinition(methodNameSeed + "12345", MethodAttributes.Public, typeRef);
mymethod.Body.Instructions.Clear();
mymethod.Body.Variables.Clear();
foreach (var il in mythodBodyList[JunlMethodIndex].Body.Instructions)
{
var ilProcessor = mythodBodyList[JunlMethodIndex].Body.GetILProcessor();
if (il.OpCode.Equals(Mono.Cecil.Cil.OpCodes.Add))
{
Instruction ilTemp = ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Sub);
mymethod.Body.Instructions.Add(ilTemp);
continue;
}
if (il.OpCode.Equals(Mono.Cecil.Cil.OpCodes.Sub))
{
Instruction ilTemp = ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Add);
mymethod.Body.Instructions.Add(ilTemp);
continue;
}
if (il.OpCode.Equals(Mono.Cecil.Cil.OpCodes.Mul))
{
Instruction ilTemp = ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Div);
mymethod.Body.Instructions.Add(ilTemp);
continue;
}
if (il.OpCode.Equals(Mono.Cecil.Cil.OpCodes.Div))
{
Instruction ilTemp = ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Mul);
mymethod.Body.Instructions.Add(ilTemp);
continue;
}
if (il.OpCode.Equals(Mono.Cecil.Cil.OpCodes.And))
{
Instruction ilTemp = ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Or);
mymethod.Body.Instructions.Add(ilTemp);
continue;
}
if (il.OpCode.Equals(Mono.Cecil.Cil.OpCodes.Or))
{
Instruction ilTemp = ilProcessor.Create(Mono.Cecil.Cil.OpCodes.And);
mymethod.Body.Instructions.Add(ilTemp);
continue;
}
mymethod.Body.Instructions.Add(il);
}
foreach (var il in mythodBodyList[JunlMethodIndex].Body.Variables)
{
mymethod.Body.Variables.Add(il);
}
foreach (var il in mythodBodyList[JunlMethodIndex].Parameters)
{
mymethod.Parameters.Add(il);
}
int index = random.Next(type.Methods.Count);
//Console.WriteLine("mymethod what error :{0}", mymethod.Name);
type.Methods.Insert(index, mymethod);
}
我这里演示一些IL指令写垃圾方法,垃圾类就不演示了。
同时,还可以检查该类或者方法是否被其他程序集引用,如果引用,则不可以混淆,或者记录下来一起混淆,
查看IL指令,不难发现
这是个单例,后面是参数,
程序集调用方法,下面是方法体
很清楚,查看所有IL指令表IL指令详细表 - 张龙豪 - 博客园,然后
method.Body.Instructions获取方法体里面所有的IL指令
if (ilLanguage.ToString().Contains("call"))
{
if (ilLanguage.Operand.GetType() == (typeof(GenericInstanceMethod)) && ((GenericInstanceMethod)ilLanguage.Operand).DeclaringType.Scope.Name == DllName)
{
GenericInstanceMethod methodRef = ((GenericInstanceMethod)ilLanguage.Operand);
//Console.WriteLine("AssemblyEditorPath class:{0} ==============ref 程序集:{1} ====== ref classs:{2} === method:{3}", type, methodRef.DeclaringType.Scope.Name, methodRef.DeclaringType, methodRef.Name);
string methodName = methodRef.Name;
string className = methodRef.DeclaringType.Name;
if (!isRefByOtherDLLMap.ContainsKey(className))
{
List<string> xx = new List<string>();
xx.Add(methodName);
isRefByOtherDLLMap.Add(className, xx);
continue;
}
if (isRefByOtherDLLMap[className].IndexOf(methodName) == 0)
continue;
isRefByOtherDLLMap[className].Add(methodName);
}
if (ilLanguage.Operand.GetType() == (typeof(MethodReference)) && ((MethodReference)ilLanguage.Operand).DeclaringType.Scope.Name == DllName)
{
MethodReference methodRef = ((MethodReference)ilLanguage.Operand);
string methodName = methodRef.Name;
string className = methodRef.DeclaringType.Name;
if (!isRefByOtherDLLMap.ContainsKey(className))
{
List<string> xx = new List<string>();
xx.Add(methodName);
isRefByOtherDLLMap.Add(className, xx);
continue;
}
if (isRefByOtherDLLMap[className].IndexOf(methodName) == 0)
continue;
isRefByOtherDLLMap[className].Add(methodName);
}
}
查找call指令的语句,
/Console.WriteLine("AssemblyEditorPath class:{0} ==============ref 程序集:{1} ====== ref classs:{2} === method:{3}", type, methodRef.DeclaringType.Scope.Name, methodRef.DeclaringType, methodRef.Name);
methodRef.DeclaringType.Scope.Name 引用程序集名
methodRef.DeclaringType 引用的class名
methodRef.Name 引用的程序名