当前位置:网站首页>Injectfix principle learning (to realize the heat of repair addition)
Injectfix principle learning (to realize the heat of repair addition)
2022-07-24 07:22:00 【Ha, big beer】
Preparation
- ILRuntime A blog that is easy to understand
- ILRuntime A blog
- IL Instruction books
- InjectFix Realization
It is strongly recommended to read this article - see DLL Of IL Instructions VS The input terminal ildasm
Pay attention to more ideas in this article , So I won't introduce too much, such as IL Instructions , Mainly in the way of posting code and commenting , In addition, the virtual machine in this article is InjectFix The virtual machine of is deducted and deleted , The following is the project address , Those who are interested can pull down and run by themselves, and basically know what they are doing by interrupting , If you really don't understand something , You can ask me in private- git The project is here
- According to reading the above article , You can see that ,InjectFix The steps are divided into the following steps
–Pile insertion :It is to specify the function to be repaired through the tag , adopt Mono.Cecil plug-in unit , Insert IL Instructions , Through unique key Value to determine whether there is repair code , If there is, the repair function will be executed
–Repair :Modify the wrong code , adopt Mono.Cecil plug-in unit , Check the code of the repair function , Production repair function IL Instructions and stored in a file , And with the unique code inserted above key Value correspondence
–Execute the repair code IL Instructions :This part is generated by parsing IL Instructions , That's virtual machine , There are a lot of unsafe Code
- First, let's take a look at the final rendering , Is to write the addition wrong , Then through repair, the original wrong subtraction is modified into addition
- First, the following picture , The function is called Sum It's for addition , Because it's wrong , The printed result is -1

- The following is through repair , The original code is still wrong , But what is printed out is the correct value 3

