Mono Cecil十分强大,强大到可以静态注入程序集(注入后生成新的程序集)和动态注入程序集(注入后不改变目标程序集,只在运行时改变程序集行为),它甚至可以用来调试PDB MDB调试符号格式文件。

注:仔细看了下,并不支持“动态”注入,cecil只支持从硬盘加载或从内存读取一个已经被加载了的assembly,然后修改它的副本,最后另存为或者直接调用这个副本。

原程序集并不会发生任何改变,也就是说,如果你要修改一个程序集的行为,那么你必须在原软件加载它之前,修改它,并代替旧的。assembly一旦别加载,cecil是无法修改它的。

若想实现动态注入,动态修改已经被加载了的程序集功能(最典型的就是Unity的游戏,程序集的加载由mono.dll加载,我们比较难去操控它的加载),

可以参考这个教程:Dynamically replace the contents of a C# method?

或者这个开源库:Harmony

他们的原理都是,先用RuntimeHelpers预先从内存中加载原函数,以及要替换掉原函数的注入函数,然后分别获取它们的指针,即它们在内存中的位置,

然后交换它们指针,交换内存空间,即可以实现,替换已经加载了的程序集里的函数内容。

(32位跟64位需要分别处理,因为指针大小不一样,还有这个只支持X86架构,ARM需要另外处理)

  1.        MethodInfo methodToReplace = typeof(Target).GetMethod("targetMethod"+ funcNum, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
  2. MethodInfo methodToInject = typeof(Injection).GetMethod("injectionMethod"+ funcNum, BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
  3. RuntimeHelpers.PrepareMethod(methodToReplace.MethodHandle);
  4. RuntimeHelpers.PrepareMethod(methodToInject.MethodHandle);
  5.  
  6. unsafe
  7. {
  8. if (IntPtr.Size == )
  9. {
  10. int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + ;
  11. int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + ;
  12. #if DEBUG
  13. Console.WriteLine("\nVersion x86 Debug\n");
  14.  
  15. byte* injInst = (byte*)*inj;
  16. byte* tarInst = (byte*)*tar;
  17.  
  18. int* injSrc = (int*)(injInst + );
  19. int* tarSrc = (int*)(tarInst + );
  20.  
  21. *tarSrc = (((int)injInst + ) + *injSrc) - ((int)tarInst + );
  22. #else
  23. Console.WriteLine("\nVersion x86 Release\n");
  24. *tar = *inj;
  25. #endif
  26. }
  27. else
  28. {
  29.  
  30. long* inj = (long*)methodToInject.MethodHandle.Value.ToPointer()+;
  31. long* tar = (long*)methodToReplace.MethodHandle.Value.ToPointer()+;
  32. #if DEBUG
  33. Console.WriteLine("\nVersion x64 Debug\n");
  34. byte* injInst = (byte*)*inj;
  35. byte* tarInst = (byte*)*tar;
  36.  
  37. int* injSrc = (int*)(injInst + );
  38. int* tarSrc = (int*)(tarInst + );
  39.  
  40. *tarSrc = (((int)injInst + ) + *injSrc) - ((int)tarInst + );
  41. #else
  42. Console.WriteLine("\nVersion x64 Release\n");
  43. *tar = *inj;
  44. #endif
  45. }
  46. }

参考文章:

注:Emit也能跟Mono.Cecil一样动态生成IL,但它貌似只支持PC平台:

Mono.Cecil与.NET Reflection的反射对比

Mono.Cecil的更多相关文章

  1. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  2. Mono.Cecil 初探(一):实现AOP

    序言 本篇文章介绍基于Mono.Cecil实现静态AOP的两种方式:无交互AOP和交互式AOP. 概念介绍 Mono.Cecil:一个可加载并浏览现有程序集并进行动态修改并保存的.NET框架. AOP ...

  3. 基于Mono.Cecil的静态注入

    Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...

  4. 使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入 用于写Log) [此文报考 xxx is declared in another module and needs to be imported的解决方法]-摘自网络

    目录 一:普通写法 二:注入定义 三:Weave函数 四:参数构造 五:业务编写 六:注入调用 7.  怎么调用别的程序集的方法示例 8. [is declared in another module ...

  5. C# Asp.net中的AOP框架 Microsoft.CCI, Mono.Cecil, Typemock Open-AOP API, PostSharp -摘自网络 (可以利用反射 Attribute 进行面向切面编程 可以用在记录整个方法的Log方面)

    Both Microsoft.CCI and Mono.Cecil are low-level, and don't validate produced assemblies. It takes lo ...

  6. 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)

    原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...

  7. 教你怎么用Mono Cecil - 动态注入 (注意代码的注释)

    原文 教你怎么用Mono Cecil - 动态注入 (注意代码的注释) 使用 Mono Cecil 进行反编译:using Mono.Cecil; using Mono.Cecil.Cil; //.. ...

  8. 使用 Mono.Cecil 辅助 Unity3D 手游进行性能测试

    Unity3D 引擎在  UnityEngine 名字空间下,提供了  Profiler 类(Unity 5.6 开始似乎改变了这个名字空间),用于辅助对项目性能进行测试.以 Android 平台为例 ...

  9. 巧用Mono.Cecil反射加载类型和方法信息

    最近在做服务的细粒度治理,统一管理所有服务的方法.参数.返回值信息.方便后续的各个模块之间的对接和协作. 目前系统中所有的服务,管理到接口契约粒度,即服务接口声明和服务接口实现.要做服务的细粒度治理: ...

随机推荐

  1. 在浏览器中浏览git上项目目录结构

    效果如下,参考:https://gitee.com/oschina/GitCodeTree

  2. 前端JS Excel导出

    本文转载自:https://blog.csdn.net/plmzaqokn11/article/details/73604705 下载table2Excel插件 <input type=&quo ...

  3. 洛谷P1463 反素数

    经典题了,很难想到这TM是搜索...... 题意:求[1, n]中约数最多的数中最小的. 解:我们有约数个数定理. 所以考虑通过枚举每个质因数个数来直接计算出约数个数. 然后就可以搜索了. 注意:若p ...

  4. gevent多协程运用

    #导包 import gevent #猴子补丁 from gevent import monkey monkey.patch_all() from d8_db import ConnectMysql ...

  5. react-native中的动画

    先看效果 这个一个渐渐显示的动画,代码如下 import React from 'react'; import { Animated, Text, View } from 'react-native' ...

  6. margin纵向重叠

    速记: 如p的纵向 margin 是 16px,那么两个之间纵向的距离是多少?-- 按常理来说应该是 16 + 16 = 32px,但是答案仍然是 16px. 因为纵向的 margin 是会重叠的,如 ...

  7. 破解phpstorm

    说下破解的版本:PHPstorm2018.2.2 打开phpstorm,选择Activation code 粘贴下面这段code EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEw ...

  8. Installation failed with message Failed to finalize session: INSTALL_FAILED_TEST_ONLY:installPackageLI.

    这样还不行的话,加 -t吧.

  9. C# BackgroundWorker使用总结

    查询了一下MSDN文档,其中微软就BackgroundWorker类的功能有这么一个描述(英文的,根据个人理解翻译):BackgroundWorker类允许您在单独的线程上执行某个可能导致用户界面(U ...

  10. CSS外边框、边界样式常用组合

    一.CSS框线一览表 border-top : 1px solid #6699cc; /*上框线*/ border-bottom : 1px solid #6699cc; /*下框线*/ border ...