最近我发现一个经常使用的架构师.net程序错误地实现了一个函数。因此,我以静态方式修改二进制文件,使用ILSpy和Reflexil 成功修补。但是,当新的次要版本发布时,您需要修补它并再次删除StrongNameCheck,这很烦人。 (顺便说一句,作者认为这是一个功能,而不是一个错误)
希望该程序完全支持程序集作为插件。我的目标是公共类中的公共非静态成员函数,可以通过插件直接调用。有没有办法修补功能动态?
我通常在非托管C ++中使用一些APIHook技巧但是dotnet实际上是另一回事。在这种情况下,我希望修改在程序集卸载后仍然有效(因此更类似于补丁,而不是挂钩)。
答案 0 :(得分:4)
是的,您可以使用代码注入来完成。但你需要知道一些MSIL。还有一个名为Mono.Cecil
的库。
这是一个示例代码
Console.WriteLine("> INJECTING INTO 12345.EXE..." + Environment.NewLine);
AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(@"C:\dummy.exe");
var writeLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
var writeLineRef = asm.MainModule.Import(writeLineMethod);
var pStartMethod = typeof(Process).GetMethod("Start", new Type[] { typeof(string) });
var pStartRef = asm.MainModule.Import(pStartMethod);
foreach (var typeDef in asm.MainModule.Types)
{
foreach (var method in typeDef.Methods)
{
//Let's push a string using the Ldstr Opcode to the stack
method.Body.Instructions.Insert(0, Instruction.Create(OpCodes.Ldstr, "INJECTED!"));
//We add the call to the Console.WriteLine() method. It will read from the stack
method.Body.Instructions.Insert(1, Instruction.Create(OpCodes.Call, writeLineRef));
//We push the path of the executable you want to run to the stack
method.Body.Instructions.Insert(2, Instruction.Create(OpCodes.Ldstr, @"calc.exe"));
//Adding the call to the Process.Start() method, It will read from the stack
method.Body.Instructions.Insert(3, Instruction.Create(OpCodes.Call, pStartRef));
//Removing the value from stack with pop
method.Body.Instructions.Insert(4, Instruction.Create(OpCodes.Pop));
}
}
asm.Write("12345.exe"); //Now we just save the new assembly
答案 1 :(得分:1)
不要修补补丁码。将功能添加到您的代码库并调用该功能。或者编写一个包装底层程序集的适配器类,它更整洁。
如果代码的作者认为它不是一个错误,那么它可能是因为您不理解的原因并且可能是任何错误修复的一部分。