Pile insertion
- This is the code for inserting piles , After implementation, it will be in Sum function IL Command top , Insert PatchLoad.HasPatch(0), Check function ,0 Because I have only one function here , To repair it, use it directly 0 This hard coding is ok , If repair is needed , Will execute genMethod This generated code
- genMethod Of IL Instruction to generate , Some of them are directly hard coded , Specifically, instantiate one Call object , The parameter Push go in , And use PatchLoad Of virtualMachine perform Execute function
static void InjectMethod(ModuleDefinition module, MethodDefinition method)
{
//TODO Use InsertBefore Insert
// Generation method
var genMethod = GenPatchMethod(module, method);
// Pile insertion
var ilp = method.Body.GetILProcessor();
var startNopIns = method.Body.Instructions[0];
var brFalseJumpIns = startNopIns.Next; // Instructions to jump when conditions are not met
var ins_ldstr = ilp.Create(OpCodes.Ldstr, "0"); // Insert patchKey
ilp.InsertBefore(startNopIns, ins_ldstr); // insert index = 0 Location
var incrIndex = 0;
var method_HasPatch = module.Types.Single(t => t.Name == "PatchLoad").Methods.Single(m => m.Name == "HasPatch");
var ins_call = ilp.Create(OpCodes.Call, method_HasPatch);
IncrAddIns(ilp, ins_call, ref incrIndex);
var ins_brfalse = ilp.Create(OpCodes.Brfalse, brFalseJumpIns);
IncrAddIns(ilp, ins_brfalse, ref incrIndex);
// Used to test direct return 0
//var ins_ldc_i4_0 = ilp.Create(OpCodes.Ldc_I4_0);
//IncrAddIns(ilp, ins_ldc_i4_0, ref incrIndex);
// Have Patch Time return receipt generation method , And back to
if(method.Parameters.Count > 0) {
// If there are parameters Put parameters on the stack from local
//for (int i = 0; i < method.Parameters.Count; i++) {
// IncrAddIns(ilp, Instruction.Create(OpCodes.Ldarg_S, (byte)i), ref incrIndex);
//}
// know Sum Yes 2 Parameters Just enter directly
IncrAddIns(ilp, Instruction.Create(OpCodes.Ldarg_1), ref incrIndex);
IncrAddIns(ilp, Instruction.Create(OpCodes.Ldarg_2), ref incrIndex);
}
IncrAddIns(ilp, Instruction.Create(OpCodes.Call, genMethod), ref incrIndex);
var ins_ret = ilp.Create(OpCodes.Ret);
IncrAddIns(ilp, ins_ret, ref incrIndex);
}
/// <summary>
/// Generate patch method
/// </summary>
/// <returns></returns>
static MethodDefinition GenPatchMethod(ModuleDefinition module, MethodDefinition method) {
// PatchLoad
var patchLoadType = module.Types.Single(t => t.Name == "PatchLoad");
var vmField = patchLoadType.Fields.Single(f => f.Name == "virtualMachine");
// Call
var callType = module.Types.Single(t => t.Name == "Call");
var callBegin = callType.Methods.Single(m => m.Name == "Begin");
var callPushInt32 = callType.Methods.Single(m => m.Name == "PushInt32");
var callGetInt32 = callType.Methods.Single(m => m.Name == "GetInt32");
// VirtualMachine
var vmExecute = module.Types.Single(t => t.Name == "VirtualMachine")
.Methods.Single(m => m.Name == "Execute" && m.Parameters.Count == 4);
// Basic method
// Return value
// Parameters
var returnType = method.ReturnType;
Mono.Cecil.MethodAttributes methodAttributes = Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Static;
MethodDefinition patchMethod = new MethodDefinition(GenPatchMethodPrefix, methodAttributes, returnType);
// Add parameter
foreach (var parameter in method.Parameters) {
patchMethod.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
}
// var call
VariableDefinition callVar = new VariableDefinition(callType);
patchMethod.Body.Variables.Add(callVar);
var ilp = patchMethod.Body.GetILProcessor();
ilp.Append(Instruction.Create(OpCodes.Nop));
ilp.Append(Instruction.Create(OpCodes.Call, callBegin));
ilp.Append(Instruction.Create(OpCodes.Stloc_0));
// Loads the address of a local variable at a specific index onto the evaluation stack
ilp.Append(Instruction.Create(OpCodes.Ldloca_S, callVar));
// Index is 0 Parameters of are loaded on the evaluation stack .
ilp.Append(Instruction.Create(OpCodes.Ldarg_0));
ilp.Append(Instruction.Create(OpCodes.Call, callPushInt32));
ilp.Append(Instruction.Create(OpCodes.Nop));
ilp.Append(Instruction.Create(OpCodes.Ldloca_S, callVar));
ilp.Append(Instruction.Create(OpCodes.Ldarg_1));
ilp.Append(Instruction.Create(OpCodes.Call, callPushInt32));
ilp.Append(Instruction.Create(OpCodes.Nop));
// Push the value of the static field onto the stack
ilp.Append(Instruction.Create(OpCodes.Ldsfld, vmField));
ilp.Append(Instruction.Create(OpCodes.Ldc_I4_0));
ilp.Append(Instruction.Create(OpCodes.Ldloca_S, callVar));
ilp.Append(Instruction.Create(OpCodes.Ldc_I4_2));
ilp.Append(Instruction.Create(OpCodes.Ldc_I4_0));
ilp.Append(Instruction.Create(OpCodes.Call, vmExecute));
ilp.Append(Instruction.Create(OpCodes.Nop));
ilp.Append(Instruction.Create(OpCodes.Ldloca_S, callVar));
ilp.Append(Instruction.Create(OpCodes.Ldc_I4_0));
ilp.Append(Instruction.Create(OpCodes.Call, callGetInt32));
// The stack will be evaluated 1 Stored in the local variable list
//ilp.Append(Instruction.Create(OpCodes.Stloc_1));
// Put the local variable 1 Load into the evaluation stack
//ilp.Append(Instruction.Create(OpCodes.Ldloc_1));
ilp.Append(Instruction.Create(OpCodes.Ret));
// The test method
//ilp.Append(Instruction.Create(OpCodes.Ldstr, " I am the method of generation "));
//var log_method = module.ImportReference(typeof(Debug).GetMethod("Log", new Type[] { typeof(object) }));
//ilp.Append(Instruction.Create(OpCodes.Call, log_method));
// Test use Go straight back to 0
//ilp.Append(Instruction.Create(OpCodes.Ldc_I4_0));
//ilp.Append(Instruction.Create(OpCodes.Ret));
patchLoadType.Methods.Add(patchMethod);
return patchMethod;
}
- Finish executing this part of the code , have access to ildasm have a look ,Sum Functional IL Changes in instructions , The blue circle is inserted IL Instructions , The red circle is the original Sum Instructions

Repair
- Repair is through traversal Body.Instructions All in IL Instructions , Parse and convert to VMInstruction Format instructions , My picture is convenient , Direct serialization Json adopt EditorPrefs.SetString Stored in Unity Editor down ,InjectFix It's very complicated. It's finally stored in a file , If you are interested, you can read InjectFix Source code
static void Fix(ModuleDefinition module, MethodDefinition method) {
//{
// .custom instance void PatchAttribute::.ctor() = (01 00 00 00 )
// // Code size 9 (0x9)
// .maxstack 2
// .locals init(int32 V_0)
// IL_0000: nop
// IL_0001: ldarg.1
// IL_0002: ldarg.2
// IL_0003: add
// IL_0004: stloc.0
// IL_0005: br.s IL_0007
// IL_0007: ldloc.0
// IL_0008: ret
//}
var ils = method.Body.Instructions;
var parseIls = new List<VMInstruction>();
for (int i = 0; i < ils.Count; i++) {
var il = ils[i];
var ilStr = ils[i].OpCode.Code.ToString();
switch (il.OpCode.Code) {
case Mono.Cecil.Cil.Code.Nop:
parseIls.Add(new VMInstruction {
Code = Code.StackSpace,
Operand = (method.Body.Variables.Count << 16) | method.Body.MaxStackSize
}); // local | maxstack
break;
case Mono.Cecil.Cil.Code.Ldarg_0:
case Mono.Cecil.Cil.Code.Ldarg_1:
case Mono.Cecil.Cil.Code.Ldarg_2:
case Mono.Cecil.Cil.Code.Ldarg_3:
parseIls.Add(new VMInstruction() {
Code = Code.Ldarg,
Operand = int.Parse(ilStr.Substring(ilStr.Length - 1)) - 1
});
break;
case Mono.Cecil.Cil.Code.Add:
parseIls.Add(new VMInstruction {
Code = (Code)Enum.Parse(typeof(Code), ilStr),
Operand = 0
});
break;
case Mono.Cecil.Cil.Code.Stloc_0:
case Mono.Cecil.Cil.Code.Stloc_1:
case Mono.Cecil.Cil.Code.Stloc_2:
case Mono.Cecil.Cil.Code.Stloc_3:
parseIls.Add(new VMInstruction {
Code = Code.Stloc,
Operand = int.Parse(ilStr.Substring(ilStr.Length - 1)),
});
break;
case Mono.Cecil.Cil.Code.Ret:
parseIls.Add(new VMInstruction {
Code = Code.Ret,
Operand = method.ReturnType.ToString() == "System.Void" ? 0 : 1,
});
break;
}
}
foreach (var vmil in parseIls) {
Debug.LogError(vmil);
}
var json = JsonMapper.ToJson(parseIls);
// Debug.LogError(json);
EditorPrefs.SetString(FixJson, json);
}
virtual machine
- This is basically InjectFix Virtual machine implementation , I'm a little sleepy today , Write it another day
边栏推荐
猜你喜欢

【FreeRTOS】11 软件定时器

C language start

AMD64(x86_64)架构abi文档:上

变量和数据类型(04)完结

Feature Selective Anchor-Free Module for Single-Shot Object Detection
![[steering wheel] code review ability of idea to ensure code quality](/img/70/dec438ba57f9cbd5020bba5da652ba.png)
[steering wheel] code review ability of idea to ensure code quality

Mongodb application scenario and model selection (massive data storage model selection)

Do you really know the judgement sentence?

17. What is the situation of using ArrayList or LinkedList?

Unity中使用深度和法线纹理
随机推荐
oracle中有A,B连个表,这两个表需要第三个表C关联,那怎么将A表中的字段MJ1更新为B表中MJ2的值
Redis master-slave mechanism
Part II - C language improvement_ 2. Memory partition
C language from introduction to soil -- super detailed summary of operators
Development system selection route
[steering wheel] the super favorite idea efficiency artifact save actions is uninstalled
Buddy: core function entry
【FreeRTOS】11 软件定时器
InjectFix原理学习(实现修复加法的热更)
[steering wheel] code review ability of idea to ensure code quality
From the perspective of CIA, common network attacks (blasting, PE, traffic attacks)
QoS服务质量四QoS边界行为之流量监管
C language from entry to Earth - array
Redis persistence
sqli-labs简单安装
Mqtt learning
安全工具之hackingtool
Learning notes - distributed transaction theory
File upload and download demo
[sequential logic circuit] - register